diff --git a/.gn b/.gn
index 54d2631..b8756e5 100644
--- a/.gn
+++ b/.gn
@@ -148,7 +148,7 @@
 
 exec_script_allowlist =
     build_dotfile_settings.exec_script_allowlist +
-    angle_dotfile_settings.exec_script_whitelist +
+    angle_dotfile_settings.exec_script_allowlist +
     [
       # Allowlist entries for //build should go into
       # //build/dotfile_settings.gni instead, so that they can be shared
diff --git a/DEPS b/DEPS
index 7ec668a..f0a70ab 100644
--- a/DEPS
+++ b/DEPS
@@ -304,15 +304,15 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'f91412f5d89d85fe2ea6b9e5ea30d04f112d2d53',
+  'skia_revision': '05f7251290b1d43eb5c89370a80846b87e9de916',
   # 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': 'cfe14766c19eb555caa2bd36dba729646eaca469',
+  'v8_revision': '82b4f3cde5bc74ed21aeeae257301550b620277b',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': 'f276df669062b83b6a33f58b764706e582a9151b',
+  'angle_revision': '6631db11d0363b524414c41ac73eacc075d3db19',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -324,7 +324,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
-  'boringssl_revision': 'f0ab91129d1a234dc127335765b794d62dc9ed4d',
+  'boringssl_revision': 'a553a9d65aa4e4f28a6c3007db14e9605e7c3bde',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Fuchsia sdk
   # and whatever else without interference from each other.
@@ -376,7 +376,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': '7236fd6c03b5c8f0e31e37207419cfdbe7bfee98',
+  'catapult_revision': '6e0dcdccb316673a6a9d498d32e6b9a61e8672d5',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling CrossBench
   # and whatever else without interference from each other.
@@ -396,7 +396,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-frontend
   # and whatever else without interference from each other.
-  'devtools_frontend_revision': '51544a715444d283fd99d4eb4dc1137a1939ee16',
+  'devtools_frontend_revision': '488f39ac7c36ee7f982335b16807a0c4472cc0bc',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libprotobuf-mutator
   # and whatever else without interference from each other.
@@ -420,7 +420,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': '5e44eb524fb6b341029180bb21de431de5717f98',
+  'dawn_revision': '39a35b8b9dc4b135e30a31f596c5f5d42a4ede30',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -1158,7 +1158,7 @@
   },
 
   'src/chrome/release_scripts': {
-      'url': Var('chrome_git') + '/chrome/tools/release/scripts' + '@' + '6f895445ad5a137f98d68ad25783f953e3713d52',
+      'url': Var('chrome_git') + '/chrome/tools/release/scripts' + '@' + '29480092413e128bbd9e417c36760d759556930c',
       'condition': 'checkout_chrome_release_scripts',
   },
 
@@ -1501,7 +1501,7 @@
 
   'src/clank': {
     'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' +
-    '984675d15dc0687e5e725ec195196357fd0bc765',
+    '84a854a1fe9a948b8df14dc5e236cd9df9f23984',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
@@ -2541,7 +2541,7 @@
     Var('pdfium_git') + '/pdfium.git' + '@' +  Var('pdfium_revision'),
 
   'src/third_party/perfetto':
-    Var('chromium_git') + '/external/github.com/google/perfetto.git' + '@' + '29152c058571b61ef71d266c422cd5f5eb4bf83f',
+    Var('chromium_git') + '/external/github.com/google/perfetto.git' + '@' + 'ca270042d1485933a6a7246c874b3c4ef561ad0d',
 
   'src/base/tracing/test/data': {
     'bucket': 'perfetto',
@@ -2855,16 +2855,16 @@
       'dep_type': 'cipd',
   },
 
-  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@897477bba57341592bfd3d6ba0c6901c31c44f27',
+  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@75036a1b874d6269a50daba6146fbd020feadcaf',
   'src/third_party/glslang/src': '{chromium_git}/external/github.com/KhronosGroup/glslang@c3d39de93955f884e443c39e9ffecf86e4aac883',
   '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@8e82b7cfeca98baae9a01a53511483da7194f854',
-  'src/third_party/spirv-tools/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Tools@6add4e478f8802d3bbd100120e5ffc6f725ec9fe',
+  'src/third_party/spirv-tools/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Tools@4bd1536ed79003a5194a4bd8c9aa2fa17a84c15b',
   'src/third_party/vulkan-headers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Headers@2ac81691baf291e7f4aad07596d7073974dbc4dd',
   'src/third_party/vulkan-loader/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Loader@723d6b4aa35853315c6e021ec86388b3a2559fae',
   'src/third_party/vulkan-tools/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Tools@289efccc7560f2b970e2b4e0f50349da87669311',
   'src/third_party/vulkan-utility-libraries/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Utility-Libraries@551221d913cc56218fcaddce086ae293d375ac28',
-  'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@1ec32dc68665bcaad2e933696f6d9bccd52173a7',
+  'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@2cfc63fcf5670a284c73fe91fe4de42d4c0e20a9',
 
   'src/third_party/vulkan_memory_allocator':
     Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + '56300b29fbfcc693ee6609ddad3fdd5b7a449a21',
@@ -3042,7 +3042,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/help_app/app',
-        'version': 'ZlQ8OTp696ZgoVNJM4_AjbwhXI3I6Dip2GEaNN1speUC',
+        'version': '1pADecPo3L2BTc3XAb6AT8TvcaezR3oTFcfL7gMNaFsC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -4635,7 +4635,7 @@
 
   'src/components/optimization_guide/internal': {
       'url': Var('chrome_git') + '/chrome/components/optimization_guide.git' + '@' +
-        'f9d7428c4e3f83168b67a9974764646f5b5741fb',
+        'd0d7e49feef85c1ef7e783521a20babc50ab3342',
       'condition': 'checkout_src_internal',
   },
 
@@ -4701,7 +4701,7 @@
 
   'src/ios_internal':  {
       'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' +
-        'c399a02597c037cc2117413c9161f72b57307121',
+        'ecc08cc10ed9e1886e0f3197eb883f648293430b',
       'condition': 'checkout_ios and checkout_src_internal',
   },
 
diff --git a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
index 2b7712a..6cc6c62 100644
--- a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
+++ b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
@@ -1068,6 +1068,14 @@
                 CcFeatures.EXPORT_FRAME_TIMING_AFTER_FRAME_DONE,
                 "When enabled, moves the layer tree client's metric export call for from beginning"
                         + " of the subsequent frame to the end of the subsequent frame."),
+        Flag.baseFeature(
+                BlinkFeatures.ASYNC_SET_COOKIE,
+                "When enabled, the communication between renderer and network service is "
+                        + "asynchronous when setting cookies."),
+        Flag.baseFeature(
+                NetworkServiceFeatures.GET_COOKIES_ON_SET,
+                "When enabled, the network service returns all the cookies when setting a new "
+                        + "cookie, so that it can be cached."),
         // Add new commandline switches and features above. The final entry should have a
         // trailing comma for cleaner diffs.
     };
diff --git a/ash/quick_pair/common/logging.cc b/ash/quick_pair/common/logging.cc
index f4e09592..9db02ed 100644
--- a/ash/quick_pair/common/logging.cc
+++ b/ash/quick_pair/common/logging.cc
@@ -34,20 +34,19 @@
     return;
 
   const std::string string_from_stream = stream_.str();
-  LogBuffer::GetInstance()->AddLogMessage(
-      LogBuffer::LogMessage(string_from_stream, base::Time::Now(),
-                            std::string(file_), line_, severity_));
+  LogBuffer::GetInstance()->AddLogMessage(LogBuffer::LogMessage(
+      string_from_stream, base::Time::Now(), file_.data(), line_, severity_));
 
   // Don't emit VERBOSE-level logging to the standard logging system unless
   // verbose logging is enabled for the source file.
   if (severity_ <= logging::LOGGING_VERBOSE &&
-      logging::GetVlogLevelHelper(file_) <= 0) {
+      logging::GetVlogLevelHelper(file_.data(), file_.size()) <= 0) {
     return;
   }
 
   // The destructor of |log_message| also creates a log for the standard logging
   // system.
-  logging::LogMessage log_message(file_, line_, severity_);
+  logging::LogMessage log_message(file_.data(), line_, severity_);
   log_message.stream() << string_from_stream;
 }
 
diff --git a/ash/quick_pair/common/logging.h b/ash/quick_pair/common/logging.h
index 5a29d40..7041cad 100644
--- a/ash/quick_pair/common/logging.h
+++ b/ash/quick_pair/common/logging.h
@@ -23,10 +23,10 @@
 // Examples:
 //   QP_LOG(INFO) << "Waiting for " << x << " pending requests.";
 //   QP_LOG(ERROR) << "Request failed: " << error_string;
-#define QP_LOG(severity)                                             \
-  ash::quick_pair::ScopedLogMessage(                                 \
-      std::string_view(__FILE__, std::size(__FILE__) - 1), __LINE__, \
-      logging::LOGGING_##severity)                                   \
+#define QP_LOG(severity)                                         \
+  ash::quick_pair::ScopedLogMessage(                             \
+      std::string_view(__FILE__, std::size(__FILE__)), __LINE__, \
+      logging::LOGGING_##severity)                               \
       .stream()
 
 // Disables all logging while in scope. Intended to be called only from test
diff --git a/ash/quick_pair/common/logging_unittest.cc b/ash/quick_pair/common/logging_unittest.cc
index 068cc070..e45859097 100644
--- a/ash/quick_pair/common/logging_unittest.cc
+++ b/ash/quick_pair/common/logging_unittest.cc
@@ -27,7 +27,7 @@
 base::LazyInstance<std::vector<std::string>>::DestructorAtExit g_standard_logs =
     LAZY_INSTANCE_INITIALIZER;
 bool HandleStandardLogMessage(int severity,
-                              std::string_view file,
+                              const char* file,
                               int line,
                               size_t message_start,
                               const std::string& str) {
diff --git a/ash/system/input_device_settings/input_device_settings_logging_unittest.cc b/ash/system/input_device_settings/input_device_settings_logging_unittest.cc
index cce3794..b89e54b8 100644
--- a/ash/system/input_device_settings/input_device_settings_logging_unittest.cc
+++ b/ash/system/input_device_settings/input_device_settings_logging_unittest.cc
@@ -6,8 +6,6 @@
 
 #include <stddef.h>
 
-#include <string_view>
-
 #include "ash/constants/ash_features.h"
 #include "base/no_destructor.h"
 #include "base/test/scoped_feature_list.h"
@@ -28,7 +26,7 @@
 }
 
 bool HandleStandardLogMessage(int severity,
-                              std::string_view file,
+                              const char* file,
                               int line,
                               size_t message_start,
                               const std::string& str) {
diff --git a/ash/system/power/power_prefs.cc b/ash/system/power/power_prefs.cc
index 420f3fc2..59652c9 100644
--- a/ash/system/power/power_prefs.cc
+++ b/ash/system/power/power_prefs.cc
@@ -487,10 +487,10 @@
         charge_limit_enabled.value_or(false)) {
       LOG(WARNING) << "Pref set to enable both Adaptive Charging and Charge "
                    << "Limit, which are mutually exclusive features. "
-                   << "Disabling charge limit.";
+                   << "Adaptive charging will be disabled.";
 
       // Update the local optional variable to maintain consistency
-      charge_limit_enabled = false;
+      adaptive_charging_enabled = false;
     }
 
     values.adaptive_charging_enabled = adaptive_charging_enabled;
diff --git a/ash/system/power/power_prefs_unittest.cc b/ash/system/power/power_prefs_unittest.cc
index 0a7b169a..c23107ea 100644
--- a/ash/system/power/power_prefs_unittest.cc
+++ b/ash/system/power/power_prefs_unittest.cc
@@ -694,17 +694,17 @@
   EXPECT_FALSE(power_manager_client()->policy().charge_limit_enabled());
 }
 
-TEST_F(PowerPrefsTest, ChargeLimit_DisabledWhenAdaptiveChargingEnabled) {
+TEST_F(PowerPrefsTest, AdaptiveChargingAndChargeLimit_MutuallyExclusive) {
   // Enable adaptive charging hardware support.
   power_manager::PowerSupplyProperties power_props;
   power_props.set_adaptive_charging_supported(true);
   power_manager_client()->UpdatePowerProperties(power_props);
 
-  // When adaptive charging is enabled, charge limit should be disabled.
-  // This ensures that the two features do not conflict.
+  // When both adaptive charging and charge limit enabled, adaptive charging
+  // should be disabled. This ensures that the two features do not conflict.
   SetAdaptiveChargingPreference(true);
   managed_pref_store_->SetBoolean(prefs::kPowerChargeLimitEnabled, true);
-  EXPECT_TRUE(power_manager_client()->policy().adaptive_charging_enabled());
-  EXPECT_FALSE(power_manager_client()->policy().charge_limit_enabled());
+  EXPECT_FALSE(power_manager_client()->policy().adaptive_charging_enabled());
+  EXPECT_TRUE(power_manager_client()->policy().charge_limit_enabled());
 }
 }  // namespace ash
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 0c24c7f..5b139f04 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -2070,6 +2070,8 @@
     sources += [
       "apple/mach_port_rendezvous.cc",
       "apple/mach_port_rendezvous.h",
+      "apple/mach_port_rendezvous_mac.cc",
+      "apple/mach_port_rendezvous_mac.h",
       "enterprise_util.cc",
       "enterprise_util.h",
       "enterprise_util_mac.mm",
@@ -2211,7 +2213,11 @@
         # the bare minimum and does not use Mach ports.
         sources += [ "process/process_tvos.cc" ]
       } else {
-        sources += [ "process/process_mac.cc" ]
+        sources += [
+          "apple/mach_port_rendezvous_ios.cc",
+          "apple/mach_port_rendezvous_ios.h",
+          "process/process_mac.cc",
+        ]
       }
 
       # We include launch_mac on simulator builds so unittests can fork. But,
diff --git a/base/apple/mach_port_rendezvous.cc b/base/apple/mach_port_rendezvous.cc
index 23c03b4..bf19f323 100644
--- a/base/apple/mach_port_rendezvous.cc
+++ b/base/apple/mach_port_rendezvous.cc
@@ -23,73 +23,10 @@
 #include "base/strings/stringprintf.h"
 #include "base/types/cxx23_to_underlying.h"
 
-#if BUILDFLAG(IS_IOS)
-#include "base/ios/sim_header_shims.h"
-#endif
-
-#if BUILDFLAG(IS_MAC)
-#include <bsm/libbsm.h>
-#include <servers/bootstrap.h>
-
-#include "base/apple/scoped_dispatch_object.h"
-#include "base/environment.h"
-#include "base/mac/info_plist_data.h"
-#include "base/strings/string_number_conversions.h"
-#endif
-
 namespace base {
 
-#if BUILDFLAG(IS_MAC)
-// Whether any peer process requirements should be validated.
-BASE_FEATURE(kMachPortRendezvousValidatePeerRequirements,
-             "MachPortRendezvousValidatePeerRequirements",
-             base::FEATURE_DISABLED_BY_DEFAULT);
-
-// Whether a failure to validate a peer process against a requirement
-// should result in aborting the rendezvous.
-BASE_FEATURE(kMachPortRendezvousEnforcePeerRequirements,
-             "MachPortRendezvousEnforcePeerRequirements",
-             base::FEATURE_DISABLED_BY_DEFAULT);
-#endif
-
 namespace {
 
-#if BUILDFLAG(IS_IOS)
-static MachPortRendezvousClientIOS* g_client = nullptr;
-#endif
-
-#if BUILDFLAG(IS_MAC)
-// The name to use in the bootstrap server, formatted with the BaseBundleID and
-// PID of the server.
-constexpr char kBootstrapNameFormat[] = "%s.MachPortRendezvousServer.%d";
-
-// This can be safely increased if Info.plist grows in the future.
-constexpr size_t kMaxInfoPlistDataSize = 18 * 1024;
-
-#endif
-
-// This limit is arbitrary and can be safely increased in the future.
-constexpr size_t kMaximumRendezvousPorts = 6;
-
-enum MachRendezvousMsgId : mach_msg_id_t {
-  kMachRendezvousMsgIdRequest = 'mrzv',
-  kMachRendezvousMsgIdResponse = 'MRZV',
-
-#if BUILDFLAG(IS_MAC)
-  // When MachPortRendezvousClientMac has a `ProcessRequirement` that requests
-  // dynamic-only validation, it will request that the server provide a copy of
-  // its Info.plist data in the rendezvous response. Dynamic-only validation
-  // validates the running process without enforcing that it matches its on-disk
-  // representation. This is necessary when validating applications such as
-  // Chrome that may be updated on disk while the application is running.
-  //
-  // The Info.plist data ends up passed to `SecCodeCopyGuestWithAttributes`,
-  // where it is validated against the hash stored within the code signature
-  // before using it to evaluate any requirements involving Info.plist data.
-  kMachRendezvousMsgIdRequestWithInfoPlistData = 'mrzV',
-#endif
-};
-
 size_t CalculateResponseSize(size_t num_ports, size_t additional_data_length) {
   return bits::AlignUp(
       sizeof(mach_msg_base_t) +
@@ -99,29 +36,6 @@
       sizeof(uint32_t));
 }
 
-#if BUILDFLAG(IS_MAC)
-
-// The state of the peer validation policy features is passed to child processes
-// via this environment variable as Mach port rendezvous is performed before the
-// feature list is initialized.
-// TODO(crbug.com/362302761): Remove once enforcement is enabled by default.
-constexpr char kPeerValidationPolicyEnvironmentVariable[] =
-    "MACH_PORT_RENDEZVOUS_PEER_VALDATION";
-
-MachPortRendezvousPeerValidationPolicy GetPeerValidationPolicy();
-
-bool ShouldValidateProcessRequirements() {
-  return GetPeerValidationPolicy() !=
-         MachPortRendezvousPeerValidationPolicy::kNoValidation;
-}
-
-bool ShouldEnforceProcessRequirements() {
-  return GetPeerValidationPolicy() ==
-         MachPortRendezvousPeerValidationPolicy::kEnforce;
-}
-
-#endif
-
 }  // namespace
 
 MachRendezvousPort::MachRendezvousPort(mach_port_t name,
@@ -207,7 +121,7 @@
   // the destruction of the reply port will break them out of a mach_msg.
   ScopedMachMsgDestroy scoped_message(&request);
 
-  if ((request.msgh_id != kMachRendezvousMsgIdRequest &&
+  if ((request.msgh_id != internal::kMachRendezvousMsgIdRequest &&
        !IsValidAdditionalMessageId(request.msgh_id)) ||
       request.msgh_size != sizeof(mach_msg_header_t)) {
     // Do not reply to messages that are unexpected.
@@ -254,7 +168,7 @@
       MACH_MSGH_BITS_COMPLEX;
   message->header.msgh_size = checked_cast<mach_msg_size_t>(buffer_size);
   message->header.msgh_remote_port = reply_port;
-  message->header.msgh_id = kMachRendezvousMsgIdResponse;
+  message->header.msgh_id = internal::kMachRendezvousMsgIdResponse;
   message->body.msgh_descriptor_count =
       checked_cast<mach_msg_size_t>(port_count);
 
@@ -284,195 +198,6 @@
   return buffer;
 }
 
-#if BUILDFLAG(IS_IOS)
-apple::ScopedMachSendRight MachPortRendezvousServerIOS::GetMachSendRight() {
-  return apple::RetainMachSendRight(send_right_.get());
-}
-
-MachPortRendezvousServerIOS::MachPortRendezvousServerIOS(
-    const MachPortsForRendezvous& ports)
-    : ports_(ports) {
-  DCHECK_LT(ports_.size(), kMaximumRendezvousPorts);
-  bool res = apple::CreateMachPort(&server_port_, &send_right_);
-  CHECK(res) << "Failed to create mach server port";
-  dispatch_source_ = std::make_unique<apple::DispatchSource>(
-      "MachPortRendezvousServer", server_port_.get(), ^{
-        HandleRequest();
-      });
-  dispatch_source_->Resume();
-}
-
-std::optional<MachPortsForRendezvous>
-MachPortRendezvousServerIOS::PortsForClient(audit_token_t audit_token) {
-  // `audit_token` is ignored as a server handles a single client on iOS.
-  return ports_;
-}
-
-bool MachPortRendezvousServerIOS::IsValidAdditionalMessageId(
-    mach_msg_id_t) const {
-  return false;
-}
-std::vector<uint8_t> MachPortRendezvousServerIOS::AdditionalDataForReply(
-    mach_msg_id_t) const {
-  return {};
-}
-
-MachPortRendezvousServerIOS::~MachPortRendezvousServerIOS() = default;
-
-#endif
-
-#if BUILDFLAG(IS_MAC)
-
-struct MachPortRendezvousServerMac::ClientData {
-  ClientData();
-  ClientData(ClientData&&);
-  ~ClientData();
-
-  // A DISPATCH_SOURCE_TYPE_PROC / DISPATCH_PROC_EXIT dispatch source. When
-  // the source is triggered, it calls OnClientExited().
-  apple::ScopedDispatchObject<dispatch_source_t> exit_watcher;
-
-  MachPortsForRendezvous ports;
-  std::optional<mac::ProcessRequirement> requirement;
-};
-
-// static
-MachPortRendezvousServerMac* MachPortRendezvousServerMac::GetInstance() {
-  static auto* instance = new MachPortRendezvousServerMac();
-  return instance;
-}
-
-// static
-void MachPortRendezvousServerMac::AddFeatureStateToEnvironment(
-    EnvironmentMap& environment) {
-  environment.insert(
-      {kPeerValidationPolicyEnvironmentVariable,
-       NumberToString(static_cast<int>(GetPeerValidationPolicy()))});
-}
-
-MachPortRendezvousServerMac::ClientData&
-MachPortRendezvousServerMac::ClientDataForPid(pid_t pid) {
-  lock_.AssertAcquired();
-
-  auto [it, inserted] = client_data_.emplace(pid, ClientData{});
-  if (inserted) {
-    apple::ScopedDispatchObject<dispatch_source_t> exit_watcher(
-        dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC,
-                               static_cast<uintptr_t>(pid), DISPATCH_PROC_EXIT,
-                               dispatch_source_->Queue()));
-    dispatch_source_set_event_handler(exit_watcher.get(), ^{
-      OnClientExited(pid);
-    });
-    dispatch_resume(exit_watcher.get());
-    it->second.exit_watcher = std::move(exit_watcher);
-  }
-
-  return it->second;
-}
-
-void MachPortRendezvousServerMac::RegisterPortsForPid(
-    pid_t pid,
-    const MachPortsForRendezvous& ports) {
-  lock_.AssertAcquired();
-  DCHECK_LT(ports.size(), kMaximumRendezvousPorts);
-  DCHECK(!ports.empty());
-
-  ClientData& client = ClientDataForPid(pid);
-  CHECK(client.ports.empty());
-  client.ports = ports;
-}
-
-void MachPortRendezvousServerMac::SetProcessRequirementForPid(
-    pid_t pid,
-    mac::ProcessRequirement requirement) {
-  lock_.AssertAcquired();
-
-  ClientData& client = ClientDataForPid(pid);
-  CHECK(!client.requirement.has_value());
-  client.requirement = std::move(requirement);
-}
-
-MachPortRendezvousServerMac::ClientData::ClientData() = default;
-MachPortRendezvousServerMac::ClientData::ClientData(ClientData&&) = default;
-
-MachPortRendezvousServerMac::ClientData::~ClientData() {
-  for (auto& pair : ports) {
-    pair.second.Destroy();
-  }
-}
-
-MachPortRendezvousServerMac::MachPortRendezvousServerMac() {
-  std::string bootstrap_name =
-      StringPrintf(kBootstrapNameFormat, apple::BaseBundleID(), getpid());
-  kern_return_t kr = bootstrap_check_in(
-      bootstrap_port, bootstrap_name.c_str(),
-      apple::ScopedMachReceiveRight::Receiver(server_port_).get());
-  BOOTSTRAP_CHECK(kr == KERN_SUCCESS, kr)
-      << "bootstrap_check_in " << bootstrap_name;
-  dispatch_source_ = std::make_unique<apple::DispatchSource>(
-      bootstrap_name.c_str(), server_port_.get(), ^{
-        HandleRequest();
-      });
-  dispatch_source_->Resume();
-}
-
-MachPortRendezvousServerMac::~MachPortRendezvousServerMac() = default;
-
-void MachPortRendezvousServerMac::ClearClientDataForTesting() {
-  client_data_.clear();
-}
-
-std::optional<MachPortsForRendezvous>
-MachPortRendezvousServerMac::PortsForClient(audit_token_t audit_token) {
-  pid_t pid = audit_token_to_pid(audit_token);
-  std::optional<mac::ProcessRequirement> requirement;
-  MachPortsForRendezvous ports_to_send;
-
-  {
-    AutoLock lock(lock_);
-    auto it = client_data_.find(pid);
-    if (it != client_data_.end()) {
-      ports_to_send = std::move(it->second.ports);
-      requirement = std::move(it->second.requirement);
-      client_data_.erase(it);
-    }
-  }
-
-  if (requirement.has_value() && ShouldValidateProcessRequirements()) {
-    bool client_is_valid = requirement->ValidateProcess(audit_token);
-    if (!client_is_valid && ShouldEnforceProcessRequirements()) {
-      return std::nullopt;
-    }
-  }
-
-  return ports_to_send;
-}
-
-void MachPortRendezvousServerMac::OnClientExited(pid_t pid) {
-  AutoLock lock(lock_);
-  client_data_.erase(pid);
-}
-
-bool MachPortRendezvousServerMac::IsValidAdditionalMessageId(
-    mach_msg_id_t request) const {
-  return request == kMachRendezvousMsgIdRequestWithInfoPlistData;
-}
-
-std::vector<uint8_t> MachPortRendezvousServerMac::AdditionalDataForReply(
-    mach_msg_id_t request) const {
-  if (request == kMachRendezvousMsgIdRequestWithInfoPlistData) {
-    std::vector<uint8_t> info_plist_data =
-        mac::OuterBundleCachedInfoPlistData();
-    if (info_plist_data.size() > kMaxInfoPlistDataSize) {
-      LOG(WARNING) << "Info.plist data too large to send to client.";
-      return {};
-    }
-    return info_plist_data;
-  }
-  return {};
-}
-
-#endif  // BUILDFLAG(IS_MAC)
 
 MachPortRendezvousClient::MachPortRendezvousClient() = default;
 
@@ -505,7 +230,7 @@
     mach_msg_id_t request_msg_id,
     size_t additional_response_data_size) {
   const size_t buffer_size =
-      CalculateResponseSize(kMaximumRendezvousPorts,
+      CalculateResponseSize(internal::kMaximumRendezvousPorts,
                             additional_response_data_size) +
       sizeof(mach_msg_audit_trailer_t);
   auto buffer = std::make_unique<uint8_t[]>(buffer_size);
@@ -537,7 +262,7 @@
     return false;
   }
 
-  if (message->header.msgh_id != kMachRendezvousMsgIdResponse) {
+  if (message->header.msgh_id != internal::kMachRendezvousMsgIdResponse) {
     // Check if the response contains a rendezvous reply. If there were no
     // ports for this client, then the send right would have been destroyed.
     if (message->header.msgh_id == MACH_NOTIFY_SEND_ONCE) {
@@ -582,236 +307,4 @@
   return port;
 }
 
-#if BUILDFLAG(IS_IOS)
-// static
-MachPortRendezvousClient* MachPortRendezvousClient::GetInstance() {
-  CHECK(g_client);
-  return g_client;
-}
-
-MachPortRendezvousClientIOS::MachPortRendezvousClientIOS() = default;
-MachPortRendezvousClientIOS::~MachPortRendezvousClientIOS() = default;
-
-bool MachPortRendezvousClientIOS::Initialize(
-    apple::ScopedMachSendRight server_port) {
-  CHECK(!g_client);
-  g_client = new MachPortRendezvousClientIOS();
-  if (!g_client->AcquirePorts(std::move(server_port))) {
-    delete g_client;
-    g_client = nullptr;
-  }
-  return true;
-}
-
-bool MachPortRendezvousClientIOS::AcquirePorts(
-    apple::ScopedMachSendRight server_port) {
-  AutoLock lock(lock_);
-  return SendRequest(std::move(server_port), kMachRendezvousMsgIdRequest);
-}
-
-bool MachPortRendezvousClientIOS::ValidateMessage(mach_msg_base_t*,
-                                                  BufferIterator<uint8_t>) {
-  return true;
-}
-
-#endif  // BUILDFLAG(IS_IOS)
-
-#if BUILDFLAG(IS_MAC)
-
-// static
-MachPortRendezvousClient* MachPortRendezvousClient::GetInstance() {
-  static MachPortRendezvousClientMac* client = []() -> auto* {
-    auto* client = new MachPortRendezvousClientMac();
-    if (!client->AcquirePorts()) {
-      delete client;
-      client = nullptr;
-    }
-    return client;
-  }();
-  return client;
-}
-
-// static
-std::string MachPortRendezvousClientMac::GetBootstrapName() {
-  return StringPrintf(kBootstrapNameFormat, apple::BaseBundleID(), getppid());
-}
-
-MachPortRendezvousClientMac::MachPortRendezvousClientMac()
-    : server_requirement_(TakeServerCodeSigningRequirement()) {}
-
-MachPortRendezvousClientMac::~MachPortRendezvousClientMac() = default;
-
-bool MachPortRendezvousClientMac::AcquirePorts() {
-  AutoLock lock(lock_);
-
-  apple::ScopedMachSendRight server_port;
-  std::string bootstrap_name = GetBootstrapName();
-  kern_return_t kr = bootstrap_look_up(
-      bootstrap_port, const_cast<char*>(bootstrap_name.c_str()),
-      apple::ScopedMachSendRight::Receiver(server_port).get());
-  if (kr != KERN_SUCCESS) {
-    BOOTSTRAP_LOG(ERROR, kr) << "bootstrap_look_up " << bootstrap_name;
-    return false;
-  }
-
-  mach_msg_id_t message_id = kMachRendezvousMsgIdRequest;
-  size_t additional_data_size = 0;
-  if (NeedsInfoPlistData()) {
-    message_id = kMachRendezvousMsgIdRequestWithInfoPlistData;
-    additional_data_size = kMaxInfoPlistDataSize;
-  }
-  return SendRequest(std::move(server_port), message_id, additional_data_size);
-}
-
-bool MachPortRendezvousClientMac::ValidateMessage(
-    mach_msg_base_t* message,
-    BufferIterator<uint8_t> iterator) {
-  if (!server_requirement_.has_value() ||
-      !ShouldValidateProcessRequirements()) {
-    return true;
-  }
-
-  span<const uint8_t> info_plist_data;
-  if (NeedsInfoPlistData()) {
-    // Skip over the Mach ports to find the Info.plist data to use for
-    // validation.
-    iterator.Seek(iterator.position() +
-                  message->body.msgh_descriptor_count *
-                      (sizeof(mach_msg_port_descriptor_t) +
-                       sizeof(MachPortsForRendezvous::key_type)));
-    auto info_plist_length = iterator.CopyObject<uint64_t>();
-    CHECK(info_plist_length.has_value());
-    CHECK(*info_plist_length <= kMaxInfoPlistDataSize);
-    info_plist_data = iterator.Span<uint8_t>(info_plist_length.value());
-  }
-
-  iterator.Seek(message->header.msgh_size);
-  auto* trailer = iterator.Object<mach_msg_audit_trailer_t>();
-  bool valid = server_requirement_->ValidateProcess(trailer->msgh_audit,
-                                                    info_plist_data);
-  if (ShouldEnforceProcessRequirements()) {
-    return valid;
-  }
-  return true;
-}
-
-bool MachPortRendezvousClientMac::NeedsInfoPlistData() const {
-  return ShouldValidateProcessRequirements() &&
-         server_requirement_.has_value() &&
-         server_requirement_->ShouldCheckDynamicValidityOnly();
-}
-
-namespace {
-
-struct RequirementWithLock {
-  Lock lock;
-  std::optional<mac::ProcessRequirement> requirement;
-};
-
-RequirementWithLock& ServerCodeSigningRequirementWithLock() {
-  static NoDestructor<RequirementWithLock> requirement_with_lock;
-  return *requirement_with_lock;
-}
-
-}  // namespace
-
-// static
-void MachPortRendezvousClientMac::SetServerProcessRequirement(
-    mac::ProcessRequirement requirement) {
-  AutoLock lock(ServerCodeSigningRequirementWithLock().lock);
-  ServerCodeSigningRequirementWithLock().requirement = requirement;
-}
-
-// static
-std::optional<mac::ProcessRequirement>
-MachPortRendezvousClientMac::TakeServerCodeSigningRequirement() {
-  AutoLock lock(ServerCodeSigningRequirementWithLock().lock);
-  return std::move(ServerCodeSigningRequirementWithLock().requirement);
-}
-
-// static
-MachPortRendezvousPeerValidationPolicy
-MachPortRendezvousClientMac::PeerValidationPolicyForTesting() {
-  return GetPeerValidationPolicy();
-}
-
-namespace {
-
-// Helper function to avoid the compiler detecting that comparisons involving
-// `default_state` are compile-time constants and declaring code as unreachable.
-bool IsEnabledByDefault(const Feature& feature) {
-  return feature.default_state == FEATURE_ENABLED_BY_DEFAULT;
-}
-
-MachPortRendezvousPeerValidationPolicy GetDefaultPeerValidationPolicy() {
-  CHECK(!FeatureList::GetInstance());
-  if (IsEnabledByDefault(kMachPortRendezvousEnforcePeerRequirements)) {
-    return MachPortRendezvousPeerValidationPolicy::kEnforce;
-  }
-  if (IsEnabledByDefault(kMachPortRendezvousValidatePeerRequirements)) {
-    return MachPortRendezvousPeerValidationPolicy::kValidateOnly;
-  }
-  return MachPortRendezvousPeerValidationPolicy::kNoValidation;
-}
-
-MachPortRendezvousPeerValidationPolicy
-GetPeerValidationPolicyFromFeatureList() {
-  if (base::FeatureList::IsEnabled(
-          kMachPortRendezvousEnforcePeerRequirements)) {
-    return MachPortRendezvousPeerValidationPolicy::kEnforce;
-  }
-  if (base::FeatureList::IsEnabled(
-          kMachPortRendezvousValidatePeerRequirements)) {
-    return MachPortRendezvousPeerValidationPolicy::kValidateOnly;
-  }
-  return MachPortRendezvousPeerValidationPolicy::kNoValidation;
-}
-
-MachPortRendezvousPeerValidationPolicy
-GetPeerValidationPolicyFromEnvironment() {
-  // The environment variable is set at launch and does not change. Compute the
-  // policy once and cache it.
-  static MachPortRendezvousPeerValidationPolicy policy = [] {
-    std::unique_ptr<Environment> environment = Environment::Create();
-    int policy_int = INT_MAX;
-    std::string policy_str;
-    if (environment->GetVar(kPeerValidationPolicyEnvironmentVariable,
-                            &policy_str)) {
-      if (!StringToInt(policy_str, &policy_int)) {
-        // StringToInt modifies the output value even on failure.
-        policy_int = INT_MAX;
-      }
-    }
-
-    switch (policy_int) {
-      case to_underlying(MachPortRendezvousPeerValidationPolicy::kNoValidation):
-        return MachPortRendezvousPeerValidationPolicy::kNoValidation;
-      case to_underlying(MachPortRendezvousPeerValidationPolicy::kValidateOnly):
-        return MachPortRendezvousPeerValidationPolicy::kValidateOnly;
-      case to_underlying(MachPortRendezvousPeerValidationPolicy::kEnforce):
-        return MachPortRendezvousPeerValidationPolicy::kEnforce;
-      default:
-        // An invalid policy or no policy was passed via the environment. Fall
-        // back to the default values of the feature flags.
-        return GetDefaultPeerValidationPolicy();
-    }
-  }();
-  return policy;
-}
-
-MachPortRendezvousPeerValidationPolicy GetPeerValidationPolicy() {
-  if (base::FeatureList::GetInstance()) {
-    return GetPeerValidationPolicyFromFeatureList();
-  }
-
-  // In child processes, MachPortRendezvousClient is used during feature list
-  // initialization so the validation policy is passed via an environment
-  // variable.
-  return GetPeerValidationPolicyFromEnvironment();
-}
-
-}  // namespace
-
-#endif
-
 }  // namespace base
diff --git a/base/apple/mach_port_rendezvous.h b/base/apple/mach_port_rendezvous.h
index 40a0e4b..eb862d6 100644
--- a/base/apple/mach_port_rendezvous.h
+++ b/base/apple/mach_port_rendezvous.h
@@ -12,7 +12,6 @@
 
 #include <map>
 #include <memory>
-#include <string>
 #include <vector>
 
 #include "base/apple/dispatch_source.h"
@@ -24,11 +23,6 @@
 #include "base/thread_annotations.h"
 #include "build/ios_buildflags.h"
 
-#if BUILDFLAG(IS_MAC)
-#include "base/environment.h"
-#include "base/mac/process_requirement.h"
-#endif
-
 namespace base {
 
 // Mach Port Rendezvous is a technique to exchange Mach port rights across
@@ -129,121 +123,6 @@
       std::vector<uint8_t> additional_data);
 };
 
-#if BUILDFLAG(IS_IOS)
-// An implementation class that works for a single process. It is intended
-// that each process spawned will create a corresponding instance and the
-// mach send right of this server will be sent using XPC to the process.
-class BASE_EXPORT MachPortRendezvousServerIOS final
-    : public MachPortRendezvousServerBase {
- public:
-  MachPortRendezvousServerIOS(const MachPortsForRendezvous& ports);
-  ~MachPortRendezvousServerIOS() override;
-  MachPortRendezvousServerIOS(const MachPortRendezvousServerIOS&) = delete;
-  MachPortRendezvousServerIOS& operator=(const MachPortRendezvousServerIOS&) =
-      delete;
-
-  // Retrieve the send right to be sent to the process.
-  apple::ScopedMachSendRight GetMachSendRight();
-
- protected:
-  std::optional<MachPortsForRendezvous> PortsForClient(audit_token_t) override;
-  bool IsValidAdditionalMessageId(mach_msg_id_t) const override;
-  std::vector<uint8_t> AdditionalDataForReply(mach_msg_id_t) const override;
-
- private:
-  apple::ScopedMachSendRight send_right_;
-  MachPortsForRendezvous ports_;
-};
-
-#endif  // BUILDFLAG(IS_IOS)
-
-#if BUILDFLAG(IS_MAC)
-
-// An implementation class that uses bootstrap to register ports to many
-// processes.
-class BASE_EXPORT MachPortRendezvousServerMac final
-    : public MachPortRendezvousServerBase {
- public:
-  // Returns the instance of the server. Upon the first call to this method,
-  // the server is created, which registers an endpoint in the Mach bootstrap
-  // namespace.
-  static MachPortRendezvousServerMac* GetInstance();
-
-  // Add feature state to an environment variable that will be used when
-  // launching a child process. MachPortRendezvousClient is used during
-  // feature list initialization so any state it uses must be passed
-  // via a side channel.
-  // TODO(crbug.com/362302761): Remove once enforcement is enabled by default.
-  static void AddFeatureStateToEnvironment(EnvironmentMap& environment);
-
-  MachPortRendezvousServerMac(const MachPortRendezvousServerMac&) = delete;
-  MachPortRendezvousServerMac& operator=(const MachPortRendezvousServerMac&) =
-      delete;
-
-  // Registers a collection of Mach ports |ports| to be acquirable by the
-  // process known by |pid|. This cannot be called again for the same |pid|
-  // until the process known by |pid| has either acquired the ports or died.
-  //
-  // This must be called with the lock from GetLock() held.
-  void RegisterPortsForPid(pid_t pid, const MachPortsForRendezvous& ports)
-      EXCLUSIVE_LOCKS_REQUIRED(GetLock());
-
-  // Sets the process requirement that `pid` must match before it
-  // can acquire any Mach ports. This cannot be called again for the same `pid`
-  // until the process known by `pid` has acquired the ports or died.
-  //
-  // This must be called with the lock from GetLock() held.
-  void SetProcessRequirementForPid(pid_t pid,
-                                   mac::ProcessRequirement requirement)
-      EXCLUSIVE_LOCKS_REQUIRED(GetLock());
-
-  // Returns a lock on the internal port registration map. The parent process
-  // should hold this lock for the duration of launching a process, including
-  // after calling RegisterPortsForPid(). This ensures that a child process
-  // cannot race acquiring ports before they are registered. The lock should
-  // be released after the child process is launched and the ports are
-  // registered.
-  Lock& GetLock() LOCK_RETURNED(lock_) { return lock_; }
-
-  void ClearClientDataForTesting() EXCLUSIVE_LOCKS_REQUIRED(GetLock());
-
- protected:
-  // Returns the registered collection of ports for the specified `audit_token`.
-  // `std::nullopt` indicates that the client is not authorized to retrieve the
-  // ports. This claims the collection of ports and removes the entry from
-  // `client_data_`.
-  std::optional<MachPortsForRendezvous> PortsForClient(
-      audit_token_t audit_token) override;
-
-  bool IsValidAdditionalMessageId(mach_msg_id_t) const override;
-  std::vector<uint8_t> AdditionalDataForReply(
-      mach_msg_id_t request) const override;
-
- private:
-  friend class MachPortRendezvousServerTest;
-  friend struct MachPortRendezvousFuzzer;
-
-  MachPortRendezvousServerMac();
-  ~MachPortRendezvousServerMac() override;
-
-  struct ClientData;
-
-  // Returns the `ClientData` for `pid`, creating it if necessary.
-  // It will be cleaned up automatically when `pid` exits.
-  ClientData& ClientDataForPid(int pid) EXCLUSIVE_LOCKS_REQUIRED(GetLock());
-
-  // Called by the ClientData::exit_watcher dispatch sources when a process
-  // for which ports have been registered exits. This releases port rights
-  // that are strongly owned, in the event that the child has not claimed them.
-  void OnClientExited(pid_t pid);
-
-  Lock lock_;
-  // Association of pid-to-ports.
-  std::map<pid_t, ClientData> client_data_ GUARDED_BY(lock_);
-};
-
-#endif
-
 // Client class for accessing the memory object exposed by the
 // MachPortRendezvousServer.
 class BASE_EXPORT MachPortRendezvousClient {
@@ -303,100 +182,31 @@
   MachPortsForRendezvous ports_ GUARDED_BY(lock_);
 };
 
-#if BUILDFLAG(IS_IOS)
-BASE_EXPORT
-class BASE_EXPORT MachPortRendezvousClientIOS final
-    : public MachPortRendezvousClient {
- public:
-  // Initialize the MacPortRendezvousClient using `server_port`.
-  static bool Initialize(apple::ScopedMachSendRight server_port);
+namespace internal {
 
- protected:
-  bool ValidateMessage(mach_msg_base_t* message,
-                       BufferIterator<uint8_t> body) override;
+// This limit is arbitrary and can be safely increased in the future.
+inline constexpr size_t kMaximumRendezvousPorts = 6;
 
- private:
-  MachPortRendezvousClientIOS();
-  ~MachPortRendezvousClientIOS() override;
-
-  // Helper method to look up the server in the bootstrap namespace and send
-  // the acquisition request message.
-  bool AcquirePorts(apple::ScopedMachSendRight server_port);
-};
-#endif
+enum MachRendezvousMsgId : mach_msg_id_t {
+  kMachRendezvousMsgIdRequest = 'mrzv',
+  kMachRendezvousMsgIdResponse = 'MRZV',
 
 #if BUILDFLAG(IS_MAC)
-
-// Describes how the `ProcessRequirement` should be used during Mach port
-// rendezvous. The active policy is derived from the feature flags in the
-// browser process and is passed via an environment variable to child processes.
-// TODO(crbug.com/362302761): Remove this policy once enforcement is enabled by
-// default.
-enum class MachPortRendezvousPeerValidationPolicy {
-  // Do not validate the peer against a process requirement.
-  kNoValidation,
-
-  // Validate the peer against a process requirement, if specified, but do not
-  // abort rendezvous if validation fails. Used to gather success metrics during
-  // experiment rollout.
-  kValidateOnly,
-
-  // Validate the peer against a process requirement, if specified, and abort
-  // rendezvous if the validation fails.
-  kEnforce,
-};
-
-class BASE_EXPORT MachPortRendezvousClientMac final
-    : public MachPortRendezvousClient {
- public:
-  // Set a ProcessRequirement that the server should be validated
-  // against before accepting any Mach ports from it.
+  // When MachPortRendezvousClientMac has a `ProcessRequirement` that requests
+  // dynamic-only validation, it will request that the server provide a copy of
+  // its Info.plist data in the rendezvous response. Dynamic-only validation
+  // validates the running process without enforcing that it matches its on-disk
+  // representation. This is necessary when validating applications such as
+  // Chrome that may be updated on disk while the application is running.
   //
-  // Must be called before `GetInstance` or this will have no effect.
-  static void SetServerProcessRequirement(mac::ProcessRequirement requirement);
-
-  // Get the peer validation policy that was derived from feature flags.
-  static MachPortRendezvousPeerValidationPolicy
-  PeerValidationPolicyForTesting();
-
- protected:
-  // Validate the server against a process requirement if one was set via
-  // `SetServerProcessRequirement`.
-  bool ValidateMessage(mach_msg_base_t* message,
-                       BufferIterator<uint8_t> body) override;
-
- private:
-  friend class MachPortRendezvousClient;
-
-  MachPortRendezvousClientMac();
-  ~MachPortRendezvousClientMac() override;
-
-  // Returns the name of the server to look up in the bootstrap namespace.
-  static std::string GetBootstrapName();
-
-  // Helper method to look up the server in the bootstrap namespace and send
-  // the acquisition request message.
-  bool AcquirePorts();
-
-  // Take ownership of the server process requirement, if any.
-  static std::optional<mac::ProcessRequirement>
-  TakeServerCodeSigningRequirement();
-
-  // Whether Info.plist data is needed from the server in order
-  // to validate `server_requirement_`.
-  bool NeedsInfoPlistData() const;
-
-  std::optional<mac::ProcessRequirement> server_requirement_;
+  // The Info.plist data ends up passed to `SecCodeCopyGuestWithAttributes`,
+  // where it is validated against the hash stored within the code signature
+  // before using it to evaluate any requirements involving Info.plist data.
+  kMachRendezvousMsgIdRequestWithInfoPlistData = 'mrzV',
+#endif  // BUILDFLAG(IS_MAC)
 };
 
-// Whether any peer process requirements should be validated.
-BASE_EXPORT BASE_DECLARE_FEATURE(kMachPortRendezvousValidatePeerRequirements);
-
-// Whether a failure to validate a peer process against a requirement
-// should result in aborting the rendezvous.
-BASE_EXPORT BASE_DECLARE_FEATURE(kMachPortRendezvousEnforcePeerRequirements);
-
-#endif
+}  // namespace internal
 
 }  // namespace base
 
diff --git a/base/apple/mach_port_rendezvous_fuzzer.cc b/base/apple/mach_port_rendezvous_fuzzer.cc
index 6d06bd0b..59beda4 100644
--- a/base/apple/mach_port_rendezvous_fuzzer.cc
+++ b/base/apple/mach_port_rendezvous_fuzzer.cc
@@ -5,6 +5,7 @@
 #include "base/apple/mach_port_rendezvous.h"
 
 #include "base/apple/mach_logging.h"
+#include "base/apple/mach_port_rendezvous_mac.h"
 #include "base/logging.h"
 #include "base/synchronization/lock.h"
 #include "testing/libfuzzer/fuzzers/mach/mach_message_converter.h"
diff --git a/base/apple/mach_port_rendezvous_ios.cc b/base/apple/mach_port_rendezvous_ios.cc
new file mode 100644
index 0000000..3ab4c83
--- /dev/null
+++ b/base/apple/mach_port_rendezvous_ios.cc
@@ -0,0 +1,92 @@
+// Copyright 2019 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/apple/mach_port_rendezvous_ios.h"
+
+#include <mach/mig.h>
+#include <unistd.h>
+
+#include <utility>
+
+#include "base/apple/scoped_mach_port.h"
+#include "base/containers/buffer_iterator.h"
+#include "base/mac/scoped_mach_msg_destroy.h"
+#include "base/numerics/byte_conversions.h"
+#include "base/synchronization/lock.h"
+
+namespace base {
+
+namespace {
+
+static MachPortRendezvousClientIOS* g_client = nullptr;
+
+}  // namespace
+
+apple::ScopedMachSendRight MachPortRendezvousServerIOS::GetMachSendRight() {
+  return apple::RetainMachSendRight(send_right_.get());
+}
+
+MachPortRendezvousServerIOS::MachPortRendezvousServerIOS(
+    const MachPortsForRendezvous& ports)
+    : ports_(ports) {
+  DCHECK_LT(ports_.size(), internal::kMaximumRendezvousPorts);
+  bool res = apple::CreateMachPort(&server_port_, &send_right_);
+  CHECK(res) << "Failed to create mach server port";
+  dispatch_source_ = std::make_unique<apple::DispatchSource>(
+      "MachPortRendezvousServer", server_port_.get(), ^{
+        HandleRequest();
+      });
+  dispatch_source_->Resume();
+}
+
+std::optional<MachPortsForRendezvous>
+MachPortRendezvousServerIOS::PortsForClient(audit_token_t audit_token) {
+  // `audit_token` is ignored as a server handles a single client on iOS.
+  return ports_;
+}
+
+bool MachPortRendezvousServerIOS::IsValidAdditionalMessageId(
+    mach_msg_id_t) const {
+  return false;
+}
+std::vector<uint8_t> MachPortRendezvousServerIOS::AdditionalDataForReply(
+    mach_msg_id_t) const {
+  return {};
+}
+
+MachPortRendezvousServerIOS::~MachPortRendezvousServerIOS() = default;
+
+// static
+MachPortRendezvousClient* MachPortRendezvousClient::GetInstance() {
+  CHECK(g_client);
+  return g_client;
+}
+
+MachPortRendezvousClientIOS::MachPortRendezvousClientIOS() = default;
+MachPortRendezvousClientIOS::~MachPortRendezvousClientIOS() = default;
+
+bool MachPortRendezvousClientIOS::Initialize(
+    apple::ScopedMachSendRight server_port) {
+  CHECK(!g_client);
+  g_client = new MachPortRendezvousClientIOS();
+  if (!g_client->AcquirePorts(std::move(server_port))) {
+    delete g_client;
+    g_client = nullptr;
+  }
+  return true;
+}
+
+bool MachPortRendezvousClientIOS::AcquirePorts(
+    apple::ScopedMachSendRight server_port) {
+  AutoLock lock(lock_);
+  return SendRequest(std::move(server_port),
+                     internal::kMachRendezvousMsgIdRequest);
+}
+
+bool MachPortRendezvousClientIOS::ValidateMessage(mach_msg_base_t*,
+                                                  BufferIterator<uint8_t>) {
+  return true;
+}
+
+}  // namespace base
diff --git a/base/apple/mach_port_rendezvous_ios.h b/base/apple/mach_port_rendezvous_ios.h
new file mode 100644
index 0000000..0e9151f
--- /dev/null
+++ b/base/apple/mach_port_rendezvous_ios.h
@@ -0,0 +1,69 @@
+// 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 BASE_APPLE_MACH_PORT_RENDEZVOUS_IOS_H_
+#define BASE_APPLE_MACH_PORT_RENDEZVOUS_IOS_H_
+
+#include <dispatch/dispatch.h>
+#include <mach/mach.h>
+#include <stdint.h>
+
+#include <memory>
+#include <vector>
+
+#include "base/apple/dispatch_source.h"
+#include "base/apple/mach_port_rendezvous.h"
+#include "base/apple/scoped_mach_port.h"
+#include "base/base_export.h"
+#include "base/containers/buffer_iterator.h"
+
+namespace base {
+
+// An implementation class that works for a single process. It is intended
+// that each process spawned will create a corresponding instance and the
+// mach send right of this server will be sent using XPC to the process.
+class BASE_EXPORT MachPortRendezvousServerIOS final
+    : public MachPortRendezvousServerBase {
+ public:
+  MachPortRendezvousServerIOS(const MachPortsForRendezvous& ports);
+  ~MachPortRendezvousServerIOS() override;
+  MachPortRendezvousServerIOS(const MachPortRendezvousServerIOS&) = delete;
+  MachPortRendezvousServerIOS& operator=(const MachPortRendezvousServerIOS&) =
+      delete;
+
+  // Retrieve the send right to be sent to the process.
+  apple::ScopedMachSendRight GetMachSendRight();
+
+ protected:
+  std::optional<MachPortsForRendezvous> PortsForClient(audit_token_t) override;
+  bool IsValidAdditionalMessageId(mach_msg_id_t) const override;
+  std::vector<uint8_t> AdditionalDataForReply(mach_msg_id_t) const override;
+
+ private:
+  apple::ScopedMachSendRight send_right_;
+  MachPortsForRendezvous ports_;
+};
+
+class BASE_EXPORT MachPortRendezvousClientIOS final
+    : public MachPortRendezvousClient {
+ public:
+  // Initialize the MacPortRendezvousClient using `server_port`.
+  static bool Initialize(apple::ScopedMachSendRight server_port);
+
+ protected:
+  bool ValidateMessage(mach_msg_base_t* message,
+                       BufferIterator<uint8_t> body) override;
+
+ private:
+  MachPortRendezvousClientIOS();
+  ~MachPortRendezvousClientIOS() override;
+
+  // Helper method to look up the server in the bootstrap namespace and send
+  // the acquisition request message.
+  bool AcquirePorts(apple::ScopedMachSendRight server_port);
+};
+
+}  // namespace base
+
+#endif  // BASE_APPLE_MACH_PORT_RENDEZVOUS_IOS_H_
diff --git a/base/apple/mach_port_rendezvous_mac.cc b/base/apple/mach_port_rendezvous_mac.cc
new file mode 100644
index 0000000..140d736c
--- /dev/null
+++ b/base/apple/mach_port_rendezvous_mac.cc
@@ -0,0 +1,417 @@
+// Copyright 2019 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/apple/mach_port_rendezvous_mac.h"
+
+#include <bsm/libbsm.h>
+#include <mach/mig.h>
+#include <servers/bootstrap.h>
+#include <unistd.h>
+
+#include <utility>
+
+#include "base/apple/foundation_util.h"
+#include "base/apple/mach_logging.h"
+#include "base/apple/scoped_dispatch_object.h"
+#include "base/bits.h"
+#include "base/compiler_specific.h"
+#include "base/containers/buffer_iterator.h"
+#include "base/environment.h"
+#include "base/feature_list.h"
+#include "base/logging.h"
+#include "base/mac/info_plist_data.h"
+#include "base/mac/scoped_mach_msg_destroy.h"
+#include "base/no_destructor.h"
+#include "base/numerics/byte_conversions.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
+#include "base/types/cxx23_to_underlying.h"
+
+namespace base {
+
+// Whether any peer process requirements should be validated.
+BASE_FEATURE(kMachPortRendezvousValidatePeerRequirements,
+             "MachPortRendezvousValidatePeerRequirements",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
+// Whether a failure to validate a peer process against a requirement
+// should result in aborting the rendezvous.
+BASE_FEATURE(kMachPortRendezvousEnforcePeerRequirements,
+             "MachPortRendezvousEnforcePeerRequirements",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
+namespace {
+
+// The name to use in the bootstrap server, formatted with the BaseBundleID and
+// PID of the server.
+constexpr char kBootstrapNameFormat[] = "%s.MachPortRendezvousServer.%d";
+
+// This can be safely increased if Info.plist grows in the future.
+constexpr size_t kMaxInfoPlistDataSize = 18 * 1024;
+
+// The state of the peer validation policy features is passed to child processes
+// via this environment variable as Mach port rendezvous is performed before the
+// feature list is initialized.
+// TODO(crbug.com/362302761): Remove once enforcement is enabled by default.
+constexpr char kPeerValidationPolicyEnvironmentVariable[] =
+    "MACH_PORT_RENDEZVOUS_PEER_VALDATION";
+
+MachPortRendezvousPeerValidationPolicy GetPeerValidationPolicy();
+
+bool ShouldValidateProcessRequirements() {
+  return GetPeerValidationPolicy() !=
+         MachPortRendezvousPeerValidationPolicy::kNoValidation;
+}
+
+bool ShouldEnforceProcessRequirements() {
+  return GetPeerValidationPolicy() ==
+         MachPortRendezvousPeerValidationPolicy::kEnforce;
+}
+
+}  // namespace
+
+struct MachPortRendezvousServerMac::ClientData {
+  ClientData();
+  ClientData(ClientData&&);
+  ~ClientData();
+
+  // A DISPATCH_SOURCE_TYPE_PROC / DISPATCH_PROC_EXIT dispatch source. When
+  // the source is triggered, it calls OnClientExited().
+  apple::ScopedDispatchObject<dispatch_source_t> exit_watcher;
+
+  MachPortsForRendezvous ports;
+  std::optional<mac::ProcessRequirement> requirement;
+};
+
+// static
+MachPortRendezvousServerMac* MachPortRendezvousServerMac::GetInstance() {
+  static auto* instance = new MachPortRendezvousServerMac();
+  return instance;
+}
+
+// static
+void MachPortRendezvousServerMac::AddFeatureStateToEnvironment(
+    EnvironmentMap& environment) {
+  environment.insert(
+      {kPeerValidationPolicyEnvironmentVariable,
+       NumberToString(static_cast<int>(GetPeerValidationPolicy()))});
+}
+
+MachPortRendezvousServerMac::ClientData&
+MachPortRendezvousServerMac::ClientDataForPid(pid_t pid) {
+  lock_.AssertAcquired();
+
+  auto [it, inserted] = client_data_.emplace(pid, ClientData{});
+  if (inserted) {
+    apple::ScopedDispatchObject<dispatch_source_t> exit_watcher(
+        dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC,
+                               static_cast<uintptr_t>(pid), DISPATCH_PROC_EXIT,
+                               dispatch_source_->Queue()));
+    dispatch_source_set_event_handler(exit_watcher.get(), ^{
+      OnClientExited(pid);
+    });
+    dispatch_resume(exit_watcher.get());
+    it->second.exit_watcher = std::move(exit_watcher);
+  }
+
+  return it->second;
+}
+
+void MachPortRendezvousServerMac::RegisterPortsForPid(
+    pid_t pid,
+    const MachPortsForRendezvous& ports) {
+  lock_.AssertAcquired();
+  DCHECK_LT(ports.size(), internal::kMaximumRendezvousPorts);
+  DCHECK(!ports.empty());
+
+  ClientData& client = ClientDataForPid(pid);
+  CHECK(client.ports.empty());
+  client.ports = ports;
+}
+
+void MachPortRendezvousServerMac::SetProcessRequirementForPid(
+    pid_t pid,
+    mac::ProcessRequirement requirement) {
+  lock_.AssertAcquired();
+
+  ClientData& client = ClientDataForPid(pid);
+  CHECK(!client.requirement.has_value());
+  client.requirement = std::move(requirement);
+}
+
+MachPortRendezvousServerMac::ClientData::ClientData() = default;
+MachPortRendezvousServerMac::ClientData::ClientData(ClientData&&) = default;
+
+MachPortRendezvousServerMac::ClientData::~ClientData() {
+  for (auto& pair : ports) {
+    pair.second.Destroy();
+  }
+}
+
+MachPortRendezvousServerMac::MachPortRendezvousServerMac() {
+  std::string bootstrap_name =
+      StringPrintf(kBootstrapNameFormat, apple::BaseBundleID(), getpid());
+  kern_return_t kr = bootstrap_check_in(
+      bootstrap_port, bootstrap_name.c_str(),
+      apple::ScopedMachReceiveRight::Receiver(server_port_).get());
+  BOOTSTRAP_CHECK(kr == KERN_SUCCESS, kr)
+      << "bootstrap_check_in " << bootstrap_name;
+  dispatch_source_ = std::make_unique<apple::DispatchSource>(
+      bootstrap_name.c_str(), server_port_.get(), ^{
+        HandleRequest();
+      });
+  dispatch_source_->Resume();
+}
+
+MachPortRendezvousServerMac::~MachPortRendezvousServerMac() = default;
+
+void MachPortRendezvousServerMac::ClearClientDataForTesting() {
+  client_data_.clear();
+}
+
+std::optional<MachPortsForRendezvous>
+MachPortRendezvousServerMac::PortsForClient(audit_token_t audit_token) {
+  pid_t pid = audit_token_to_pid(audit_token);
+  std::optional<mac::ProcessRequirement> requirement;
+  MachPortsForRendezvous ports_to_send;
+
+  {
+    AutoLock lock(lock_);
+    auto it = client_data_.find(pid);
+    if (it != client_data_.end()) {
+      ports_to_send = std::move(it->second.ports);
+      requirement = std::move(it->second.requirement);
+      client_data_.erase(it);
+    }
+  }
+
+  if (requirement.has_value() && ShouldValidateProcessRequirements()) {
+    bool client_is_valid = requirement->ValidateProcess(audit_token);
+    if (!client_is_valid && ShouldEnforceProcessRequirements()) {
+      return std::nullopt;
+    }
+  }
+
+  return ports_to_send;
+}
+
+void MachPortRendezvousServerMac::OnClientExited(pid_t pid) {
+  AutoLock lock(lock_);
+  client_data_.erase(pid);
+}
+
+bool MachPortRendezvousServerMac::IsValidAdditionalMessageId(
+    mach_msg_id_t request) const {
+  return request == internal::kMachRendezvousMsgIdRequestWithInfoPlistData;
+}
+
+std::vector<uint8_t> MachPortRendezvousServerMac::AdditionalDataForReply(
+    mach_msg_id_t request) const {
+  if (request == internal::kMachRendezvousMsgIdRequestWithInfoPlistData) {
+    std::vector<uint8_t> info_plist_data =
+        mac::OuterBundleCachedInfoPlistData();
+    if (info_plist_data.size() > kMaxInfoPlistDataSize) {
+      LOG(WARNING) << "Info.plist data too large to send to client.";
+      return {};
+    }
+    return info_plist_data;
+  }
+  return {};
+}
+
+// static
+MachPortRendezvousClient* MachPortRendezvousClient::GetInstance() {
+  static MachPortRendezvousClientMac* client = []() -> auto* {
+    auto* client = new MachPortRendezvousClientMac();
+    if (!client->AcquirePorts()) {
+      delete client;
+      client = nullptr;
+    }
+    return client;
+  }();
+  return client;
+}
+
+// static
+std::string MachPortRendezvousClientMac::GetBootstrapName() {
+  return StringPrintf(kBootstrapNameFormat, apple::BaseBundleID(), getppid());
+}
+
+MachPortRendezvousClientMac::MachPortRendezvousClientMac()
+    : server_requirement_(TakeServerCodeSigningRequirement()) {}
+
+MachPortRendezvousClientMac::~MachPortRendezvousClientMac() = default;
+
+bool MachPortRendezvousClientMac::AcquirePorts() {
+  AutoLock lock(lock_);
+
+  apple::ScopedMachSendRight server_port;
+  std::string bootstrap_name = GetBootstrapName();
+  kern_return_t kr = bootstrap_look_up(
+      bootstrap_port, const_cast<char*>(bootstrap_name.c_str()),
+      apple::ScopedMachSendRight::Receiver(server_port).get());
+  if (kr != KERN_SUCCESS) {
+    BOOTSTRAP_LOG(ERROR, kr) << "bootstrap_look_up " << bootstrap_name;
+    return false;
+  }
+
+  mach_msg_id_t message_id = internal::kMachRendezvousMsgIdRequest;
+  size_t additional_data_size = 0;
+  if (NeedsInfoPlistData()) {
+    message_id = internal::kMachRendezvousMsgIdRequestWithInfoPlistData;
+    additional_data_size = kMaxInfoPlistDataSize;
+  }
+  return SendRequest(std::move(server_port), message_id, additional_data_size);
+}
+
+bool MachPortRendezvousClientMac::ValidateMessage(
+    mach_msg_base_t* message,
+    BufferIterator<uint8_t> iterator) {
+  if (!server_requirement_.has_value() ||
+      !ShouldValidateProcessRequirements()) {
+    return true;
+  }
+
+  span<const uint8_t> info_plist_data;
+  if (NeedsInfoPlistData()) {
+    // Skip over the Mach ports to find the Info.plist data to use for
+    // validation.
+    iterator.Seek(iterator.position() +
+                  message->body.msgh_descriptor_count *
+                      (sizeof(mach_msg_port_descriptor_t) +
+                       sizeof(MachPortsForRendezvous::key_type)));
+    auto info_plist_length = iterator.CopyObject<uint64_t>();
+    CHECK(info_plist_length.has_value());
+    CHECK(*info_plist_length <= kMaxInfoPlistDataSize);
+    info_plist_data = iterator.Span<uint8_t>(info_plist_length.value());
+  }
+
+  iterator.Seek(message->header.msgh_size);
+  auto* trailer = iterator.Object<mach_msg_audit_trailer_t>();
+  bool valid = server_requirement_->ValidateProcess(trailer->msgh_audit,
+                                                    info_plist_data);
+  if (ShouldEnforceProcessRequirements()) {
+    return valid;
+  }
+  return true;
+}
+
+bool MachPortRendezvousClientMac::NeedsInfoPlistData() const {
+  return ShouldValidateProcessRequirements() &&
+         server_requirement_.has_value() &&
+         server_requirement_->ShouldCheckDynamicValidityOnly();
+}
+
+namespace {
+
+struct RequirementWithLock {
+  Lock lock;
+  std::optional<mac::ProcessRequirement> requirement;
+};
+
+RequirementWithLock& ServerCodeSigningRequirementWithLock() {
+  static NoDestructor<RequirementWithLock> requirement_with_lock;
+  return *requirement_with_lock;
+}
+
+}  // namespace
+
+// static
+void MachPortRendezvousClientMac::SetServerProcessRequirement(
+    mac::ProcessRequirement requirement) {
+  AutoLock lock(ServerCodeSigningRequirementWithLock().lock);
+  ServerCodeSigningRequirementWithLock().requirement = requirement;
+}
+
+// static
+std::optional<mac::ProcessRequirement>
+MachPortRendezvousClientMac::TakeServerCodeSigningRequirement() {
+  AutoLock lock(ServerCodeSigningRequirementWithLock().lock);
+  return std::move(ServerCodeSigningRequirementWithLock().requirement);
+}
+
+// static
+MachPortRendezvousPeerValidationPolicy
+MachPortRendezvousClientMac::PeerValidationPolicyForTesting() {
+  return GetPeerValidationPolicy();
+}
+
+namespace {
+
+// Helper function to avoid the compiler detecting that comparisons involving
+// `default_state` are compile-time constants and declaring code as unreachable.
+bool IsEnabledByDefault(const Feature& feature) {
+  return feature.default_state == FEATURE_ENABLED_BY_DEFAULT;
+}
+
+MachPortRendezvousPeerValidationPolicy GetDefaultPeerValidationPolicy() {
+  CHECK(!FeatureList::GetInstance());
+  if (IsEnabledByDefault(kMachPortRendezvousEnforcePeerRequirements)) {
+    return MachPortRendezvousPeerValidationPolicy::kEnforce;
+  }
+  if (IsEnabledByDefault(kMachPortRendezvousValidatePeerRequirements)) {
+    return MachPortRendezvousPeerValidationPolicy::kValidateOnly;
+  }
+  return MachPortRendezvousPeerValidationPolicy::kNoValidation;
+}
+
+MachPortRendezvousPeerValidationPolicy
+GetPeerValidationPolicyFromFeatureList() {
+  if (base::FeatureList::IsEnabled(
+          kMachPortRendezvousEnforcePeerRequirements)) {
+    return MachPortRendezvousPeerValidationPolicy::kEnforce;
+  }
+  if (base::FeatureList::IsEnabled(
+          kMachPortRendezvousValidatePeerRequirements)) {
+    return MachPortRendezvousPeerValidationPolicy::kValidateOnly;
+  }
+  return MachPortRendezvousPeerValidationPolicy::kNoValidation;
+}
+
+MachPortRendezvousPeerValidationPolicy
+GetPeerValidationPolicyFromEnvironment() {
+  // The environment variable is set at launch and does not change. Compute the
+  // policy once and cache it.
+  static MachPortRendezvousPeerValidationPolicy policy = [] {
+    std::unique_ptr<Environment> environment = Environment::Create();
+    int policy_int = INT_MAX;
+    std::string policy_str;
+    if (environment->GetVar(kPeerValidationPolicyEnvironmentVariable,
+                            &policy_str)) {
+      if (!StringToInt(policy_str, &policy_int)) {
+        // StringToInt modifies the output value even on failure.
+        policy_int = INT_MAX;
+      }
+    }
+
+    switch (policy_int) {
+      case to_underlying(MachPortRendezvousPeerValidationPolicy::kNoValidation):
+        return MachPortRendezvousPeerValidationPolicy::kNoValidation;
+      case to_underlying(MachPortRendezvousPeerValidationPolicy::kValidateOnly):
+        return MachPortRendezvousPeerValidationPolicy::kValidateOnly;
+      case to_underlying(MachPortRendezvousPeerValidationPolicy::kEnforce):
+        return MachPortRendezvousPeerValidationPolicy::kEnforce;
+      default:
+        // An invalid policy or no policy was passed via the environment. Fall
+        // back to the default values of the feature flags.
+        return GetDefaultPeerValidationPolicy();
+    }
+  }();
+  return policy;
+}
+
+MachPortRendezvousPeerValidationPolicy GetPeerValidationPolicy() {
+  if (base::FeatureList::GetInstance()) {
+    return GetPeerValidationPolicyFromFeatureList();
+  }
+
+  // In child processes, MachPortRendezvousClient is used during feature list
+  // initialization so the validation policy is passed via an environment
+  // variable.
+  return GetPeerValidationPolicyFromEnvironment();
+}
+
+}  // namespace
+
+}  // namespace base
diff --git a/base/apple/mach_port_rendezvous_mac.h b/base/apple/mach_port_rendezvous_mac.h
new file mode 100644
index 0000000..faeb3b17
--- /dev/null
+++ b/base/apple/mach_port_rendezvous_mac.h
@@ -0,0 +1,185 @@
+// 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 BASE_APPLE_MACH_PORT_RENDEZVOUS_MAC_H_
+#define BASE_APPLE_MACH_PORT_RENDEZVOUS_MAC_H_
+
+#include <dispatch/dispatch.h>
+#include <mach/mach.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/apple/dispatch_source.h"
+#include "base/apple/mach_port_rendezvous.h"
+#include "base/apple/scoped_mach_port.h"
+#include "base/base_export.h"
+#include "base/containers/buffer_iterator.h"
+#include "base/environment.h"
+#include "base/feature_list.h"
+#include "base/mac/process_requirement.h"
+#include "base/synchronization/lock.h"
+#include "base/thread_annotations.h"
+
+namespace base {
+
+// An implementation class that uses bootstrap to register ports to many
+// processes.
+class BASE_EXPORT MachPortRendezvousServerMac final
+    : public MachPortRendezvousServerBase {
+ public:
+  // Returns the instance of the server. Upon the first call to this method,
+  // the server is created, which registers an endpoint in the Mach bootstrap
+  // namespace.
+  static MachPortRendezvousServerMac* GetInstance();
+
+  // Add feature state to an environment variable that will be used when
+  // launching a child process. MachPortRendezvousClient is used during
+  // feature list initialization so any state it uses must be passed
+  // via a side channel.
+  // TODO(crbug.com/362302761): Remove once enforcement is enabled by default.
+  static void AddFeatureStateToEnvironment(EnvironmentMap& environment);
+
+  MachPortRendezvousServerMac(const MachPortRendezvousServerMac&) = delete;
+  MachPortRendezvousServerMac& operator=(const MachPortRendezvousServerMac&) =
+      delete;
+
+  // Registers a collection of Mach ports |ports| to be acquirable by the
+  // process known by |pid|. This cannot be called again for the same |pid|
+  // until the process known by |pid| has either acquired the ports or died.
+  //
+  // This must be called with the lock from GetLock() held.
+  void RegisterPortsForPid(pid_t pid, const MachPortsForRendezvous& ports)
+      EXCLUSIVE_LOCKS_REQUIRED(GetLock());
+
+  // Sets the process requirement that `pid` must match before it
+  // can acquire any Mach ports. This cannot be called again for the same `pid`
+  // until the process known by `pid` has acquired the ports or died.
+  //
+  // This must be called with the lock from GetLock() held.
+  void SetProcessRequirementForPid(pid_t pid,
+                                   mac::ProcessRequirement requirement)
+      EXCLUSIVE_LOCKS_REQUIRED(GetLock());
+
+  // Returns a lock on the internal port registration map. The parent process
+  // should hold this lock for the duration of launching a process, including
+  // after calling RegisterPortsForPid(). This ensures that a child process
+  // cannot race acquiring ports before they are registered. The lock should
+  // be released after the child process is launched and the ports are
+  // registered.
+  Lock& GetLock() LOCK_RETURNED(lock_) { return lock_; }
+
+  void ClearClientDataForTesting() EXCLUSIVE_LOCKS_REQUIRED(GetLock());
+
+ protected:
+  // Returns the registered collection of ports for the specified `audit_token`.
+  // `std::nullopt` indicates that the client is not authorized to retrieve the
+  // ports. This claims the collection of ports and removes the entry from
+  // `client_data_`.
+  std::optional<MachPortsForRendezvous> PortsForClient(
+      audit_token_t audit_token) override;
+
+  bool IsValidAdditionalMessageId(mach_msg_id_t) const override;
+  std::vector<uint8_t> AdditionalDataForReply(
+      mach_msg_id_t request) const override;
+
+ private:
+  friend class MachPortRendezvousServerTest;
+  friend struct MachPortRendezvousFuzzer;
+
+  MachPortRendezvousServerMac();
+  ~MachPortRendezvousServerMac() override;
+
+  struct ClientData;
+
+  // Returns the `ClientData` for `pid`, creating it if necessary.
+  // It will be cleaned up automatically when `pid` exits.
+  ClientData& ClientDataForPid(int pid) EXCLUSIVE_LOCKS_REQUIRED(GetLock());
+
+  // Called by the ClientData::exit_watcher dispatch sources when a process
+  // for which ports have been registered exits. This releases port rights
+  // that are strongly owned, in the event that the child has not claimed them.
+  void OnClientExited(pid_t pid);
+
+  Lock lock_;
+  // Association of pid-to-ports.
+  std::map<pid_t, ClientData> client_data_ GUARDED_BY(lock_);
+};
+
+// Describes how the `ProcessRequirement` should be used during Mach port
+// rendezvous. The active policy is derived from the feature flags in the
+// browser process and is passed via an environment variable to child processes.
+// TODO(crbug.com/362302761): Remove this policy once enforcement is enabled by
+// default.
+enum class MachPortRendezvousPeerValidationPolicy {
+  // Do not validate the peer against a process requirement.
+  kNoValidation,
+
+  // Validate the peer against a process requirement, if specified, but do not
+  // abort rendezvous if validation fails. Used to gather success metrics during
+  // experiment rollout.
+  kValidateOnly,
+
+  // Validate the peer against a process requirement, if specified, and abort
+  // rendezvous if the validation fails.
+  kEnforce,
+};
+
+class BASE_EXPORT MachPortRendezvousClientMac final
+    : public MachPortRendezvousClient {
+ public:
+  // Set a ProcessRequirement that the server should be validated
+  // against before accepting any Mach ports from it.
+  //
+  // Must be called before `GetInstance` or this will have no effect.
+  static void SetServerProcessRequirement(mac::ProcessRequirement requirement);
+
+  // Get the peer validation policy that was derived from feature flags.
+  static MachPortRendezvousPeerValidationPolicy
+  PeerValidationPolicyForTesting();
+
+ protected:
+  // Validate the server against a process requirement if one was set via
+  // `SetServerProcessRequirement`.
+  bool ValidateMessage(mach_msg_base_t* message,
+                       BufferIterator<uint8_t> body) override;
+
+ private:
+  friend class MachPortRendezvousClient;
+
+  MachPortRendezvousClientMac();
+  ~MachPortRendezvousClientMac() override;
+
+  // Returns the name of the server to look up in the bootstrap namespace.
+  static std::string GetBootstrapName();
+
+  // Helper method to look up the server in the bootstrap namespace and send
+  // the acquisition request message.
+  bool AcquirePorts();
+
+  // Take ownership of the server process requirement, if any.
+  static std::optional<mac::ProcessRequirement>
+  TakeServerCodeSigningRequirement();
+
+  // Whether Info.plist data is needed from the server in order
+  // to validate `server_requirement_`.
+  bool NeedsInfoPlistData() const;
+
+  std::optional<mac::ProcessRequirement> server_requirement_;
+};
+
+// Whether any peer process requirements should be validated.
+BASE_EXPORT BASE_DECLARE_FEATURE(kMachPortRendezvousValidatePeerRequirements);
+
+// Whether a failure to validate a peer process against a requirement
+// should result in aborting the rendezvous.
+BASE_EXPORT BASE_DECLARE_FEATURE(kMachPortRendezvousEnforcePeerRequirements);
+
+}  // namespace base
+
+#endif  // BASE_APPLE_MACH_PORT_RENDEZVOUS_MAC_H_
diff --git a/base/apple/mach_port_rendezvous_unittest.cc b/base/apple/mach_port_rendezvous_unittest.cc
index 8347e09..276a1a3 100644
--- a/base/apple/mach_port_rendezvous_unittest.cc
+++ b/base/apple/mach_port_rendezvous_unittest.cc
@@ -27,6 +27,10 @@
 #include "base/time/time.h"
 #include "testing/multiprocess_func_list.h"
 
+#if BUILDFLAG(IS_MAC)
+#include "base/apple/mach_port_rendezvous_mac.h"
+#endif
+
 namespace base {
 
 namespace {
diff --git a/base/check_unittest.cc b/base/check_unittest.cc
index 6553ec3b..d6f0e42 100644
--- a/base/check_unittest.cc
+++ b/base/check_unittest.cc
@@ -112,43 +112,45 @@
     }                                                                          \
   } while (0)
 
-#define EXPECT_LOG_ERROR_WITH_FILENAME(expected_file, expected_line, expr, \
-                                       msg)                                \
-  do {                                                                     \
-    static bool got_log_message = false;                                   \
-    ASSERT_EQ(logging::GetLogMessageHandler(), nullptr);                   \
-    logging::SetLogMessageHandler([](int severity, std::string_view file,  \
-                                     int line, size_t message_start,       \
-                                     const std::string& str) {             \
-      EXPECT_FALSE(got_log_message);                                       \
-      got_log_message = true;                                              \
-      EXPECT_EQ(severity, logging::LOGGING_ERROR);                         \
-      EXPECT_EQ(str.substr(message_start), (msg));                         \
-      EXPECT_EQ(std::string_view(expected_file), file);                    \
-      if (expected_line != -1) {                                           \
-        EXPECT_EQ(expected_line, line);                                    \
-      }                                                                    \
-      return true;                                                         \
-    });                                                                    \
-    expr;                                                                  \
-    EXPECT_TRUE(got_log_message);                                          \
-    logging::SetLogMessageHandler(nullptr);                                \
+#define EXPECT_LOG_ERROR_WITH_FILENAME(expected_file, expected_line, expr,     \
+                                       msg)                                    \
+  do {                                                                         \
+    static bool got_log_message = false;                                       \
+    ASSERT_EQ(logging::GetLogMessageHandler(), nullptr);                       \
+    logging::SetLogMessageHandler([](int severity, const char* file, int line, \
+                                     size_t message_start,                     \
+                                     const std::string& str) {                 \
+      EXPECT_FALSE(got_log_message);                                           \
+      got_log_message = true;                                                  \
+      EXPECT_EQ(severity, logging::LOGGING_ERROR);                             \
+      EXPECT_EQ(str.substr(message_start), (msg));                             \
+      if (std::string_view(expected_file) != "") {                             \
+        EXPECT_STREQ(expected_file, file);                                     \
+      }                                                                        \
+      if (expected_line != -1) {                                               \
+        EXPECT_EQ(expected_line, line);                                        \
+      }                                                                        \
+      return true;                                                             \
+    });                                                                        \
+    expr;                                                                      \
+    EXPECT_TRUE(got_log_message);                                              \
+    logging::SetLogMessageHandler(nullptr);                                    \
   } while (0)
 
 #define EXPECT_LOG_ERROR(expected_line, expr, msg) \
   EXPECT_LOG_ERROR_WITH_FILENAME(__FILE__, expected_line, expr, msg)
 
-#define EXPECT_NO_LOG(expr)                                               \
-  do {                                                                    \
-    ASSERT_EQ(logging::GetLogMessageHandler(), nullptr);                  \
-    logging::SetLogMessageHandler([](int severity, std::string_view file, \
-                                     int line, size_t message_start,      \
-                                     const std::string& str) {            \
-      EXPECT_TRUE(false) << "Unexpected log: " << str;                    \
-      return true;                                                        \
-    });                                                                   \
-    expr;                                                                 \
-    logging::SetLogMessageHandler(nullptr);                               \
+#define EXPECT_NO_LOG(expr)                                                    \
+  do {                                                                         \
+    ASSERT_EQ(logging::GetLogMessageHandler(), nullptr);                       \
+    logging::SetLogMessageHandler([](int severity, const char* file, int line, \
+                                     size_t message_start,                     \
+                                     const std::string& str) {                 \
+      EXPECT_TRUE(false) << "Unexpected log: " << str;                         \
+      return true;                                                             \
+    });                                                                        \
+    expr;                                                                      \
+    logging::SetLogMessageHandler(nullptr);                                    \
   } while (0)
 
 #if defined(OFFICIAL_BUILD)
diff --git a/base/files/file_path_unittest.cc b/base/files/file_path_unittest.cc
index af82964..1b03b89 100644
--- a/base/files/file_path_unittest.cc
+++ b/base/files/file_path_unittest.cc
@@ -650,46 +650,73 @@
 }
 
 TEST_F(FilePathTest, IsParentTest) {
+#if defined(FILE_PATH_USES_WIN_SEPARATORS)
+  auto swap_separators = [](const FilePath& path) {
+    FilePath::StringType new_path(path.value());
+    for (auto& character : new_path) {
+      if (character == '/') {
+        character = '\\';
+      } else if (character == '\\') {
+        character = '/';
+      }
+    }
+    return new_path;
+  };
+#endif  // defined(FILE_PATH_USES_WIN_SEPARATORS)
+
   const auto cases = std::to_array<BinaryBooleanTestData>({
-      {{FPL("/"), FPL("/foo/bar/baz")}, true},
-      {{FPL("/foo"), FPL("/foo/bar/baz")}, true},
-      {{FPL("/foo/bar"), FPL("/foo/bar/baz")}, true},
-      {{FPL("/foo/bar/"), FPL("/foo/bar/baz")}, true},
-      {{FPL("//foo/bar/"), FPL("//foo/bar/baz")}, true},
-      {{FPL("/foo/bar"), FPL("/foo2/bar/baz")}, false},
-      {{FPL("/foo/bar.txt"), FPL("/foo/bar/baz")}, false},
-      {{FPL("/foo/bar"), FPL("/foo/bar2/baz")}, false},
-      {{FPL("/foo/bar"), FPL("/foo/bar")}, false},
-      {{FPL("/foo/bar/baz"), FPL("/foo/bar")}, false},
-      {{FPL("foo"), FPL("foo/bar/baz")}, true},
-      {{FPL("foo/bar"), FPL("foo/bar/baz")}, true},
-      {{FPL("foo/bar"), FPL("foo2/bar/baz")}, false},
-      {{FPL("foo/bar"), FPL("foo/bar2/baz")}, false},
+      {{FPL(""), FPL("")}, false},
       {{FPL(""), FPL("foo")}, false},
+      {{FPL("/"), FPL("/")}, false},
+      {{FPL("/"), FPL("/foo/bar/baz")}, true},
+      {{FPL("//////host/bar/"), FPL("//////HOST/bar/baz")}, true},
+      {{FPL("//host/bar/"), FPL("//host/bar/baz")}, true},
+      {{FPL("//host/bar/"), FPL("//host2/bar/baz")}, false},
+      {{FPL("//host/bar/"), FPL("/HOST/bar/baz")}, false},
+      {{FPL("//host/bar/"), FPL("/host/bar/baz")}, false},
+      {{FPL("//HOST/foo"), FPL("//host/foo/bar")}, true},
+      {{FPL("/foo"), FPL("/foo/bar/baz")}, true},
+      {{FPL("/foo/bar.txt"), FPL("/foo/bar/baz")}, false},
+      {{FPL("/foo/bar"), FPL("/foo//bar/baz")}, true},
+      {{FPL("/foo/bar"), FPL("/FOO//bar/baz/")}, false},
+      {{FPL("/foo/bar"), FPL("/foo//bar/baz/")}, true},
+      {{FPL("/foo/bar"), FPL("/foo/bar")}, false},
+      {{FPL("/foo/bar"), FPL("/foo/bar/baz")}, true},
+      {{FPL("/foo/bar"), FPL("/foo/bar2/baz")}, false},
+      {{FPL("/foo/bar"), FPL("/foo2/bar/baz")}, false},
+      {{FPL("/foo/bar/"), FPL("/foo/bar/baz")}, true},
+      {{FPL("/foo/bar/baz"), FPL("/foo/bar")}, false},
+      {{FPL("foo"), FPL("")}, false},
+      {{FPL("foo"), FPL("foo/bar/baz")}, true},
+      {{FPL("foo/b:"), FPL("foo/B:/baz")}, false},
+      {{FPL("foo/bar"), FPL("/foo/bar/baz")}, false},
+      {{FPL("foo/bar"), FPL("foo/bar/baz")}, true},
+      {{FPL("foo/bar"), FPL("foo/bar2/baz")}, false},
+      {{FPL("foo/bar"), FPL("foo2/bar/baz")}, false},
+      // As documented, IsParent() does not follow directory navigation.
+      {{FPL("foo/bar/../baz"), FPL("foo/baz/aaa")}, false},
 #if defined(FILE_PATH_USES_DRIVE_LETTERS)
-      {{FPL("c:/foo/bar"), FPL("c:/foo/bar/baz")}, true},
-      {{FPL("E:/foo/bar"), FPL("e:/foo/bar/baz")}, true},
-      {{FPL("f:/foo/bar"), FPL("F:/foo/bar/baz")}, true},
-      {{FPL("E:/Foo/bar"), FPL("e:/foo/bar/baz")}, false},
-      {{FPL("f:/foo/bar"), FPL("F:/foo/Bar/baz")}, false},
-      {{FPL("c:/"), FPL("c:/foo/bar/baz")}, true},
+      {{FPL("c:"), FPL("*:/foo/bar/baz")}, false},
       {{FPL("c:"), FPL("c:/foo/bar/baz")}, true},
+      {{FPL("c:/"), FPL("c:/foo/bar/baz")}, true},
+      {{FPL("c:/foo/bar"), FPL("c:/foo/bar/baz")}, true},
+      {{FPL("c:/foo/bar"), FPL("c:/foo/bar2/baz")}, false},
+      {{FPL("c:/foo/bar"), FPL("c:/foo2/bar/baz")}, false},
       {{FPL("c:/foo/bar"), FPL("d:/foo/bar/baz")}, false},
       {{FPL("c:/foo/bar"), FPL("D:/foo/bar/baz")}, false},
       {{FPL("C:/foo/bar"), FPL("d:/foo/bar/baz")}, false},
-      {{FPL("c:/foo/bar"), FPL("c:/foo2/bar/baz")}, false},
+      {{FPL("E:/Foo/bar"), FPL("e:/foo/bar/baz")}, false},
+      {{FPL("E:/foo/bar"), FPL("e:/foo/bar/baz")}, true},
       {{FPL("e:/foo/bar"), FPL("E:/foo2/bar/baz")}, false},
+      {{FPL("f:/foo/bar"), FPL("F:/foo/Bar/baz")}, false},
+      {{FPL("f:/foo/bar"), FPL("F:/foo/bar/baz")}, true},
       {{FPL("F:/foo/bar"), FPL("f:/foo2/bar/baz")}, false},
-      {{FPL("c:/foo/bar"), FPL("c:/foo/bar2/baz")}, false},
 #endif  // FILE_PATH_USES_DRIVE_LETTERS
 #if defined(FILE_PATH_USES_WIN_SEPARATORS)
-      {{FPL("\\foo\\bar"), FPL("\\foo\\bar\\baz")}, true},
-      {{FPL("\\foo/bar"), FPL("\\foo\\bar\\baz")}, true},
+      // Mix different types of separators in the same test case.
       {{FPL("\\foo/bar"), FPL("\\foo/bar/baz")}, true},
-      {{FPL("\\"), FPL("\\foo\\bar\\baz")}, true},
-      {{FPL(""), FPL("\\foo\\bar\\baz")}, false},
-      {{FPL("\\foo\\bar"), FPL("\\foo2\\bar\\baz")}, false},
-      {{FPL("\\foo\\bar"), FPL("\\foo\\bar2\\baz")}, false},
+      {{FPL("\\foo/bar"), FPL("\\foo\\bar/baz")}, true},
+      {{FPL("\\foo/bar"), FPL("\\foo\\/\\/bar/baz")}, true},
 #endif  // FILE_PATH_USES_WIN_SEPARATORS
   });
 
@@ -700,6 +727,16 @@
     EXPECT_EQ(parent.IsParent(child), cases[i].expected)
         << "i: " << i << ", parent: " << parent.value()
         << ", child: " << child.value();
+
+#if defined(FILE_PATH_USES_WIN_SEPARATORS)
+    // Using different separators should not affect the result.
+    FilePath parent_swapped(swap_separators(parent));
+    FilePath child_swapped(swap_separators(child));
+
+    EXPECT_EQ(parent_swapped.IsParent(child_swapped), cases[i].expected)
+        << "i (swapped): " << i << ", parent: " << parent_swapped.value()
+        << ", child: " << child_swapped.value();
+#endif  // defined(FILE_PATH_USES_WIN_SEPARATORS)
   }
 }
 
diff --git a/base/ios/device_util.h b/base/ios/device_util.h
index 868dbaa9..01f220c3 100644
--- a/base/ios/device_util.h
+++ b/base/ios/device_util.h
@@ -5,6 +5,8 @@
 #ifndef BASE_IOS_DEVICE_UTIL_H_
 #define BASE_IOS_DEVICE_UTIL_H_
 
+#include <base/types/expected.h>
+#include <mach/mach.h>
 #include <stdint.h>
 
 #include <string>
@@ -54,6 +56,9 @@
 std::string GetSaltedString(const std::string& in_string,
                             const std::string& salt);
 
+// Returns a task_vm_info runtime memory data on Apple platforms in
+// case of KERN_SUCCESS. Otherwise returns an error of kern_return_t type.
+[[nodiscard]] base::expected<task_vm_info, kern_return_t> GetTaskVMInfo();
 }  // namespace device_util
 }  // namespace ios
 
diff --git a/base/ios/device_util.mm b/base/ios/device_util.mm
index e5ef3ebd..3592c2b 100644
--- a/base/ios/device_util.mm
+++ b/base/ios/device_util.mm
@@ -181,4 +181,15 @@
   return base::SysCFStringRefToUTF8(device_id.get());
 }
 
+base::expected<task_vm_info, kern_return_t> GetTaskVMInfo() {
+  task_vm_info task_vm_info_data = {0};
+  mach_msg_type_number_t count = TASK_VM_INFO_COUNT;
+  kern_return_t result =
+      task_info(mach_task_self(), TASK_VM_INFO,
+                reinterpret_cast<task_info_t>(&task_vm_info_data), &count);
+  if (result == KERN_SUCCESS) {
+    return task_vm_info_data;
+  }
+  return base::unexpected(result);
+}
 }  // namespace ios::device_util
diff --git a/base/logging.cc b/base/logging.cc
index 22aa47800..26ba1a2 100644
--- a/base/logging.cc
+++ b/base/logging.cc
@@ -463,41 +463,33 @@
 #endif  // !BUILDFLAG(IS_NACL)
 }
 
-std::string BuildCrashString(std::string_view file,
+std::string BuildCrashString(const char* file,
                              int line,
-                             std::string_view message_without_prefix) {
+                             const char* message_without_prefix) {
   // Only log last path component.
-  char separator =
+  if (file) {
+    const char* slash = UNSAFE_TODO(strrchr(file,
 #if BUILDFLAG(IS_WIN)
-      '\\';
+                                            '\\'
 #else
-      '/';
+                                            '/'
 #endif  // BUILDFLAG(IS_WIN)
-
-  auto pos = file.rfind(separator);
-  if (pos == std::string_view::npos) {
-    pos = 0;
-  } else {
-    pos += 1;
+                                            ));
+    if (slash) {
+      file = UNSAFE_TODO(slash + 1);
+    }
   }
 
-  file = file.substr(pos);
-
-  return base::StringPrintf("%.*s:%d: %.*s", static_cast<int>(file.length()),
-                            file.data(), line,
-                            static_cast<int>(message_without_prefix.length()),
-                            message_without_prefix.data());
+  return base::StringPrintf("%s:%d: %s", file, line, message_without_prefix);
 }
 
 // Invokes macro to record trace event when a log message is emitted.
-void TraceLogMessage(std::string_view file,
-                     int line,
-                     const std::string& message) {
+void TraceLogMessage(const char* file, int line, const std::string& message) {
   TRACE_EVENT_INSTANT("log", "LogMessage", [&](perfetto::EventContext ctx) {
     perfetto::protos::pbzero::LogMessage* log = ctx.event()->set_log_message();
     log->set_source_location_iid(base::trace_event::InternedSourceLocation::Get(
-        &ctx, base::trace_event::TraceSourceLocation(
-                  /*function_name=*/std::string_view(), file, line)));
+        &ctx, base::trace_event::TraceSourceLocation(/*function_name=*/nullptr,
+                                                     file, line)));
     log->set_body_iid(
         base::trace_event::InternedLogMessage::Get(&ctx, message));
   });
@@ -621,11 +613,14 @@
   return std::max(-1, LOGGING_INFO - GetMinLogLevel());
 }
 
-int GetVlogLevelHelper(std::string_view file) {
+int GetVlogLevelHelper(const char* file, size_t N) {
+  DCHECK_GT(N, 0U);
+
   // Note: |g_vlog_info| may change on a different thread during startup
   // (but will always be valid or nullptr).
   VlogInfo* vlog_info = GetVlogInfo();
-  return vlog_info ? vlog_info->GetVlogLevel(file) : GetVlogVerbosity();
+  return vlog_info ? vlog_info->GetVlogLevel(std::string_view(file, N - 1))
+                   : GetVlogVerbosity();
 }
 
 void SetLogItems(bool enable_process_id,
@@ -658,7 +653,7 @@
   // This simulates a NOTREACHED() at file:line instead of here. This is used
   // instead of base::ImmediateCrash() to give better error messages locally
   // (printed stack for one).
-  LogMessageFatal(std::string_view(file), line, LOGGING_FATAL).stream()
+  LogMessageFatal(file, line, LOGGING_FATAL).stream()
       << "NOTREACHED hit. " << prefix_end;
 }
 
@@ -717,14 +712,11 @@
 }
 #endif  // !defined(NDEBUG)
 
-LogMessage::LogMessage(std::string_view file, int line, LogSeverity severity)
+LogMessage::LogMessage(const char* file, int line, LogSeverity severity)
     : severity_(severity), file_(file), line_(line) {
   Init(file, line);
 }
 
-LogMessage::LogMessage(const char* file, int line, LogSeverity severity)
-    : LogMessage(std::string_view(file), line, severity) {}
-
 LogMessage::~LogMessage() {
   Flush();
 }
@@ -959,12 +951,12 @@
 }
 
 std::string LogMessage::BuildCrashString() const {
-  return logging::BuildCrashString(
-      file(), line(), std::string_view(str()).substr(message_start_));
+  return logging::BuildCrashString(file(), line(),
+                                   UNSAFE_TODO(str().c_str() + message_start_));
 }
 
 // writes the common header info to the stream
-void LogMessage::Init(std::string_view file, int line) {
+void LogMessage::Init(const char* file, int line) {
   // Don't let actions from this method affect the system error after returning.
   base::ScopedClearLastError scoped_clear_last_error;
 
@@ -979,14 +971,15 @@
   // TODO(pbos): Consider migrating LogMessage and the LOG() macros to use
   // base::Location directly. See base/check.h for inspiration.
   const std::string_view filename =
-      file[0] == '.' ? file.substr(std::min(std::size_t{6}, file.length()))
+      file[0] == '.' ? std::string_view(file).substr(
+                           std::min(std::size_t{6}, strlen(file)))
                      : file;
 
 #if BUILDFLAG(IS_CHROMEOS)
   if (g_log_format == LogFormat::LOG_FORMAT_SYSLOG) {
-    InitWithSyslogPrefix(file, line, TickCount(), log_severity_name(severity_),
-                         g_log_prefix, g_log_process_id, g_log_thread_id,
-                         g_log_timestamp, g_log_tickcount);
+    InitWithSyslogPrefix(
+        filename, line, TickCount(), log_severity_name(severity_), g_log_prefix,
+        g_log_process_id, g_log_thread_id, g_log_timestamp, g_log_tickcount);
   } else
 #endif  // BUILDFLAG(IS_CHROMEOS)
   {
@@ -1124,7 +1117,7 @@
 }
 
 #if BUILDFLAG(IS_WIN)
-Win32ErrorLogMessage::Win32ErrorLogMessage(std::string_view file,
+Win32ErrorLogMessage::Win32ErrorLogMessage(const char* file,
                                            int line,
                                            LogSeverity severity,
                                            SystemErrorCode err)
@@ -1152,7 +1145,7 @@
 }
 
 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
-ErrnoLogMessage::ErrnoLogMessage(std::string_view file,
+ErrnoLogMessage::ErrnoLogMessage(const char* file,
                                  int line,
                                  LogSeverity severity,
                                  SystemErrorCode err)
diff --git a/base/logging.h b/base/logging.h
index 164698b..52147df 100644
--- a/base/logging.h
+++ b/base/logging.h
@@ -310,7 +310,8 @@
 // Gets the VLOG default verbosity level.
 BASE_EXPORT int GetVlogVerbosity();
 
-BASE_EXPORT int GetVlogLevelHelper(std::string_view file);
+// Note that |N| is the size *with* the null terminator.
+BASE_EXPORT int GetVlogLevelHelper(const char* file_start, size_t N);
 
 // Gets the current vlog level for the given file (usually taken from __FILE__).
 template <size_t N>
@@ -322,7 +323,7 @@
 #if defined(OFFICIAL_BUILD) && !DCHECK_IS_ON() && BUILDFLAG(IS_ANDROID)
   return -1;
 #else
-  return GetVlogLevelHelper(std::string_view(file, N - 1));
+  return GetVlogLevelHelper(file, N);
 #endif  // defined(OFFICIAL_BUILD) && !DCHECK_IS_ON() && BUILDFLAG(IS_ANDROID)
 }
 
@@ -357,7 +358,7 @@
 // however clients can use this function to override with their own handling
 // (e.g. a silent one for Unit Tests)
 using LogAssertHandlerFunction =
-    base::RepeatingCallback<void(std::string_view file,
+    base::RepeatingCallback<void(const char* file,
                                  int line,
                                  std::string_view message,
                                  std::string_view stack_trace)>;
@@ -375,7 +376,7 @@
 // Returns true to signal that it handled the message and the message
 // should not be sent to other log destinations.
 typedef bool (*LogMessageHandlerFunction)(int severity,
-                                          std::string_view file,
+                                          const char* file,
                                           int line,
                                           size_t message_start,
                                           const std::string& str);
@@ -603,21 +604,17 @@
 // above.
 class BASE_EXPORT LogMessage {
  public:
-  // file must be a static string, such as one obtained from the __FILE__ macro.
-  LogMessage(std::string_view file LIFETIME_BOUND,
-             int line,
-             LogSeverity severity);
-
   LogMessage(const char* file, int line, LogSeverity severity);
 
   LogMessage(const LogMessage&) = delete;
+  LogMessage& operator=(const LogMessage&) = delete;
   virtual ~LogMessage();
 
   std::ostream& stream() { return stream_; }
 
   LogSeverity severity() const { return severity_; }
   std::string str() const { return stream_.str(); }
-  std::string_view file() const { return file_; }
+  const char* file() const { return file_; }
   int line() const { return line_; }
 
   // Gets file:line: message in a format suitable for crash reporting.
@@ -627,7 +624,7 @@
   void Flush();
 
  private:
-  void Init(std::string_view file, int line);
+  void Init(const char* file, int line);
 
   void HandleFatal(size_t stack_start, const std::string& str_newline) const;
 
@@ -636,7 +633,7 @@
   size_t message_start_;  // Offset of the start of the message (past prefix
                           // info).
   // The file and line information passed in to the constructor.
-  const std::string_view file_;
+  const char* const file_;
   const int line_;
 
 #if BUILDFLAG(IS_CHROMEOS)
@@ -684,7 +681,7 @@
 // Appends a formatted system message of the GetLastError() type.
 class BASE_EXPORT Win32ErrorLogMessage : public LogMessage {
  public:
-  Win32ErrorLogMessage(std::string_view file LIFETIME_BOUND,
+  Win32ErrorLogMessage(const char* file,
                        int line,
                        LogSeverity severity,
                        SystemErrorCode err);
@@ -711,7 +708,7 @@
 // Appends a formatted system message of the errno type
 class BASE_EXPORT ErrnoLogMessage : public LogMessage {
  public:
-  ErrnoLogMessage(std::string_view file LIFETIME_BOUND,
+  ErrnoLogMessage(const char* file,
                   int line,
                   LogSeverity severity,
                   SystemErrorCode err);
diff --git a/base/logging_unittest.cc b/base/logging_unittest.cc
index a2befbfd..6f51f365 100644
--- a/base/logging_unittest.cc
+++ b/base/logging_unittest.cc
@@ -88,11 +88,9 @@
 
 class MockLogAssertHandler {
  public:
-  MOCK_METHOD4(HandleLogAssert,
-               void(std::string_view,
-                    int,
-                    const std::string_view,
-                    const std::string_view));
+  MOCK_METHOD4(
+      HandleLogAssert,
+      void(const char*, int, const std::string_view, const std::string_view));
 };
 
 TEST_F(LoggingTest, BasicLogging) {
@@ -757,7 +755,7 @@
   // Use a static because only captureless lambdas can be converted to a
   // function pointer for SetLogMessageHandler().
   static base::NoDestructor<std::string> log_string;
-  SetLogMessageHandler([](int severity, std::string_view file, int line,
+  SetLogMessageHandler([](int severity, const char* file, int line,
                           size_t start, const std::string& str) -> bool {
     *log_string = str;
     return true;
@@ -786,7 +784,7 @@
   // Use a static because only captureless lambdas can be converted to a
   // function pointer for SetLogMessageHandler().
   static base::NoDestructor<std::string> log_string;
-  SetLogMessageHandler([](int severity, std::string_view file, int line,
+  SetLogMessageHandler([](int severity, const char* file, int line,
                           size_t start, const std::string& str) -> bool {
     *log_string = str;
     return true;
@@ -989,7 +987,7 @@
   // Use a static because only captureless lambdas can be converted to a
   // function pointer for SetLogMessageHandler().
   static base::NoDestructor<std::string> log_string;
-  SetLogMessageHandler([](int severity, std::string_view file, int line,
+  SetLogMessageHandler([](int severity, const char* file, int line,
                           size_t start, const std::string& str) -> bool {
     *log_string = str;
     return true;
@@ -1018,7 +1016,7 @@
   // Use a static because only captureless lambdas can be converted to a
   // function pointer for SetLogMessageHandler().
   static base::NoDestructor<std::string> log_string;
-  SetLogMessageHandler([](int severity, std::string_view file, int line,
+  SetLogMessageHandler([](int severity, const char* file, int line,
                           size_t start, const std::string& str) -> bool {
     *log_string = str;
     return true;
diff --git a/base/logging_win.cc b/base/logging_win.cc
index fb4e36b..be3f2920 100644
--- a/base/logging_win.cc
+++ b/base/logging_win.cc
@@ -11,8 +11,6 @@
 
 #include <initguid.h>
 
-#include <string_view>
-
 #include "base/memory/singleton.h"
 
 namespace logging {
@@ -41,7 +39,7 @@
 }
 
 bool LogEventProvider::LogMessage(logging::LogSeverity severity,
-                                  std::string_view file,
+                                  const char* file,
                                   int line,
                                   size_t message_start,
                                   const std::string& message) {
@@ -93,6 +91,9 @@
     }
 
     EtwMofEvent<5> event(kLogEventId, LOG_MESSAGE_FULL, level);
+    if (file == NULL) {
+      file = "";
+    }
 
     // Add the stack trace.
     event.SetField(0, sizeof(depth), &depth);
@@ -100,7 +101,7 @@
     // The line.
     event.SetField(2, sizeof(line), &line);
     // The file.
-    event.SetField(3, file.length(), file.data());
+    event.SetField(3, strlen(file) + 1, file);
     // And finally the message.
     event.SetField(4, message.length() + 1 - message_start,
                    message.c_str() + message_start);
diff --git a/base/logging_win.h b/base/logging_win.h
index b6171a52..76bf0559 100644
--- a/base/logging_win.h
+++ b/base/logging_win.h
@@ -8,7 +8,6 @@
 #include <stddef.h>
 
 #include <string>
-#include <string_view>
 
 #include "base/base_export.h"
 #include "base/logging.h"
@@ -60,7 +59,7 @@
   static LogEventProvider* GetInstance();
 
   static bool LogMessage(logging::LogSeverity severity,
-                         std::string_view file,
+                         const char* file,
                          int line,
                          size_t message_start,
                          const std::string& str);
diff --git a/base/process/launch_mac.cc b/base/process/launch_mac.cc
index 1baeaec..29e6d750 100644
--- a/base/process/launch_mac.cc
+++ b/base/process/launch_mac.cc
@@ -22,6 +22,10 @@
 #include "base/threading/thread_restrictions.h"
 #include "base/trace_event/base_tracing.h"
 
+#if BUILDFLAG(IS_MAC)
+#include "base/apple/mach_port_rendezvous_mac.h"
+#endif
+
 extern "C" {
 // Changes the current thread's directory to a path or directory file
 // descriptor.
diff --git a/base/process/process_util_unittest.cc b/base/process/process_util_unittest.cc
index 43b5da1..2b3435b 100644
--- a/base/process/process_util_unittest.cc
+++ b/base/process/process_util_unittest.cc
@@ -94,7 +94,7 @@
 #if BUILDFLAG(IS_MAC)
 #include <mach/mach.h>
 
-#include "base/apple/mach_port_rendezvous.h"
+#include "base/apple/mach_port_rendezvous_mac.h"
 #include "base/apple/scoped_mach_port.h"
 #include "base/mac/process_requirement.h"
 #endif
diff --git a/base/test/gtest_xml_unittest_result_printer.cc b/base/test/gtest_xml_unittest_result_printer.cc
index 441993a..ce9ba37 100644
--- a/base/test/gtest_xml_unittest_result_printer.cc
+++ b/base/test/gtest_xml_unittest_result_printer.cc
@@ -157,7 +157,7 @@
   return true;
 }
 
-void XmlUnitTestResultPrinter::OnAssert(std::string_view file,
+void XmlUnitTestResultPrinter::OnAssert(const char* file,
                                         int line,
                                         const std::string& summary,
                                         const std::string& message) {
@@ -240,7 +240,7 @@
 }
 
 void XmlUnitTestResultPrinter::WriteTestPartResult(
-    std::string_view file,
+    const char* file,
     int line,
     testing::TestPartResult::Type result_type,
     const std::string& summary,
@@ -268,12 +268,11 @@
   std::string summary_encoded = base::Base64Encode(summary);
   std::string message_encoded = base::Base64Encode(message);
   fprintf(output_file_.get(),
-          "      <x-test-result-part type=\"%s\" file=\"%.*s\" line=\"%d\">\n"
+          "      <x-test-result-part type=\"%s\" file=\"%s\" line=\"%d\">\n"
           "        <summary>%s</summary>\n"
           "        <message>%s</message>\n"
           "      </x-test-result-part>\n",
-          type, static_cast<int>(file.length()), file.data(), line,
-          summary_encoded.c_str(), message_encoded.c_str());
+          type, file, line, summary_encoded.c_str(), message_encoded.c_str());
   fflush(output_file_);
 }
 
diff --git a/base/test/gtest_xml_unittest_result_printer.h b/base/test/gtest_xml_unittest_result_printer.h
index 242354e..f3010fa 100644
--- a/base/test/gtest_xml_unittest_result_printer.h
+++ b/base/test/gtest_xml_unittest_result_printer.h
@@ -51,7 +51,7 @@
   [[nodiscard]] bool Initialize(const FilePath& output_file_path);
 
   // CHECK/DCHECK failed. Print file/line and message to the xml.
-  void OnAssert(std::string_view file,
+  void OnAssert(const char* file,
                 int line,
                 const std::string& summary,
                 const std::string& message);
@@ -63,7 +63,7 @@
   void OnTestEnd(const testing::TestInfo& test_info) override;
   void OnTestSuiteEnd(const testing::TestSuite& test_suite) override;
 
-  void WriteTestPartResult(std::string_view file,
+  void WriteTestPartResult(const char* file,
                            int line,
                            testing::TestPartResult::Type type,
                            const std::string& summary,
diff --git a/base/test/mock_log.cc b/base/test/mock_log.cc
index ae16941..ecacbf3 100644
--- a/base/test/mock_log.cc
+++ b/base/test/mock_log.cc
@@ -49,7 +49,7 @@
 
 // static
 bool MockLog::LogMessageHandler(int severity,
-                                std::string_view file,
+                                const char* file,
                                 int line,
                                 size_t message_start,
                                 const std::string& str) {
diff --git a/base/test/mock_log.h b/base/test/mock_log.h
index 78096be..7d8e75e3 100644
--- a/base/test/mock_log.h
+++ b/base/test/mock_log.h
@@ -67,7 +67,7 @@
   // destinations.
   MOCK_METHOD5(Log,
                bool(int severity,
-                    std::string_view file,
+                    const char* file,
                     int line,
                     size_t message_start,
                     const std::string& str));
@@ -82,7 +82,7 @@
   // Static function which is set as the logging message handler.
   // Called once for each message.
   static bool LogMessageHandler(int severity,
-                                std::string_view file,
+                                const char* file,
                                 int line,
                                 size_t message_start,
                                 const std::string& str);
diff --git a/base/test/task_environment_unittest.cc b/base/test/task_environment_unittest.cc
index 407e51c6..1999b2a 100644
--- a/base/test/task_environment_unittest.cc
+++ b/base/test/task_environment_unittest.cc
@@ -1573,7 +1573,7 @@
 
 namespace {
 bool FailOnTaskEnvironmentLog(int severity,
-                              std::string_view file,
+                              const char* file,
                               int line,
                               size_t message_start,
                               const std::string& str) {
diff --git a/base/test/test_suite.cc b/base/test/test_suite.cc
index b12a887..2486fcd 100644
--- a/base/test/test_suite.cc
+++ b/base/test/test_suite.cc
@@ -444,7 +444,7 @@
   check_for_leaked_globals_ = false;
 }
 
-void TestSuite::UnitTestAssertHandler(const std::string_view file,
+void TestSuite::UnitTestAssertHandler(const char* file,
                                       int line,
                                       std::string_view summary,
                                       std::string_view stack_trace) {
diff --git a/base/test/test_suite.h b/base/test/test_suite.h
index 09370a6..071110d 100644
--- a/base/test/test_suite.h
+++ b/base/test/test_suite.h
@@ -71,7 +71,7 @@
   // By default fatal log messages (e.g. from DCHECKs) result in error dialogs
   // which gum up buildbots. Use a minimalistic assert handler which just
   // terminates the process.
-  void UnitTestAssertHandler(std::string_view file,
+  void UnitTestAssertHandler(const char* file,
                              int line,
                              std::string_view summary,
                              std::string_view stack_trace);
diff --git a/base/trace_event/interned_args_helper.cc b/base/trace_event/interned_args_helper.cc
index 2fb01f04..b230b97 100644
--- a/base/trace_event/interned_args_helper.cc
+++ b/base/trace_event/interned_args_helper.cc
@@ -37,12 +37,11 @@
     const TraceSourceLocation& location) {
   auto* msg = interned_data->add_source_locations();
   msg->set_iid(iid);
-  if (!location.file_name.empty()) {
-    msg->set_file_name(location.file_name.data(), location.file_name.length());
+  if (location.file_name != nullptr) {
+    msg->set_file_name(location.file_name);
   }
-  if (!location.function_name.empty()) {
-    msg->set_function_name(location.function_name.data(),
-                           location.function_name.length());
+  if (location.function_name != nullptr) {
+    msg->set_function_name(location.function_name);
   }
   // TODO(ssid): Add line number once it is allowed in internal proto.
   // TODO(ssid): Add program counter to the proto fields when
diff --git a/base/trace_event/interned_args_helper.h b/base/trace_event/interned_args_helper.h
index 01a157fb..9fc9d98 100644
--- a/base/trace_event/interned_args_helper.h
+++ b/base/trace_event/interned_args_helper.h
@@ -7,7 +7,6 @@
 
 #include <optional>
 #include <string>
-#include <string_view>
 
 #include "base/base_export.h"
 #include "base/hash/hash.h"
@@ -26,16 +25,13 @@
 // for log event's location since base::Location uses program counter based
 // location.
 struct BASE_EXPORT TraceSourceLocation {
-  // While these are string_views, only the address is used for equality and
-  // hashing. The length is still needed when interning a new location since the
-  // strings may not be null-terminated.
-  std::string_view function_name;
-  std::string_view file_name;
+  const char* function_name = nullptr;
+  const char* file_name = nullptr;
   int line_number = 0;
 
   TraceSourceLocation() = default;
-  TraceSourceLocation(std::string_view function_name,
-                      std::string_view file_name,
+  TraceSourceLocation(const char* function_name,
+                      const char* file_name,
                       int line_number)
       : function_name(function_name),
         file_name(file_name),
@@ -46,19 +42,11 @@
   explicit TraceSourceLocation(const base::Location& location)
       : function_name(location.function_name()),
         file_name(location.file_name()),
-        line_number(location.line_number()) {
-    if (location.function_name()) {
-      function_name = std::string_view(location.function_name());
-    }
-
-    if (location.file_name()) {
-      file_name = std::string_view(location.file_name());
-    }
-  }
+        line_number(location.line_number()) {}
 
   bool operator==(const TraceSourceLocation& other) const {
-    return file_name.data() == other.file_name.data() &&
-           function_name.data() == other.function_name.data() &&
+    return file_name == other.file_name &&
+           function_name == other.function_name &&
            line_number == other.line_number;
   }
 };
@@ -88,8 +76,8 @@
   std::size_t operator()(
       const base::trace_event::TraceSourceLocation& loc) const {
     return base::HashInts(
-        base::HashInts(reinterpret_cast<uintptr_t>(loc.file_name.data()),
-                       reinterpret_cast<uintptr_t>(loc.function_name.data())),
+        base::HashInts(reinterpret_cast<uintptr_t>(loc.file_name),
+                       reinterpret_cast<uintptr_t>(loc.function_name)),
         static_cast<size_t>(loc.line_number));
   }
 };
diff --git a/base/trace_event/trace_event_unittest.cc b/base/trace_event/trace_event_unittest.cc
index e68e496..8b07b6e 100644
--- a/base/trace_event/trace_event_unittest.cc
+++ b/base/trace_event/trace_event_unittest.cc
@@ -20,7 +20,6 @@
 #include <map>
 #include <memory>
 #include <string>
-#include <string_view>
 #include <utility>
 #include <vector>
 
@@ -1640,7 +1639,7 @@
 
 std::string* g_log_buffer = nullptr;
 bool MockLogMessageHandler(int,
-                           std::string_view,
+                           const char*,
                            int,
                            size_t,
                            const std::string& str) {
@@ -1673,7 +1672,7 @@
 }
 
 bool LogMessageHandlerWithTraceEvent(int,
-                                     std::string_view,
+                                     const char*,
                                      int,
                                      size_t,
                                      const std::string&) {
diff --git a/build/config/android/config.gni b/build/config/android/config.gni
index e9b3014..ee90a64 100644
--- a/build/config/android/config.gni
+++ b/build/config/android/config.gni
@@ -87,12 +87,28 @@
     # "build_server" ensures that fast_local_dev_server.py is running and
     #     offloads analysis tasks to it to be run after the build completes.
     #     This is the recommended setting for local development.
-    android_static_analysis = "on"
+    # Temporarily default to "" to detect if it is explicitly set. Remove after
+    # crbug.com/404503040
+    android_static_analysis = ""
     if (is_official_build) {
       android_static_analysis = "off"
     }
   }
 
+  if (android_static_analysis == "") {
+    android_static_analysis = "on"
+    if (enable_java_templates && getenv("SWARMING_TASK_ID") != "") {
+      # All android bots that can build java targets need to explicitly set
+      # android_static_analysis = "on" or "off" rather than rely on the default
+      # value, because the default value of "build_server" (coming soon, see
+      # crbug.com/404503040) does not work on bots. This is an assert instead of
+      # a dynamic default so that copy pasting gn args reproduces bot behavior.
+      assert(
+          false,
+          "All android bots must explicitly set android_static_analysis gn arg.")
+    }
+  }
+
   # Our build system no longer supports legacy multidex.
   min_supported_sdk_version = 21
 
diff --git a/cc/mojo_embedder/viz_layer_context.cc b/cc/mojo_embedder/viz_layer_context.cc
index b67e5ee66f..097f316 100644
--- a/cc/mojo_embedder/viz_layer_context.cc
+++ b/cc/mojo_embedder/viz_layer_context.cc
@@ -793,6 +793,36 @@
   return wire;
 }
 
+viz::mojom::ViewTransitionRequestPtr SerializeViewTransitionRequest(
+    const cc::ViewTransitionRequest& request) {
+  auto wire = viz::mojom::ViewTransitionRequest::New();
+  switch (request.type()) {
+    case cc::ViewTransitionRequest::Type::kSave:
+      wire->type = viz::mojom::CompositorFrameTransitionDirectiveType::kSave;
+      break;
+    case cc::ViewTransitionRequest::Type::kAnimateRenderer:
+      wire->type =
+          viz::mojom::CompositorFrameTransitionDirectiveType::kAnimateRenderer;
+      break;
+    case cc::ViewTransitionRequest::Type::kRelease:
+      wire->type = viz::mojom::CompositorFrameTransitionDirectiveType::kRelease;
+      break;
+  }
+  wire->transition_token = request.token();
+  wire->maybe_cross_frame_sink = request.maybe_cross_frame_sink();
+  wire->sequence_id = request.sequence_id();
+  if (request.type() == cc::ViewTransitionRequest::Type::kSave &&
+      !request.capture_resource_ids().empty()) {
+    wire->capture_resource_ids.reserve(request.capture_resource_ids().size());
+    for (const auto& id : request.capture_resource_ids()) {
+      wire->capture_resource_ids.push_back(id);
+    }
+  } else {
+    DCHECK(request.capture_resource_ids().empty());
+  }
+  return wire;
+}
+
 }  // namespace
 
 VizLayerContext::VizLayerContext(viz::mojom::CompositorFrameSink& frame_sink,
@@ -827,6 +857,7 @@
   update->device_viewport = tree.GetDeviceViewport();
   update->device_scale_factor = tree.device_scale_factor();
   update->painted_device_scale_factor = tree.painted_device_scale_factor();
+  update->display_color_spaces = tree.display_color_spaces();
   if (tree.local_surface_id_from_parent().is_valid()) {
     update->local_surface_id_from_parent = tree.local_surface_id_from_parent();
   }
@@ -885,6 +916,16 @@
     }
     tree.set_needs_surface_ranges_sync(false);
   }
+  if (tree.HasViewTransitionRequests()) {
+    auto requests = tree.TakeViewTransitionRequests(
+        /*should_set_needs_update_draw_properties=*/false);
+    update->view_transition_requests.emplace();
+    update->view_transition_requests->reserve(requests.size());
+    for (const auto& request : requests) {
+      auto data = SerializeViewTransitionRequest(*request);
+      update->view_transition_requests->push_back(std::move(data));
+    }
+  }
 
   if (base::FeatureList::IsEnabled(features::kTreeAnimationsInViz)) {
     SerializeAnimationUpdates(tree, *update);
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 330392e..fdfbdcf 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -3070,39 +3070,56 @@
 
   viz::CompositorFrameMetadata metadata = MakeCompositorFrameMetadata();
 
-  ViewTransitionRequest::ViewTransitionElementMap view_transition_element_map;
-  const auto& capture_view_transition_tokens =
-      active_tree_->GetCaptureViewTransitionTokens();
-  for (RenderSurfaceImpl* render_surface : *frame->render_surface_list) {
-    const auto& view_transition_element_resource_id =
-        render_surface->OwningEffectNode()->view_transition_element_resource_id;
-    if (!view_transition_element_resource_id.IsValid()) {
-      continue;
+  // Don't compute transition directives in TreesInViz mode because
+  // the requests will be sent over to viz to compute them.
+  // If we call TakeViewTransitionRequests() here, it will clear the requests
+  // and send none to viz.
+  if (!use_layer_context_for_display_) {
+    ViewTransitionRequest::ViewTransitionElementMap view_transition_element_map;
+    const auto& capture_view_transition_tokens =
+        active_tree_->GetCaptureViewTransitionTokens();
+    for (RenderSurfaceImpl* render_surface : *frame->render_surface_list) {
+      const auto& view_transition_element_resource_id =
+          render_surface->OwningEffectNode()
+              ->view_transition_element_resource_id;
+      if (!view_transition_element_resource_id.IsValid()) {
+        continue;
+      }
+
+      DCHECK(!base::Contains(view_transition_element_map,
+                             view_transition_element_resource_id))
+          << "Cannot map " << view_transition_element_resource_id.ToString()
+          << " to render pass "
+          << render_surface->render_pass_id().GetUnsafeValue()
+          << "; It already maps to render pass "
+          << view_transition_element_map[view_transition_element_resource_id]
+                 .GetUnsafeValue();
+
+      if (view_transition_element_resource_id.MatchesToken(
+              capture_view_transition_tokens)) {
+        view_transition_element_map[view_transition_element_resource_id] =
+            render_surface->view_transition_capture_render_pass_id();
+      } else {
+        view_transition_element_map[view_transition_element_resource_id] =
+            render_surface->render_pass_id();
+      }
     }
 
-    DCHECK(!base::Contains(view_transition_element_map,
-                           view_transition_element_resource_id))
-        << "Cannot map " << view_transition_element_resource_id.ToString()
-        << " to render pass "
-        << render_surface->render_pass_id().GetUnsafeValue()
-        << "; It already maps to render pass "
-        << view_transition_element_map[view_transition_element_resource_id]
-               .GetUnsafeValue();
-
-    if (view_transition_element_resource_id.MatchesToken(
-            capture_view_transition_tokens)) {
-      view_transition_element_map[view_transition_element_resource_id] =
-          render_surface->view_transition_capture_render_pass_id();
-    } else {
-      view_transition_element_map[view_transition_element_resource_id] =
-          render_surface->render_pass_id();
+    auto display_color_spaces = GetDisplayColorSpaces();
+    for (auto& request : active_tree_->TakeViewTransitionRequests(
+             /*should_set_needs_update_draw_properties=*/true)) {
+      metadata.transition_directives.push_back(request->ConstructDirective(
+          view_transition_element_map, display_color_spaces));
     }
-  }
-
-  auto display_color_spaces = GetDisplayColorSpaces();
-  for (auto& request : active_tree_->TakeViewTransitionRequests()) {
-    metadata.transition_directives.push_back(request->ConstructDirective(
-        view_transition_element_map, display_color_spaces));
+  } else {
+    // In TreesInViz mode, we call TakeViewTransitionRequest() later in
+    // VizLayerContext::UpdateDisplayTreeFrom(), but we still want to set
+    // the flag here to avoid changing the flow of computing. Also, we will
+    // skip setting the flag when TakeViewTransitionRequest() is called later
+    // to avoid triggering a DCHECK.
+    if (active_tree_->HasViewTransitionRequests()) {
+      active_tree_->set_needs_update_draw_properties();
+    }
   }
 
   PopulateMetadataContentColorUsage(frame, &metadata);
diff --git a/cc/trees/layer_tree_host_pixeltest_filters.cc b/cc/trees/layer_tree_host_pixeltest_filters.cc
index e1db2355..07c96894 100644
--- a/cc/trees/layer_tree_host_pixeltest_filters.cc
+++ b/cc/trees/layer_tree_host_pixeltest_filters.cc
@@ -304,6 +304,78 @@
       base::FilePath(FILE_PATH_LITERAL("backdrop_filter_blur_outsets.png")));
 }
 
+TEST_P(LayerTreeHostFiltersPixelTest, BackdropFilterQuality_0_33) {
+#if defined(MEMORY_SANITIZER)
+  if (renderer_type() == viz::RendererType::kSkiaVk) {
+    GTEST_SKIP() << "TODO(crbug.com/40839215): Uninitialized data error";
+  }
+#endif
+  scoped_refptr<SolidColorLayer> background =
+      CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE);
+
+  scoped_refptr<SolidColorLayer> green =
+      CreateSolidColorLayer(gfx::Rect(50, 50, 100, 100), kCSSGreen);
+  scoped_refptr<SolidColorLayer> blur =
+      CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorTRANSPARENT);
+  background->AddChild(green);
+  background->AddChild(blur);
+
+  FilterOperations filters;
+  filters.Append(FilterOperation::CreateBlurFilter(30.0f, SkTileMode::kClamp));
+  blur->SetBackdropFilters(filters);
+  blur->SetBackdropFilterQuality(0.33);
+
+#if BUILDFLAG(IS_WIN) || defined(ARCH_CPU_ARM64)
+  // Windows and ARM64 have 436 pixels off by 1: crbug.com/259915
+  pixel_comparator_ = std::make_unique<FuzzyPixelComparator>(
+      FuzzyPixelComparator()
+          .DiscardAlpha()
+          .SetErrorPixelsPercentageLimit(1.09f)  // 436px / (200*200)
+          .SetAbsErrorLimit(1));
+#endif
+
+  RunPixelTest(
+      background,
+      base::FilePath(FILE_PATH_LITERAL("backdrop_filter_quality_0_33.png"))
+          .InsertBeforeExtensionASCII(GetRendererSuffix()));
+}
+
+TEST_P(LayerTreeHostFiltersPixelTest, BackdropFilterQuality_1_0) {
+#if defined(MEMORY_SANITIZER)
+  if (renderer_type() == viz::RendererType::kSkiaVk) {
+    GTEST_SKIP() << "TODO(crbug.com/40839215): Uninitialized data error";
+  }
+#endif
+  scoped_refptr<SolidColorLayer> background =
+      CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE);
+
+  scoped_refptr<SolidColorLayer> green =
+      CreateSolidColorLayer(gfx::Rect(50, 50, 100, 100), kCSSGreen);
+  scoped_refptr<SolidColorLayer> blur =
+      CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorTRANSPARENT);
+  background->AddChild(green);
+  background->AddChild(blur);
+
+  FilterOperations filters;
+  filters.Append(FilterOperation::CreateBlurFilter(30.0f, SkTileMode::kClamp));
+  blur->SetBackdropFilters(filters);
+  blur->SetBackdropFilterQuality(1.0);
+
+#if BUILDFLAG(IS_WIN) || defined(ARCH_CPU_ARM64)
+  // Windows and ARM64 have 436 pixels off by 1: crbug.com/259915
+  pixel_comparator_ = std::make_unique<FuzzyPixelComparator>(
+      FuzzyPixelComparator()
+          .DiscardAlpha()
+          .SetErrorPixelsPercentageLimit(1.09f)  // 436px / (200*200)
+          .SetAbsErrorLimit(1));
+#endif
+
+  RunPixelTest(
+      background,
+      base::FilePath(FILE_PATH_LITERAL("backdrop_filter_quality_1_0.png"))
+          .InsertBeforeExtensionASCII(GetRendererSuffix()));
+}
+
 class LayerTreeHostBlurFiltersPixelTestGPULayerList
     : public LayerTreeHostFiltersPixelTest {
  public:
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index 45b0bcd2..b2f1404df 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -83,6 +83,7 @@
 #include "components/viz/common/frame_sinks/begin_frame_args.h"
 #include "components/viz/common/frame_sinks/copy_output_request.h"
 #include "components/viz/common/frame_sinks/copy_output_result.h"
+#include "components/viz/common/quads/compositor_frame.h"
 #include "components/viz/common/quads/compositor_frame_transition_directive.h"
 #include "components/viz/common/quads/compositor_render_pass_draw_quad.h"
 #include "components/viz/common/quads/draw_quad.h"
@@ -130,6 +131,30 @@
   return info;
 }
 
+// Returns the delta scale of all quads in the frame's root pass from their
+// ideal, or 0 if they are not all the same.
+float FrameQuadScaleDeltaFromIdeal(const viz::CompositorFrame& frame) {
+  float frame_scale = 0.f;
+  viz::CompositorRenderPass* root_pass = frame.render_pass_list.back().get();
+  for (auto* draw_quad : root_pass->quad_list) {
+    // Checkerboards mean an incomplete frame.
+    if (draw_quad->material != viz::DrawQuad::Material::kTiledContent) {
+      return 0.f;
+    }
+    const viz::TileDrawQuad* quad = viz::TileDrawQuad::MaterialCast(draw_quad);
+    float quad_scale =
+        quad->tex_coord_rect.width() / static_cast<float>(quad->rect.width());
+    float transform_scale = SkScalarToFloat(
+        quad->shared_quad_state->quad_to_target_transform.rc(0, 0));
+    float scale = quad_scale / transform_scale;
+    if (frame_scale != 0.f && frame_scale != scale) {
+      return 0.f;
+    }
+    frame_scale = scale;
+  }
+  return frame_scale;
+}
+
 using LayerTreeHostTest = LayerTreeTest;
 
 class LayerTreeHostTestHasImplThreadTest : public LayerTreeHostTest {
@@ -7216,65 +7241,16 @@
     client_.set_bounds(root->bounds());
   }
 
-  // Returns the delta scale of all quads in the frame's root pass from their
-  // ideal, or 0 if they are not all the same.
-  float FrameQuadScaleDeltaFromIdeal(LayerTreeHostImpl::FrameData* frame_data) {
-    if (frame_data->has_no_damage)
-      return 0.f;
-    float frame_scale = 0.f;
-    viz::CompositorRenderPass* root_pass =
-        frame_data->render_passes.back().get();
-    for (auto* draw_quad : root_pass->quad_list) {
-      // Checkerboards mean an incomplete frame.
-      if (draw_quad->material != viz::DrawQuad::Material::kTiledContent)
-        return 0.f;
-      const viz::TileDrawQuad* quad =
-          viz::TileDrawQuad::MaterialCast(draw_quad);
-      float quad_scale =
-          quad->tex_coord_rect.width() / static_cast<float>(quad->rect.width());
-      float transform_scale = SkScalarToFloat(
-          quad->shared_quad_state->quad_to_target_transform.rc(0, 0));
-      float scale = quad_scale / transform_scale;
-      if (frame_scale != 0.f && frame_scale != scale)
-        return 0.f;
-      frame_scale = scale;
-    }
-    return frame_scale;
-  }
-
   void BeginTest() override { PostSetNeedsCommitToMainThread(); }
 
   DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
                                    LayerTreeHostImpl::FrameData* frame_data,
                                    DrawResult draw_result) override {
-    float quad_scale_delta = FrameQuadScaleDeltaFromIdeal(frame_data);
+    host_impl_ = host_impl;
+    current_page_scale_factor_ =
+        host_impl->active_tree()->current_page_scale_factor();
+
     switch (frame_) {
-      case 1:
-        // Drew at page scale 1 before any pinching.
-        EXPECT_EQ(1.f, host_impl->active_tree()->current_page_scale_factor());
-        EXPECT_EQ(1.f, quad_scale_delta);
-        PostNextAfterDraw(host_impl);
-        break;
-      case 2:
-        if (quad_scale_delta != 1.f)
-          break;
-        // Drew at page scale 1.5 after pinching in.
-        EXPECT_EQ(1.5f, host_impl->active_tree()->current_page_scale_factor());
-        EXPECT_EQ(1.f, quad_scale_delta);
-        PostNextAfterDraw(host_impl);
-        break;
-      case 3:
-        // By pinching out, we will create a new tiling and raster it. This may
-        // cause some additional draws, though we should still be drawing with
-        // the old 1.5 tiling.
-        if (frame_data->has_no_damage)
-          break;
-        // Drew at page scale 1 with the 1.5 tiling while pinching out.
-        EXPECT_EQ(1.f, host_impl->active_tree()->current_page_scale_factor());
-        EXPECT_EQ(1.5f, quad_scale_delta);
-        // We don't PostNextAfterDraw here, instead we wait for the new tiling
-        // to finish rastering so we don't get any noise in further steps.
-        break;
       case 4:
         // Drew at page scale 1 with the 1.5 tiling after pinching out completed
         // while waiting for texture uploads to complete.
@@ -7286,16 +7262,52 @@
         EXPECT_TRUE(frame_data->has_no_damage);
         PostNextAfterDraw(host_impl);
         break;
+    }
+
+    return draw_result;
+  }
+
+  void DisplayReceivedCompositorFrameOnThread(
+      const viz::CompositorFrame& frame) override {
+    float quad_scale_delta = FrameQuadScaleDeltaFromIdeal(frame);
+
+    // Frame 4 should have no damage to be displayed.
+    EXPECT_NE(4, frame_);
+
+    switch (frame_) {
+      case 1:
+        // Drew at page scale 1 before any pinching.
+        EXPECT_EQ(1.f, current_page_scale_factor_);
+        EXPECT_EQ(1.f, quad_scale_delta);
+        PostNextAfterDraw(host_impl_);
+        break;
+      case 2:
+        if (quad_scale_delta != 1.f)
+          break;
+        // Drew at page scale 1.5 after pinching in.
+        EXPECT_EQ(1.5f, current_page_scale_factor_);
+        EXPECT_EQ(1.f, quad_scale_delta);
+        PostNextAfterDraw(host_impl_);
+        break;
+      case 3:
+        // Drew at page scale 1 with the 1.5 tiling while pinching out.
+        EXPECT_EQ(1.f, current_page_scale_factor_);
+        EXPECT_EQ(1.5f, quad_scale_delta);
+        // We don't PostNextAfterDraw here, instead we wait for the new tiling
+        // to finish rastering so we don't get any noise in further steps.
+        break;
+
       case 5:
         if (quad_scale_delta != 1.f)
           break;
         // Drew at scale 1 after texture uploads are done.
-        EXPECT_EQ(1.f, host_impl->active_tree()->current_page_scale_factor());
+        EXPECT_EQ(1.f, current_page_scale_factor_);
         EXPECT_EQ(1.f, quad_scale_delta);
+
+        host_impl_ = nullptr;
         EndTest();
         break;
     }
-    return draw_result;
   }
 
   void PostNextAfterDraw(LayerTreeHostImpl* host_impl) {
@@ -7361,7 +7373,9 @@
   }
 
   FakeContentLayerClient client_;
+  raw_ptr<LayerTreeHostImpl> host_impl_;
   int frame_;
+  float current_page_scale_factor_;
   bool posted_;
   base::WaitableEvent playback_allowed_event_;
 };
@@ -7486,59 +7500,42 @@
     client_.set_bounds(root->bounds());
   }
 
-  // Returns the delta scale of all quads in the frame's root pass from their
-  // ideal, or 0 if they are not all the same.
-  float FrameQuadScaleDeltaFromIdeal(LayerTreeHostImpl::FrameData* frame_data) {
-    if (frame_data->has_no_damage)
-      return 0.f;
-    float frame_scale = 0.f;
-    viz::CompositorRenderPass* root_pass =
-        frame_data->render_passes.back().get();
-    for (auto* draw_quad : root_pass->quad_list) {
-      const viz::TileDrawQuad* quad =
-          viz::TileDrawQuad::MaterialCast(draw_quad);
-      float quad_scale =
-          quad->tex_coord_rect.width() / static_cast<float>(quad->rect.width());
-      float transform_scale = SkScalarToFloat(
-          quad->shared_quad_state->quad_to_target_transform.rc(0, 0));
-      float scale = quad_scale / transform_scale;
-      if (frame_scale != 0.f && frame_scale != scale)
-        return 0.f;
-      frame_scale = scale;
-    }
-    return frame_scale;
-  }
-
   void BeginTest() override { PostSetNeedsCommitToMainThread(); }
 
   DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
                                    LayerTreeHostImpl::FrameData* frame_data,
                                    DrawResult draw_result) override {
-    float quad_scale_delta = FrameQuadScaleDeltaFromIdeal(frame_data);
+    current_page_scale_factor_ =
+        host_impl->active_tree()->current_page_scale_factor();
+    return draw_result;
+  }
+
+  void DisplayReceivedCompositorFrameOnThread(
+      const viz::CompositorFrame& frame) override {
+    float quad_scale_delta = FrameQuadScaleDeltaFromIdeal(frame);
     switch (step_) {
       case 1:
         // Drew at scale 1 before any pinching.
-        EXPECT_EQ(1.f, host_impl->active_tree()->current_page_scale_factor());
+        EXPECT_EQ(1.f, current_page_scale_factor_);
         EXPECT_EQ(1.f, quad_scale_delta);
         break;
       case 2:
         if (quad_scale_delta != 1.f / 1.5f)
           break;
         // Drew at scale 1 still though the ideal is 1.5.
-        EXPECT_EQ(1.5f, host_impl->active_tree()->current_page_scale_factor());
+        EXPECT_EQ(1.5f, current_page_scale_factor_);
         EXPECT_EQ(1.f / 1.5f, quad_scale_delta);
         break;
       case 3:
         // Continuous draws are attempted.
-        EXPECT_EQ(1.5f, host_impl->active_tree()->current_page_scale_factor());
-        if (!frame_data->has_no_damage)
-          EXPECT_EQ(1.f / 1.5f, quad_scale_delta);
+        EXPECT_EQ(1.5f, current_page_scale_factor_);
+        EXPECT_EQ(1.f / 1.5f, quad_scale_delta);
         break;
       case 4:
         if (quad_scale_delta != 1.f)
           break;
         // Drew at scale 1.5 when all the tiles completed.
-        EXPECT_EQ(1.5f, host_impl->active_tree()->current_page_scale_factor());
+        EXPECT_EQ(1.5f, current_page_scale_factor_);
         EXPECT_EQ(1.f, quad_scale_delta);
         break;
       case 5:
@@ -7552,7 +7549,6 @@
       case 7:
         NOTREACHED() << "No draws should happen once we have a complete frame.";
     }
-    return draw_result;
   }
 
   void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
@@ -7601,6 +7597,7 @@
   FakeContentLayerClient client_;
   int step_;
   int continuous_draws_;
+  float current_page_scale_factor_;
   base::WaitableEvent playback_allowed_event_;
 };
 
@@ -10796,9 +10793,9 @@
 
   void BeginTest() override { layer_tree_host()->SetNeedsCommit(); }
 
-  void WillSubmitCompositorFrame(LayerTreeHostImpl* host_impl,
-                                 const viz::CompositorFrame& frame) override {
-    switch (host_impl->active_tree()->source_frame_number()) {
+  void DisplayReceivedCompositorFrameOnThread(
+      const viz::CompositorFrame& frame) override {
+    switch (frame_) {
       case 0: {
         // First frame draws the entire tree with full damage.
         ASSERT_EQ(frame.render_pass_list.size(), 3u);
@@ -10899,6 +10896,7 @@
       default:
         break;
     }
+    ++frame_;
   }
 
  private:
@@ -10907,6 +10905,8 @@
   scoped_refptr<ViewTransitionContentLayer> view_transition_layer_;
   scoped_refptr<SolidColorLayer> layer_with_view_transition_content_;
 
+  int frame_ = 0;
+
   // All rects are in the root coordinate space.
   const gfx::Rect root_rect_ = gfx::Rect(0, 0, 50, 50);
   const gfx::Rect layer_with_view_transition_content_rect_ =
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index 4fce607..91caafb8 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -994,8 +994,10 @@
     target_tree->clear_delegated_ink_metadata();
   }
 
-  for (auto& request : TakeViewTransitionRequests())
+  for (auto& request : TakeViewTransitionRequests(
+           /*should_set_needs_update_draw_properties=*/true)) {
     target_tree->AddViewTransitionRequest(std::move(request));
+  }
 
   // Make sure that property tree based changes are moved to layers
   // and draw properties are invalidated.
@@ -3036,8 +3038,9 @@
 }
 
 std::vector<std::unique_ptr<ViewTransitionRequest>>
-LayerTreeImpl::TakeViewTransitionRequests() {
-  if (HasViewTransitionRequests()) {
+LayerTreeImpl::TakeViewTransitionRequests(
+    bool should_set_needs_update_draw_properties) {
+  if (HasViewTransitionRequests() && should_set_needs_update_draw_properties) {
     set_needs_update_draw_properties();
   }
   return std::move(view_transition_requests_);
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h
index 4b14fcf..1c9a812 100644
--- a/cc/trees/layer_tree_impl.h
+++ b/cc/trees/layer_tree_impl.h
@@ -793,7 +793,7 @@
   // Returns all of the view transition requests stored so far, and empties
   // the internal list.
   std::vector<std::unique_ptr<ViewTransitionRequest>>
-  TakeViewTransitionRequests();
+  TakeViewTransitionRequests(bool should_set_needs_update_draw_properties);
 
   // Returns true if there are pending ViewTransition requests that need a draw.
   bool HasViewTransitionRequests() const;
diff --git a/cc/view_transition/view_transition_request.h b/cc/view_transition/view_transition_request.h
index cfcaad4f..d6adeec 100644
--- a/cc/view_transition/view_transition_request.h
+++ b/cc/view_transition/view_transition_request.h
@@ -77,13 +77,23 @@
 
   // Returns the sequence id for this request.
   uint32_t sequence_id() const { return sequence_id_; }
+  // This is only called on the viz side where the request is constructed from
+  // mojo wire and the sequence id is originally created on the renderer side.
+  void set_sequence_id(uint32_t id) { sequence_id_ = id; }
 
   Type type() const { return type_; }
 
   // Testing / debugging functionality.
   std::string ToString() const;
 
-  const blink::ViewTransitionToken& token() { return transition_token_; }
+  const blink::ViewTransitionToken& token() const { return transition_token_; }
+
+  bool maybe_cross_frame_sink() const { return maybe_cross_frame_sink_; }
+
+  const std::vector<viz::ViewTransitionElementResourceId>&
+  capture_resource_ids() const {
+    return capture_resource_ids_;
+  }
 
  private:
   ViewTransitionRequest(
@@ -97,7 +107,7 @@
   const blink::ViewTransitionToken transition_token_;
   const bool maybe_cross_frame_sink_;
   ViewTransitionCaptureCallback commit_callback_;
-  const uint32_t sequence_id_;
+  uint32_t sequence_id_;
   const std::vector<viz::ViewTransitionElementResourceId> capture_resource_ids_;
 
   static uint32_t s_next_sequence_id_;
diff --git a/chrome/VERSION b/chrome/VERSION
index deba1809..60d51fc 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=137
 MINOR=0
-BUILD=7107
+BUILD=7108
 PATCH=0
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java
index 2b30096..8a0dbcad 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java
@@ -1246,9 +1246,6 @@
     @Override
     public @Nullable CancelLongPressTabItemEventListener onLongPressEvent(
             int tabId, @Nullable View cardView) {
-        if (setupAndShowTabListEditor(tabId)) {
-            RecordUserAction.record("TabMultiSelectV2.OpenLongPressInDialog");
-        }
         return null;
     }
 
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupVisualDataDialogManager.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupVisualDataDialogManager.java
index 9cc0c21..b743d55 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupVisualDataDialogManager.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupVisualDataDialogManager.java
@@ -21,7 +21,6 @@
 import org.chromium.base.Token;
 import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
-import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.sync.SyncServiceFactory;
 import org.chromium.chrome.browser.tab.Tab;
@@ -239,7 +238,6 @@
             // TabGroupPane flags are enabled.
             if (!tabModel.isIncognitoBranded()
                     && TabGroupSyncFeatures.isTabGroupSyncEnabled(profile)
-                    && ChromeFeatureList.sTabGroupPaneAndroid.isEnabled()
                     && tracker.shouldTriggerHelpUi(
                             FeatureConstants.TAB_GROUP_CREATION_DIALOG_SYNC_TEXT_FEATURE)) {
                 mTracker = tracker;
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
index 4840c55..2c47846 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
@@ -54,7 +54,6 @@
 import org.chromium.chrome.browser.collaboration.CollaborationServiceFactory;
 import org.chromium.chrome.browser.data_sharing.DataSharingServiceFactory;
 import org.chromium.chrome.browser.data_sharing.DataSharingTabManager;
-import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
 import org.chromium.chrome.browser.preferences.ChromeSharedPreferences;
 import org.chromium.chrome.browser.price_tracking.PriceTrackingFeatures;
@@ -1750,7 +1749,7 @@
         // A tab is deemed a tab group card representation if it is part of a tab group and
         // based in the tab switcher.
         boolean isTabGroup = isTabInTabGroup(tab) && mActionsOnAllRelatedTabs;
-        if (ChromeFeatureList.sTabGroupPaneAndroid.isEnabled() && isTabGroup) {
+        if (isTabGroup) {
             return new TabActionButtonData(
                     TabActionButtonData.TabActionButtonType.OVERFLOW,
                     getTabGroupOverflowMenuClickListener());
@@ -2702,41 +2701,22 @@
         String colorDesc = mActivity.getResources().getString(colorDescRes);
         return (context) -> {
             Resources res = context.getResources();
-            if (ChromeFeatureList.sTabGroupPaneAndroid.isEnabled()) {
-                String descriptionTitle = title;
-                if (TextUtils.isEmpty(descriptionTitle)) {
-                    descriptionTitle =
-                            TabGroupTitleUtils.getDefaultTitle(mActivity, numOfRelatedTabs);
-                }
-                if (!TabUiUtils.isDataSharingFunctionalityEnabled() || !hasCollaboration(tab)) {
-                    return res.getString(
-                            R.string
-                                    .accessibility_open_tab_group_overflow_menu_with_group_name_with_color,
-                            descriptionTitle,
-                            colorDesc);
-                } else {
-                    return res.getString(
-                            R.string
-                                    .accessibility_open_shared_tab_group_overflow_menu_with_group_name_with_color,
-                            descriptionTitle,
-                            colorDesc);
-                }
+            String descriptionTitle = title;
+            if (TextUtils.isEmpty(descriptionTitle)) {
+                descriptionTitle = TabGroupTitleUtils.getDefaultTitle(mActivity, numOfRelatedTabs);
+            }
+            if (!TabUiUtils.isDataSharingFunctionalityEnabled() || !hasCollaboration(tab)) {
+                return res.getString(
+                        R.string
+                                .accessibility_open_tab_group_overflow_menu_with_group_name_with_color,
+                        descriptionTitle,
+                        colorDesc);
             } else {
-                if (TextUtils.isEmpty(title)) {
-                    return res.getQuantityString(
-                            R.plurals.accessibility_close_tab_group_button_with_color,
-                            numOfRelatedTabs,
-                            numOfRelatedTabs,
-                            colorDesc);
-                } else {
-                    return res.getQuantityString(
-                            R.plurals
-                                    .accessibility_close_tab_group_button_with_group_name_with_color,
-                            numOfRelatedTabs,
-                            title,
-                            numOfRelatedTabs,
-                            colorDesc);
-                }
+                return res.getString(
+                        R.string
+                                .accessibility_open_shared_tab_group_overflow_menu_with_group_name_with_color,
+                        descriptionTitle,
+                        colorDesc);
             }
         };
     }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiFeatureUtilities.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiFeatureUtilities.java
index 70e3e2d..b0530821 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiFeatureUtilities.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiFeatureUtilities.java
@@ -33,11 +33,6 @@
         return XrUtils.isXrDevice();
     }
 
-    /** Returns if the tab group pane should be displayed in the hub. */
-    public static boolean isTabGroupPaneEnabled() {
-        return ChromeFeatureList.sTabGroupPaneAndroid.isEnabled();
-    }
-
     /** Returns whether drag drop from tab strip to create new instance is enabled. */
     public static boolean isTabDragToCreateInstanceSupported() {
         // TODO(crbug/328511660): Add OS version check once available.
diff --git a/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings.grd b/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings.grd
index f1ecc12..27886dd9 100644
--- a/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings.grd
+++ b/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings.grd
@@ -663,18 +663,6 @@
           other {Expand shared <ph name="TITLE_OF_GROUP">%1$s<ex>Shopping cart</ex></ph> tab group with <ph name="TABS_COUNT_MANY">%2$d<ex>2</ex></ph> tabs, color <ph name="COLOR_NAME">%3$s<ex>Blue</ex></ph>.}
         }
       </message>
-      <message name="IDS_ACCESSIBILITY_CLOSE_TAB_GROUP_BUTTON_WITH_COLOR" desc="The accessibility text to read when the close button on a card representing a tab group is focused in grid tab switcher. When this close button is tapped, all tabs within the tab group will be closed. NUMBER_OF_TABS is the number of tabs within this group. COLOR_NAME is the color of this group.">
-        {NUMBER_OF_TABS, plural,
-          =1 {Close tab group with <ph name="TABS_COUNT_ONE">%1$d<ex>1</ex></ph> tab, color <ph name="COLOR_NAME">%2$s<ex>Blue</ex></ph>.}
-          other {Close tab group with <ph name="TABS_COUNT_MANY">%1$d<ex>2</ex></ph> tabs, color <ph name="COLOR_NAME">%2$s<ex>Blue</ex></ph>.}
-        }
-      </message>
-      <message name="IDS_ACCESSIBILITY_CLOSE_TAB_GROUP_BUTTON_WITH_GROUP_NAME_WITH_COLOR" desc="The accessibility text to read when the close button on a card representing a tab group is focused in grid tab switcher. When this close button is tapped, all tabs within the tab group will be closed. TITLE_OF_GROUP is the title of the group. NUMBER_OF_TABS is the number of tabs within this group. COLOR_NAME is the color of this group.">
-        {NUMBER_OF_TABS, plural,
-          =1 {Close <ph name="TITLE_OF_GROUP">%1$s<ex>shopping</ex></ph> group with <ph name="TABS_COUNT_ONE">%2$d<ex>1</ex></ph> tab, color <ph name="COLOR_NAME">%3$s<ex>Blue</ex></ph>.}
-          other {Close <ph name="TITLE_OF_GROUP">%1$s<ex>shopping</ex></ph> group with <ph name="TABS_COUNT_MANY">%2$d<ex>2</ex></ph> tabs, color <ph name="COLOR_NAME">%3$s<ex>Blue</ex></ph>.}
-        }
-      </message>
       <message name="IDS_TAB_GROUP_CREATION_DIALOG_DESCRIPTION_TEXT_SYNC_ON" desc="A subtitle on the dialog for new tab group creations. Explains the group automatically saves and updates across all devices.">
         Your tab groups automatically save and update across all your signed-in devices
       </message>
diff --git a/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings_grd/IDS_ACCESSIBILITY_CLOSE_TAB_GROUP_BUTTON_WITH_COLOR.png.sha1 b/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings_grd/IDS_ACCESSIBILITY_CLOSE_TAB_GROUP_BUTTON_WITH_COLOR.png.sha1
deleted file mode 100644
index 5f3128bb..0000000
--- a/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings_grd/IDS_ACCESSIBILITY_CLOSE_TAB_GROUP_BUTTON_WITH_COLOR.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-7329e69909cac18e8daa6ef9f4991e3412b6c98b
\ No newline at end of file
diff --git a/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings_grd/IDS_ACCESSIBILITY_CLOSE_TAB_GROUP_BUTTON_WITH_GROUP_NAME_WITH_COLOR.png.sha1 b/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings_grd/IDS_ACCESSIBILITY_CLOSE_TAB_GROUP_BUTTON_WITH_GROUP_NAME_WITH_COLOR.png.sha1
deleted file mode 100644
index 5f3128bb..0000000
--- a/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings_grd/IDS_ACCESSIBILITY_CLOSE_TAB_GROUP_BUTTON_WITH_GROUP_NAME_WITH_COLOR.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-7329e69909cac18e8daa6ef9f4991e3412b6c98b
\ No newline at end of file
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java
index 598592a..a78013f 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java
@@ -45,7 +45,6 @@
 
 import static org.chromium.chrome.browser.flags.ChromeFeatureList.DATA_SHARING;
 import static org.chromium.chrome.browser.flags.ChromeFeatureList.NAV_BAR_COLOR_MATCHES_TAB_BACKGROUND;
-import static org.chromium.chrome.browser.flags.ChromeFeatureList.TAB_GROUP_PANE_ANDROID;
 import static org.chromium.chrome.browser.flags.ChromeFeatureList.TAB_GROUP_SYNC_ANDROID;
 import static org.chromium.chrome.browser.ntp.HomeSurfaceTestUtils.createTabStatesAndMetadataFile;
 import static org.chromium.chrome.browser.ntp.HomeSurfaceTestUtils.createThumbnailBitmapAndWriteToFile;
@@ -1109,7 +1108,6 @@
     @Test
     @MediumTest
     @RequiresRestart("crbug.com/344674734")
-    @EnableFeatures({TAB_GROUP_SYNC_ANDROID, TAB_GROUP_PANE_ANDROID})
     public void testDialogSelectionEditor_UngroupAll() {
         final ChromeTabbedActivity cta = sActivityTestRule.getActivity();
         createTabs(cta, false, 4);
@@ -1143,7 +1141,7 @@
 
     @Test
     @MediumTest
-    @EnableFeatures({TAB_GROUP_SYNC_ANDROID, TAB_GROUP_PANE_ANDROID})
+    @EnableFeatures({TAB_GROUP_SYNC_ANDROID})
     @DisableIf.Build(
             sdk_is_less_than = Build.VERSION_CODES.TIRAMISU,
             supported_abis_includes = "x86_64",
@@ -1746,7 +1744,7 @@
     @Test
     @MediumTest
     @DisableIf.Device(DeviceFormFactor.TABLET)
-    @EnableFeatures({TAB_GROUP_SYNC_ANDROID, TAB_GROUP_PANE_ANDROID})
+    @EnableFeatures({TAB_GROUP_SYNC_ANDROID})
     public void testStripDialog_TabListEditorCloseAll_NoCustomHomepage() {
         ChromeTabbedActivity cta = sActivityTestRule.getActivity();
         // Create a tab group with 2 tabs.
@@ -1794,7 +1792,7 @@
     @Test
     @MediumTest
     @DisableIf.Device(DeviceFormFactor.TABLET)
-    @EnableFeatures({TAB_GROUP_SYNC_ANDROID, TAB_GROUP_PANE_ANDROID})
+    @EnableFeatures({TAB_GROUP_SYNC_ANDROID})
     public void testStripDialog_TabListEditorCloseAll_CustomHomepage() {
         GURL url =
                 new GURL(
@@ -1945,7 +1943,7 @@
     @Test
     @MediumTest
     @Feature({"RenderTest"})
-    @EnableFeatures({TAB_GROUP_SYNC_ANDROID, TAB_GROUP_PANE_ANDROID})
+    @EnableFeatures({TAB_GROUP_SYNC_ANDROID})
     @RequiresRestart("Group creation modal dialog is sometimes persistent when dismissing")
     @ParameterAnnotations.UseMethodParameter(NightModeTestUtils.NightModeParams.class)
     @DisabledTest(message = "crbug.com/362762206, see also crbug.com/360072870")
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherLayoutTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherLayoutTest.java
index b950a97..67c48a5 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherLayoutTest.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherLayoutTest.java
@@ -315,61 +315,6 @@
         verifyTabModelTabCount(cta, 0, 0);
     }
 
-    @Test
-    @MediumTest
-    @DisableFeatures(ChromeFeatureList.TAB_GROUP_PANE_ANDROID)
-    public void testCloseButtonDescription() {
-        String expectedDescription = "Close New tab tab";
-        ChromeTabbedActivity cta = mActivityTestRule.getActivity();
-        enterTabSwitcher(cta);
-
-        // Test single tab.
-        onView(
-                        allOf(
-                                withParent(withId(R.id.content_view)),
-                                withId(R.id.action_button),
-                                withEffectiveVisibility(VISIBLE)))
-                .check(ViewContentDescription.havingDescription(expectedDescription));
-
-        // Create 2 tabs and merge them into one group.
-        createTabs(cta, false, 2);
-        enterTabSwitcher(cta);
-        TabModel normalTabModel = cta.getTabModelSelector().getModel(false);
-        List<Tab> tabGroup =
-                new ArrayList<>(
-                        Arrays.asList(normalTabModel.getTabAt(0), normalTabModel.getTabAt(1)));
-        createTabGroup(cta, false, tabGroup);
-        verifyTabSwitcherCardCount(cta, 1);
-
-        // Test group tab.
-        expectedDescription = "Close tab group with 2 tabs, color Grey.";
-        onView(
-                        allOf(
-                                withParent(withId(R.id.content_view)),
-                                withId(R.id.action_button),
-                                withEffectiveVisibility(VISIBLE)))
-                .check(ViewContentDescription.havingDescription(expectedDescription));
-    }
-
-    private static class ViewContentDescription implements ViewAssertion {
-        private String mExpectedDescription;
-
-        public static ViewContentDescription havingDescription(String description) {
-            return new ViewContentDescription(description);
-        }
-
-        public ViewContentDescription(String description) {
-            mExpectedDescription = description;
-        }
-
-        @Override
-        public void check(View view, NoMatchingViewException noMatchException) {
-            if (noMatchException != null) throw noMatchException;
-
-            assertEquals(mExpectedDescription, view.getContentDescription());
-        }
-    }
-
     private static class ThumbnailAspectRatioAssertion implements ViewAssertion {
         private double mExpectedRatio;
 
@@ -514,7 +459,6 @@
 
     @Test
     @MediumTest
-    @EnableFeatures({ChromeFeatureList.TAB_GROUP_PANE_ANDROID})
     @DisabledTest(message = "crbug.com/360393681")
     public void testTabGroupOverflowMenuInTabSwitcher_renameGroupAccept() {
         final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
@@ -568,7 +512,6 @@
 
     @Test
     @MediumTest
-    @EnableFeatures({ChromeFeatureList.TAB_GROUP_PANE_ANDROID})
     @DisabledTest(message = "crbug.com/360393681")
     public void testTabGroupOverflowMenuInTabSwitcher_renameGroupDecline() {
         final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
@@ -623,7 +566,6 @@
     @Test
     @MediumTest
     @EnableFeatures({
-        ChromeFeatureList.TAB_GROUP_PANE_ANDROID,
         ChromeFeatureList.TAB_GROUP_SYNC_ANDROID,
     })
     @DisabledTest(message = "crbug.com/360393681")
@@ -658,7 +600,6 @@
 
     @Test
     @MediumTest
-    @EnableFeatures({ChromeFeatureList.TAB_GROUP_PANE_ANDROID})
     @DisabledTest(message = "crbug.com/353946452")
     public void testTabGroupOverflowMenuInTabSwitcher_ungroupDecline() {
         final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
@@ -691,7 +632,6 @@
 
     @Test
     @MediumTest
-    @EnableFeatures({ChromeFeatureList.TAB_GROUP_PANE_ANDROID})
     @DisabledTest(message = "Flaky - crbug.com/353463207")
     public void testTabGroupOverflowMenuInTabSwitcher_ungroupDoNotShowAgain() {
         final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
@@ -739,7 +679,6 @@
     @Test
     @MediumTest
     @EnableFeatures({
-        ChromeFeatureList.TAB_GROUP_PANE_ANDROID,
         ChromeFeatureList.TAB_GROUP_SYNC_ANDROID,
     })
     @DisabledTest(message = "Flaky - crbug.com/353463207")
@@ -775,7 +714,6 @@
     @Test
     @MediumTest
     @EnableFeatures({
-        ChromeFeatureList.TAB_GROUP_PANE_ANDROID,
         ChromeFeatureList.TAB_GROUP_SYNC_ANDROID,
     })
     @DisabledTest(message = "crbug.com/360393681")
@@ -816,7 +754,6 @@
     @Test
     @MediumTest
     @EnableFeatures({
-        ChromeFeatureList.TAB_GROUP_PANE_ANDROID,
         ChromeFeatureList.TAB_GROUP_SYNC_ANDROID,
     })
     @DisabledTest(message = "crbug.com/353463207")
@@ -852,7 +789,6 @@
     @Test
     @MediumTest
     @EnableFeatures({
-        ChromeFeatureList.TAB_GROUP_PANE_ANDROID,
         ChromeFeatureList.TAB_GROUP_SYNC_ANDROID,
     })
     @DisabledTest(message = "crbug.com/360393681")
@@ -933,9 +869,6 @@
 
     @Test
     @MediumTest
-    @EnableFeatures({
-        ChromeFeatureList.TAB_GROUP_PANE_ANDROID,
-    })
     @DisableFeatures({
         ChromeFeatureList.TAB_GROUP_SYNC_ANDROID,
     })
@@ -952,7 +885,6 @@
 
     @Test
     @MediumTest
-    @EnableFeatures({ChromeFeatureList.TAB_GROUP_PANE_ANDROID})
     @DisableFeatures({
         ChromeFeatureList.TAB_GROUP_SYNC_ANDROID,
     })
@@ -1034,7 +966,6 @@
 
     @Test
     @MediumTest
-    @EnableFeatures({ChromeFeatureList.TAB_GROUP_PANE_ANDROID})
     public void testGroupMerge_UndoBarGoneAfterManualUngroup() {
         final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
         createTabs(cta, false, 3);
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 6bf7bfd..68097e1b 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
@@ -65,7 +65,6 @@
 import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.compositor.layouts.Layout;
 import org.chromium.chrome.browser.compositor.layouts.LayoutManagerChrome;
-import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.hub.HubLayout;
 import org.chromium.chrome.browser.layouts.LayoutStateProvider.LayoutStateObserver;
 import org.chromium.chrome.browser.layouts.LayoutTestUtils;
@@ -281,9 +280,7 @@
      */
     public static void closeFirstTabGroupInTabSwitcher(Context context) {
         closeFirstTabInTabSwitcher(context);
-        if (ChromeFeatureList.sTabGroupPaneAndroid.isEnabled()) {
-            onView(withText("Close")).perform(click());
-        }
+        onView(withText("Close")).perform(click());
     }
 
     /**
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupVisualDataDialogManagerUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupVisualDataDialogManagerUnitTest.java
index 2982163..c65b27e 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupVisualDataDialogManagerUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupVisualDataDialogManagerUnitTest.java
@@ -99,10 +99,7 @@
     }
 
     @Test
-    @EnableFeatures({
-        ChromeFeatureList.TAB_GROUP_PANE_ANDROID,
-        ChromeFeatureList.TAB_GROUP_SYNC_ANDROID
-    })
+    @EnableFeatures({ChromeFeatureList.TAB_GROUP_SYNC_ANDROID})
     public void testVisualDataDialogDelegate_showDialog() {
         mTabGroupVisualDataDialogManager.showDialog(
                 TAB_GROUP_ID, mTabGroupModelFilter, mDialogController);
@@ -124,10 +121,7 @@
     }
 
     @Test
-    @EnableFeatures({
-        ChromeFeatureList.TAB_GROUP_PANE_ANDROID,
-        ChromeFeatureList.TAB_GROUP_SYNC_ANDROID
-    })
+    @EnableFeatures({ChromeFeatureList.TAB_GROUP_SYNC_ANDROID})
     public void testVisualDataDialogDelegate_doubleShowDismissed() {
         // Mock a double trigger for the creation dialog observer method for the same group action,
         // but show dialog is only called once.
@@ -140,10 +134,7 @@
     }
 
     @Test
-    @EnableFeatures({
-        ChromeFeatureList.TAB_GROUP_PANE_ANDROID,
-        ChromeFeatureList.TAB_GROUP_SYNC_ANDROID
-    })
+    @EnableFeatures({ChromeFeatureList.TAB_GROUP_SYNC_ANDROID})
     public void testVisualDataDialog_descriptionTextNotSet() {
         // Set the opposite values for the conditional statement to be true.
         doReturn(true).when(mTabModel).isIncognitoBranded();
@@ -167,10 +158,7 @@
     }
 
     @Test
-    @EnableFeatures({
-        ChromeFeatureList.TAB_GROUP_PANE_ANDROID,
-        ChromeFeatureList.TAB_GROUP_SYNC_ANDROID
-    })
+    @EnableFeatures({ChromeFeatureList.TAB_GROUP_SYNC_ANDROID})
     public void testVisualDataDialog_descriptionTextSetButNotSyncing() {
         doReturn(false).when(mTabModel).isIncognitoBranded();
         doReturn(true)
@@ -199,10 +187,7 @@
     }
 
     @Test
-    @EnableFeatures({
-        ChromeFeatureList.TAB_GROUP_PANE_ANDROID,
-        ChromeFeatureList.TAB_GROUP_SYNC_ANDROID
-    })
+    @EnableFeatures({ChromeFeatureList.TAB_GROUP_SYNC_ANDROID})
     public void testVisualDataDialog_descriptionTextSetAndSyncing() {
         doReturn(false).when(mTabModel).isIncognitoBranded();
         doReturn(true)
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
index 0687f8f..68c8be5b 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
@@ -3787,129 +3787,6 @@
     }
 
     @Test
-    @DisableFeatures({ChromeFeatureList.TAB_GROUP_PANE_ANDROID})
-    public void testCloseButtonDescriptionStringSetup_TabSwitcher() {
-        setUpCloseButtonDescriptionString(false);
-        String targetString = "Close Tab1 tab";
-
-        List<Tab> tabs = new ArrayList<>();
-        for (int i = 0; i < mTabModel.getCount(); i++) {
-            tabs.add(mTabModel.getTabAt(i));
-        }
-
-        mMediator.resetWithListOfTabs(tabs, false);
-        assertThat(
-                mModelList
-                        .get(POSITION1)
-                        .model
-                        .get(TabProperties.ACTION_BUTTON_DESCRIPTION_TEXT_RESOLVER)
-                        .resolve(mContext),
-                equalTo(targetString));
-
-        // Create tab group.
-        Tab tab3 = prepareTab(TAB3_ID, TAB3_TITLE, TAB3_URL);
-        List<Tab> group1 = new ArrayList<>(Arrays.asList(mTab1, tab3));
-        createTabGroup(group1, TAB1_ID, TAB_GROUP_ID);
-        setUpCloseButtonDescriptionString(true);
-        targetString = "Close tab group with 2 tabs, color Grey.";
-
-        mMediator.resetWithListOfTabs(tabs, false);
-        assertThat(
-                mModelList
-                        .get(POSITION1)
-                        .model
-                        .get(TabProperties.ACTION_BUTTON_DESCRIPTION_TEXT_RESOLVER)
-                        .resolve(mContext),
-                equalTo(targetString));
-
-        // Set group name.
-        targetString =
-                String.format("Close %s group with 2 tabs, color Grey.", CUSTOMIZED_DIALOG_TITLE1);
-        mTabGroupModelFilter.setTabGroupTitle(TAB1_ID, CUSTOMIZED_DIALOG_TITLE1);
-        mTabGroupModelFilterObserverCaptor
-                .getValue()
-                .didChangeTabGroupTitle(TAB1_ID, CUSTOMIZED_DIALOG_TITLE1);
-        assertThat(
-                mModelList
-                        .get(POSITION1)
-                        .model
-                        .get(TabProperties.ACTION_BUTTON_DESCRIPTION_TEXT_RESOLVER)
-                        .resolve(mContext),
-                equalTo(targetString));
-    }
-
-    @Test
-    @DisableFeatures({ChromeFeatureList.TAB_GROUP_PANE_ANDROID})
-    public void testCloseButtonDescriptionStringSetup_SingleTabGroup_TabSwitcher() {
-        // Create tab group.
-        List<Tab> tabs = Arrays.asList(mTab1);
-        createTabGroup(tabs, TAB1_ID, TAB_GROUP_ID);
-        setUpCloseButtonDescriptionString(true);
-        String targetString = "Close tab group with 1 tab, color Grey.";
-
-        mMediator.resetWithListOfTabs(tabs, false);
-        assertThat(
-                mModelList
-                        .get(POSITION1)
-                        .model
-                        .get(TabProperties.ACTION_BUTTON_DESCRIPTION_TEXT_RESOLVER)
-                        .resolve(mContext),
-                equalTo(targetString));
-
-        // Set group name.
-        targetString =
-                String.format("Close %s group with 1 tab, color Grey.", CUSTOMIZED_DIALOG_TITLE1);
-        mTabGroupModelFilter.setTabGroupTitle(TAB1_ID, CUSTOMIZED_DIALOG_TITLE1);
-        mTabGroupModelFilterObserverCaptor
-                .getValue()
-                .didChangeTabGroupTitle(TAB1_ID, CUSTOMIZED_DIALOG_TITLE1);
-        assertThat(
-                mModelList
-                        .get(POSITION1)
-                        .model
-                        .get(TabProperties.ACTION_BUTTON_DESCRIPTION_TEXT_RESOLVER)
-                        .resolve(mContext),
-                equalTo(targetString));
-    }
-
-    @Test
-    @DisableFeatures({ChromeFeatureList.TAB_GROUP_PANE_ANDROID})
-    public void testCloseButtonDescriptionStringWithColorSetup_TabSwitcher() {
-        // Create tab group.
-        Tab tab3 = prepareTab(TAB3_ID, TAB3_TITLE, TAB3_URL);
-        List<Tab> group1 = new ArrayList<>(Arrays.asList(mTab1, tab3));
-        createTabGroup(group1, TAB1_ID, TAB_GROUP_ID);
-        String targetString = "Close tab group with 2 tabs, color Grey.";
-
-        mMediator.resetWithListOfTabs(group1, false);
-        assertThat(
-                mModelList
-                        .get(POSITION1)
-                        .model
-                        .get(TabProperties.ACTION_BUTTON_DESCRIPTION_TEXT_RESOLVER)
-                        .resolve(mContext),
-                equalTo(targetString));
-
-        // Set group name.
-        targetString =
-                String.format("Close %s group with 2 tabs, color Grey.", CUSTOMIZED_DIALOG_TITLE1);
-        mTabGroupModelFilter.setTabGroupTitle(TAB1_ID, CUSTOMIZED_DIALOG_TITLE1);
-        mTabGroupModelFilterObserverCaptor
-                .getValue()
-                .didChangeTabGroupTitle(TAB1_ID, CUSTOMIZED_DIALOG_TITLE1);
-        assertThat(
-                mModelList
-                        .get(POSITION1)
-                        .model
-                        .get(TabProperties.ACTION_BUTTON_DESCRIPTION_TEXT_RESOLVER)
-                        .resolve(mContext),
-                equalTo(targetString));
-    }
-
-    @Test
-    @EnableFeatures({
-        ChromeFeatureList.TAB_GROUP_PANE_ANDROID,
-    })
     public void testActionButtonDescriptionStringGroupOverflowMenu_TabSwitcher() {
         // Create tab group.
         Tab tab3 = prepareTab(TAB3_ID, TAB3_TITLE, TAB3_URL);
@@ -3951,7 +3828,7 @@
     }
 
     @Test
-    @EnableFeatures({ChromeFeatureList.TAB_GROUP_PANE_ANDROID, ChromeFeatureList.DATA_SHARING})
+    @EnableFeatures({ChromeFeatureList.DATA_SHARING})
     public void testActionButtonDescriptionStringGroupOverflowMenu_TabSwitcherSharedGroup() {
         when(mProfile.isOffTheRecord()).thenReturn(false);
         when(mTabGroupSyncFeaturesJniMock.isTabGroupSyncEnabled(mProfile)).thenReturn(true);
@@ -4303,7 +4180,7 @@
     }
 
     @Test
-    @EnableFeatures({ChromeFeatureList.TAB_GROUP_PANE_ANDROID, ChromeFeatureList.DATA_SHARING})
+    @EnableFeatures({ChromeFeatureList.DATA_SHARING})
     public void testIsTabGroup_TabSwitcher() {
         mMediator.setComponentNameForTesting(TabSwitcherPaneCoordinator.COMPONENT_NAME);
 
@@ -4766,35 +4643,6 @@
         XrUtils.resetXrDeviceForTesting();
     }
 
-    private void setUpCloseButtonDescriptionString(boolean isGroup) {
-        if (isGroup) {
-            doAnswer(
-                            invocation -> {
-                                String title = invocation.getArgument(1);
-                                String num = invocation.getArgument(2);
-                                return String.format("Close %s group with %s tabs", title, num);
-                            })
-                    .when(mActivity)
-                    .getString(anyInt(), anyString(), anyString());
-
-            doAnswer(
-                            invocation -> {
-                                String num = invocation.getArgument(1);
-                                return String.format("Close tab group with %s tabs", num);
-                            })
-                    .when(mActivity)
-                    .getString(anyInt(), anyString());
-        } else {
-            doAnswer(
-                            invocation -> {
-                                String title = invocation.getArgument(1);
-                                return String.format("Close %s tab", title);
-                            })
-                    .when(mActivity)
-                    .getString(anyInt(), anyString());
-        }
-    }
-
     private void setUpTabGroupCardDescriptionString() {
         doAnswer(
                         invocation -> {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index 5671f7a..779d6b4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -168,6 +168,7 @@
 import org.chromium.chrome.browser.ntp.NewTabPageUma;
 import org.chromium.chrome.browser.ntp.NewTabPageUtils;
 import org.chromium.chrome.browser.ntp_customization.NtpCustomizationCoordinator;
+import org.chromium.chrome.browser.ntp_customization.NtpCustomizationMetricsUtils;
 import org.chromium.chrome.browser.offlinepages.OfflinePageUtils;
 import org.chromium.chrome.browser.omnibox.OmniboxFocusReason;
 import org.chromium.chrome.browser.paint_preview.StartupPaintPreviewHelper;
@@ -938,10 +939,8 @@
         builder.registerPane(
                 PaneId.INCOGNITO_TAB_SWITCHER,
                 LazyOneshotSupplier.fromSupplier(() -> createTabSwitcherPane(true)));
-        if (TabUiFeatureUtilities.isTabGroupPaneEnabled()) {
-            builder.registerPane(
-                    PaneId.TAB_GROUPS, LazyOneshotSupplier.fromSupplier(this::createTabGroupsPane));
-        }
+        builder.registerPane(
+                PaneId.TAB_GROUPS, LazyOneshotSupplier.fromSupplier(this::createTabGroupsPane));
         if (ChromeFeatureList.sCrossDeviceTabPaneAndroid.isEnabled()) {
             builder.registerPane(
                     PaneId.CROSS_DEVICE,
@@ -1611,11 +1610,27 @@
                             intent);
             tabs.add(tab);
         }
+
+        // Dragging a collapsed tab group to a new window can result in a window with a single
+        // collapsed group and no tab in foreground. To prevent this, we skip applying the
+        // collapsed state and select the first tab in the dropped group instead.
+        TabModel tabModel = getCurrentTabModel();
+        Tab selectedTab = TabModelUtils.getCurrentTab(tabModel);
+        if (selectedTab == null) {
+            TabModelUtils.setIndex(tabModel, /* index= */ 0);
+        }
+
+        // 4. Regroup tabs and restore the original group properties(e.g. color, title, collapsed
+        // state).
         TabGroupModelFilter tabGroupModelFilter =
                 mTabModelSelector
                         .getTabGroupModelFilterProvider()
                         .getTabGroupModelFilter(tabGroupMetadata.isIncognito);
-        TabGroupUtils.regroupTabs(tabGroupModelFilter, tabs, tabGroupMetadata);
+        TabGroupUtils.regroupTabs(
+                tabGroupModelFilter,
+                tabs,
+                tabGroupMetadata,
+                /* shouldApplyCollapse= */ selectedTab != null);
         return true;
     }
 
@@ -3292,8 +3307,14 @@
             mTabModelSelector.selectModel(false);
             RecordUserAction.record("MobileMenuSwitchOutOfIncognito");
         } else if (id == R.id.ntp_customization_id) {
-            new NtpCustomizationCoordinator(this, mRootUiCoordinator.getBottomSheetController())
+            new NtpCustomizationCoordinator(
+                            this,
+                            mRootUiCoordinator.getBottomSheetController(),
+                            getProfileProviderSupplier())
                     .showBottomSheet();
+            NtpCustomizationMetricsUtils.recordOpenBottomSheetEntry(
+                    NtpCustomizationCoordinator.EntryPointType.MAIN_MENU);
+            RecordUserAction.record("MobileMenuNtpCustomization");
         } else if (id == R.id.toggle_bookmark_bar) {
             BookmarkBarUtils.toggleSettingEnabled(this, getProfileProviderSupplier());
         } else {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/mostvisited/CustomLinkOperations.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/mostvisited/CustomLinkOperations.java
index cab46dc..e6febee 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/mostvisited/CustomLinkOperations.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/mostvisited/CustomLinkOperations.java
@@ -8,7 +8,7 @@
 import org.chromium.build.annotations.Nullable;
 import org.chromium.url.GURL;
 
-/** Methods to change and query custom links that exist alongside Most Visited links. */
+/** Methods to access Custom Links, which may exist alongside Most Visited links. */
 @NullMarked
 public interface CustomLinkOperations {
     /**
@@ -42,10 +42,10 @@
     boolean deleteCustomLink(GURL keyUrl);
 
     /**
-     * Queries the existence of a custom link identified by {@param keyUrl}.
+     * Tests the existence of a custom link identified by {@param keyUrl}.
      *
-     * @param keyUrl The URL of an existing custom tile to query.
+     * @param keyUrl The URL to search.
      * @return Whether a custom link identified by {@param keyUrl} exists.
      */
-    boolean queryCustomLink(GURL keyUrl);
+    boolean hasCustomLink(GURL keyUrl);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesBridge.java
index 27122fa5..fc9956c8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/mostvisited/MostVisitedSitesBridge.java
@@ -66,10 +66,9 @@
     }
 
     @Override
-    public boolean queryCustomLink(GURL keyUrl) {
+    public boolean hasCustomLink(GURL keyUrl) {
         if (mNativeMostVisitedSitesBridge == 0) return false;
-        return MostVisitedSitesBridgeJni.get()
-                .queryCustomLink(mNativeMostVisitedSitesBridge, keyUrl);
+        return MostVisitedSitesBridgeJni.get().hasCustomLink(mNativeMostVisitedSitesBridge, keyUrl);
     }
 
     // MostVisitedSites implementation.
@@ -204,7 +203,7 @@
 
         boolean deleteCustomLink(long nativeMostVisitedSitesBridge, @JniType("GURL") GURL keyUrl);
 
-        boolean queryCustomLink(long nativeMostVisitedSitesBridge, @JniType("GURL") GURL keyUrl);
+        boolean hasCustomLink(long nativeMostVisitedSitesBridge, @JniType("GURL") GURL keyUrl);
 
         void destroy(long nativeMostVisitedSitesBridge, MostVisitedSitesBridge caller);
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/TileGroupDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/TileGroupDelegateImpl.java
index fa9b770d..c4d32ea 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/TileGroupDelegateImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/TileGroupDelegateImpl.java
@@ -83,9 +83,9 @@
     }
 
     @Override
-    public boolean queryCustomLink(GURL keyUrl) {
+    public boolean hasCustomLink(GURL keyUrl) {
         assert !mIsDestroyed;
-        return mMostVisitedSites.queryCustomLink(keyUrl);
+        return mMostVisitedSites.hasCustomLink(keyUrl);
     }
 
     // TileGroup.Delegate implementation.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java
index ac07597..a81c29be 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java
@@ -267,7 +267,7 @@
 
     @Override
     public @NonNull TabCreator getTabCreator() {
-        return isIncognitoBranded() ? mIncognitoTabCreator : mRegularTabCreator;
+        return getTabCreator(isIncognitoBranded());
     }
 
     /**
@@ -912,11 +912,6 @@
         return true;
     }
 
-    @Override
-    protected TabCreator getTabCreator(boolean incognito) {
-        return incognito ? mIncognitoTabCreator : mRegularTabCreator;
-    }
-
     /** Used to restore tabs from native. */
     @Override
     protected boolean createTabWithWebContents(
@@ -1085,4 +1080,18 @@
             obs.onFinishingMultipleTabClosure(tabs, saveToTabRestoreService);
         }
     }
+
+    /**
+     * Returns the {@link TabCreator} for the given {@link Profile}.
+     *
+     * <p>Please note that, the {@link TabCreator} and {@TabModelImpl} are separate instances for
+     * {@link ChromeTabbedActivity} and {@link CustomTabActivity} across both regular and Incognito
+     * modes which allows us to pass the boolean directly.
+     *
+     * @param incognito A boolean to indicate whether to return IncognitoTabCreator or
+     *     RegularTabCreator.
+     */
+    private TabCreator getTabCreator(boolean incognito) {
+        return incognito ? mIncognitoTabCreator : mRegularTabCreator;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelJniBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelJniBridge.java
index 43e9d713..16668a9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelJniBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelJniBridge.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.tabmodel;
 
+import androidx.annotation.CallSuper;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
@@ -60,6 +61,7 @@
     }
 
     @Override
+    @CallSuper
     public void destroy() {
         if (isNativeInitialized()) {
             // This will invalidate all other native references to this object in child classes.
@@ -84,11 +86,28 @@
     }
 
     @Override
+    @CalledByNative
+    public abstract int index();
+
+    @Override
+    @CalledByNative
+    public abstract int getCount();
+
+    @Override
+    @CalledByNative
+    public abstract Tab getTabAt(int index);
+
+    @Override
     public Profile getProfile() {
         return mProfile;
     }
 
+    @CalledByNative
+    @Override
+    public abstract boolean isActiveModel();
+
     /** Broadcast a native-side notification that all tabs are now loaded from storage. */
+    @CallSuper
     public void broadcastSessionRestoreComplete() {
         assert isNativeInitialized();
         TabModelJniBridgeJni.get()
@@ -116,10 +135,6 @@
         TabModelUtils.setIndex(this, index);
     }
 
-    @Override
-    @CalledByNative
-    public abstract Tab getTabAt(int index);
-
     /**
      * Closes all tabs. This bypasses protections for shared tab groups where placeholder tabs are
      * created to ensure collaboration data is not destroyed. Prefer {@link #closeTabAt()} to ensure
@@ -139,18 +154,6 @@
     protected abstract boolean closeTabAt(int index);
 
     /**
-     * Returns a tab creator for this {@link TabModel}.
-     *
-     * Please note that, the {@link TabCreator} and {@TabModelImpl} are separate instances for
-     * {@link ChromeTabbedActivity} and {@link CustomTabActivity} across both regular and Incognito
-     * modes which allows us to pass the boolean directly.
-     *
-     * @param incognito A boolean to indicate whether to return IncognitoTabCreator or
-     *         RegularTabCreator.
-     */
-    protected abstract TabCreator getTabCreator(boolean incognito);
-
-    /**
      * Creates a Tab with the given WebContents.
      * @param parent      The parent tab that creates the new tab.
      * @param profile     The profile for which to create the new tab.
@@ -182,10 +185,15 @@
     @CalledByNative
     protected abstract Tab createNewTabForDevTools(GURL url, boolean newWindow);
 
-    /** Returns whether supplied Tab instance has been grouped together with other Tabs. */
+    /**
+     * Returns whether supplied Tab instance has been grouped together with other Tabs.
+     *
+     * <p>This is a legacy static implementation which will be replaced in the future by a
+     * non-static implementation once TabModel understands tab groups.
+     */
     @CalledByNative
     @VisibleForTesting
-    static boolean isTabInTabGroup(@NonNull Tab tab) {
+    static boolean isTabInTabGroupLegacy(@NonNull Tab tab) {
         final TabGroupModelFilter filter = TabModelUtils.getTabGroupModelFilterByTab(tab);
         if (filter == null) return false;
 
@@ -207,25 +215,10 @@
     @CalledByNative
     protected abstract void closeTabsNavigatedInTimeWindow(long beginTimeMs, long endTimeMs);
 
-    @Override
-    @CalledByNative
-    public abstract int getCount();
-
-    @Override
-    @CalledByNative
-    public abstract int index();
-
     /** Returns whether or not a sync session is currently being restored. */
     @CalledByNative
     protected abstract boolean isSessionRestoreInProgress();
 
-    @CalledByNative
-    @Override
-    public abstract boolean isActiveModel();
-
-    @Override
-    public abstract void setActive(boolean active);
-
     @NativeMethods
     @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
     public interface Natives {
diff --git a/chrome/android/javatests/BUILD.gn b/chrome/android/javatests/BUILD.gn
index 23c28e9..be88df1 100644
--- a/chrome/android/javatests/BUILD.gn
+++ b/chrome/android/javatests/BUILD.gn
@@ -332,6 +332,7 @@
   "//components/webauthn/android:java",
   "//components/webauthn/android:test_support_java",
   "//content/public/android:content_java",
+  "//content/public/browser:transfer_input_to_viz_result_enum",
   "//content/public/common:common_java",
   "//content/public/test/android:content_java_test_support",
   "//content/public/test/android:content_transit_java",
@@ -1469,6 +1470,7 @@
     "src/org/chromium/chrome/browser/infobar/InfoBarContainerTest.java",
     "src/org/chromium/chrome/browser/init/ChromeBrowserInitializerTest.java",
     "src/org/chromium/chrome/browser/init/LaunchFailedActivityTest.java",
+    "src/org/chromium/chrome/browser/input/InputOnVizTest.java",
     "src/org/chromium/chrome/browser/input/SelectPopupOtherContentViewTest.java",
     "src/org/chromium/chrome/browser/interstitials/LookalikeInterstitialTest.java",
     "src/org/chromium/chrome/browser/javascript/CloseWatcherTest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/input/InputOnVizTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/input/InputOnVizTest.java
new file mode 100644
index 0000000..f268081
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/input/InputOnVizTest.java
@@ -0,0 +1,137 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+package org.chromium.chrome.browser.input;
+
+import android.os.Build;
+import android.view.MotionEvent;
+import android.view.View;
+
+import androidx.test.filters.MediumTest;
+
+import org.hamcrest.Matchers;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.ThreadUtils;
+import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.Criteria;
+import org.chromium.base.test.util.CriteriaHelper;
+import org.chromium.base.test.util.Features.EnableFeatures;
+import org.chromium.base.test.util.MinAndroidSdkLevel;
+import org.chromium.base.test.util.UrlUtils;
+import org.chromium.chrome.browser.flags.ChromeSwitches;
+import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
+import org.chromium.chrome.test.pagecontroller.utils.UiAutomatorUtils;
+import org.chromium.content_public.browser.GestureListenerManager;
+import org.chromium.content_public.browser.GestureStateListener;
+
+@RunWith(ChromeJUnit4ClassRunner.class)
+@MediumTest
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
+@EnableFeatures({"InputOnViz"})
+@MinAndroidSdkLevel(Build.VERSION_CODES.VANILLA_ICE_CREAM)
+public class InputOnVizTest {
+    private final String mLongHtmlTestPage =
+            UrlUtils.encodeHtmlDataUri("<html><body style='height:100000px;'></body></html>");
+
+    @Rule
+    public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
+
+    private GestureStateListener mGestureListener;
+    private View.OnTouchListener mViewOnTouchListener;
+    // Initialized to a value that is not a valid masked MotionEvent action.
+    private int mLastSeenEventAction = -1;
+
+    public int mScrollOffsetY;
+    private boolean mScrolling;
+
+    @Before
+    public void setUp() {
+        mActivityTestRule.startMainActivityWithURL(mLongHtmlTestPage);
+        mGestureListener =
+                new GestureStateListener() {
+                    @Override
+                    public void onScrollStarted(
+                            int scrollOffsetY, int scrollExtentY, boolean isDirectionUp) {
+                        mScrolling = true;
+                    }
+
+                    @Override
+                    public void onScrollEnded(int scrollOffsetY, int scrollExtentY) {
+                        mScrolling = false;
+                    }
+
+                    @Override
+                    public void onScrollOffsetOrExtentChanged(
+                            int scrollOffsetY, int scrollExtentY) {
+                        mScrollOffsetY = scrollOffsetY;
+                    }
+                };
+        mViewOnTouchListener =
+                new View.OnTouchListener() {
+                    @Override
+                    public boolean onTouch(View view, MotionEvent event) {
+                        mLastSeenEventAction = event.getActionMasked();
+                        // Let the event go through normal view input handling.
+                        return false;
+                    }
+                };
+
+        ThreadUtils.runOnUiThreadBlocking(
+                () -> {
+                    GestureListenerManager.fromWebContents(
+                                    mActivityTestRule
+                                            .getActivity()
+                                            .getActivityTab()
+                                            .getWebContents())
+                            .addListener(mGestureListener);
+                    mActivityTestRule
+                            .getActivity()
+                            .getActivityTab()
+                            .getContentView()
+                            .setOnTouchListener(mViewOnTouchListener);
+                });
+    }
+
+    @Test
+    public void secondScrollIsHandledOnViz() {
+        // Scroll 1 will be handled by the browser. On the browser side it says not to transfer
+        // the sequence when the web contents is at 0 offset, which would be the case when the
+        // page loads and we are scrolling for the first time.
+        UiAutomatorUtils.getInstance().swipeUpVertically(0.3f);
+        // Wait for the scroll offset to have changed as a result of scroll.
+        CriteriaHelper.pollInstrumentationThread(
+                () -> {
+                    Criteria.checkThat(mScrollOffsetY, Matchers.greaterThan(0));
+                });
+        // Wait for scroll end.
+        CriteriaHelper.pollInstrumentationThread(
+                () -> {
+                    Criteria.checkThat(mScrolling, Matchers.equalTo(false));
+                });
+
+        // Scroll 2 should be handled by Viz since the page would be at non-zero offset after
+        // the first scroll.
+        // This is not completely accurate since it's possible a late
+        // running frame updates the scroll offset due to scroll updates from previous scroll.
+        // TODO(crbug.com/393576167): Remove this and just check for offset>0, once the first
+        // scroll goes to Viz as well.
+        int scrollOffsetAfterScroll1 = mScrollOffsetY;
+        UiAutomatorUtils.getInstance().swipeUpVertically(0.3f);
+        // We should have received a cancel corresponding to a successful touch transfer.
+        CriteriaHelper.pollInstrumentationThread(
+                () -> {
+                    Criteria.checkThat(
+                            mLastSeenEventAction, Matchers.equalTo(MotionEvent.ACTION_CANCEL));
+                });
+        CriteriaHelper.pollInstrumentationThread(
+                () -> {
+                    Criteria.checkThat(
+                            mScrollOffsetY, Matchers.greaterThan(scrollOffsetAfterScroll1));
+                });
+    }
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelImplTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelImplTest.java
index f0035fcc..f753b0b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelImplTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelImplTest.java
@@ -162,18 +162,18 @@
                     final Tab tab2 = tabModel.getTabAt(1);
                     final Tab tab3 = tabModel.getTabAt(2);
 
-                    assertFalse(TabModelImpl.isTabInTabGroup(tab1));
-                    assertFalse(TabModelImpl.isTabInTabGroup(tab2));
-                    assertFalse(TabModelImpl.isTabInTabGroup(tab3));
+                    assertFalse(TabModelImpl.isTabInTabGroupLegacy(tab1));
+                    assertFalse(TabModelImpl.isTabInTabGroupLegacy(tab2));
+                    assertFalse(TabModelImpl.isTabInTabGroupLegacy(tab3));
 
                     ChromeTabUtils.mergeTabsToGroup(tab2, tab3);
 
-                    assertFalse(TabModelImpl.isTabInTabGroup(tab1));
-                    assertTrue(TabModelImpl.isTabInTabGroup(tab2));
-                    assertTrue(TabModelImpl.isTabInTabGroup(tab3));
+                    assertFalse(TabModelImpl.isTabInTabGroupLegacy(tab1));
+                    assertTrue(TabModelImpl.isTabInTabGroupLegacy(tab2));
+                    assertTrue(TabModelImpl.isTabInTabGroupLegacy(tab3));
 
                     tab1.setTabGroupId(new Token(1L, 2L));
-                    assertTrue(TabModelImpl.isTabInTabGroup(tab1));
+                    assertTrue(TabModelImpl.isTabInTabGroupLegacy(tab1));
 
                     tab1.setTabGroupId(null);
                 });
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 27541fb2..cbae44e9 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -9697,10 +9697,6 @@
 #endif  // BUILDFLAG(IS_CHROMEOS)
 
 #if BUILDFLAG(IS_ANDROID)
-    {"tab-group-pane-android", flag_descriptions::kTabGroupPaneAndroidName,
-     flag_descriptions::kTabGroupPaneAndroidDescription, kOsAndroid,
-     FEATURE_VALUE_TYPE(tab_groups::kTabGroupPaneAndroid)},
-
     {"tab-group-entry-points-android",
      flag_descriptions::kTabGroupEntryPointsAndroidName,
      flag_descriptions::kTabGroupEntryPointsAndroidDescription, kOsAndroid,
diff --git a/chrome/browser/actor/BUILD.gn b/chrome/browser/actor/BUILD.gn
index 10fadf4c..220e1c4 100644
--- a/chrome/browser/actor/BUILD.gn
+++ b/chrome/browser/actor/BUILD.gn
@@ -37,6 +37,8 @@
     "//components/optimization_guide/proto:optimization_guide_proto",
   ]
   deps = [
+    "//chrome/browser/optimization_guide:optimization_guide",
+    "//chrome/browser/profiles:profile",
     "//chrome/browser/safe_browsing",
     "//chrome/browser/ui/tabs:tabs_public",
     "//chrome/common",
@@ -68,6 +70,7 @@
     ":actor",
     ":test_support",
     "//base/test:test_support",
+    "//chrome/browser/optimization_guide:test_support",
     "//chrome/test:test_support",
     "//testing/gtest",
   ]
@@ -84,10 +87,12 @@
     ":actor",
     ":test_support",
     "//base/test:test_support",
+    "//chrome/browser/optimization_guide:test_support",
     "//chrome/browser/safe_browsing",
     "//chrome/browser/ui:ui",
     "//chrome/test:test_support",
     "//chrome/test:test_support_ui",
+    "//components/optimization_guide/core:bloomfilter",
     "//components/safe_browsing:buildflags",
     "//components/safe_browsing/core/common:features",
     "//content/test:test_support",
diff --git a/chrome/browser/actor/actor_coordinator.cc b/chrome/browser/actor/actor_coordinator.cc
index 2e75187..71c6d11 100644
--- a/chrome/browser/actor/actor_coordinator.cc
+++ b/chrome/browser/actor/actor_coordinator.cc
@@ -31,6 +31,11 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
+// static
+void ActorCoordinator::RegisterWithProfile(Profile* profile) {
+  InitActionBlocklist(profile);
+}
+
 void ActorCoordinator::Act(TabInterface& tab,
                            const BrowserAction& action,
                            ActionResultCallback callback) {
diff --git a/chrome/browser/actor/actor_coordinator.h b/chrome/browser/actor/actor_coordinator.h
index e367442..34148472 100644
--- a/chrome/browser/actor/actor_coordinator.h
+++ b/chrome/browser/actor/actor_coordinator.h
@@ -22,6 +22,8 @@
 class BrowserAction;
 }  // namespace optimization_guide::proto
 
+class Profile;
+
 namespace actor {
 
 // Coordinates the execution of a multi-step task.
@@ -34,6 +36,8 @@
   ActorCoordinator& operator=(const ActorCoordinator&) = delete;
   ~ActorCoordinator();
 
+  static void RegisterWithProfile(Profile* profile);
+
   // Performs the next action.
   void Act(tabs::TabInterface& tab,
            const optimization_guide::proto::BrowserAction& action,
diff --git a/chrome/browser/actor/actor_features.cc b/chrome/browser/actor/actor_features.cc
index c6c9d52..fb0d7387 100644
--- a/chrome/browser/actor/actor_features.cc
+++ b/chrome/browser/actor/actor_features.cc
@@ -31,4 +31,8 @@
                    "allowlist_only",
                    true);
 
+BASE_FEATURE(kGlicActionUseOptimizationGuide,
+             "GlicActionUseOptimizationGuide",
+             base::FEATURE_ENABLED_BY_DEFAULT);
+
 }  // namespace actor
diff --git a/chrome/browser/actor/actor_features.h b/chrome/browser/actor/actor_features.h
index ed56b3f..3d46d9a 100644
--- a/chrome/browser/actor/actor_features.h
+++ b/chrome/browser/actor/actor_features.h
@@ -18,6 +18,8 @@
 BASE_DECLARE_FEATURE_PARAM(std::string, kAllowlistExact);
 BASE_DECLARE_FEATURE_PARAM(bool, kAllowlistOnly);
 
+BASE_DECLARE_FEATURE(kGlicActionUseOptimizationGuide);
+
 }  // namespace actor
 
 #endif  // CHROME_BROWSER_ACTOR_ACTOR_FEATURES_H_
diff --git a/chrome/browser/actor/site_policy.cc b/chrome/browser/actor/site_policy.cc
index f561db0..77c54eb 100644
--- a/chrome/browser/actor/site_policy.cc
+++ b/chrome/browser/actor/site_policy.cc
@@ -15,6 +15,11 @@
 #include "base/strings/string_split.h"
 #include "base/task/sequenced_task_runner.h"
 #include "chrome/browser/actor/actor_features.h"
+#include "chrome/browser/optimization_guide/optimization_guide_keyed_service.h"
+#include "chrome/browser/optimization_guide/optimization_guide_keyed_service_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "components/optimization_guide/core/optimization_guide_decision.h"
+#include "components/optimization_guide/proto/hints.pb.h"
 #include "components/safe_browsing/buildflags.h"
 #include "components/tab_collections/public/tab_interface.h"
 #include "content/public/browser/web_contents.h"
@@ -56,7 +61,16 @@
   return false;
 }
 
-void MayActOnUrl(const GURL& url, DecisionCallback callback) {
+void OnOptimizationGuideDecision(
+    DecisionCallback callback,
+    optimization_guide::OptimizationGuideDecision decision,
+    const optimization_guide::OptimizationMetadata& metadata) {
+  ResolveDecision(
+      std::move(callback),
+      decision == optimization_guide::OptimizationGuideDecision::kTrue);
+}
+
+void MayActOnUrl(const GURL& url, Profile* profile, DecisionCallback callback) {
   if (net::IsLocalhost(url)) {
     ResolveDecision(std::move(callback), true);
     return;
@@ -93,17 +107,35 @@
     }
   }
 
-  // TODO(mcnee): Implement blocklist.
-  NOTIMPLEMENTED();
+  if (auto* optimization_guide_decider =
+          OptimizationGuideKeyedServiceFactory::GetForProfile(profile);
+      optimization_guide_decider &&
+      base::FeatureList::IsEnabled(kGlicActionUseOptimizationGuide)) {
+    optimization_guide_decider->CanApplyOptimization(
+        url, optimization_guide::proto::GLIC_ACTION_PAGE_BLOCK,
+        base::BindOnce(&OnOptimizationGuideDecision, std::move(callback)));
+    return;
+  }
 
-  ResolveDecision(std::move(callback), true);
+  // Fail closed.
+  ResolveDecision(std::move(callback), false);
 }
 
 }  // namespace
 
+void InitActionBlocklist(Profile* profile) {
+  if (auto* optimization_guide_decider =
+          OptimizationGuideKeyedServiceFactory::GetForProfile(profile);
+      optimization_guide_decider &&
+      base::FeatureList::IsEnabled(kGlicActionUseOptimizationGuide)) {
+    optimization_guide_decider->RegisterOptimizationTypes(
+        {optimization_guide::proto::GLIC_ACTION_PAGE_BLOCK});
+  }
+}
+
 // TODO(mcnee): Add UMA for the outcomes.
 void MayActOnTab(const tabs::TabInterface& tab, DecisionCallback callback) {
-  const content::WebContents& web_contents = *tab.GetContents();
+  content::WebContents& web_contents = *tab.GetContents();
 
   if (web_contents.GetPrimaryMainFrame()->IsErrorDocument()) {
     ResolveDecision(std::move(callback), false);
@@ -123,7 +155,9 @@
 #endif
 
   const GURL& url = web_contents.GetPrimaryMainFrame()->GetLastCommittedURL();
-  MayActOnUrl(url, std::move(callback));
+  MayActOnUrl(url,
+              Profile::FromBrowserContext(web_contents.GetBrowserContext()),
+              std::move(callback));
 }
 
 }  // namespace actor
diff --git a/chrome/browser/actor/site_policy.h b/chrome/browser/actor/site_policy.h
index 877ed72..598c585f 100644
--- a/chrome/browser/actor/site_policy.h
+++ b/chrome/browser/actor/site_policy.h
@@ -11,8 +11,13 @@
 class TabInterface;
 }
 
+class Profile;
+
 namespace actor {
 
+// Called during initialization of the given profile, to load the blocklist.
+void InitActionBlocklist(Profile* profile);
+
 using DecisionCallback = base::OnceCallback<void(/*may_act=*/bool)>;
 
 // Checks whether the actor may perform actions on the given tab based on the
diff --git a/chrome/browser/actor/site_policy_browsertest.cc b/chrome/browser/actor/site_policy_browsertest.cc
index c08b9e31..09634fd 100644
--- a/chrome/browser/actor/site_policy_browsertest.cc
+++ b/chrome/browser/actor/site_policy_browsertest.cc
@@ -4,14 +4,21 @@
 
 #include "chrome/browser/actor/site_policy.h"
 
+#include "base/base64.h"
+#include "base/command_line.h"
 #include "base/metrics/field_trial_params.h"
+#include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/test_future.h"
 #include "chrome/browser/actor/actor_features.h"
+#include "chrome/browser/optimization_guide/browser_test_util.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
+#include "components/optimization_guide/core/bloom_filter.h"
+#include "components/optimization_guide/core/optimization_guide_switches.h"
+#include "components/optimization_guide/proto/hints.pb.h"
 #include "components/safe_browsing/buildflags.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/test/browser_test.h"
@@ -41,10 +48,50 @@
 
   ~ActorSitePolicyBrowserTest() override = default;
 
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    InProcessBrowserTest::SetUpCommandLine(command_line);
+
+    constexpr std::string kBlockedHost = "bar.com";
+    constexpr uint32_t kNumHashFunctions = 7;
+    constexpr uint32_t kNumBits = 511;
+    optimization_guide::BloomFilter blocklist_bloom_filter(kNumHashFunctions,
+                                                           kNumBits);
+    blocklist_bloom_filter.Add(kBlockedHost);
+    std::string blocklist_bloom_filter_data(
+        reinterpret_cast<const char*>(&blocklist_bloom_filter.bytes()[0]),
+        blocklist_bloom_filter.bytes().size());
+
+    optimization_guide::proto::Configuration config;
+    optimization_guide::proto::OptimizationFilter*
+        blocklist_optimization_filter = config.add_optimization_blocklists();
+    blocklist_optimization_filter->set_optimization_type(
+        optimization_guide::proto::GLIC_ACTION_PAGE_BLOCK);
+    blocklist_optimization_filter->mutable_bloom_filter()
+        ->set_num_hash_functions(kNumHashFunctions);
+    blocklist_optimization_filter->mutable_bloom_filter()->set_num_bits(
+        kNumBits);
+    blocklist_optimization_filter->mutable_bloom_filter()->set_data(
+        blocklist_bloom_filter_data);
+
+    std::string encoded_config;
+    config.SerializeToString(&encoded_config);
+    encoded_config = base::Base64Encode(encoded_config);
+
+    command_line->AppendSwitchASCII(
+        optimization_guide::switches::kHintsProtoOverride, encoded_config);
+  }
+
   void SetUpOnMainThread() override {
     InProcessBrowserTest::SetUpOnMainThread();
     host_resolver()->AddRule("*", "127.0.0.1");
     ASSERT_TRUE(embedded_https_test_server().Start());
+
+    // Optimization guide uses this histogram to signal initialization in tests.
+    optimization_guide::RetryForHistogramUntilCountReached(
+        &histogram_tester_for_init_,
+        "OptimizationGuide.HintsManager.HintCacheInitialized", 1);
+
+    InitActionBlocklist(browser()->profile());
   }
 
  protected:
@@ -60,6 +107,7 @@
   }
 
  private:
+  base::HistogramTester histogram_tester_for_init_;
   base::test::ScopedFeatureList scoped_feature_list_;
 };
 
@@ -69,6 +117,25 @@
   CheckUrl(allowed_url, true);
 }
 
+IN_PROC_BROWSER_TEST_F(ActorSitePolicyBrowserTest, AllowIfNotInBlocklist) {
+  const GURL allowed_url =
+      embedded_https_test_server().GetURL("c.com", "/title1.html");
+  CheckUrl(allowed_url, true);
+}
+
+IN_PROC_BROWSER_TEST_F(ActorSitePolicyBrowserTest, BlockIfInBlocklist) {
+  const GURL blocked_url =
+      embedded_https_test_server().GetURL("bar.com", "/title1.html");
+  CheckUrl(blocked_url, false);
+}
+
+IN_PROC_BROWSER_TEST_F(ActorSitePolicyBrowserTest,
+                       BlockSubdomainIfInBlocklist) {
+  const GURL blocked_url =
+      embedded_https_test_server().GetURL("sub.bar.com", "/title1.html");
+  CheckUrl(blocked_url, false);
+}
+
 #if BUILDFLAG(SAFE_BROWSING_AVAILABLE)
 
 class ActorSitePolicySafeBrowsingBrowserTest
diff --git a/chrome/browser/actor/site_policy_unittest.cc b/chrome/browser/actor/site_policy_unittest.cc
index 1b16bce..3174bbc4 100644
--- a/chrome/browser/actor/site_policy_unittest.cc
+++ b/chrome/browser/actor/site_policy_unittest.cc
@@ -8,6 +8,8 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/test/test_future.h"
 #include "chrome/browser/actor/actor_features.h"
+#include "chrome/browser/optimization_guide/mock_optimization_guide_keyed_service.h"
+#include "chrome/browser/optimization_guide/optimization_guide_keyed_service_factory.h"
 #include "chrome/browser/ui/tabs/test/mock_tab_interface.h"
 #include "chrome/common/webui_url_constants.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
@@ -29,6 +31,28 @@
         kGlicActionAllowlist, CreateFieldTrialParams());
 
     ChromeRenderViewHostTestHarness::SetUp();
+
+    mock_optimization_guide_keyed_service_ =
+        static_cast<MockOptimizationGuideKeyedService*>(
+            OptimizationGuideKeyedServiceFactory::GetInstance()
+                ->SetTestingFactoryAndUse(
+                    profile(),
+                    base::BindOnce(
+                        &ActorSitePolicyTest::CreateOptimizationService)));
+
+    ON_CALL(*mock_optimization_guide_keyed_service_,
+            CanApplyOptimization(
+                testing::_, optimization_guide::proto::GLIC_ACTION_PAGE_BLOCK,
+                testing::An<
+                    optimization_guide::OptimizationGuideDecisionCallback>()))
+        .WillByDefault(base::test::RunOnceCallback<2>(
+            optimization_guide::OptimizationGuideDecision::kTrue,
+            optimization_guide::OptimizationMetadata{}));
+  }
+
+  void TearDown() override {
+    mock_optimization_guide_keyed_service_ = nullptr;
+    ChromeRenderViewHostTestHarness::TearDown();
   }
 
   virtual base::FieldTrialParams CreateFieldTrialParams() {
@@ -39,6 +63,19 @@
   }
 
  protected:
+  void SetExpectedOptimizationGuideCall(
+      const GURL& url,
+      optimization_guide::OptimizationGuideDecision result) {
+    EXPECT_CALL(
+        *mock_optimization_guide_keyed_service_,
+        CanApplyOptimization(
+            url, optimization_guide::proto::GLIC_ACTION_PAGE_BLOCK,
+            testing::An<
+                optimization_guide::OptimizationGuideDecisionCallback>()))
+        .WillOnce(base::test::RunOnceCallback<2>(
+            result, optimization_guide::OptimizationMetadata{}));
+  }
+
   void CheckUrl(const GURL& url, bool expected_allowed) {
     content::NavigationSimulator::NavigateAndCommitFromBrowser(web_contents(),
                                                                url);
@@ -54,6 +91,14 @@
   }
 
  private:
+  static std::unique_ptr<KeyedService> CreateOptimizationService(
+      content::BrowserContext* context) {
+    return std::make_unique<MockOptimizationGuideKeyedService>();
+  }
+
+  raw_ptr<MockOptimizationGuideKeyedService>
+      mock_optimization_guide_keyed_service_;
+
   base::test::ScopedFeatureList scoped_feature_list_;
 };
 
@@ -103,6 +148,22 @@
   CheckUrl(GURL("https://c.test/"), true);
 }
 
+TEST_F(ActorSitePolicyTest, BlockIfInBlocklist) {
+  const GURL url("https://c.test/");
+  SetExpectedOptimizationGuideCall(
+      url, optimization_guide::OptimizationGuideDecision::kFalse);
+  CheckUrl(url, false);
+}
+
+TEST_F(ActorSitePolicyTest, BlockIfBlocklistUnavailable) {
+  const GURL url("https://c.test/");
+  // Simulate the blocklist not being loaded. This should cause the URL check to
+  // fail closed.
+  SetExpectedOptimizationGuideCall(
+      url, optimization_guide::OptimizationGuideDecision::kUnknown);
+  CheckUrl(url, false);
+}
+
 TEST_F(ActorSitePolicyAllowlistOnlyTest, BlockIfNotInAllowlist) {
   CheckUrl(GURL("https://c.test/"), false);
 }
diff --git a/chrome/browser/android/devtools_manager_delegate_android.cc b/chrome/browser/android/devtools_manager_delegate_android.cc
index a94daa3..15adeb8 100644
--- a/chrome/browser/android/devtools_manager_delegate_android.cc
+++ b/chrome/browser/android/devtools_manager_delegate_android.cc
@@ -13,6 +13,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "chrome/browser/android/tab_android.h"
+#include "chrome/browser/devtools/chrome_devtools_session_android.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/android/tab_model/tab_model.h"
 #include "chrome/browser/ui/android/tab_model/tab_model_list.h"
@@ -205,16 +206,6 @@
 
 static const void* const kCreatedByDevTools = &kCreatedByDevTools;
 
-bool IsCreatedByDevTools(const WebContents& web_contents) {
-  return !!web_contents.GetUserData(kCreatedByDevTools);
-}
-
-void MarkCreatedByDevTools(WebContents& web_contents) {
-  DCHECK(!IsCreatedByDevTools(web_contents));
-  web_contents.SetUserData(kCreatedByDevTools,
-                           std::make_unique<base::SupportsUserData::Data>());
-}
-
 } //  namespace
 
 DevToolsManagerDelegateAndroid::DevToolsManagerDelegateAndroid() = default;
@@ -226,6 +217,18 @@
   return ProfileManager::GetActiveUserProfile()->GetOriginalProfile();
 }
 
+bool DevToolsManagerDelegateAndroid::IsCreatedByDevTools(
+    const WebContents& web_contents) {
+  return !!web_contents.GetUserData(kCreatedByDevTools);
+}
+
+void DevToolsManagerDelegateAndroid::MarkCreatedByDevTools(
+    WebContents& web_contents) {
+  DCHECK(!IsCreatedByDevTools(web_contents));
+  web_contents.SetUserData(kCreatedByDevTools,
+                           std::make_unique<base::SupportsUserData::Data>());
+}
+
 std::string DevToolsManagerDelegateAndroid::GetTargetType(
     content::WebContents* web_contents) {
   TabAndroid* tab = web_contents ? TabAndroid::FromWebContents(web_contents)
@@ -273,30 +276,31 @@
   return result;
 }
 
-scoped_refptr<DevToolsAgentHost>
-DevToolsManagerDelegateAndroid::CreateNewTarget(
-    const GURL& url,
-    DevToolsManagerDelegate::TargetType target_type,
-    bool new_window) {
-  if (TabModelList::models().empty())
-    return nullptr;
-
-  TabModel* tab_model = TabModelList::models()[0];
-  if (!tab_model)
-    return nullptr;
-
-  WebContents* web_contents =
-      tab_model->CreateNewTabForDevTools(url, new_window);
-  if (!web_contents) {
-    return nullptr;
-  }
-
-  MarkCreatedByDevTools(*web_contents);
-  return target_type == DevToolsManagerDelegate::kTab
-             ? DevToolsAgentHost::GetOrCreateForTab(web_contents)
-             : DevToolsAgentHost::GetOrCreateFor(web_contents);
-}
-
 bool DevToolsManagerDelegateAndroid::IsBrowserTargetDiscoverable() {
   return true;
 }
+
+void DevToolsManagerDelegateAndroid::HandleCommand(
+    content::DevToolsAgentHostClientChannel* channel,
+    base::span<const uint8_t> message,
+    NotHandledCallback callback) {
+  auto it = sessions_.find(channel);
+  if (it == sessions_.end()) {
+    // This should not happen, but happens. NOTREACHED tries to get
+    // a repro in some test.
+    NOTREACHED();
+  }
+  it->second->HandleCommand(message, std::move(callback));
+}
+
+void DevToolsManagerDelegateAndroid::ClientAttached(
+    content::DevToolsAgentHostClientChannel* channel) {
+  DCHECK(sessions_.find(channel) == sessions_.end());
+  sessions_.emplace(channel,
+                    std::make_unique<ChromeDevToolsSessionAndroid>(channel));
+}
+
+void DevToolsManagerDelegateAndroid::ClientDetached(
+    content::DevToolsAgentHostClientChannel* channel) {
+  sessions_.erase(channel);
+}
diff --git a/chrome/browser/android/devtools_manager_delegate_android.h b/chrome/browser/android/devtools_manager_delegate_android.h
index a7a5a43..3ffe484 100644
--- a/chrome/browser/android/devtools_manager_delegate_android.h
+++ b/chrome/browser/android/devtools_manager_delegate_android.h
@@ -10,6 +10,8 @@
 #include "content/public/browser/devtools_agent_host_observer.h"
 #include "content/public/browser/devtools_manager_delegate.h"
 
+class ChromeDevToolsSessionAndroid;
+
 class DevToolsManagerDelegateAndroid : public content::DevToolsManagerDelegate {
  public:
   DevToolsManagerDelegateAndroid();
@@ -21,17 +23,28 @@
 
   ~DevToolsManagerDelegateAndroid() override;
 
+  static void MarkCreatedByDevTools(content::WebContents& web_contents);
+  static bool IsCreatedByDevTools(const content::WebContents& web_contents);
+
  private:
   // content::DevToolsManagerDelegate implementation.
   content::BrowserContext* GetDefaultBrowserContext() override;
   std::string GetTargetType(content::WebContents* web_contents) override;
   content::DevToolsAgentHost::List RemoteDebuggingTargets(
       TargetType target_type) override;
-  scoped_refptr<content::DevToolsAgentHost> CreateNewTarget(
-      const GURL& url,
-      TargetType target_type,
-      bool new_window) override;
   bool IsBrowserTargetDiscoverable() override;
+
+  void HandleCommand(content::DevToolsAgentHostClientChannel* channel,
+                     base::span<const uint8_t> message,
+                     NotHandledCallback callback) override;
+  void ClientAttached(
+      content::DevToolsAgentHostClientChannel* channel) override;
+  void ClientDetached(
+      content::DevToolsAgentHostClientChannel* channel) override;
+
+  base::flat_map<content::DevToolsAgentHostClientChannel*,
+                 std::unique_ptr<ChromeDevToolsSessionAndroid>>
+      sessions_;
 };
 
 #endif  // CHROME_BROWSER_ANDROID_DEVTOOLS_MANAGER_DELEGATE_ANDROID_H_
diff --git a/chrome/browser/android/ntp/most_visited_sites_bridge.cc b/chrome/browser/android/ntp/most_visited_sites_bridge.cc
index 3c8772d..551b8fc 100644
--- a/chrome/browser/android/ntp/most_visited_sites_bridge.cc
+++ b/chrome/browser/android/ntp/most_visited_sites_bridge.cc
@@ -230,8 +230,8 @@
   return false;
 }
 
-jboolean MostVisitedSitesBridge::QueryCustomLink(JNIEnv* env,
-                                                 const GURL& key_url) {
+jboolean MostVisitedSitesBridge::HasCustomLink(JNIEnv* env,
+                                               const GURL& key_url) {
   // TODO(crbug.com/397421743): Implement.
   return false;
 }
diff --git a/chrome/browser/android/ntp/most_visited_sites_bridge.h b/chrome/browser/android/ntp/most_visited_sites_bridge.h
index ef81f7cb..c41b140d 100644
--- a/chrome/browser/android/ntp/most_visited_sites_bridge.h
+++ b/chrome/browser/android/ntp/most_visited_sites_bridge.h
@@ -53,7 +53,7 @@
 
   jboolean DeleteCustomLink(JNIEnv* env, const GURL& key_url);
 
-  jboolean QueryCustomLink(JNIEnv* env, const GURL& key_url);
+  jboolean HasCustomLink(JNIEnv* env, const GURL& key_url);
 
   void AddOrRemoveBlockedUrl(JNIEnv* env,
                              const base::android::JavaParamRef<jobject>& obj,
diff --git a/chrome/browser/ash/policy/fuzzer/policy_fuzzer.cc b/chrome/browser/ash/policy/fuzzer/policy_fuzzer.cc
index dff9ae2..865d592 100644
--- a/chrome/browser/ash/policy/fuzzer/policy_fuzzer.cc
+++ b/chrome/browser/ash/policy/fuzzer/policy_fuzzer.cc
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 #include <string>
-#include <string_view>
 
 #include "base/at_exit.h"
 #include "base/check_op.h"
@@ -52,7 +51,7 @@
 // threshold. It's needed in order to suppress unneeded syslog logging (which by
 // default is exempt from the level set by `logging::SetMinLogLevel()`).
 bool VoidifyingLogHandler(int severity,
-                          std::string_view /*file*/,
+                          const char* /*file*/,
                           int /*line*/,
                           size_t /*message_start*/,
                           const std::string& /*str*/) {
diff --git a/chrome/browser/ash/policy/remote_commands/remote_commands_fuzzer.cc b/chrome/browser/ash/policy/remote_commands/remote_commands_fuzzer.cc
index 9c13a11..f00531a 100644
--- a/chrome/browser/ash/policy/remote_commands/remote_commands_fuzzer.cc
+++ b/chrome/browser/ash/policy/remote_commands/remote_commands_fuzzer.cc
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <fuzzer/FuzzedDataProvider.h>
 #include <stddef.h>
 #include <stdint.h>
 
 #include <initializer_list>
 #include <memory>
 #include <string>
-#include <string_view>
+
+#include <fuzzer/FuzzedDataProvider.h>
 
 #include "base/at_exit.h"
 #include "base/check.h"
@@ -40,7 +40,7 @@
 // threshold. It's needed in order to suppress unneeded syslog logging (which by
 // default is exempt from the level set by `logging::SetMinLogLevel()`).
 bool VoidifyingLogHandler(int severity,
-                          std::string_view /*file*/,
+                          const char* /*file*/,
                           int /*line*/,
                           size_t /*message_start*/,
                           const std::string& /*str*/) {
diff --git a/chrome/browser/ash/scalable_iph/scalable_iph_browsertest.cc b/chrome/browser/ash/scalable_iph/scalable_iph_browsertest.cc
index 14529ff..69445fce 100644
--- a/chrome/browser/ash/scalable_iph/scalable_iph_browsertest.cc
+++ b/chrome/browser/ash/scalable_iph/scalable_iph_browsertest.cc
@@ -1153,8 +1153,8 @@
   // variable as a captureless lambda can be converted to a function pointer.
   static base::NoDestructor<std::vector<std::string>> captured_logs;
   CHECK_EQ(nullptr, logging::GetLogMessageHandler());
-  logging::SetLogMessageHandler([](int severity, std::string_view file,
-                                   int line, size_t message_start,
+  logging::SetLogMessageHandler([](int severity, const char* file, int line,
+                                   size_t message_start,
                                    const std::string& str) {
     captured_logs->push_back(str);
     return true;
@@ -1196,8 +1196,8 @@
   // variable as a captureless lambda can be converted to a function pointer.
   static base::NoDestructor<std::vector<std::string>> captured_logs;
   CHECK_EQ(nullptr, logging::GetLogMessageHandler());
-  logging::SetLogMessageHandler([](int severity, std::string_view file,
-                                   int line, size_t message_start,
+  logging::SetLogMessageHandler([](int severity, const char* file, int line,
+                                   size_t message_start,
                                    const std::string& str) {
     captured_logs->push_back(str);
     return true;
diff --git a/chrome/browser/bitmap_fetcher/bitmap_fetcher.cc b/chrome/browser/bitmap_fetcher/bitmap_fetcher.cc
index 55d3ace..12a02f8 100644
--- a/chrome/browser/bitmap_fetcher/bitmap_fetcher.cc
+++ b/chrome/browser/bitmap_fetcher/bitmap_fetcher.cc
@@ -10,6 +10,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/storage_partition.h"
 #include "net/base/data_url.h"
+#include "net/cookies/site_for_cookies.h"
 #include "net/http/http_request_headers.h"
 #include "services/network/public/cpp/resource_request.h"
 #include "url/url_constants.h"
@@ -35,7 +36,8 @@
 void BitmapFetcher::Init(net::ReferrerPolicy referrer_policy,
                          network::mojom::CredentialsMode credentials_mode,
                          const net::HttpRequestHeaders& additional_headers,
-                         const url::Origin& initiator) {
+                         const url::Origin& initiator,
+                         bool is_same_site_request) {
   if (simple_loader_ != nullptr)
     return;
 
@@ -43,6 +45,10 @@
   resource_request->url = url_;
   resource_request->referrer_policy = referrer_policy;
   resource_request->credentials_mode = credentials_mode;
+  if (is_same_site_request) {
+    resource_request->site_for_cookies =
+        net::SiteForCookies::FromUrl(resource_request->url);
+  }
   resource_request->headers.MergeFrom(additional_headers);
   resource_request->request_initiator = initiator;
   simple_loader_ = network::SimpleURLLoader::Create(std::move(resource_request),
diff --git a/chrome/browser/bitmap_fetcher/bitmap_fetcher.h b/chrome/browser/bitmap_fetcher/bitmap_fetcher.h
index 6f196cf4..a5161847 100644
--- a/chrome/browser/bitmap_fetcher/bitmap_fetcher.h
+++ b/chrome/browser/bitmap_fetcher/bitmap_fetcher.h
@@ -41,16 +41,19 @@
 
   const GURL& url() const { return url_; }
 
-  // |credentials_mode| determines whether credentials such as cookies should be
+  // `credentials_mode` determines whether credentials such as cookies should be
   // sent.  Init may be called more than once in some cases.  If so, subsequent
   // calls will be ignored.
-  // |additional_headers| will be merged with default HTTP headers provided by
-  // |BitmapFetcher| when fetching the image.
+  // `additional_headers` will be merged with default HTTP headers provided by
+  // `BitmapFetcher` when fetching the image.
+  // If `is_same_site_request` is true, the request is initiated as same-site:
+  // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#name-same-site-and-cross-site-re.
   // TODO(tommycli): Init and Start should likely be combined.
   virtual void Init(net::ReferrerPolicy referrer_policy,
                     network::mojom::CredentialsMode credentials_mode,
                     const net::HttpRequestHeaders& additional_headers = {},
-                    const url::Origin& initiator = url::Origin());
+                    const url::Origin& initiator = url::Origin(),
+                    bool is_same_site_request = false);
 
   // Start fetching the URL with the fetcher. The delegate is notified
   // asynchronously when done.  Start may be called more than once in some
diff --git a/chrome/browser/bitmap_fetcher/bitmap_fetcher_service.cc b/chrome/browser/bitmap_fetcher/bitmap_fetcher_service.cc
index b39fa1d..ff455c13 100644
--- a/chrome/browser/bitmap_fetcher/bitmap_fetcher_service.cc
+++ b/chrome/browser/bitmap_fetcher/bitmap_fetcher_service.cc
@@ -58,10 +58,12 @@
             "Change of results for the query typed by the user in the "
             "omnibox."
           data:
-            "The only data sent is the path to an image. No user data is "
-            "included, although some might be inferrable (e.g. whether the "
-            "weather is sunny or rainy in the user's current location) "
-            "from the name of the image in the path."
+            "The only data sent is the path to an image and cookies. User data "
+            "might be present in cookies, and some user data might be "
+            "inferrable (e.g. whether the weather is sunny or rainy in the "
+            "user's current location) from the name of the image in the path. "
+            "Requests are sent as same-site: "
+            "https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#name-same-site-and-cross-site-re."
           destination: WEBSITE
         }
         policy {
@@ -200,12 +202,14 @@
 std::unique_ptr<BitmapFetcher> BitmapFetcherService::CreateFetcher(
     const GURL& url,
     const net::NetworkTrafficAnnotationTag& traffic_annotation) {
+  // TODO(https://crbug.com/408008982): Consider merging to `ImageFetcher.`
   std::unique_ptr<BitmapFetcher> new_fetcher = std::make_unique<BitmapFetcher>(
       url, this, traffic_annotation, shared_data_decoder_.get());
 
   new_fetcher->Init(
       net::ReferrerPolicy::REDUCE_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN,
-      network::mojom::CredentialsMode::kInclude);
+      network::mojom::CredentialsMode::kInclude, /*additional_headers=*/{},
+      /*initiator=*/url::Origin(), /*is_same_site_request=*/true);
   new_fetcher->Start(context_->GetDefaultStoragePartition()
                          ->GetURLLoaderFactoryForBrowserProcess()
                          .get());
diff --git a/chrome/browser/bookmarks/android/bookmark_bridge.cc b/chrome/browser/bookmarks/android/bookmark_bridge.cc
index 9b5ba7c0..eb0a7fee 100644
--- a/chrome/browser/bookmarks/android/bookmark_bridge.cc
+++ b/chrome/browser/bookmarks/android/bookmark_bridge.cc
@@ -1596,6 +1596,10 @@
       CreateJavaBookmark(node));
 }
 
+void BookmarkBridge::BookmarkNodeFaviconChanged(const BookmarkNode* node) {
+  BookmarkNodeChanged(node);
+}
+
 void BookmarkBridge::BookmarkNodeChildrenReordered(const BookmarkNode* node) {
   if (!IsLoaded() || !java_bookmark_model_ ||
       suppress_observer_notifications_) {
diff --git a/chrome/browser/bookmarks/android/bookmark_bridge.h b/chrome/browser/bookmarks/android/bookmark_bridge.h
index 64c94ae..f2697075 100644
--- a/chrome/browser/bookmarks/android/bookmark_bridge.h
+++ b/chrome/browser/bookmarks/android/bookmark_bridge.h
@@ -335,6 +335,7 @@
   void BookmarkAllUserNodesRemoved(const std::set<GURL>& removed_urls,
                                    const base::Location& location) override;
   void BookmarkNodeChanged(const bookmarks::BookmarkNode* node) override;
+  void BookmarkNodeFaviconChanged(const bookmarks::BookmarkNode* node) override;
   void BookmarkNodeChildrenReordered(
       const bookmarks::BookmarkNode* node) override;
   void ExtensiveBookmarkChangesBeginning() override;
diff --git a/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkModelObserver.java b/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkModelObserver.java
index b0daebdd..eb1b29eb 100644
--- a/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkModelObserver.java
+++ b/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkModelObserver.java
@@ -73,7 +73,7 @@
     }
 
     /**
-     * Invoked when the title or url of a node changes.
+     * Invoked when the favicon, title, or url of a node changes.
      *
      * @param node The node being changed.
      */
diff --git a/chrome/browser/bookmarks/bookmark_merged_surface_service.h b/chrome/browser/bookmarks/bookmark_merged_surface_service.h
index 9d14781..a2f60bf 100644
--- a/chrome/browser/bookmarks/bookmark_merged_surface_service.h
+++ b/chrome/browser/bookmarks/bookmark_merged_surface_service.h
@@ -131,6 +131,10 @@
   bool IsNodeManaged(const bookmarks::BookmarkNode* node) const;
 
   bookmarks::BookmarkModel* bookmark_model() { return model_; }
+  const bookmarks::BookmarkModel* bookmark_model() const { return model_; }
+  const bookmarks::ManagedBookmarkService* managed_bookmark_service() const {
+    return managed_bookmark_service_;
+  }
 
   // Must be called for trackers to be initialized.
   // `BookmarkModel` also must complete loading for this to complete loading.
diff --git a/chrome/browser/bookmarks/bookmark_merged_surface_service_unittest.cc b/chrome/browser/bookmarks/bookmark_merged_surface_service_unittest.cc
index 35a10aae..9c262dd7 100644
--- a/chrome/browser/bookmarks/bookmark_merged_surface_service_unittest.cc
+++ b/chrome/browser/bookmarks/bookmark_merged_surface_service_unittest.cc
@@ -16,9 +16,9 @@
 #include "chrome/browser/bookmarks/bookmark_merged_surface_service_observer.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/bookmarks/bookmark_parent_folder_children.h"
+#include "chrome/browser/bookmarks/bookmark_test_utils.h"
 #include "components/bookmarks/browser/bookmark_model.h"
 #include "components/bookmarks/browser/bookmark_node.h"
-#include "components/bookmarks/common/bookmark_pref_names.h"
 #include "components/bookmarks/managed/managed_bookmark_service.h"
 #include "components/bookmarks/test/bookmark_test_helpers.h"
 #include "components/bookmarks/test/test_bookmark_client.h"
@@ -73,48 +73,6 @@
   return BookmarkParentFolder::FromFolderNode(node->parent()) == parent;
 }
 
-base::Value::List ConstructManagedBookmarks(size_t managed_bookmarks_size) {
-  const GURL url("http://google.com/");
-  base::Value::List bookmarks_list;
-  for (size_t i = 0; i < managed_bookmarks_size; ++i) {
-    base::Value::List folder_items;
-    folder_items.Append(
-        base::Value::Dict().Set("name", "Google").Set("url", url.spec()));
-    bookmarks_list.Append(
-        base::Value::Dict()
-            .Set("name", "Bookmark folder " + base::NumberToString(i))
-            .Set("children", std::move(folder_items)));
-  }
-  return bookmarks_list;
-}
-
-class TestBookmarkClientWithManagedService
-    : public bookmarks::TestBookmarkClient {
- public:
-  explicit TestBookmarkClientWithManagedService(
-      bookmarks::ManagedBookmarkService* managed_bookmark_service)
-      : managed_bookmark_service_(managed_bookmark_service) {
-    CHECK(managed_bookmark_service);
-  }
-
-  // BookmarkClient:
-  void Init(bookmarks::BookmarkModel* model) override {
-    managed_bookmark_service_->BookmarkModelCreated(model);
-  }
-  bookmarks::LoadManagedNodeCallback GetLoadManagedNodeCallback() override {
-    return managed_bookmark_service_->GetLoadManagedNodeCallback();
-  }
-  bool CanSetPermanentNodeTitle(const BookmarkNode* permanent_node) override {
-    return managed_bookmark_service_->CanSetPermanentNodeTitle(permanent_node);
-  }
-  bool IsNodeManaged(const BookmarkNode* node) override {
-    return managed_bookmark_service_->IsNodeManaged(node);
-  }
-
- private:
-  const raw_ptr<bookmarks::ManagedBookmarkService> managed_bookmark_service_;
-};
-
 class MockBookmarkMergedSurfaceServiceObserver
     : public BookmarkMergedSurfaceServiceObserver {
  public:
@@ -164,7 +122,7 @@
     if (with_managed_node) {
       CHECK(managed_bookmarks_size);
       managed_bookmark_service_ =
-          CreateManagedBookmarkService(managed_bookmarks_size);
+          CreateManagedBookmarkService(&prefs_, managed_bookmarks_size);
       bookmark_client = std::make_unique<TestBookmarkClientWithManagedService>(
           managed_bookmark_service_.get());
     } else {
@@ -201,21 +159,6 @@
   }
 
  private:
-  std::unique_ptr<bookmarks::ManagedBookmarkService>
-  CreateManagedBookmarkService(size_t managed_bookmarks_size) {
-    prefs_.registry()->RegisterListPref(bookmarks::prefs::kManagedBookmarks);
-    prefs_.registry()->RegisterStringPref(
-        bookmarks::prefs::kManagedBookmarksFolderName, std::string());
-
-    prefs_.SetString(bookmarks::prefs::kManagedBookmarksFolderName, "Managed");
-    prefs_.SetManagedPref(bookmarks::prefs::kManagedBookmarks,
-                          ConstructManagedBookmarks(managed_bookmarks_size));
-
-    return std::make_unique<bookmarks::ManagedBookmarkService>(
-        &prefs_, base::BindRepeating(
-                     []() -> std::string { return "managedDomain.com"; }));
-  }
-
   base::test::ScopedFeatureList features_{
       switches::kSyncEnableBookmarksInTransportMode};
   sync_preferences::TestingPrefServiceSyncable prefs_;
diff --git a/chrome/browser/bookmarks/bookmark_test_utils.cc b/chrome/browser/bookmarks/bookmark_test_utils.cc
new file mode 100644
index 0000000..770fcda
--- /dev/null
+++ b/chrome/browser/bookmarks/bookmark_test_utils.cc
@@ -0,0 +1,67 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/bookmarks/bookmark_test_utils.h"
+
+#include "components/bookmarks/common/bookmark_pref_names.h"
+#include "components/bookmarks/managed/managed_bookmark_service.h"
+#include "components/sync_preferences/testing_pref_service_syncable.h"
+
+namespace {
+
+base::Value::List ConstructManagedBookmarks(size_t managed_bookmarks_size) {
+  const GURL url("http://google.com/");
+  base::Value::List bookmarks_list;
+  for (size_t i = 0; i < managed_bookmarks_size; ++i) {
+    base::Value::List folder_items;
+    folder_items.Append(
+        base::Value::Dict().Set("name", "Google").Set("url", url.spec()));
+    bookmarks_list.Append(
+        base::Value::Dict()
+            .Set("name", "Bookmark folder " + base::NumberToString(i))
+            .Set("children", std::move(folder_items)));
+  }
+  return bookmarks_list;
+}
+
+}  // namespace
+
+std::unique_ptr<bookmarks::ManagedBookmarkService> CreateManagedBookmarkService(
+    sync_preferences::TestingPrefServiceSyncable* prefs,
+    size_t managed_bookmarks_size) {
+  prefs->registry()->RegisterListPref(bookmarks::prefs::kManagedBookmarks);
+  prefs->registry()->RegisterStringPref(
+      bookmarks::prefs::kManagedBookmarksFolderName, std::string());
+
+  prefs->SetString(bookmarks::prefs::kManagedBookmarksFolderName, "Managed");
+  prefs->SetManagedPref(bookmarks::prefs::kManagedBookmarks,
+                        ConstructManagedBookmarks(managed_bookmarks_size));
+
+  return std::make_unique<bookmarks::ManagedBookmarkService>(
+      prefs,
+      base::BindRepeating([]() -> std::string { return "managedDomain.com"; }));
+}
+
+TestBookmarkClientWithManagedService::TestBookmarkClientWithManagedService(
+    bookmarks::ManagedBookmarkService* managed_bookmark_service)
+    : managed_bookmark_service_(managed_bookmark_service) {
+  CHECK(managed_bookmark_service);
+}
+
+void TestBookmarkClientWithManagedService::Init(
+    bookmarks::BookmarkModel* model) {
+  managed_bookmark_service_->BookmarkModelCreated(model);
+}
+bookmarks::LoadManagedNodeCallback
+TestBookmarkClientWithManagedService::GetLoadManagedNodeCallback() {
+  return managed_bookmark_service_->GetLoadManagedNodeCallback();
+}
+bool TestBookmarkClientWithManagedService::CanSetPermanentNodeTitle(
+    const bookmarks::BookmarkNode* permanent_node) {
+  return managed_bookmark_service_->CanSetPermanentNodeTitle(permanent_node);
+}
+bool TestBookmarkClientWithManagedService::IsNodeManaged(
+    const bookmarks::BookmarkNode* node) {
+  return managed_bookmark_service_->IsNodeManaged(node);
+}
diff --git a/chrome/browser/bookmarks/bookmark_test_utils.h b/chrome/browser/bookmarks/bookmark_test_utils.h
new file mode 100644
index 0000000..448fe28
--- /dev/null
+++ b/chrome/browser/bookmarks/bookmark_test_utils.h
@@ -0,0 +1,45 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/bookmarks/test/test_bookmark_client.h"
+
+#ifndef CHROME_BROWSER_BOOKMARKS_BOOKMARK_TEST_UTILS_H_
+#define CHROME_BROWSER_BOOKMARKS_BOOKMARK_TEST_UTILS_H_
+
+namespace bookmarks {
+class ManagedBookmarkService;
+class BookmarkNode;
+}  // namespace bookmarks
+
+namespace sync_preferences {
+class TestingPrefServiceSyncable;
+}  // namespace sync_preferences
+
+// Creates an instance of `bookmarks::ManagedBookmarkService` for testing. It
+// will generate `managed_bookmarks_size` number of bookmarks within the managed
+// node.
+std::unique_ptr<bookmarks::ManagedBookmarkService> CreateManagedBookmarkService(
+    sync_preferences::TestingPrefServiceSyncable* prefs,
+    size_t managed_bookmarks_size);
+
+// Bookmark client to be used with `bookmarks::ManagedBookmarkService` for
+// testing managed nodes.
+class TestBookmarkClientWithManagedService
+    : public bookmarks::TestBookmarkClient {
+ public:
+  explicit TestBookmarkClientWithManagedService(
+      bookmarks::ManagedBookmarkService* managed_bookmark_service);
+
+  // BookmarkClient:
+  void Init(bookmarks::BookmarkModel* model) override;
+  bookmarks::LoadManagedNodeCallback GetLoadManagedNodeCallback() override;
+  bool CanSetPermanentNodeTitle(
+      const bookmarks::BookmarkNode* permanent_node) override;
+  bool IsNodeManaged(const bookmarks::BookmarkNode* node) override;
+
+ private:
+  const raw_ptr<bookmarks::ManagedBookmarkService> managed_bookmark_service_;
+};
+
+#endif  // CHROME_BROWSER_BOOKMARKS_BOOKMARK_TEST_UTILS_H_
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 8066a737..37ac77e 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -1620,9 +1620,6 @@
   registry->RegisterBooleanPref(prefs::kDataUrlInSvgUseEnabled, false);
   registry->RegisterBooleanPref(prefs::kPartitionedBlobUrlUsage, true);
 
-  registry->RegisterBooleanPref(policy::policy_prefs::kMutationEventsEnabled,
-                                false);
-
   registry->RegisterBooleanPref(
       policy::policy_prefs::kCSSCustomStateDeprecatedSyntaxEnabled,
       /*default_value=*/false);
@@ -2809,10 +2806,6 @@
             blink::switches::kDisableBlobUrlPartitioning);
       }
 
-      if (prefs->GetBoolean(policy::policy_prefs::kMutationEventsEnabled)) {
-        command_line->AppendSwitch(blink::switches::kMutationEventsEnabled);
-      }
-
       if (!prefs->GetBoolean(
               policy::policy_prefs::kKeyboardFocusableScrollersEnabled)) {
         command_line->AppendSwitch(
diff --git a/chrome/browser/devtools/BUILD.gn b/chrome/browser/devtools/BUILD.gn
index 22055e17..9b69713d 100644
--- a/chrome/browser/devtools/BUILD.gn
+++ b/chrome/browser/devtools/BUILD.gn
@@ -13,11 +13,16 @@
   import("//tools/grit/grit_rule.gni")
 }
 
-if (enable_devtools_frontend) {
-  _inspector_protocol = "//third_party/inspector_protocol"
-  import("$_inspector_protocol/inspector_protocol.gni")
+_inspector_protocol = "//third_party/inspector_protocol"
+import("$_inspector_protocol/inspector_protocol.gni")
 
-  _protocol_generated = [
+_protocol_generated = [
+  "protocol/target.cc",
+  "protocol/target.h",
+]
+
+if (!is_android || is_desktop_android) {
+  _protocol_generated += [
     "protocol/autofill.cc",
     "protocol/autofill.h",
     "protocol/extensions.cc",
@@ -39,8 +44,6 @@
     "protocol/storage.h",
     "protocol/system_info.cc",
     "protocol/system_info.h",
-    "protocol/target.cc",
-    "protocol/target.h",
   ]
 
   if (is_chromeos) {
@@ -49,47 +52,47 @@
       "protocol/window_manager.h",
     ]
   }
+}
 
-  _concatenated_protocol_path =
-      "$root_gen_dir/chrome/browser/devtools/protocol.json"
-  action("concatenate_protocols") {
-    script = _inspector_protocol + "/concatenate_protocols.py"
+_concatenated_protocol_path =
+    "$root_gen_dir/chrome/browser/devtools/protocol.json"
+action("concatenate_protocols") {
+  script = _inspector_protocol + "/concatenate_protocols.py"
 
-    deps = [ "//third_party/blink/public/devtools_protocol:protocol_version" ]
+  deps = [ "//third_party/blink/public/devtools_protocol:protocol_version" ]
 
-    _blink_protocol_path =
-        "$root_gen_dir/third_party/blink/public/devtools_protocol/protocol.json"
-    inputs = [ _blink_protocol_path ]
-    output_file = _concatenated_protocol_path
-    outputs = [ output_file ]
+  _blink_protocol_path =
+      "$root_gen_dir/third_party/blink/public/devtools_protocol/protocol.json"
+  inputs = [ _blink_protocol_path ]
+  output_file = _concatenated_protocol_path
+  outputs = [ output_file ]
 
-    args = [ rebase_path(_blink_protocol_path, root_build_dir) ]
-    if (is_chromeos) {
-      inputs += [ "cros_protocol.pdl" ]
-      args += [ rebase_path("cros_protocol.pdl", root_build_dir) ]
-    }
-
-    args += [ rebase_path(output_file, root_build_dir) ]
+  args = [ rebase_path(_blink_protocol_path, root_build_dir) ]
+  if (is_chromeos) {
+    inputs += [ "cros_protocol.pdl" ]
+    args += [ rebase_path("cros_protocol.pdl", root_build_dir) ]
   }
 
-  inspector_protocol_generate("protocol_generated_sources") {
-    inspector_protocol_dir = _inspector_protocol
-    visibility = [ ":*" ]  # Only targets in this file can depend on this.
-    deps = [ ":concatenate_protocols" ]
-    out_dir = target_gen_dir
-    config_file = "inspector_protocol_config.json"
-    use_embedder_types = true
+  args += [ rebase_path(output_file, root_build_dir) ]
+}
 
-    protocol_path = rebase_path(_concatenated_protocol_path, root_build_dir)
-    config_values = [ "protocol.path=$protocol_path" ]
+inspector_protocol_generate("protocol_generated_sources") {
+  inspector_protocol_dir = _inspector_protocol
+  visibility = [ ":*" ]  # Only targets in this file can depend on this.
+  deps = [ ":concatenate_protocols" ]
+  out_dir = target_gen_dir
+  config_file = "inspector_protocol_config.json"
+  use_embedder_types = true
 
-    inputs = [
-      _concatenated_protocol_path,
-      "inspector_protocol_config.json",
-    ]
+  protocol_path = rebase_path(_concatenated_protocol_path, root_build_dir)
+  config_values = [ "protocol.path=$protocol_path" ]
 
-    outputs = _protocol_generated
-  }
+  inputs = [
+    _concatenated_protocol_path,
+    "inspector_protocol_config.json",
+  ]
+
+  outputs = _protocol_generated
 }
 
 static_library("devtools") {
@@ -124,6 +127,7 @@
 
     # Similar bandaid as the above. Since we cannot depend on
     # //chrome/browser:browser, we include indirect dependencies here.
+    ":protocol_generated_sources",
     "//chrome/browser/autofill:autofill",
     "//components/autofill/content/browser:browser",
     "//components/autofill/core/browser:browser",
@@ -177,7 +181,6 @@
       "visual_logging.h",
     ]
     deps += [
-      ":protocol_generated_sources",
       "//chrome/browser:browser_process",
       "//chrome/browser/profiles:profile",
       "//chrome/browser/profiles:profile_util",
@@ -196,7 +199,13 @@
   }
 
   if (is_android) {
-    sources += [ "devtools_window_android.cc" ]
+    sources += [
+      "chrome_devtools_session_android.cc",
+      "chrome_devtools_session_android.h",
+      "devtools_window_android.cc",
+      "protocol/target_handler_android.cc",
+      "protocol/target_handler_android.h",
+    ]
   } else {
     public_deps += [
       "//chrome/browser/ui:browser_list",
@@ -367,9 +376,10 @@
         deps += [ "//chrome/services/printing/public/mojom" ]
       }
     }
-    sources += rebase_path(_protocol_generated, ".", target_gen_dir)
   }
 
+  sources += rebase_path(_protocol_generated, ".", target_gen_dir)
+
   if (enable_extensions) {
     deps += [
       "//chrome/common/extensions/api",
diff --git a/chrome/browser/devtools/chrome_devtools_session_android.cc b/chrome/browser/devtools/chrome_devtools_session_android.cc
new file mode 100644
index 0000000..320f1322
--- /dev/null
+++ b/chrome/browser/devtools/chrome_devtools_session_android.cc
@@ -0,0 +1,86 @@
+// 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/devtools/chrome_devtools_session_android.h"
+
+#include "base/metrics/histogram_functions.h"
+#include "base/metrics/metrics_hashes.h"
+#include "chrome/browser/devtools/protocol/target_handler_android.h"
+#include "content/public/browser/devtools_agent_host_client_channel.h"
+
+namespace {
+
+template <typename Handler>
+bool IsDomainAvailableToUntrustedClient() {
+  return std::disjunction_v<std::is_same<Handler, TargetHandlerAndroid>>;
+}
+
+}  // namespace
+
+ChromeDevToolsSessionAndroid::ChromeDevToolsSessionAndroid(
+    content::DevToolsAgentHostClientChannel* channel)
+    : dispatcher_(this), client_channel_(channel) {
+  if (IsDomainAvailableToUntrustedClient<TargetHandlerAndroid>() ||
+      channel->GetClient()->IsTrusted()) {
+    target_handler_ = std::make_unique<TargetHandlerAndroid>(
+        &dispatcher_, channel->GetClient()->IsTrusted(),
+        channel->GetClient()->MayReadLocalFiles());
+  }
+}
+
+ChromeDevToolsSessionAndroid::~ChromeDevToolsSessionAndroid() = default;
+
+base::HistogramBase::Sample32 GetCommandUmaId(std::string_view command_name) {
+  return static_cast<base::HistogramBase::Sample32>(
+      base::HashMetricName(command_name));
+}
+
+void ChromeDevToolsSessionAndroid::HandleCommand(
+    base::span<const uint8_t> message,
+    content::DevToolsManagerDelegate::NotHandledCallback callback) {
+  crdtp::Dispatchable dispatchable(crdtp::SpanFrom(message));
+  DCHECK(dispatchable.ok());  // Checked by content::DevToolsSession.
+  crdtp::UberDispatcher::DispatchResult dispatched =
+      dispatcher_.Dispatch(dispatchable);
+
+  auto command_uma_id = GetCommandUmaId(std::string_view(
+      reinterpret_cast<const char*>(dispatchable.Method().data()),
+      dispatchable.Method().size()));
+  std::string client_type = client_channel_->GetClient()->GetTypeForMetrics();
+  DCHECK(client_type == "DevTools" || client_type == "Extension" ||
+         client_type == "RemoteDebugger" || client_type == "Other");
+  base::UmaHistogramSparse("DevTools.CDPCommandFrom" + client_type,
+                           command_uma_id);
+
+  if (!dispatched.MethodFound()) {
+    std::move(callback).Run(message);
+    return;
+  }
+  pending_commands_[dispatchable.CallId()] = std::move(callback);
+  dispatched.Run();
+}
+
+// The following methods handle responses or notifications coming from
+// the browser to the client.
+void ChromeDevToolsSessionAndroid::SendProtocolResponse(
+    int call_id,
+    std::unique_ptr<protocol::Serializable> message) {
+  pending_commands_.erase(call_id);
+  client_channel_->DispatchProtocolMessageToClient(message->Serialize());
+}
+
+void ChromeDevToolsSessionAndroid::SendProtocolNotification(
+    std::unique_ptr<protocol::Serializable> message) {
+  client_channel_->DispatchProtocolMessageToClient(message->Serialize());
+}
+
+void ChromeDevToolsSessionAndroid::FlushProtocolNotifications() {}
+
+void ChromeDevToolsSessionAndroid::FallThrough(int call_id,
+                                               crdtp::span<uint8_t> method,
+                                               crdtp::span<uint8_t> message) {
+  auto callback = std::move(pending_commands_[call_id]);
+  pending_commands_.erase(call_id);
+  std::move(callback).Run(message);
+}
diff --git a/chrome/browser/devtools/chrome_devtools_session_android.h b/chrome/browser/devtools/chrome_devtools_session_android.h
new file mode 100644
index 0000000..a6620bd
--- /dev/null
+++ b/chrome/browser/devtools/chrome_devtools_session_android.h
@@ -0,0 +1,59 @@
+// 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_DEVTOOLS_CHROME_DEVTOOLS_SESSION_ANDROID_H_
+#define CHROME_BROWSER_DEVTOOLS_CHROME_DEVTOOLS_SESSION_ANDROID_H_
+
+#include <memory>
+
+#include "base/containers/flat_map.h"
+#include "base/containers/span.h"
+#include "base/memory/raw_ptr.h"
+#include "chrome/browser/devtools/protocol/protocol.h"
+#include "content/public/browser/devtools_manager_delegate.h"
+
+namespace content {
+class DevToolsAgentHostClientChannel;
+}  // namespace content
+
+class TargetHandlerAndroid;
+
+class ChromeDevToolsSessionAndroid : public protocol::FrontendChannel {
+ public:
+  explicit ChromeDevToolsSessionAndroid(
+      content::DevToolsAgentHostClientChannel* channel);
+
+  ChromeDevToolsSessionAndroid(const ChromeDevToolsSessionAndroid&) = delete;
+  ChromeDevToolsSessionAndroid& operator=(const ChromeDevToolsSessionAndroid&) =
+      delete;
+
+  ~ChromeDevToolsSessionAndroid() override;
+
+  void HandleCommand(
+      base::span<const uint8_t> message,
+      content::DevToolsManagerDelegate::NotHandledCallback callback);
+
+  TargetHandlerAndroid* target_handler() { return target_handler_.get(); }
+
+ private:
+  // protocol::FrontendChannel:
+  void SendProtocolResponse(
+      int call_id,
+      std::unique_ptr<protocol::Serializable> message) override;
+  void SendProtocolNotification(
+      std::unique_ptr<protocol::Serializable> message) override;
+  void FlushProtocolNotifications() override;
+  void FallThrough(int call_id,
+                   crdtp::span<uint8_t> method,
+                   crdtp::span<uint8_t> message) override;
+
+  base::flat_map<int, content::DevToolsManagerDelegate::NotHandledCallback>
+      pending_commands_;
+
+  protocol::UberDispatcher dispatcher_;
+  std::unique_ptr<TargetHandlerAndroid> target_handler_;
+  raw_ptr<content::DevToolsAgentHostClientChannel> client_channel_;
+};
+
+#endif  // CHROME_BROWSER_DEVTOOLS_CHROME_DEVTOOLS_SESSION_ANDROID_H_
diff --git a/chrome/browser/devtools/protocol/target_handler_android.cc b/chrome/browser/devtools/protocol/target_handler_android.cc
new file mode 100644
index 0000000..35ae7e8
--- /dev/null
+++ b/chrome/browser/devtools/protocol/target_handler_android.cc
@@ -0,0 +1,77 @@
+// 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/devtools/protocol/target_handler_android.h"
+
+#include "chrome/browser/android/devtools_manager_delegate_android.h"
+#include "chrome/browser/ui/android/tab_model/tab_model.h"
+#include "chrome/browser/ui/android/tab_model/tab_model_list.h"
+#include "content/public/browser/web_contents.h"
+
+using content::WebContents;
+
+TargetHandlerAndroid::TargetHandlerAndroid(protocol::UberDispatcher* dispatcher,
+                                           bool is_trusted,
+                                           bool may_read_local_files) {
+  protocol::Target::Dispatcher::wire(dispatcher, this);
+}
+
+TargetHandlerAndroid::~TargetHandlerAndroid() = default;
+
+protocol::Response TargetHandlerAndroid::SetRemoteLocations(
+    std::unique_ptr<protocol::Array<protocol::Target::RemoteLocation>>
+        locations) {
+  remote_locations_.clear();
+  if (!locations) {
+    return protocol::Response::Success();
+  }
+
+  for (const auto& location : *locations) {
+    remote_locations_.insert(
+        net::HostPortPair(location->GetHost(), location->GetPort()));
+  }
+
+  return protocol::Response::Success();
+}
+
+protocol::Response TargetHandlerAndroid::CreateTarget(
+    const std::string& url,
+    std::optional<int> left,
+    std::optional<int> top,
+    std::optional<int> width,
+    std::optional<int> height,
+    std::optional<std::string> window_state,
+    std::optional<std::string> browser_context_id,
+    std::optional<bool> enable_begin_frame_control,
+    std::optional<bool> new_window,
+    std::optional<bool> background,
+    std::optional<bool> for_tab,
+    std::optional<bool> hidden,
+    std::string* out_target_id) {
+  const TabModelList::TabModelVector& models = TabModelList::models();
+  if (models.empty()) {
+    return protocol::Response::ServerError("Could not find TabModelList");
+  }
+
+  TabModel* tab_model = models[0];
+  CHECK(tab_model);
+
+  WebContents* web_contents =
+      tab_model->CreateNewTabForDevTools(GURL(url), new_window.value_or(false));
+  if (!web_contents) {
+    return protocol::Response::ServerError("Could not create a Tab");
+  }
+
+  DevToolsManagerDelegateAndroid::MarkCreatedByDevTools(*web_contents);
+
+  if (for_tab.value_or(false)) {
+    *out_target_id =
+        content::DevToolsAgentHost::GetOrCreateForTab(web_contents)->GetId();
+  } else {
+    *out_target_id =
+        content::DevToolsAgentHost::GetOrCreateFor(web_contents)->GetId();
+  }
+
+  return protocol::Response::Success();
+}
diff --git a/chrome/browser/devtools/protocol/target_handler_android.h b/chrome/browser/devtools/protocol/target_handler_android.h
new file mode 100644
index 0000000..715dd78d
--- /dev/null
+++ b/chrome/browser/devtools/protocol/target_handler_android.h
@@ -0,0 +1,51 @@
+// 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_DEVTOOLS_PROTOCOL_TARGET_HANDLER_ANDROID_H_
+#define CHROME_BROWSER_DEVTOOLS_PROTOCOL_TARGET_HANDLER_ANDROID_H_
+
+#include <set>
+
+#include "chrome/browser/devtools/protocol/target.h"
+#include "net/base/host_port_pair.h"
+
+using RemoteLocations = std::set<net::HostPortPair>;
+
+class TargetHandlerAndroid : public protocol::Target::Backend {
+ public:
+  TargetHandlerAndroid(protocol::UberDispatcher* dispatcher,
+                       bool is_trusted,
+                       bool may_read_local_files);
+
+  TargetHandlerAndroid(const TargetHandlerAndroid&) = delete;
+  TargetHandlerAndroid& operator=(const TargetHandlerAndroid&) = delete;
+
+  ~TargetHandlerAndroid() override;
+
+  RemoteLocations& remote_locations() { return remote_locations_; }
+
+  // Target::Backend:
+  protocol::Response SetRemoteLocations(
+      std::unique_ptr<protocol::Array<protocol::Target::RemoteLocation>>
+          in_locations) override;
+  protocol::Response CreateTarget(
+      const std::string& url,
+      std::optional<int> left,
+      std::optional<int> top,
+      std::optional<int> width,
+      std::optional<int> height,
+      std::optional<std::string> window_state,
+      std::optional<std::string> browser_context_id,
+      std::optional<bool> enable_begin_frame_control,
+      std::optional<bool> new_window,
+      std::optional<bool> background,
+      std::optional<bool> for_tab,
+      std::optional<bool> hidden,
+      std::string* out_target_id) override;
+
+ private:
+  RemoteLocations remote_locations_;
+};
+
+#endif  // CHROME_BROWSER_DEVTOOLS_PROTOCOL_TARGET_HANDLER_ANDROID_H_
diff --git a/chrome/browser/dom_distiller/dom_distiller_service_factory.cc b/chrome/browser/dom_distiller/dom_distiller_service_factory.cc
index 4dccc99..eb4d453 100644
--- a/chrome/browser/dom_distiller/dom_distiller_service_factory.cc
+++ b/chrome/browser/dom_distiller/dom_distiller_service_factory.cc
@@ -9,7 +9,6 @@
 
 #include "chrome/browser/dom_distiller/dom_distiller_service_factory.h"
 
-#include <string_view>
 #include <utility>
 
 #include "base/task/sequenced_task_runner.h"
@@ -91,7 +90,8 @@
 
   dom_distiller::proto::DomDistillerOptions options;
   if (VLOG_IS_ON(1)) {
-    options.set_debug_level(logging::GetVlogLevelHelper(FROM_HERE.file_name()));
+    options.set_debug_level(logging::GetVlogLevelHelper(
+        FROM_HERE.file_name(), ::strlen(FROM_HERE.file_name())));
   }
   // Options for pagination algorithm:
   // - "next": detect anchors with "next" text
diff --git a/chrome/browser/educational_tip/java/src/org/chromium/chrome/browser/educational_tip/EducationalTipModuleBuilder.java b/chrome/browser/educational_tip/java/src/org/chromium/chrome/browser/educational_tip/EducationalTipModuleBuilder.java
index e319064..83ffd802c 100644
--- a/chrome/browser/educational_tip/java/src/org/chromium/chrome/browser/educational_tip/EducationalTipModuleBuilder.java
+++ b/chrome/browser/educational_tip/java/src/org/chromium/chrome/browser/educational_tip/EducationalTipModuleBuilder.java
@@ -48,11 +48,6 @@
             return false;
         }
 
-        if (mModuleType == ModuleType.TAB_GROUP_SYNC_PROMO
-                && !ChromeFeatureList.sTabGroupPaneAndroid.isEnabled()) {
-            return false;
-        }
-
         if (mModuleType == ModuleType.DEFAULT_BROWSER_PROMO
                 && !ChromeFeatureList.sEducationalTipDefaultBrowserPromoCard.isEnabled()) {
             return false;
diff --git a/chrome/browser/educational_tip/junit/src/org/chromium/chrome/browser/educational_tip/EducationalTipModuleBuilderUnitTest.java b/chrome/browser/educational_tip/junit/src/org/chromium/chrome/browser/educational_tip/EducationalTipModuleBuilderUnitTest.java
index 4a5ac740..bc56bf9 100644
--- a/chrome/browser/educational_tip/junit/src/org/chromium/chrome/browser/educational_tip/EducationalTipModuleBuilderUnitTest.java
+++ b/chrome/browser/educational_tip/junit/src/org/chromium/chrome/browser/educational_tip/EducationalTipModuleBuilderUnitTest.java
@@ -137,23 +137,7 @@
     @SmallTest
     @EnableFeatures({
         ChromeFeatureList.EDUCATIONAL_TIP_MODULE,
-        ChromeFeatureList.SEGMENTATION_PLATFORM_EPHEMERAL_CARD_RANKER
-    })
-    @DisableFeatures({ChromeFeatureList.TAB_GROUP_PANE_ANDROID})
-    public void testBuildEducationalTipTabGroupSyncModule_NotEligible() {
-        EducationalTipModuleBuilder moduleBuilderForTabGroupSync =
-                new EducationalTipModuleBuilder(ModuleType.TAB_GROUP_SYNC_PROMO, mActionDelegate);
-
-        assertFalse(moduleBuilderForTabGroupSync.build(mModuleDelegate, mBuildCallback));
-        verify(mBuildCallback, never()).onResult(any(ModuleProvider.class));
-    }
-
-    @Test
-    @SmallTest
-    @EnableFeatures({
-        ChromeFeatureList.EDUCATIONAL_TIP_MODULE,
         ChromeFeatureList.SEGMENTATION_PLATFORM_EPHEMERAL_CARD_RANKER,
-        ChromeFeatureList.TAB_GROUP_PANE_ANDROID
     })
     public void testBuildEducationalTipTabGroupSyncModule_Eligible() {
         EducationalTipModuleBuilder moduleBuilderForTabGroupSync =
diff --git a/chrome/browser/enterprise/signin/interstitials/managed_profile_required_page.cc b/chrome/browser/enterprise/signin/interstitials/managed_profile_required_page.cc
index 91bb9b1..dfb55069 100644
--- a/chrome/browser/enterprise/signin/interstitials/managed_profile_required_page.cc
+++ b/chrome/browser/enterprise/signin/interstitials/managed_profile_required_page.cc
@@ -143,9 +143,6 @@
   load_time_data.Set("managed-profile-required", true);
   load_time_data.Set("overridable", false);
   load_time_data.Set("hide_primary_button", false);
-  load_time_data.Set("show_recurrent_error_paragraph", false);
-
-  load_time_data.Set("recurrentErrorParagraph", "");
   load_time_data.Set("openDetails", "");
   load_time_data.Set("optInLink", "");
   load_time_data.Set("enhancedProtectionMessage", "");
diff --git a/chrome/browser/error_reporting/webui_js_error_reporting_browsertest.cc b/chrome/browser/error_reporting/webui_js_error_reporting_browsertest.cc
index 4311d54c..ebdacfd 100644
--- a/chrome/browser/error_reporting/webui_js_error_reporting_browsertest.cc
+++ b/chrome/browser/error_reporting/webui_js_error_reporting_browsertest.cc
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 #include <memory>
-#include <string_view>
 
 #include "base/containers/contains.h"
 #include "base/test/scoped_feature_list.h"
@@ -108,7 +107,7 @@
 
  private:
   static bool MessageHandler(int severity,
-                             std::string_view file,
+                             const char* file,
                              int line,
                              size_t message_start,
                              const std::string& str) {
diff --git a/chrome/browser/extensions/api/preference/cookie_controls_mode_transformer.cc b/chrome/browser/extensions/api/preference/cookie_controls_mode_transformer.cc
index 24405729..ca39cf3 100644
--- a/chrome/browser/extensions/api/preference/cookie_controls_mode_transformer.cc
+++ b/chrome/browser/extensions/api/preference/cookie_controls_mode_transformer.cc
@@ -33,10 +33,10 @@
       static_cast<content_settings::CookieControlsMode>(browser_pref.GetInt());
 
   bool third_party_cookies_allowed = cookie_control_mode == kOff;
-  if ((third_party_cookies_allowed &&
+  if (cookie_control_mode == kIncognitoOnly ||
+      (third_party_cookies_allowed &&
        base::FeatureList::IsEnabled(
-           privacy_sandbox::kAlwaysBlock3pcsIncognito)) ||
-      cookie_control_mode == kIncognitoOnly) {
+           privacy_sandbox::kAlwaysBlock3pcsIncognito))) {
     third_party_cookies_allowed = !is_incognito_profile;
   }
   return base::Value(third_party_cookies_allowed);
diff --git a/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc b/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
index 7d9c757d..2341a5f 100644
--- a/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
+++ b/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
@@ -617,6 +617,7 @@
 
   Browser* otr_browser = OpenURLOffTheRecord(browser()->profile(), url);
   WebContents* tab = otr_browser->tab_strip_model()->GetActiveWebContents();
+  content::SimulateEndOfPaintHoldingOnPrimaryMainFrame(tab);
 
   // There's a link with target=_blank on a.html. Click on it to open it in a
   // new tab.
diff --git a/chrome/browser/extensions/chrome_extension_registrar_delegate.cc b/chrome/browser/extensions/chrome_extension_registrar_delegate.cc
index 42e3372..a727bf4 100644
--- a/chrome/browser/extensions/chrome_extension_registrar_delegate.cc
+++ b/chrome/browser/extensions/chrome_extension_registrar_delegate.cc
@@ -117,6 +117,14 @@
   CheckPermissionsIncrease(extension, !!old_extension);
 }
 
+void ChromeExtensionRegistrarDelegate::OnAddNewOrUpdatedExtension(
+    const Extension* extension) {
+  delayed_install_manager_->Remove(extension->id());
+  if (InstallVerifier::NeedsVerification(*extension, profile_)) {
+    InstallVerifier::Get(profile_)->VerifyExtension(extension->id());
+  }
+}
+
 void ChromeExtensionRegistrarDelegate::PostActivateExtension(
     scoped_refptr<const Extension> extension) {
   // Update policy permissions in case they were changed while extension was not
diff --git a/chrome/browser/extensions/chrome_extension_registrar_delegate.h b/chrome/browser/extensions/chrome_extension_registrar_delegate.h
index 9bb63ed..b14da52d 100644
--- a/chrome/browser/extensions/chrome_extension_registrar_delegate.h
+++ b/chrome/browser/extensions/chrome_extension_registrar_delegate.h
@@ -45,6 +45,7 @@
   // ExtensionRegistrar::Delegate:
   void PreAddExtension(const Extension* extension,
                        const Extension* old_extension) override;
+  void OnAddNewOrUpdatedExtension(const Extension* extension) override;
   void PostActivateExtension(scoped_refptr<const Extension> extension) override;
   void PostDeactivateExtension(
       scoped_refptr<const Extension> extension) override;
diff --git a/chrome/browser/extensions/desktop_android/desktop_android_extension_system.cc b/chrome/browser/extensions/desktop_android/desktop_android_extension_system.cc
index 8cbfe73..97c9dda 100644
--- a/chrome/browser/extensions/desktop_android/desktop_android_extension_system.cc
+++ b/chrome/browser/extensions/desktop_android/desktop_android_extension_system.cc
@@ -102,6 +102,7 @@
   // ExtensionRegistrar::Delegate:
   void PreAddExtension(const Extension* extension,
                        const Extension* old_extension) override {}
+  void OnAddNewOrUpdatedExtension(const Extension* extension) override {}
   void PostActivateExtension(
       scoped_refptr<const Extension> extension) override {}
   void PostDeactivateExtension(
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index 49c8477..8ebb737d98 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -829,9 +829,9 @@
 
     // TODO(crbug.com/40508457): If needed, add support for Declarative Net
     // Request to component extensions and pass the ruleset install prefs here.
-    AddNewOrUpdatedExtension(extension, {}, kInstallFlagNone,
-                             syncer::StringOrdinal(), std::string(),
-                             /*ruleset_install_prefs=*/{});
+    extension_registrar_->AddNewOrUpdatedExtension(
+        extension, {}, kInstallFlagNone, syncer::StringOrdinal(), std::string(),
+        /*ruleset_install_prefs=*/{});
     return;
   }
 
@@ -965,9 +965,9 @@
           &delay_reason);
   switch (action) {
     case InstallGate::INSTALL:
-      AddNewOrUpdatedExtension(extension, disable_reasons, install_flags,
-                               page_ordinal, install_parameter,
-                               std::move(ruleset_install_prefs));
+      extension_registrar_->AddNewOrUpdatedExtension(
+          extension, disable_reasons, install_flags, page_ordinal,
+          install_parameter, std::move(ruleset_install_prefs));
       return;
     case InstallGate::DELAY:
       extension_prefs_->SetDelayedInstallInfo(
@@ -1027,25 +1027,6 @@
   }
 }
 
-void ExtensionService::AddNewOrUpdatedExtension(
-    const Extension* extension,
-    const base::flat_set<int>& disable_reasons,
-    int install_flags,
-    const syncer::StringOrdinal& page_ordinal,
-    const std::string& install_parameter,
-    base::Value::Dict ruleset_install_prefs) {
-  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  extension_prefs_->OnExtensionInstalled(
-      extension, disable_reasons, page_ordinal, install_flags,
-      install_parameter, std::move(ruleset_install_prefs));
-  delayed_install_manager_->Remove(extension->id());
-  if (InstallVerifier::NeedsVerification(*extension, GetBrowserContext())) {
-    InstallVerifier::Get(GetBrowserContext())->VerifyExtension(extension->id());
-  }
-
-  extension_registrar_->FinishInstallation(extension);
-}
-
 bool ExtensionService::FinishDelayedInstallationIfReady(
     const std::string& extension_id,
     bool install_immediately) {
diff --git a/chrome/browser/extensions/extension_service.h b/chrome/browser/extensions/extension_service.h
index 5be35b42..cfd6ae0 100644
--- a/chrome/browser/extensions/extension_service.h
+++ b/chrome/browser/extensions/extension_service.h
@@ -440,18 +440,6 @@
   // Signals *ready_ and sends a notification to the listeners.
   void SetReadyAndNotifyListeners();
 
-  // Update preferences for a new or updated extension; notify observers that
-  // the extension is installed, e.g., to update event handlers on background
-  // pages; and perform other extension install tasks before calling
-  // AddExtension.
-  // |install_flags| is a bitmask of InstallFlags.
-  void AddNewOrUpdatedExtension(const Extension* extension,
-                                const base::flat_set<int>& disable_reasons,
-                                int install_flags,
-                                const syncer::StringOrdinal& page_ordinal,
-                                const std::string& install_parameter,
-                                base::Value::Dict ruleset_install_prefs);
-
   // Manages the blocklisted extensions, intended as callback from
   // Blocklist::GetBlocklistedIDs.
   void ManageBlocklist(const Blocklist::BlocklistStateMap& blocklisted_ids);
diff --git a/chrome/browser/extensions/updater/extension_updater_unittest.cc b/chrome/browser/extensions/updater/extension_updater_unittest.cc
index 0db18281..eb779e5 100644
--- a/chrome/browser/extensions/updater/extension_updater_unittest.cc
+++ b/chrome/browser/extensions/updater/extension_updater_unittest.cc
@@ -200,6 +200,7 @@
   // ExtensionRegistrar::Delegate:
   void PreAddExtension(const Extension* extension,
                        const Extension* old_extension) override {}
+  void OnAddNewOrUpdatedExtension(const Extension* extension) override {}
   void PostActivateExtension(
       scoped_refptr<const Extension> extension) override {}
   void PostDeactivateExtension(
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 0e755bb..5dd91e3 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -5241,11 +5241,6 @@
     "expiry_milestone": 140
   },
   {
-    "name": "home-customization",
-    "owners": [ "adamta@google.com", "rkgibson@google.com" ],
-    "expiry_milestone": 140
-  },
-  {
     "name": "home-memory-improvements",
     "owners": [ "thegreenfrog@google.com", "ajuma@google.com" ],
     "expiry_milestone": 140
@@ -8804,7 +8799,8 @@
     "owners": [ "gambard@chromium.org", "bling-flags@google.com" ],
     "expiry_milestone": 142
   },
-  { "name": "tab-group-entry-points-android",
+  {
+    "name": "tab-group-entry-points-android",
     "owners": [ "mfiaz@google.com", "clank-tab-dev@google.com" ],
     "expiry_milestone": 143
   },
@@ -8814,11 +8810,7 @@
     "expiry_milestone": 140
   },
   {
-    "name": "tab-group-pane-android",
-    "owners": [ "skym@chromium.org", "clank-tab-dev@google.com" ],
-    "expiry_milestone": 140
-  },
-  { "name": "tab-group-parity-bottom-sheet-android",
+    "name": "tab-group-parity-bottom-sheet-android",
     "owners": [ "mfiaz@google.com", "clank-tab-dev@google.com" ],
     "expiry_milestone": 140
   },
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 36e721e9..a53d105 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -4954,12 +4954,6 @@
 const char kHistoryPaneAndroidDescription[] =
     "Enables showing a new pane in the hub that displays History.";
 
-const char kTabGroupPaneAndroidName[] = "Tab Group Pane Android";
-const char kTabGroupPaneAndroidDescription[] =
-    "Enables showing a new pane in the hub that displays and allows "
-    "interactions with tab groups. These groups may be currently opened in the "
-    "tab mode or currently hidden.";
-
 const char kTabGroupSyncAndroidName[] = "Tab Group Sync on Android";
 const char kTabGroupSyncAndroidDescription[] =
     "Enables syncing of tab groups on Android with other devices.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index d3a7510..30bb4a6 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -2917,9 +2917,6 @@
 extern const char kHistoryPaneAndroidName[];
 extern const char kHistoryPaneAndroidDescription[];
 
-extern const char kTabGroupPaneAndroidName[];
-extern const char kTabGroupPaneAndroidDescription[];
-
 extern const char kTabGroupsForTabletsName[];
 extern const char kTabGroupsForTabletsDescription[];
 
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc
index 43c20e94..4977e4b 100644
--- a/chrome/browser/flags/android/chrome_feature_list.cc
+++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -422,7 +422,6 @@
     &syncer::kUnoPhase2FollowUp,
     &syncer::kSyncEnablePasswordsSyncErrorMessageAlternative,
     &tab_groups::kTabGroupSyncAndroid,
-    &tab_groups::kTabGroupPaneAndroid,
     &tab_groups::kTabGroupSyncAutoOpenKillSwitch,
     &tab_groups::kUseAlternateHistorySyncIllustration,
     &visited_url_ranking::features::kGroupSuggestionService,
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
index e860690c..a8f6f12cb 100644
--- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
+++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -540,7 +540,6 @@
     public static final String SYNC_ENABLE_PASSWORDS_SYNC_ERROR_MESSAGE_ALTERNATIVE =
             "SyncEnablePasswordsSyncErrorMessageAlternative";
     public static final String TAB_CLOSURE_METHOD_REFACTOR = "TabClosureMethodRefactor";
-    public static final String TAB_GROUP_PANE_ANDROID = "TabGroupPaneAndroid";
     public static final String TAB_GROUP_SYNC_ANDROID = "TabGroupSyncAndroid";
     public static final String TAB_GROUP_SYNC_AUTO_OPEN_KILL_SWITCH =
             "TabGroupSyncAutoOpenKillSwitch";
@@ -817,8 +816,6 @@
             newCachedFlag(START_SURFACE_RETURN_TIME, true);
     public static final CachedFlag sTabClosureMethodRefactor =
             newCachedFlag(TAB_CLOSURE_METHOD_REFACTOR, false);
-    public static final CachedFlag sTabGroupPaneAndroid =
-            newCachedFlag(TAB_GROUP_PANE_ANDROID, /* defaultValue= */ true);
     public static final CachedFlag sTabStateFlatBuffer =
             newCachedFlag(
                     TAB_STATE_FLAT_BUFFER,
@@ -939,7 +936,6 @@
                     sSmallerTabStripTitleLimit,
                     sStartSurfaceReturnTime,
                     sTabClosureMethodRefactor,
-                    sTabGroupPaneAndroid,
                     sTabStateFlatBuffer,
                     sTabStripIncognitoMigration,
                     sTabStripLayoutOptimization,
diff --git a/chrome/browser/glic/fre/glic_fre_controller.cc b/chrome/browser/glic/fre/glic_fre_controller.cc
index 9b5a327c..cc3b17f 100644
--- a/chrome/browser/glic/fre/glic_fre_controller.cc
+++ b/chrome/browser/glic/fre/glic_fre_controller.cc
@@ -387,10 +387,11 @@
     return;
   }
 
-  fre_view_ = std::make_unique<GlicFreDialogView>(
-      profile_, gfx::Size(features::kGlicFreInitialWidth.Get(),
-                          features::kGlicFreInitialHeight.Get()));
+  gfx::Size initial_size(features::kGlicFreInitialWidth.Get(),
+                         features::kGlicFreInitialHeight.Get());
+  fre_view_ = std::make_unique<GlicFreDialogView>(profile_, initial_size);
   web_contents_ = fre_view_->web_contents();
+  web_contents_->Resize(gfx::Rect(initial_size));
   auto* service = GlicKeyedServiceFactory::GetGlicKeyedService(profile_);
   GlicProfileManager::GetInstance()->OnLoadingClientForService(service);
 }
diff --git a/chrome/browser/glic/glic_keyed_service.cc b/chrome/browser/glic/glic_keyed_service.cc
index d0c5a70..84660a9 100644
--- a/chrome/browser/glic/glic_keyed_service.cc
+++ b/chrome/browser/glic/glic_keyed_service.cc
@@ -91,7 +91,7 @@
   }
 
   if (base::FeatureList::IsEnabled(features::kGlicActor)) {
-    actor_controller_ = std::make_unique<GlicActorController>();
+    actor_controller_ = std::make_unique<GlicActorController>(profile_);
   }
 
   // This is only used by automation for tests.
diff --git a/chrome/browser/glic/glic_profile_manager_interactive_uitest.cc b/chrome/browser/glic/glic_profile_manager_interactive_uitest.cc
index fe86d901..05335ca 100644
--- a/chrome/browser/glic/glic_profile_manager_interactive_uitest.cc
+++ b/chrome/browser/glic/glic_profile_manager_interactive_uitest.cc
@@ -133,16 +133,25 @@
     });
   }
 
-  auto CheckWarmed(bool primary_warmed, bool secondary_warmed) {
+  auto CheckWarmedAndSized(bool primary_warmed, bool secondary_warmed) {
     return Do([primary_warmed, secondary_warmed, this]() {
-      auto IsWarmed = [](GlicKeyedService* service) {
-        return service->window_controller().IsWarmed() ||
-               service->window_controller().fre_controller()->IsWarmed() ||
-               service->window_controller().IsPanelOrFreShowing();
+      auto IsWarmedAndSized = [](GlicKeyedService* service) {
+        const bool warmed =
+            service->window_controller().IsWarmed() ||
+            service->window_controller().fre_controller()->IsWarmed() ||
+            service->window_controller().IsPanelOrFreShowing();
+        if (!warmed) {
+          return false;
+        }
+        auto* contents = service->window_controller().GetWebContents();
+        if (!contents) {
+          contents = service->window_controller().GetFreWebContents();
+        }
+        return contents && !contents->GetSize().IsEmpty();
       };
 
-      EXPECT_EQ(primary_warmed, IsWarmed(GetService(true)));
-      EXPECT_EQ(secondary_warmed, IsWarmed(GetService(false)));
+      EXPECT_EQ(primary_warmed, IsWarmedAndSized(GetService(true)));
+      EXPECT_EQ(secondary_warmed, IsWarmedAndSized(GetService(false)));
     });
   }
 
@@ -212,7 +221,7 @@
       WaitForShow(kGlicButtonElementId),
       // Since we've artificially set high memory pressure, nothing
       // should be preloaded yet.
-      CheckWarmed(false, false),
+      CheckWarmedAndSized(false, false),
       // Resetting the memory pressure will enable preloading again.
       ResetMemoryPressure(),
       // Attempt to preload for the primary profile.
@@ -220,7 +229,7 @@
       // Since there is no contention, this should have succeeded
       // (and we should not have attempted to warm the other web
       // client, so it should not yet be warmed).
-      CheckWarmed(true, false),
+      CheckWarmedAndSized(true, false),
       // This stores a pointer to the web client contents so that we can check
       // that the the shown contents match (otherwise, we've warmed for no
       // reason).
@@ -244,7 +253,7 @@
   RunTestSequence(WaitForShow(kGlicButtonElementId),
                   // Since we've artificially set high memory pressure, nothing
                   // should be preloaded yet.
-                  CheckWarmed(false, false),
+                  CheckWarmedAndSized(false, false),
                   // Resetting the memory pressure will enable preloading again.
                   ResetMemoryPressure(),
                   // Attempt to preload for the primary profile.
@@ -252,20 +261,20 @@
                   // Since there is no contention, this should have succeeded
                   // (and we should not have attempted to warm the other web
                   // client, so it should not yet be warmed).
-                  CheckWarmed(true, false),
+                  CheckWarmedAndSized(true, false),
                   // Warming the secondary profile will cause another web client
                   // to come into existence.
                   CreateAndWarmGlic(/*primary_profile=*/false),
                   // The first service should only remain warmed if we have the
                   // feature `kGlicWarmMultiple` enabled.
-                  CheckWarmed(ShouldWarmMultiple(), true));
+                  CheckWarmedAndSized(ShouldWarmMultiple(), true));
 }
 
 IN_PROC_BROWSER_TEST_P(GlicProfileManagerUiTest, ShowMutex) {
   RunTestSequence(WaitForShow(kGlicButtonElementId),
                   // Since we've artificially set high memory pressure, nothing
                   // should be preloaded yet.
-                  CheckWarmed(false, false),
+                  CheckWarmedAndSized(false, false),
                   // Resetting the memory pressure will enable preloading again.
                   ResetMemoryPressure(),
                   // Attempt to preload for the secondary profile.
@@ -273,11 +282,11 @@
                   // Since there is no contention, this should have succeeded
                   // (and we should not have attempted to warm the other web
                   // client, so it should not yet be warmed).
-                  CheckWarmed(false, true),
+                  CheckWarmedAndSized(false, true),
                   OpenGlicWindow(GlicWindowMode::kAttached),
                   // The first service should only remain warmed if we have the
                   // feature `kGlicWarmMultiple` enabled.
-                  CheckWarmed(true, ShouldWarmMultiple()));
+                  CheckWarmedAndSized(true, ShouldWarmMultiple()));
 }
 
 IN_PROC_BROWSER_TEST_P(GlicProfileManagerUiTest, FreMutex) {
@@ -285,7 +294,7 @@
       WaitForShow(kGlicButtonElementId),
       // Since we've artificially set high memory pressure, nothing
       // should be preloaded yet.
-      CheckWarmed(false, false),
+      CheckWarmedAndSized(false, false),
       // Resetting the memory pressure will enable preloading again.
       ResetMemoryPressure(),
       // Attempt to preload for the secondary profile.
@@ -293,7 +302,7 @@
       // Since there is no contention, this should have succeeded
       // (and we should not have attempted to warm the other web
       // client, so it should not yet be warmed).
-      CheckWarmed(false, true), SetNeedsFRE(),
+      CheckWarmedAndSized(false, true), SetNeedsFRE(),
       ObserveState(
           kFreWebUiState,
           base::BindOnce(&GlicProfileManagerUiTest::GetFreController,
@@ -302,21 +311,21 @@
       WaitForState(kFreWebUiState, mojom::FreWebUiState::kReady),
       // The first service should only remain warmed if we have the
       // feature `kGlicWarmMultiple` enabled.
-      CheckWarmed(true, ShouldWarmMultiple()));
+      CheckWarmedAndSized(true, ShouldWarmMultiple()));
 }
 
 IN_PROC_BROWSER_TEST_P(GlicProfileManagerUiTest, DoNotWarmWhenShowing) {
   RunTestSequence(WaitForShow(kGlicButtonElementId),
                   // Since we've artificially set high memory pressure, nothing
                   // should be preloaded yet.
-                  CheckWarmed(false, false),
+                  CheckWarmedAndSized(false, false),
                   // Resetting the memory pressure will enable preloading again.
                   ResetMemoryPressure(),
                   OpenGlicWindow(GlicWindowMode::kAttached),
-                  CheckWarmed(true, false),
+                  CheckWarmedAndSized(true, false),
                   // Attempt to preload for the secondary profile.
                   CreateAndWarmGlic(/*primary_profile=*/false),
-                  CheckWarmed(true, ShouldWarmMultiple()));
+                  CheckWarmedAndSized(true, ShouldWarmMultiple()));
 }
 
 IN_PROC_BROWSER_TEST_P(GlicProfileManagerUiTest, DoNotWarmWhenShowingFre) {
@@ -324,7 +333,7 @@
       WaitForShow(kGlicButtonElementId),
       // Since we've artificially set high memory pressure, nothing
       // should be preloaded yet.
-      CheckWarmed(false, false),
+      CheckWarmedAndSized(false, false),
       // Resetting the memory pressure will enable preloading again.
       ResetMemoryPressure(), SetNeedsFRE(),
       ObserveState(
@@ -333,17 +342,17 @@
                          base::Unretained(this), /*primary_profile=*/true)),
       ToggleGlicWindow(GlicWindowMode::kAttached),
       WaitForState(kFreWebUiState, mojom::FreWebUiState::kReady),
-      CheckWarmed(true, false),
+      CheckWarmedAndSized(true, false),
       // Attempt to preload for the secondary profile.
       CreateAndWarmGlic(/*primary_profile=*/false),
-      CheckWarmed(true, ShouldWarmMultiple()));
+      CheckWarmedAndSized(true, ShouldWarmMultiple()));
 }
 
 IN_PROC_BROWSER_TEST_P(GlicProfileManagerUiTest, MemPressureClearsCache) {
   RunTestSequence(WaitForShow(kGlicButtonElementId),
                   // Since we've artificially set high memory pressure, nothing
                   // should be preloaded yet.
-                  CheckWarmed(false, false),
+                  CheckWarmedAndSized(false, false),
                   // Resetting the memory pressure will enable preloading again.
                   ResetMemoryPressure(),
                   // Attempt to preload for the primary profile.
@@ -351,29 +360,29 @@
                   // Since there is no contention, this should have succeeded
                   // (and we should not have attempted to warm the other web
                   // client, so it should not yet be warmed).
-                  CheckWarmed(true, false),
+                  CheckWarmedAndSized(true, false),
                   SendMemoryPressureSignal(/*primary_profile=*/true),
-                  CheckWarmed(false, false));
+                  CheckWarmedAndSized(false, false));
 }
 
 IN_PROC_BROWSER_TEST_P(GlicProfileManagerUiTest, MemPressureDoesNotClearShown) {
   RunTestSequence(WaitForShow(kGlicButtonElementId),
                   // Since we've artificially set high memory pressure, nothing
                   // should be preloaded yet.
-                  CheckWarmed(false, false),
+                  CheckWarmedAndSized(false, false),
                   // Resetting the memory pressure will enable preloading again.
                   ResetMemoryPressure(),
                   OpenGlicWindow(GlicWindowMode::kAttached),
-                  CheckWarmed(true, false),
+                  CheckWarmedAndSized(true, false),
                   SendMemoryPressureSignal(/*primary_profile=*/true),
                   // Since the window is showing, we shouldn't close it.
-                  CheckWarmed(true, false),
+                  CheckWarmedAndSized(true, false),
                   // This should close the window.
                   ToggleGlicWindow(GlicWindowMode::kAttached),
                   // Since the window was shown, it is the last active glic and
                   // should not be cleared.
                   SendMemoryPressureSignal(/*primary_profile=*/true),
-                  CheckWarmed(true, false));
+                  CheckWarmedAndSized(true, false));
 }
 
 INSTANTIATE_TEST_SUITE_P(
diff --git a/chrome/browser/glic/host/glic_actor_controller.cc b/chrome/browser/glic/host/glic_actor_controller.cc
index 960a5af..2b7e1c2 100644
--- a/chrome/browser/glic/host/glic_actor_controller.cc
+++ b/chrome/browser/glic/host/glic_actor_controller.cc
@@ -44,7 +44,9 @@
 
 }  // namespace
 
-GlicActorController::GlicActorController() = default;
+GlicActorController::GlicActorController(Profile* profile) {
+  actor::ActorCoordinator::RegisterWithProfile(profile);
+}
 
 GlicActorController::~GlicActorController() = default;
 
diff --git a/chrome/browser/glic/host/glic_actor_controller.h b/chrome/browser/glic/host/glic_actor_controller.h
index 18baa90..00f10624 100644
--- a/chrome/browser/glic/host/glic_actor_controller.h
+++ b/chrome/browser/glic/host/glic_actor_controller.h
@@ -18,12 +18,14 @@
 class ActorCoordinator;
 }
 
+class Profile;
+
 namespace glic {
 
 // Controls the interaction with the actor to complete an action.
 class GlicActorController {
  public:
-  GlicActorController();
+  explicit GlicActorController(Profile* profile);
   GlicActorController(const GlicActorController&) = delete;
   GlicActorController& operator=(const GlicActorController&) = delete;
   ~GlicActorController();
diff --git a/chrome/browser/glic/host/glic_annotation_manager.cc b/chrome/browser/glic/host/glic_annotation_manager.cc
index 68a5cf4..5e3b83d 100644
--- a/chrome/browser/glic/host/glic_annotation_manager.cc
+++ b/chrome/browser/glic/host/glic_annotation_manager.cc
@@ -152,7 +152,7 @@
     return;
   }
 
-  annotation_agent_->ScrollIntoView(/*applies_focus=*/false);
+  annotation_agent_->ScrollIntoView(/*applies_focus=*/true);
   std::move(scroll_to_callback_).Run(std::nullopt);
 }
 
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 ddde45fe..297694af 100644
--- a/chrome/browser/glic/host/glic_annotation_manager_interactive_uitest.cc
+++ b/chrome/browser/glic/host/glic_annotation_manager_interactive_uitest.cc
@@ -533,6 +533,21 @@
           mojom::ScrollToErrorReason::kNoMatchingDocument));
 }
 
+IN_PROC_BROWSER_TEST_F(GlicAnnotationManagerUiTest, TextFocusedAfterScroll) {
+  RunTestSequence(
+      InstrumentTab(kActiveTabId),
+      NavigateWebContents(
+          kActiveTabId,
+          embedded_test_server()->GetURL("/scrollable_page_with_content.html")),
+      OpenGlicWindow(GlicWindowMode::kDetached),
+      ExecuteJs(kActiveTabId,
+                "() => { document.getElementById('text').tabIndex = 0; }"),
+      ScrollTo(ExactTextSelector("Some text")),
+      WaitForJsResult(kActiveTabId, "() => did_scroll"),
+      CheckJsResult(kActiveTabId, "() => { return document.activeElement.id; }",
+                    ::testing::Eq("text")));
+}
+
 class GlicAnnotationManagerWithScrollToDisabledUiTest
     : public test::InteractiveGlicTest {
  public:
diff --git a/chrome/browser/glic/widget/glic_window_controller.cc b/chrome/browser/glic/widget/glic_window_controller.cc
index 8a0dfe42..684b1fda 100644
--- a/chrome/browser/glic/widget/glic_window_controller.cc
+++ b/chrome/browser/glic/widget/glic_window_controller.cc
@@ -1423,6 +1423,7 @@
 void GlicWindowController::Preload() {
   if (!contents_) {
     CreateContents();
+    contents_->web_contents()->Resize(GetInitialDetachedBounds(nullptr));
   }
 }
 
diff --git a/chrome/browser/media/webrtc/webrtc_browsertest_base.cc b/chrome/browser/media/webrtc/webrtc_browsertest_base.cc
index ed897f2..c0d5b23 100644
--- a/chrome/browser/media/webrtc/webrtc_browsertest_base.cc
+++ b/chrome/browser/media/webrtc/webrtc_browsertest_base.cc
@@ -7,7 +7,6 @@
 #include <stddef.h>
 
 #include <limits>
-#include <string_view>
 #include <tuple>
 
 #include "base/json/json_reader.h"
@@ -80,13 +79,12 @@
 // WebrtcTestBase-inheriting test cases do not run in parallel (if they did they
 // would race to look at the log, which is global to all tests).
 bool JavascriptErrorDetectingLogHandler(int severity,
-                                        std::string_view file,
+                                        const char* file,
                                         int line,
                                         size_t message_start,
                                         const std::string& str) {
-  if (file != "CONSOLE") {
+  if (file == nullptr || std::string("CONSOLE") != file)
     return false;
-  }
 
   // TODO(crbug.com/40608140): Fix AppRTC and stop ignoring this error.
   if (str.find("Synchronous XHR in page dismissal") != std::string::npos)
diff --git a/chrome/browser/ntp_customization/BUILD.gn b/chrome/browser/ntp_customization/BUILD.gn
index a7920a6..6f0594a9 100644
--- a/chrome/browser/ntp_customization/BUILD.gn
+++ b/chrome/browser/ntp_customization/BUILD.gn
@@ -15,6 +15,7 @@
     "java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationBottomSheetContent.java",
     "java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationCoordinator.java",
     "java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationMediator.java",
+    "java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationMetricsUtils.java",
     "java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationUtils.java",
     "java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationViewProperties.java",
     "java/src/org/chromium/chrome/browser/ntp_customization/ntp_cards/NtpCardsCoordinator.java",
@@ -25,12 +26,15 @@
   deps = [
     ":java_resources",
     "//base:log_java",
+    "//base:metrics_java",
     "//base:supplier_java",
     "//chrome/browser/feed/android:java",
     "//chrome/browser/magic_stack/android:java",
     "//chrome/browser/profiles/android:java",
+    "//chrome/browser/search_engines/android:java",
     "//components/browser_ui/bottomsheet/android:java",
     "//components/browser_ui/widget/android:java",
+    "//components/search_engines/android:java",
     "//third_party/android_deps:com_android_support_support_annotations_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
     "//third_party/androidx:androidx_appcompat_appcompat_java",
@@ -76,6 +80,7 @@
     "junit/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationBottomSheetContentUnitTest.java",
     "junit/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationCoordinatorUnitTest.java",
     "junit/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationMediatorUnitTest.java",
+    "junit/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationMetricsUtilsUnitTest.java",
     "junit/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationUtilsUnitTest.java",
     "junit/src/org/chromium/chrome/browser/ntp_customization/ntp_cards/NtpCardsCoordinatorUnitTest.java",
     "junit/src/org/chromium/chrome/browser/ntp_customization/ntp_cards/NtpCardsListContainerViewUnitTest.java",
@@ -89,10 +94,14 @@
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
     "//chrome/android:chrome_java",
+    "//chrome/browser/feed/android:java",
     "//chrome/browser/magic_stack/android:java",
+    "//chrome/browser/preferences:java",
+    "//chrome/browser/profiles/android:java",
     "//components/browser_ui/bottomsheet/android:java",
     "//components/browser_ui/theme/android:java_resources",
     "//components/browser_ui/widget/android:java",
+    "//components/prefs/android:java",
     "//third_party/androidx:androidx_core_core_java",
     "//third_party/androidx:androidx_test_core_java",
     "//third_party/androidx:androidx_test_runner_java",
diff --git a/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationCoordinator.java b/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationCoordinator.java
index f104c77..2fb8f96 100644
--- a/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationCoordinator.java
+++ b/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationCoordinator.java
@@ -18,7 +18,9 @@
 import android.view.View;
 import android.widget.ViewFlipper;
 
+import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.browser.ntp_customization.ntp_cards.NtpCardsCoordinator;
+import org.chromium.chrome.browser.profiles.ProfileProvider;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel;
@@ -46,10 +48,21 @@
         int MAIN = 0;
         int NTP_CARDS = 1;
         int DISCOVER_FEED = 2;
+        int NUM_ENTRIES = 3;
+    }
+
+    @IntDef({EntryPointType.MAIN_MENU, EntryPointType.TOOL_BAR})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface EntryPointType {
+        int MAIN_MENU = 0;
+        int TOOL_BAR = 1;
+        int NUM_ENTRIES = 2;
     }
 
     public NtpCustomizationCoordinator(
-            Context context, BottomSheetController bottomSheetController) {
+            Context context,
+            BottomSheetController bottomSheetController,
+            Supplier<ProfileProvider> profileSupplier) {
         mContext = context;
         View contentView =
                 LayoutInflater.from(mContext)
@@ -84,7 +97,8 @@
                         bottomSheetController,
                         bottomSheetContent,
                         viewFlipperPropertyModel,
-                        containerPropertyModel);
+                        containerPropertyModel,
+                        profileSupplier);
         mMediator.registerBottomSheetLayout(MAIN);
 
         mDelegate = createBottomSheetDelegate();
@@ -112,7 +126,7 @@
                     if (mNtpCardsCoordinator == null) {
                         mNtpCardsCoordinator = new NtpCardsCoordinator(mContext, mDelegate);
                     }
-                    mMediator.showBottomSheet(BottomSheetType.NTP_CARDS);
+                    mMediator.showBottomSheet(NTP_CARDS);
                 };
             case DISCOVER_FEED:
                 return null;
diff --git a/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationMediator.java b/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationMediator.java
index 8f0f1e9..fc9fa89f 100644
--- a/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationMediator.java
+++ b/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationMediator.java
@@ -12,9 +12,14 @@
 
 import android.content.Context;
 import android.support.annotation.Nullable;
+import android.support.annotation.VisibleForTesting;
 import android.view.View;
 import android.widget.ViewFlipper;
 
+import org.chromium.base.supplier.Supplier;
+import org.chromium.chrome.browser.feed.FeedFeatures;
+import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.profiles.ProfileProvider;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetObserver;
@@ -44,17 +49,20 @@
     private final PropertyModel mViewFlipperPropertyModel;
     private final List<Integer> mListContent;
     private final PropertyModel mContainerPropertyModel;
+    private final Supplier<ProfileProvider> mProfileSupplier;
     private Integer mCurrentBottomSheet;
 
     public NtpCustomizationMediator(
             BottomSheetController bottomSheetController,
             NtpCustomizationBottomSheetContent bottomSheetContent,
             PropertyModel viewFlipperPropertyModel,
-            PropertyModel containerPropertyModel) {
+            PropertyModel containerPropertyModel,
+            Supplier<ProfileProvider> profileSupplier) {
         mBottomSheetController = bottomSheetController;
         mBottomSheetContent = bottomSheetContent;
         mViewFlipperPropertyModel = viewFlipperPropertyModel;
         mContainerPropertyModel = containerPropertyModel;
+        mProfileSupplier = profileSupplier;
         mViewFlipperMap = new HashMap<>();
         mTypeToListenersMap = new HashMap<>();
         mListContent = buildListContent();
@@ -101,6 +109,7 @@
         if (shouldRequestShowContent) {
             mBottomSheetController.requestShowContent(mBottomSheetContent, /* animate= */ true);
         }
+        NtpCustomizationMetricsUtils.recordBottomSheetShown(type);
     }
 
     /** Handles system back press and back button clicks on the bottom sheet. */
@@ -177,12 +186,23 @@
         mTypeToListenersMap.put(type, listener);
     }
 
-    /** Returns the content of the list displayed in the main bottom sheet. */
+    /**
+     * Returns the content of the list displayed in the main bottom sheet and includes the "Discover
+     * Feed" list item only if the feed section exists in the new tab page.
+     */
+    @VisibleForTesting
     List<Integer> buildListContent() {
+        if (!mProfileSupplier.hasValue()) {
+            return List.of(NTP_CARDS);
+        }
+
+        Profile profile = mProfileSupplier.get().getOriginalProfile();
         List<Integer> content = new ArrayList<>();
         content.add(NTP_CARDS);
-        // TODO(crbug.com/397439004): Add logics to hide the "feeds" list item.
-        content.add(DISCOVER_FEED);
+
+        if (FeedFeatures.isFeedEnabled(profile)) {
+            content.add(DISCOVER_FEED);
+        }
         return content;
     }
 
diff --git a/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationMetricsUtils.java b/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationMetricsUtils.java
new file mode 100644
index 0000000..1d80d86
--- /dev/null
+++ b/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationMetricsUtils.java
@@ -0,0 +1,77 @@
+// 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.ntp_customization;
+
+import android.support.annotation.VisibleForTesting;
+
+import org.chromium.base.metrics.RecordHistogram;
+import org.chromium.chrome.browser.magic_stack.ModuleDelegate;
+
+/** The utility class for logging the NTP customization bottom sheet's metrics. */
+public class NtpCustomizationMetricsUtils {
+    @VisibleForTesting
+    static final String HISTOGRAM_NTP_CUSTOMIZATION_PREFIX = "NewTabPage.Customization";
+
+    @VisibleForTesting
+    static final String HISTOGRAM_BOTTOM_SHEET_SHOWN =
+            HISTOGRAM_NTP_CUSTOMIZATION_PREFIX + ".BottomSheet.Shown";
+
+    @VisibleForTesting
+    static final String HISTOGRAM_BOTTOM_SHEET_ENTRY =
+            HISTOGRAM_NTP_CUSTOMIZATION_PREFIX + ".OpenBottomSheetEntry";
+
+    @VisibleForTesting static final String HISTOGRAM_CUSTOMIZATION_TURN_ON_MODULE = ".TurnOnModule";
+
+    @VisibleForTesting
+    static final String HISTOGRAM_CUSTOMIZATION_TURN_OFF_MODULE = ".TurnOffModule";
+
+    /**
+     * Records the total number of times each NTP customization bottom sheet is shown. Each opening
+     * of the bottom sheet is counted, regardless of whether it has been opened previously.
+     *
+     * @param bottomSheetType The type of the NTP customization bottom sheet.
+     */
+    public static void recordBottomSheetShown(
+            @NtpCustomizationCoordinator.BottomSheetType int bottomSheetType) {
+        RecordHistogram.recordEnumeratedHistogram(
+                HISTOGRAM_BOTTOM_SHEET_SHOWN,
+                bottomSheetType,
+                NtpCustomizationCoordinator.BottomSheetType.NUM_ENTRIES);
+    }
+
+    /**
+     * Records the number of times the NTP customization bottom sheet is opened by the user,
+     * categorized by the specific source of the opening action: either from the main menu or from
+     * the toolbar.
+     *
+     * @param entryPointType The type of the entry point to open the NTP customization main bottom
+     *     sheet.
+     */
+    public static void recordOpenBottomSheetEntry(
+            @NtpCustomizationCoordinator.EntryPointType int entryPointType) {
+        RecordHistogram.recordEnumeratedHistogram(
+                HISTOGRAM_BOTTOM_SHEET_ENTRY,
+                entryPointType,
+                NtpCustomizationCoordinator.EntryPointType.NUM_ENTRIES);
+    }
+
+    /**
+     * Records when a magic stack module is activated or deactivated in the bottom sheet.
+     *
+     * @param moduleType The type of the module.
+     * @param isEnabled True if the module is turned on.
+     */
+    public static void recordModuleToggledInBottomSheet(
+            @ModuleDelegate.ModuleType int moduleType, boolean isEnabled) {
+        String name =
+                isEnabled
+                        ? HISTOGRAM_CUSTOMIZATION_TURN_ON_MODULE
+                        : HISTOGRAM_CUSTOMIZATION_TURN_OFF_MODULE;
+        RecordHistogram.recordEnumeratedHistogram(
+                HISTOGRAM_NTP_CUSTOMIZATION_PREFIX + name,
+                moduleType,
+                NtpCustomizationCoordinator.BottomSheetType.NUM_ENTRIES);
+    }
+}
diff --git a/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/ntp_cards/NtpCardsListContainerView.java b/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/ntp_cards/NtpCardsListContainerView.java
index 1f3bc987..3e6d99f 100644
--- a/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/ntp_cards/NtpCardsListContainerView.java
+++ b/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/ntp_cards/NtpCardsListContainerView.java
@@ -17,6 +17,7 @@
 import org.chromium.chrome.browser.magic_stack.HomeModulesConfigManager;
 import org.chromium.chrome.browser.ntp_customization.BottomSheetListContainerView;
 import org.chromium.chrome.browser.ntp_customization.ListContainerViewDelegate;
+import org.chromium.chrome.browser.ntp_customization.NtpCustomizationMetricsUtils;
 import org.chromium.chrome.browser.ntp_customization.NtpCustomizationUtils;
 import org.chromium.chrome.browser.ntp_customization.R;
 
@@ -80,6 +81,7 @@
         listItemView.setOnCheckedChangeListener(
                 (button, newValue) -> {
                     homeModulesConfigManager.setPrefModuleTypeEnabled(type, newValue);
+                    NtpCustomizationMetricsUtils.recordModuleToggledInBottomSheet(type, newValue);
                 });
     }
 
diff --git a/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationCoordinatorUnitTest.java b/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationCoordinatorUnitTest.java
index d51ff6fe..c42de81 100644
--- a/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationCoordinatorUnitTest.java
+++ b/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationCoordinatorUnitTest.java
@@ -27,6 +27,7 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 
+import org.chromium.base.supplier.Supplier;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.chrome.browser.ntp_customization.ntp_cards.NtpCardsCoordinator;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
@@ -48,7 +49,8 @@
     public void setUp() {
         mContext = ApplicationProvider.getApplicationContext();
         mNtpCustomizationCoordinator =
-                new NtpCustomizationCoordinator(mContext, mBottomSheetController);
+                new NtpCustomizationCoordinator(
+                        mContext, mBottomSheetController, mock(Supplier.class));
         mNtpCustomizationCoordinator.setViewFlipperForTesting(mViewFlipper);
         mNtpCustomizationCoordinator.setMediatorForTesting(mMediator);
     }
diff --git a/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationMediatorUnitTest.java b/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationMediatorUnitTest.java
index e64b9040..14f45fd 100644
--- a/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationMediatorUnitTest.java
+++ b/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationMediatorUnitTest.java
@@ -5,8 +5,10 @@
 package org.chromium.chrome.browser.ntp_customization;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -15,6 +17,7 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import static org.chromium.chrome.browser.ntp_customization.NtpCustomizationCoordinator.BottomSheetType.DISCOVER_FEED;
 import static org.chromium.chrome.browser.ntp_customization.NtpCustomizationCoordinator.BottomSheetType.MAIN;
@@ -36,12 +39,20 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 
+import org.chromium.base.supplier.OneshotSupplierImpl;
 import org.chromium.base.test.BaseRobolectricTestRunner;
-import org.chromium.chrome.browser.magic_stack.ModuleDelegate;
+import org.chromium.base.test.util.HistogramWatcher;
+import org.chromium.chrome.browser.feed.FeedFeatures;
+import org.chromium.chrome.browser.feed.FeedServiceBridge;
+import org.chromium.chrome.browser.feed.FeedServiceBridgeJni;
 import org.chromium.chrome.browser.ntp_customization.NtpCustomizationCoordinator.BottomSheetType;
+import org.chromium.chrome.browser.preferences.Pref;
+import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.profiles.ProfileProvider;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetObserver;
+import org.chromium.components.prefs.PrefService;
 import org.chromium.ui.modelutil.PropertyModel;
 
 import java.util.List;
@@ -56,21 +67,28 @@
     @Mock private NtpCustomizationBottomSheetContent mBottomSheetContent;
     @Mock private PropertyModel mViewFlipperPropertyModel;
     @Mock private PropertyModel mContainerPropertyModel;
+    @Mock private PrefService mPrefService;
+    @Mock private FeedServiceBridge.Natives mFeedServiceBridgeJniMock;
+    @Mock private Profile mProfile;
+    @Mock private ProfileProvider mProfileProvider;
 
     private NtpCustomizationMediator mMediator;
     private Map<Integer, Integer> mViewFlipperMap;
     private ListContainerViewDelegate mListDelegate;
     private Context mContext;
+    private OneshotSupplierImpl<ProfileProvider> mSupplier;
 
     @Before
     public void setUp() {
         mContext = ApplicationProvider.getApplicationContext();
+        mSupplier = new OneshotSupplierImpl<>();
         mMediator =
                 new NtpCustomizationMediator(
                         mBottomSheetController,
                         mBottomSheetContent,
                         mViewFlipperPropertyModel,
-                        mContainerPropertyModel);
+                        mContainerPropertyModel,
+                        mSupplier);
         mViewFlipperMap = mMediator.getViewFlipperMapForTesting();
         mListDelegate = mMediator.createListDelegate();
     }
@@ -140,7 +158,7 @@
     @SmallTest
     public void testShowBottomSheet() {
         // Verifies that setDisplayChild() is called and mCurrentBottomSheet is set correctly.
-        @ModuleDelegate.ModuleType int bottomSheetType = BottomSheetType.NTP_CARDS;
+        @BottomSheetType int bottomSheetType = NTP_CARDS;
         int viewFlipperIndex = 2;
         mViewFlipperMap.put(bottomSheetType, viewFlipperIndex);
 
@@ -152,6 +170,24 @@
 
     @Test
     @SmallTest
+    public void testMetricsInShowBottomSheet() {
+        String histogramName = "NewTabPage.Customization.BottomSheet.Shown";
+        @BottomSheetType int[] bottomSheetTypes = new int[] {NTP_CARDS, MAIN};
+
+        for (int i = 0; i < bottomSheetTypes.length; i++) {
+            @BottomSheetType int type = bottomSheetTypes[i];
+            mViewFlipperMap.put(type, i);
+            mMediator.showBottomSheet(type);
+
+            HistogramWatcher histogramWatcher =
+                    HistogramWatcher.newSingleRecordWatcher(histogramName, type);
+            NtpCustomizationMetricsUtils.recordBottomSheetShown(type);
+            histogramWatcher.assertExpected();
+        }
+    }
+
+    @Test
+    @SmallTest
     public void testShowBottomSheetAssertionError() {
         // Verifies that AssertionError will be raised if maybeAddBottomSheetLayout() is not
         // called before calling showBottomSheet()
@@ -246,12 +282,6 @@
     @Test
     @SmallTest
     public void testListContainerViewDelegate() {
-        // Verifies that the content of the delegate.getListItems() is consist of MAIN and FEEDS
-        // while MAIN comes before FEEDS.
-        List<Integer> content = mListDelegate.getListItems();
-        assertEquals(NTP_CARDS, (int) content.get(0));
-        assertEquals(DISCOVER_FEED, (int) content.get(1));
-
         // Verifies the subtitle of the "feeds" list item is "On" and is null for other list item.
         assertEquals("On", mListDelegate.getListItemSubtitle(DISCOVER_FEED, mContext));
         assertNull(mListDelegate.getListItemSubtitle(MAIN, mContext));
@@ -282,4 +312,35 @@
         verify(mContainerPropertyModel)
                 .set(eq(LIST_CONTAINER_VIEW_DELEGATE), any(ListContainerViewDelegate.class));
     }
+
+    @Test
+    @SmallTest
+    public void testBuildListContentWhenProfileIsNotReady() {
+        List<Integer> listContent = mMediator.buildListContent();
+        assertEquals(List.of(NTP_CARDS), listContent);
+    }
+
+    @Test
+    @SmallTest
+    public void testBuildListContent() {
+        // Verifies that "DISCOVER_FEED" misses from the result list if and if only isFeedEnabled()
+        // is false;
+        FeedServiceBridgeJni.setInstanceForTesting(mFeedServiceBridgeJniMock);
+        mSupplier.set(mProfileProvider);
+        when(mProfileProvider.getOriginalProfile()).thenReturn(mProfile);
+        FeedFeatures.setFakePrefsForTest(mPrefService);
+
+        // Mock dependencies to enable FeedFeatures.isFeedEnabled(profile) to return true.
+        when(mPrefService.getBoolean(Pref.ENABLE_SNIPPETS_BY_DSE)).thenReturn(true);
+        when(mFeedServiceBridgeJniMock.isEnabled()).thenReturn(true);
+
+        assertTrue(FeedFeatures.isFeedEnabled(mProfile));
+        assertEquals(List.of(NTP_CARDS, DISCOVER_FEED), mMediator.buildListContent());
+
+        // Mock dependencies to enable FeedFeatures.isFeedEnabled(profile) to return false.
+        when(mPrefService.getBoolean(Pref.ENABLE_SNIPPETS_BY_DSE)).thenReturn(false);
+
+        assertFalse(FeedFeatures.isFeedEnabled(mProfile));
+        assertEquals(List.of(NTP_CARDS), mMediator.buildListContent());
+    }
 }
diff --git a/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationMetricsUtilsUnitTest.java b/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationMetricsUtilsUnitTest.java
new file mode 100644
index 0000000..6f93fc8
--- /dev/null
+++ b/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationMetricsUtilsUnitTest.java
@@ -0,0 +1,74 @@
+// 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.ntp_customization;
+
+import static org.chromium.chrome.browser.magic_stack.ModuleDelegate.ModuleType.PRICE_CHANGE;
+import static org.chromium.chrome.browser.ntp_customization.NtpCustomizationCoordinator.BottomSheetType.MAIN;
+import static org.chromium.chrome.browser.ntp_customization.NtpCustomizationCoordinator.BottomSheetType.NTP_CARDS;
+import static org.chromium.chrome.browser.ntp_customization.NtpCustomizationCoordinator.EntryPointType.MAIN_MENU;
+import static org.chromium.chrome.browser.ntp_customization.NtpCustomizationCoordinator.EntryPointType.TOOL_BAR;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.base.test.util.HistogramWatcher;
+import org.chromium.chrome.browser.magic_stack.ModuleDelegate;
+import org.chromium.chrome.browser.ntp_customization.NtpCustomizationCoordinator.BottomSheetType;
+
+/** Unit tests for {@link NtpCustomizationMetricsUtils} */
+@RunWith(BaseRobolectricTestRunner.class)
+public class NtpCustomizationMetricsUtilsUnitTest {
+    @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    @Test
+    public void testRecordBottomSheetShown() {
+        String histogramName = "NewTabPage.Customization.BottomSheet.Shown";
+        @BottomSheetType int[] bottomSheetTypes = new int[] {MAIN, NTP_CARDS};
+
+        for (@BottomSheetType int type : bottomSheetTypes) {
+            HistogramWatcher histogramWatcher =
+                    HistogramWatcher.newSingleRecordWatcher(histogramName, type);
+            NtpCustomizationMetricsUtils.recordBottomSheetShown(type);
+            histogramWatcher.assertExpected();
+        }
+    }
+
+    @Test
+    public void testRecordOpenBottomSheetEntry() {
+        String histogramName = "NewTabPage.Customization.OpenBottomSheetEntry";
+        @NtpCustomizationCoordinator.EntryPointType
+        int[] entryPointTypes = new int[] {MAIN_MENU, TOOL_BAR};
+
+        for (@NtpCustomizationCoordinator.EntryPointType int type : entryPointTypes) {
+            HistogramWatcher histogramWatcher =
+                    HistogramWatcher.newSingleRecordWatcher(histogramName, type);
+            NtpCustomizationMetricsUtils.recordOpenBottomSheetEntry(type);
+            histogramWatcher.assertExpected();
+        }
+    }
+
+    @Test
+    public void testRecordModuleToggledInBottomSheet() {
+        @ModuleDelegate.ModuleType int moduleType = PRICE_CHANGE;
+        boolean isEnabled = true;
+        String histogramName = "NewTabPage.Customization.TurnOnModule";
+
+        HistogramWatcher histogramWatcher =
+                HistogramWatcher.newSingleRecordWatcher(histogramName, moduleType);
+        NtpCustomizationMetricsUtils.recordModuleToggledInBottomSheet(moduleType, isEnabled);
+        histogramWatcher.assertExpected();
+
+        isEnabled = false;
+        histogramName = "NewTabPage.Customization.TurnOffModule";
+
+        histogramWatcher = HistogramWatcher.newSingleRecordWatcher(histogramName, moduleType);
+        NtpCustomizationMetricsUtils.recordModuleToggledInBottomSheet(moduleType, isEnabled);
+        histogramWatcher.assertExpected();
+    }
+}
diff --git a/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/ntp_cards/NtpCardsListContainerViewUnitTest.java b/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/ntp_cards/NtpCardsListContainerViewUnitTest.java
index 4e7b805..b420dd69 100644
--- a/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/ntp_cards/NtpCardsListContainerViewUnitTest.java
+++ b/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/ntp_cards/NtpCardsListContainerViewUnitTest.java
@@ -38,8 +38,10 @@
 import org.mockito.junit.MockitoRule;
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.base.test.util.HistogramWatcher;
 import org.chromium.chrome.browser.magic_stack.HomeModulesConfigManager;
 import org.chromium.chrome.browser.ntp_customization.ListContainerViewDelegate;
+import org.chromium.chrome.browser.ntp_customization.NtpCustomizationMetricsUtils;
 import org.chromium.chrome.browser.ntp_customization.R;
 
 import java.util.List;
@@ -111,10 +113,12 @@
     public void testSetUpSwitch() {
         HomeModulesConfigManager manager = mock(HomeModulesConfigManager.class);
         NtpCardsListItemView listItemView = mock(NtpCardsListItemView.class);
+        String histogramTurnOnName = "NewTabPage.Customization.TurnOnModule";
+        String histogramTurnOffName = "NewTabPage.Customization.TurnOffModule";
 
         // Verifies that getPrefModuleTypeEnabled() is called.
-        mContainerView.setUpSwitch(manager, listItemView, 10);
-        verify(manager).getPrefModuleTypeEnabled(10);
+        mContainerView.setUpSwitch(manager, listItemView, SINGLE_TAB);
+        verify(manager).getPrefModuleTypeEnabled(SINGLE_TAB);
 
         // Verifies setPrefModuleTypeEnabled() is called inside the OnCheckedChangeListener to
         // update the checked state of the switch.
@@ -122,11 +126,19 @@
         mOnCheckedChangeListenerCaptor
                 .getValue()
                 .onCheckedChanged(mock(CompoundButton.class), true);
-        verify(manager).setPrefModuleTypeEnabled(10, true);
+        verify(manager).setPrefModuleTypeEnabled(SINGLE_TAB, true);
+        HistogramWatcher histogramWatcher =
+                HistogramWatcher.newSingleRecordWatcher(histogramTurnOnName, SINGLE_TAB);
+        NtpCustomizationMetricsUtils.recordModuleToggledInBottomSheet(SINGLE_TAB, true);
+        histogramWatcher.assertExpected();
 
         mOnCheckedChangeListenerCaptor
                 .getValue()
                 .onCheckedChanged(mock(CompoundButton.class), false);
-        verify(manager).setPrefModuleTypeEnabled(10, false);
+        verify(manager).setPrefModuleTypeEnabled(SINGLE_TAB, false);
+        histogramWatcher =
+                HistogramWatcher.newSingleRecordWatcher(histogramTurnOffName, SINGLE_TAB);
+        NtpCustomizationMetricsUtils.recordModuleToggledInBottomSheet(SINGLE_TAB, false);
+        histogramWatcher.assertExpected();
     }
 }
diff --git a/chrome/browser/payments/payment_manifest_parser_browsertest.cc b/chrome/browser/payments/payment_manifest_parser_browsertest.cc
index 0028b8c3..801ed8a1 100644
--- a/chrome/browser/payments/payment_manifest_parser_browsertest.cc
+++ b/chrome/browser/payments/payment_manifest_parser_browsertest.cc
@@ -122,7 +122,34 @@
   std::vector<url::Origin> supported_origins_;
 };
 
-// Handles a a manifest with 100 web app URLs.
+// A simple payment method manifest can be parsed.
+IN_PROC_BROWSER_TEST_F(PaymentManifestParserTest, SimpleMethod) {
+  ParsePaymentMethodManifest(R"(
+    {
+      "default_applications": ["https://test.example/app.json"]
+    }
+  )");
+
+  ASSERT_EQ(1U, web_app_manifest_urls().size());
+  EXPECT_EQ(GURL("https://test.example/app.json"),
+            web_app_manifest_urls().front());
+}
+
+// A JavaScript style comment that starts with two forward slashes is not
+// allowed.
+IN_PROC_BROWSER_TEST_F(PaymentManifestParserTest, SlasSlashCommentNotAllowed) {
+  ParsePaymentMethodManifest(R"(
+    {
+      // This is a JavaScript style comment that should result in parsing
+      // failure.
+      "default_applications": ["https://test.example/app.json"]
+    }
+  )");
+
+  EXPECT_TRUE(web_app_manifest_urls().empty());
+}
+
+// Handles a manifest with 100 web app URLs.
 IN_PROC_BROWSER_TEST_F(PaymentManifestParserTest, TooManyWebAppUrls) {
   std::vector<GURL> web_app_manifest_urls_in;
   web_app_manifest_urls_in.insert(web_app_manifest_urls_in.begin(),
diff --git a/chrome/browser/policy/BUILD.gn b/chrome/browser/policy/BUILD.gn
index 25c10a02..17396a4 100644
--- a/chrome/browser/policy/BUILD.gn
+++ b/chrome/browser/policy/BUILD.gn
@@ -227,7 +227,6 @@
     "test/force_permission_policy_unload_default_enabled_policy_browsertest.cc",
     "test/hsts_policy_browsertest.cc",
     "test/keyboard_focusable_scollers_policy_browsertest.cc",
-    "test/mutation_events_policy_browsertest.cc",
     "test/network_prediction_policy_browsertest.cc",
     "test/policy_statistics_collector_browsertest.cc",
     "test/proxy_policies_browsertest.cc",
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
index 8d27ecc..cc471a9c5 100644
--- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -2274,9 +2274,6 @@
   { key::kAllowBackForwardCacheForCacheControlNoStorePageEnabled,
     policy_prefs::kAllowBackForwardCacheForCacheControlNoStorePageEnabled,
     base::Value::Type::BOOLEAN},
-  { key::kMutationEventsEnabled,
-    policy_prefs::kMutationEventsEnabled,
-    base::Value::Type::BOOLEAN},
   { key::kSelectParserRelaxationEnabled,
     policy_prefs::kSelectParserRelaxationEnabled,
     base::Value::Type::BOOLEAN},
diff --git a/chrome/browser/policy/test/mutation_events_policy_browsertest.cc b/chrome/browser/policy/test/mutation_events_policy_browsertest.cc
deleted file mode 100644
index 6cbff0c..0000000
--- a/chrome/browser/policy/test/mutation_events_policy_browsertest.cc
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/test/scoped_feature_list.h"
-#include "chrome/browser/policy/policy_test_utils.h"
-#include "components/policy/policy_constants.h"
-#include "content/public/test/browser_test.h"
-#include "content/public/test/browser_test_utils.h"
-#include "content/public/test/test_utils.h"
-#include "third_party/blink/public/common/features.h"
-
-namespace policy {
-
-enum class Policy {
-  kDefault,
-  kTrue,
-  kFalse,
-};
-
-class MutationEventsEnabledPolicyBrowserTest
-    : public PolicyTest,
-      public ::testing::WithParamInterface<Policy> {
- public:
-  static std::string DescribeParams(
-      const ::testing::TestParamInfo<ParamType>& info) {
-    switch (info.param) {
-      case Policy::kDefault:
-        return "Default";
-      case Policy::kTrue:
-        return "True";
-      case Policy::kFalse:
-        return "False";
-    }
-  }
-
- protected:
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    feature_list_.InitAndDisableFeature(blink::features::kMutationEvents);
-  }
-
-  void SetUpInProcessBrowserTestFixture() override {
-    PolicyTest::SetUpInProcessBrowserTestFixture();
-
-    if (GetParam() == Policy::kDefault) {
-      return;
-    }
-    PolicyMap policies;
-    SetPolicy(&policies, key::kMutationEventsEnabled,
-              base::Value(GetParam() == Policy::kTrue));
-    UpdateProviderPolicy(policies);
-  }
-
- private:
-  base::test::ScopedFeatureList feature_list_;
-};
-
-IN_PROC_BROWSER_TEST_P(MutationEventsEnabledPolicyBrowserTest,
-                       PolicyIsFollowed) {
-  // Both false and the default (no parameter) should be disabled.
-  const bool expected_enabled = GetParam() == Policy::kTrue;
-
-  ASSERT_TRUE(embedded_test_server()->Start());
-  const GURL url(embedded_test_server()->GetURL("/empty.html"));
-  ASSERT_TRUE(NavigateToUrl(url, this));
-
-  content::DOMMessageQueue message_queue(
-      chrome_test_utils::GetActiveWebContents(this));
-  content::ExecuteScriptAsync(chrome_test_utils::GetActiveWebContents(this),
-                              R"(
-        document.addEventListener('DOMNodeRemoved',() => {
-          window.domAutomationController.send(true);
-        });
-        // This should synchronously fire the mutation event:
-        document.body.remove();
-        window.domAutomationController.send(false);
-      )");
-  std::string message;
-  EXPECT_TRUE(message_queue.WaitForMessage(&message));
-  EXPECT_TRUE(message == "true" || message == "false");
-  EXPECT_EQ(message == "true", expected_enabled);
-}
-
-INSTANTIATE_TEST_SUITE_P(
-    /* no prefix */,
-    MutationEventsEnabledPolicyBrowserTest,
-    ::testing::Values(Policy::kDefault, Policy::kTrue, Policy::kFalse),
-    &MutationEventsEnabledPolicyBrowserTest::DescribeParams);
-
-}  // namespace policy
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_queue_manager.cc b/chrome/browser/privacy_sandbox/privacy_sandbox_queue_manager.cc
index 8e094cf..3300428 100644
--- a/chrome/browser/privacy_sandbox/privacy_sandbox_queue_manager.cc
+++ b/chrome/browser/privacy_sandbox/privacy_sandbox_queue_manager.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_queue_manager.h"
 
+#include "base/metrics/histogram_functions.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_service.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_service_factory.h"
 #include "chrome/browser/ui/privacy_sandbox/privacy_sandbox_prompt_helper.h"
@@ -43,6 +44,24 @@
   suppress_queue_ = suppress_queue;
 }
 
+void PrivacySandboxQueueManager::MaybeEmitQueueStateMetrics() {
+  // We only want to count when we are not holding the handle.
+  if (IsHoldingHandle()) {
+    return;
+  }
+
+  handle_check_failed_count_++;
+  if (IsNoticeQueued()) {
+    base::UmaHistogramCounts100(
+        "PrivacySandbox.Notice.NotHoldingHandle.InQueue",
+        handle_check_failed_count_);
+  } else {
+    base::UmaHistogramCounts100(
+        "PrivacySandbox.Notice.NotHoldingHandle.NotInQueue",
+        handle_check_failed_count_);
+  }
+}
+
 bool PrivacySandboxQueueManager::IsHoldingHandle() {
   return static_cast<bool>(notice_handle_);
 }
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_queue_manager.h b/chrome/browser/privacy_sandbox/privacy_sandbox_queue_manager.h
index 0c3b03d6fe..9521bf8 100644
--- a/chrome/browser/privacy_sandbox/privacy_sandbox_queue_manager.h
+++ b/chrome/browser/privacy_sandbox/privacy_sandbox_queue_manager.h
@@ -42,13 +42,16 @@
   // Returns true if the Privacy Sandbox notice is in queue. Exposed for testing
   // purposes.
   bool IsNoticeQueued();
+  // Returns instance of product messaging controller. Exposed for testing
+  // purposes.
+  user_education::ProductMessagingController* GetProductMessagingController();
   // Returns true if the handle is currently being held.
   bool IsHoldingHandle();
+  // Emits queue state metrics when IsHoldingHandle check fails in
+  // DidFinishNavigation.
+  void MaybeEmitQueueStateMetrics();
 
  private:
-  // Returns instance of product messaging controller.
-  user_education::ProductMessagingController* GetProductMessagingController();
-
   raw_ptr<user_education::ProductMessagingController>
       product_messaging_controller_;
   raw_ptr<Profile> profile_;
@@ -56,6 +59,7 @@
   // TODO(crbug.com/370804492): When we add DMA notice to queue, remove this.
   bool suppress_queue_ = false;
   user_education::RequiredNoticePriorityHandle notice_handle_;
+  int handle_check_failed_count_ = 0;
   base::WeakPtrFactory<PrivacySandboxQueueManager> weak_factory_{this};
 };
 }  // namespace privacy_sandbox
diff --git a/chrome/browser/resources/bookmarks/router.ts b/chrome/browser/resources/bookmarks/router.ts
index 112ed4e..45d8bee4e 100644
--- a/chrome/browser/resources/bookmarks/router.ts
+++ b/chrome/browser/resources/bookmarks/router.ts
@@ -8,7 +8,7 @@
 import type {StoreObserver} from 'chrome://resources/js/store.js';
 
 import {selectFolder, setSearchTerm} from './actions.js';
-import {BOOKMARKS_BAR_ID} from './constants.js';
+import {ACCOUNT_HEADING_NODE_ID, BOOKMARKS_BAR_ID} from './constants.js';
 import {Store} from './store.js';
 import type {BookmarksPageState} from './types.js';
 
@@ -20,6 +20,7 @@
 export class BookmarksRouter implements StoreObserver<BookmarksPageState> {
   private searchTerm_: string = '';
   private selectedId_: string = '';
+  private defaultId_: string = '';
   private updateStateTimeout_: number|null = null;
   private tracker_: EventTracker = new EventTracker();
 
@@ -52,7 +53,7 @@
     const searchTerm = newParams.get('q') || '';
     let selectedId = newParams.get('id');
     if (!selectedId && !searchTerm) {
-      selectedId = BOOKMARKS_BAR_ID;
+      selectedId = this.defaultId_;
     }
 
     if (searchTerm !== this.searchTerm_) {
@@ -74,6 +75,9 @@
   onStateChanged(state: BookmarksPageState) {
     this.selectedId_ = state.selectedFolder;
     this.searchTerm_ = state.search.term;
+    this.defaultId_ = state.nodes[ACCOUNT_HEADING_NODE_ID] ?
+        ACCOUNT_HEADING_NODE_ID :
+        BOOKMARKS_BAR_ID;
     if (this.updateStateTimeout_) {
       clearTimeout(this.updateStateTimeout_);
     }
@@ -89,7 +93,7 @@
     const queryParams = new URLSearchParams();
     if (this.searchTerm_) {
       queryParams.set('q', this.searchTerm_);
-    } else if (this.selectedId_ !== BOOKMARKS_BAR_ID) {
+    } else if (this.selectedId_ !== this.defaultId_) {
       queryParams.set('id', this.selectedId_);
     }
     CrRouter.getInstance().setQueryParams(queryParams);
diff --git a/chrome/browser/resources/password_manager/credential_details/credential_note.html b/chrome/browser/resources/password_manager/credential_details/credential_note.html
index 592ce296..b52500b19 100644
--- a/chrome/browser/resources/password_manager/credential_details/credential_note.html
+++ b/chrome/browser/resources/password_manager/credential_details/credential_note.html
@@ -26,6 +26,7 @@
   #noteValue[empty] {
     color: var(--cr-input-placeholder-color, var(--cr-secondary-text-color));
     letter-spacing: var(--cr-input-placeholder-letter-spacing);
+    user-select: none;
   }
 
   #showMore {
diff --git a/chrome/browser/resources/side_panel/bookmarks/bookmarks_api_proxy.ts b/chrome/browser/resources/side_panel/bookmarks/bookmarks_api_proxy.ts
index 29ba635..a37a3c2d 100644
--- a/chrome/browser/resources/side_panel/bookmarks/bookmarks_api_proxy.ts
+++ b/chrome/browser/resources/side_panel/bookmarks/bookmarks_api_proxy.ts
@@ -6,14 +6,39 @@
 import type {ClickModifiers} from 'chrome://resources/mojo/ui/base/mojom/window_open_disposition.mojom-webui.js';
 
 import type {ActionSource, SortOrder, ViewType} from './bookmarks.mojom-webui.js';
-import {BookmarksPageHandlerFactory, BookmarksPageHandlerRemote} from './bookmarks.mojom-webui.js';
+import {BookmarksPageCallbackRouter, BookmarksPageHandlerFactory, BookmarksPageHandlerRemote} from './bookmarks.mojom-webui.js';
+import type {BookmarksTreeNode} from './bookmarks.mojom-webui.js';
 
 let instance: BookmarksApiProxy|null = null;
 
 export interface BookmarksApiProxy {
   callbackRouter: {[key: string]: ChromeEvent<Function>};
+  pageCallbackRouter: BookmarksPageCallbackRouter;
+
+  // Side Panel Activation and basic bookmark information retrieval.
+  showUi(): void;
+  getAllBookmarks(): Promise<{nodes: BookmarksTreeNode[]}>;
+  getActiveUrl(): Promise<string|undefined>;
+
+  // Side Panel display choices.
+  setSortOrder(sortOrder: SortOrder): void;
+  setViewType(viewType: ViewType): void;
+
+  // Side Panel operations.
   bookmarkCurrentTabInFolder(folderId: string): void;
-  cutBookmark(id: string): void;
+  createFolder(parentId: string, title: string): Promise<{newFolderId: string}>;
+  editBookmarks(
+      ids: string[], newTitle: string|undefined, newUrl: string|undefined,
+      newParentId: string|undefined): void;
+  deleteBookmarks(ids: string[]): Promise<void>;
+  undo(): void;
+  renameBookmark(id: string, title: string): void;
+  openBookmark(
+      id: string, depth: number, clickModifiers: ClickModifiers,
+      source: ActionSource): void;
+
+  // Context menu.
+  showContextMenu(id: string, x: number, y: number, source: ActionSource): void;
   contextMenuOpenBookmarkInNewTab(ids: string[], source: ActionSource): void;
   contextMenuOpenBookmarkInNewWindow(ids: string[], source: ActionSource): void;
   contextMenuOpenBookmarkInIncognitoWindow(ids: string[], source: ActionSource):
@@ -25,55 +50,31 @@
   contextMenuAddToBookmarksBar(id: string, source: ActionSource): void;
   contextMenuRemoveFromBookmarksBar(id: string, source: ActionSource): void;
   contextMenuDelete(ids: string[], source: ActionSource): void;
-  copyBookmark(id: string): Promise<void>;
-  createFolder(parentId: string, title: string):
-      Promise<chrome.bookmarks.BookmarkTreeNode>;
-  editBookmarks(
-      ids: string[], newTitle: string|undefined, newUrl: string|undefined,
-      newParentId: string|undefined): void;
-  deleteBookmarks(ids: string[]): Promise<void>;
-  getActiveUrl(): Promise<string|undefined>;
-  getFolders(): Promise<chrome.bookmarks.BookmarkTreeNode[]>;
-  openBookmark(
-      id: string, depth: number, clickModifiers: ClickModifiers,
-      source: ActionSource): void;
-  pasteToBookmark(parentId: string, destinationId?: string): Promise<void>;
-  renameBookmark(id: string, title: string): void;
-  setSortOrder(sortOrder: SortOrder): void;
-  setViewType(viewType: ViewType): void;
-  showContextMenu(id: string, x: number, y: number, source: ActionSource): void;
-  showUi(): void;
-  undo(): void;
 }
 
 export class BookmarksApiProxyImpl implements BookmarksApiProxy {
   callbackRouter: {[key: string]: ChromeEvent<Function>};
+
+  pageCallbackRouter: BookmarksPageCallbackRouter;
   handler: BookmarksPageHandlerRemote;
 
   constructor() {
     this.callbackRouter = {
-      onChanged: chrome.bookmarks.onChanged,
-      onChildrenReordered: chrome.bookmarks.onChildrenReordered,
-      onCreated: chrome.bookmarks.onCreated,
-      onMoved: chrome.bookmarks.onMoved,
-      onRemoved: chrome.bookmarks.onRemoved,
       onTabActivated: chrome.tabs.onActivated,
       onTabUpdated: chrome.tabs.onUpdated,
     };
 
+    this.pageCallbackRouter = new BookmarksPageCallbackRouter();
     this.handler = new BookmarksPageHandlerRemote();
 
     const factory = BookmarksPageHandlerFactory.getRemote();
     factory.createBookmarksPageHandler(
+        this.pageCallbackRouter.$.bindNewPipeAndPassRemote(),
         this.handler.$.bindNewPipeAndPassReceiver());
   }
 
   bookmarkCurrentTabInFolder(folderId: string) {
-    this.handler.bookmarkCurrentTabInFolder(BigInt(folderId));
-  }
-
-  cutBookmark(id: string) {
-    chrome.bookmarkManagerPrivate.cut([id]);
+    this.handler.bookmarkCurrentTabInFolder(folderId);
   }
 
   contextMenuOpenBookmarkInNewTab(ids: string[], source: ActionSource) {
@@ -116,13 +117,8 @@
     this.handler.executeDeleteCommand(ids.map(id => BigInt(id)), source);
   }
 
-  copyBookmark(id: string) {
-    return chrome.bookmarkManagerPrivate.copy([id]);
-  }
-
   createFolder(parentId: string, title: string) {
-    return chrome.bookmarks.create(
-        {parentId: parentId, title: title, index: 0});
+    return this.handler.createFolder(parentId, title);
   }
 
   editBookmarks(
@@ -132,18 +128,21 @@
     // provided without the other.
     if (newTitle !== undefined && newUrl !== undefined) {
       ids.forEach(id => {
+        // TODO(crbug.com/408181043): Keeping this extensions call as an
+        // exception since this dialog will not be used anymore after Butter for
+        // Bookmarks will be launched.
         chrome.bookmarks.update(id, {title: newTitle, url: newUrl});
       });
     }
     if (newParentId) {
       ids.forEach(id => {
-        chrome.bookmarks.move(id, {parentId: newParentId});
+        this.handler.moveBookmark(BigInt(id), newParentId);
       });
     }
   }
 
   deleteBookmarks(ids: string[]) {
-    return chrome.bookmarkManagerPrivate.removeTrees(ids);
+    return this.handler.removeBookmarks(ids.map(id => BigInt(id)));
   }
 
   getActiveUrl() {
@@ -155,28 +154,14 @@
     });
   }
 
-  getFolders() {
-    return chrome.bookmarks.getTree().then(results => {
-      if (results[0] && results[0].children) {
-        return results[0].children;
-      }
-      return [];
-    });
-  }
-
   openBookmark(
       id: string, depth: number, clickModifiers: ClickModifiers,
       source: ActionSource) {
     this.handler.openBookmark(BigInt(id), depth, clickModifiers, source);
   }
 
-  pasteToBookmark(parentId: string, destinationId?: string) {
-    const destination = destinationId ? [destinationId] : [];
-    return chrome.bookmarkManagerPrivate.paste(parentId, destination);
-  }
-
   renameBookmark(id: string, title: string) {
-    chrome.bookmarks.update(id, {title: title});
+    this.handler.renameBookmark(BigInt(id), title);
   }
 
   setSortOrder(sortOrder: SortOrder) {
@@ -196,7 +181,12 @@
   }
 
   undo() {
-    chrome.bookmarkManagerPrivate.undo();
+    this.handler.undo();
+  }
+
+  // Asynchronously gets the list of non empty permanent bookmark nodes.
+  getAllBookmarks(): Promise<{nodes: BookmarksTreeNode[]}> {
+    return this.handler.getAllBookmarks();
   }
 
   static getInstance(): BookmarksApiProxy {
diff --git a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_drag_manager.ts b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_drag_manager.ts
index 1049b47..c412836 100644
--- a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_drag_manager.ts
+++ b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_drag_manager.ts
@@ -132,6 +132,13 @@
   }
 }
 
+// Listens to standard drag events for taking care of drag and drop events
+// generating from the Side Panel.
+// Listens to `chrome.bookmarkManagerPrivate` for events that originates from
+// different sources and affect the Side Panel - e.g. drop event in the Side
+// Panel that originates from the BookmarkBar.
+// Dependency on the chrome extension private API is an exception here since it
+// allows to get information from different sources.
 export class PowerBookmarksDragManager {
   private delegate_: PowerBookmarksDragDelegate;
   private dragSession_: DragSession|null;
diff --git a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.ts b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.ts
index d8d95bb..55f9272 100644
--- a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.ts
+++ b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.ts
@@ -60,6 +60,7 @@
 import {getTemplate} from './power_bookmarks_list.html.js';
 import type {Label} from './power_bookmarks_service.js';
 import {editingDisabledByPolicy, PowerBookmarksService} from './power_bookmarks_service.js';
+import type {PowerBookmarksDelegate} from './power_bookmarks_service.js';
 import {getFolderLabel} from './power_bookmarks_utils.js';
 
 const ADD_FOLDER_ACTION_UMA = 'Bookmarks.FolderAddedFromSidePanel';
@@ -116,7 +117,8 @@
   footer?: boolean;
 }
 
-export class PowerBookmarksListElement extends PolymerElement {
+export class PowerBookmarksListElement extends PolymerElement implements
+    PowerBookmarksDelegate {
   static get is() {
     return 'power-bookmarks-list';
   }
@@ -385,20 +387,19 @@
     this.hasLoadedData_ = true;
   }
 
-  onBookmarkChanged(id: string, changedInfo: chrome.bookmarks.ChangeInfo) {
+  onBookmarkChanged(id: string) {
     const bookmark = this.bookmarksService_.findBookmarkWithId(id)!;
      this.updatedElementIds_ = [bookmark.id];
     if (this.bookmarkShouldShow_(bookmark) ||
         this.bookmarkIsShowing_(bookmark)) {
       this.updateDisplayLists_();
     }
-    Object.keys(changedInfo).forEach(key => {
-      this.notifyPathIfVisible_(id, key);
-    });
+    this.notifyPathIfVisible_(id, 'title');
+    this.notifyPathIfVisible_(id, 'url');
     this.updateShoppingData_();
   }
 
-  onBookmarkCreated(
+  onBookmarkAdded(
       bookmark: chrome.bookmarks.BookmarkTreeNode,
       parent: chrome.bookmarks.BookmarkTreeNode) {
     if (this.bookmarkShouldShow_(bookmark)) {
@@ -898,11 +899,11 @@
     let parentId = event.detail.folderId;
     for (const folder of event.detail.newFolders) {
       chrome.metricsPrivate.recordUserAction(ADD_FOLDER_ACTION_UMA);
-      const newFolder =
+      const result: {newFolderId: string} =
           await this.bookmarksApi_.createFolder(folder.parentId!, folder.title);
-      folder.children!.forEach(child => child.parentId = newFolder.id);
+      folder.children!.forEach(child => child.parentId = result.newFolderId);
       if (folder.id === parentId) {
-        parentId = newFolder.id;
+        parentId = result.newFolderId;
       }
       // Removing folders added in edit menu while editing a bookmark as they
       // are made with TEMP_FOLDER_ID_PREFIX bookmark-id and are again created
@@ -1057,8 +1058,8 @@
     chrome.metricsPrivate.recordUserAction(ADD_FOLDER_ACTION_UMA);
     this.bookmarksApi_
         .createFolder(newParent.id, loadTimeData.getString('newFolderTitle'))
-        .then((newFolder) => {
-          this.renamingId_ = newFolder.id;
+        .then((result: {newFolderId: string}) => {
+          this.renamingId_ = result.newFolderId;
         });
   }
 
diff --git a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_service.ts b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_service.ts
index 9a5ba306..5ae2704 100644
--- a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_service.ts
+++ b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_service.ts
@@ -9,7 +9,9 @@
 import {ClientId as PageImageServiceClientId} from '//resources/cr_components/page_image_service/page_image_service.mojom-webui.js';
 import {loadTimeData} from '//resources/js/load_time_data.js';
 import type {Url} from '//resources/mojo/url/mojom/url.mojom-webui.js';
+import {assert} from 'chrome://resources/js/assert.js';
 
+import type {BookmarksTreeNode} from './bookmarks.mojom-webui.js';
 import type {BookmarksApiProxy} from './bookmarks_api_proxy.js';
 import {BookmarksApiProxyImpl} from './bookmarks_api_proxy.js';
 
@@ -25,12 +27,12 @@
   active: boolean;
 }
 
-interface PowerBookmarksDelegate {
+export interface PowerBookmarksDelegate {
   setCurrentUrl(url: string|undefined): void;
   setImageUrl(bookmark: chrome.bookmarks.BookmarkTreeNode, url: string): void;
   onBookmarksLoaded(): void;
-  onBookmarkChanged(id: string, changedInfo: chrome.bookmarks.ChangeInfo): void;
-  onBookmarkCreated(
+  onBookmarkChanged(id: string): void;
+  onBookmarkAdded(
       bookmark: chrome.bookmarks.BookmarkTreeNode,
       parent: chrome.bookmarks.BookmarkTreeNode): void;
   onBookmarkMoved(
@@ -77,6 +79,36 @@
   return expanded;
 }
 
+// Transforms Bookmarks Mojo object into the Bookmarks extensions API version.
+// TODO(crbug.com/380806881): Consider using the mojo object throughout the code
+// instead of the extensions object. If so, this function would be removed.
+function toExtensionsBookmarkTreeNode(mojoNode: BookmarksTreeNode):
+    chrome.bookmarks.BookmarkTreeNode {
+  const extensionNode: chrome.bookmarks.BookmarkTreeNode = {
+    id: mojoNode.id,
+    parentId: mojoNode.parentId,
+    title: mojoNode.title,
+    index: mojoNode.index,
+  };
+
+  if (mojoNode.url && mojoNode.url.length !== 0) {
+    extensionNode.url = mojoNode.url;
+  } else if (mojoNode.children) {
+    extensionNode.children =
+        mojoNode.children.map(child => toExtensionsBookmarkTreeNode(child));
+  }
+
+  if (mojoNode.dateAdded !== null) {
+    extensionNode.dateAdded = mojoNode.dateAdded;
+  }
+
+  if (mojoNode.dateLastUsed !== null) {
+    extensionNode.dateLastUsed = mojoNode.dateLastUsed;
+  }
+
+  return extensionNode;
+}
+
 // Compares bookmarks based on the newest dateAdded of the bookmark
 // itself and all descendants.
 function compareNewest(
@@ -176,21 +208,12 @@
   startListening() {
     this.bookmarksApi_.getActiveUrl().then(
         url => this.delegate_.setCurrentUrl(url));
-    this.bookmarksApi_.getFolders().then(folders => {
-      this.folders_ = folders;
-      this.addListener_(
-          'onChanged',
-          (id: string, changedInfo: chrome.bookmarks.ChangeInfo) =>
-              this.onChanged_(id, changedInfo));
-      this.addListener_(
-          'onCreated',
-          (_id: string, node: chrome.bookmarks.BookmarkTreeNode) =>
-              this.onCreated_(node));
-      this.addListener_(
-          'onMoved',
-          (_id: string, movedInfo: chrome.bookmarks.MoveInfo) =>
-              this.onMoved_(movedInfo));
-      this.addListener_('onRemoved', (id: string) => this.onRemoved_(id));
+
+    this.bookmarksApi_.getAllBookmarks().then((result: {
+                                                nodes: BookmarksTreeNode[],
+                                              }) => {
+      this.folders_ =
+          result.nodes.map((node) => toExtensionsBookmarkTreeNode(node));
       this.addListener_('onTabActivated', (_info: chrome.tabs.ActiveInfo) => {
         this.bookmarksApi_.getActiveUrl().then(
             url => this.delegate_.setCurrentUrl(url));
@@ -202,6 +225,20 @@
               this.delegate_.setCurrentUrl(tab.url);
             }
           });
+
+      this.bookmarksApi_.pageCallbackRouter.onBookmarkNodeAdded.addListener(
+          this.onBookmarkNodeAdded_.bind(this));
+      this.bookmarksApi_.pageCallbackRouter.onBookmarkNodesRemoved.addListener(
+          this.onBookmarkNodesRemoved_.bind(this));
+      this.bookmarksApi_.pageCallbackRouter
+          .onBookmarkParentFolderChildrenReordered.addListener(
+              this.onBookmarkParentFolderChildrenReordered_.bind(this));
+      this.bookmarksApi_.pageCallbackRouter.onBookmarkNodeMoved.addListener(
+          this.onBookmarkNodeMoved_.bind(this));
+      this.bookmarksApi_.pageCallbackRouter.onBookmarkNodeChanged.addListener(
+          this.onBookmarkNodeChanged_.bind(this));
+
+
       this.delegate_.onBookmarksLoaded();
     });
   }
@@ -405,9 +442,12 @@
     this.listeners_.set(eventName, callback);
   }
 
-  private onChanged_(id: string, changedInfo: chrome.bookmarks.ChangeInfo) {
+  private onBookmarkNodeChanged_(id: string, newTitle: string, newUrl: string) {
     const bookmark = this.findBookmarkWithId(id)!;
-    Object.assign(bookmark, changedInfo);
+    bookmark.title = newTitle;
+    if (bookmark.url && newUrl) {
+      bookmark.url = newUrl;
+    }
     // Deep copy is necessary to ensure that the original bookmark object is
     // not directly mutated. This helps LitElement's change detection recognize
     // the changes since the reference to the object will change.
@@ -419,10 +459,11 @@
       parent.children![index] = deepCopyBookmark;
     }
     this.findBookmarkImageUrls_(deepCopyBookmark, false, true);
-    this.delegate_.onBookmarkChanged(id, changedInfo);
+    this.delegate_.onBookmarkChanged(id);
   }
 
-  private onCreated_(node: chrome.bookmarks.BookmarkTreeNode) {
+  private onBookmarkNodeAdded_(addedNode: BookmarksTreeNode): void {
+    const node = toExtensionsBookmarkTreeNode(addedNode);
     const parent = this.findBookmarkWithId(node.parentId as string)!;
     if (!node.url && !node.children) {
       // Newly created folders in this session may not have an array of
@@ -430,33 +471,66 @@
       node.children = [];
     }
     parent.children!.splice(node.index!, 0, node);
-    this.delegate_.onBookmarkCreated(node, parent);
+    this.delegate_.onBookmarkAdded(node, parent);
     this.findBookmarkImageUrls_(node, false, false);
   }
 
-  private onMoved_(movedInfo: chrome.bookmarks.MoveInfo) {
+  private onBookmarkNodeMoved_(
+      oldParentId: string, oldIndex: number, newParentId: string,
+      newIndex: number) {
     // Remove node from oldParent at oldIndex.
-    const oldParent = this.findBookmarkWithId(movedInfo.oldParentId)!;
-    const movedNode = oldParent.children![movedInfo.oldIndex];
-    Object.assign(
-        movedNode, {index: movedInfo.index, parentId: movedInfo.parentId});
-    oldParent.children!.splice(movedInfo.oldIndex, 1);
+    const oldParent = this.findBookmarkWithId(oldParentId)!;
+    const movedNode = oldParent.children![oldIndex];
+    Object.assign(movedNode, {index: newIndex, parentId: newParentId});
+    oldParent.children!.splice(oldIndex, 1);
 
     // Add the node to the new parent at index.
-    const newParent = this.findBookmarkWithId(movedInfo.parentId)!;
+    const newParent = this.findBookmarkWithId(newParentId)!;
     if (!newParent.children) {
       newParent.children = [];
     }
-    newParent.children.splice(movedInfo.index, 0, movedNode);
+    newParent.children.splice(newIndex, 0, movedNode);
     this.delegate_.onBookmarkMoved(movedNode, oldParent, newParent);
   }
 
-  private onRemoved_(id: string) {
-    const oldPath = this.findPathToId(id);
-    const removedNode = oldPath.pop()!;
-    const oldParent = oldPath[oldPath.length - 1];
-    oldParent.children!.splice(oldParent.children!.indexOf(removedNode), 1);
-    this.delegate_.onBookmarkRemoved(removedNode);
+  private onBookmarkNodesRemoved_(removedNodeIds: string[]) {
+    for (const id of removedNodeIds) {
+      const path = this.findPathToId(id);
+      const removedNode = path.pop()!;
+      const parent = path[path.length - 1];
+      parent.children!.splice(parent.children!.indexOf(removedNode), 1);
+      this.delegate_.onBookmarkRemoved(removedNode);
+    }
+  }
+
+  // Reorders the children of the node with `folderId` based on the new order in
+  // `childrenOrderedIds`.
+  private onBookmarkParentFolderChildrenReordered_(
+      folderId: string, childrenOrderedIds: string[]) {
+    const folder = this.findBookmarkWithId(folderId)!;
+
+    if (!folder.children) {
+      assert(childrenOrderedIds.length === 0);
+      return;
+    }
+
+    assert(folder.children.length === childrenOrderedIds.length);
+
+    // Create a temporary map of "id -> node" to lookup the nodes based on the
+    // ids.
+    const childrenMap = new Map<string, chrome.bookmarks.BookmarkTreeNode>();
+    for (const child of folder.children) {
+      childrenMap.set(child.id, child);
+    }
+    // Clear and refill the nodes with the proper order from the map.
+    folder.children = [];
+    for (const id of childrenOrderedIds) {
+      folder.children.push(childrenMap.get(id)!);
+    }
+
+    // There is no need to notify the Ui since the order displayed does not
+    // depend on the order of the children in the array of the node. The
+    // displayed order depends on properties of the nodes.
   }
 
   /**
diff --git a/chrome/browser/resources/signin/profile_picker/profile_card_menu.css b/chrome/browser/resources/signin/profile_picker/profile_card_menu.css
index 1095b3b..616b929 100644
--- a/chrome/browser/resources/signin/profile_picker/profile_card_menu.css
+++ b/chrome/browser/resources/signin/profile_picker/profile_card_menu.css
@@ -113,7 +113,7 @@
 
 .count {
   align-self: center;
-  color: var(--google-grey-500);
+  color: var(--color-sys-on-surface-subtle);
   text-align: end;
 }
 
diff --git a/chrome/browser/safe_browsing/BUILD.gn b/chrome/browser/safe_browsing/BUILD.gn
index 9277e6e8..63dfe46b 100644
--- a/chrome/browser/safe_browsing/BUILD.gn
+++ b/chrome/browser/safe_browsing/BUILD.gn
@@ -494,6 +494,7 @@
         "//components/safe_browsing:buildflags",
         "//components/safe_browsing/android:remote_database_manager",
         "//components/safe_browsing/android:safe_browsing_mobile",
+        "//google_apis/common:request_util",
         "//ui/android:android",
 
         # TODO(crbug.com/41437292): Use //chrome/browser after fixing cyclic
diff --git a/chrome/browser/safe_browsing/download_protection/check_client_download_request_base.cc b/chrome/browser/safe_browsing/download_protection/check_client_download_request_base.cc
index 89190cb..016b9df5 100644
--- a/chrome/browser/safe_browsing/download_protection/check_client_download_request_base.cc
+++ b/chrome/browser/safe_browsing/download_protection/check_client_download_request_base.cc
@@ -464,6 +464,8 @@
       net::SiteForCookies::FromUrl(resource_request->url);
 
 #if !BUILDFLAG(IS_ANDROID)
+  // TODO(chlily): Factor this out into
+  // DownloadProtectionDelegate::FinalizeResourceRequest.
   if (!access_token_.empty()) {
     LogAuthenticatedCookieResets(
         *resource_request,
@@ -480,6 +482,8 @@
     return;
   }
 
+  service_->delegate()->FinalizeResourceRequest(*resource_request);
+
   loader_ = network::SimpleURLLoader::Create(
       std::move(resource_request),
       service_->delegate()->CompleteClientDownloadRequestTrafficAnnotation(
diff --git a/chrome/browser/safe_browsing/download_protection/download_protection_delegate.h b/chrome/browser/safe_browsing/download_protection/download_protection_delegate.h
index 4872a7d0..019c9a2 100644
--- a/chrome/browser/safe_browsing/download_protection/download_protection_delegate.h
+++ b/chrome/browser/safe_browsing/download_protection/download_protection_delegate.h
@@ -19,6 +19,10 @@
 class DownloadItem;
 }
 
+namespace network {
+struct ResourceRequest;
+}
+
 namespace safe_browsing {
 
 class ClientDownloadRequest;
@@ -57,6 +61,12 @@
   virtual void PreSerializeRequest(const download::DownloadItem* item,
                                    ClientDownloadRequest& request_proto) {}
 
+  // Called immediately prior to consuming the ResourceRequest used to send out
+  // a download ping. Allows the delegate to make final modifications to the
+  // ResourceRequest.
+  virtual void FinalizeResourceRequest(
+      network::ResourceRequest& resource_request) {}
+
   // Returns the URL that will be contacted for download protection requests.
   virtual const GURL& GetDownloadRequestUrl() const = 0;
 
diff --git a/chrome/browser/safe_browsing/download_protection/download_protection_delegate_android.cc b/chrome/browser/safe_browsing/download_protection/download_protection_delegate_android.cc
index 7f2d3579..766324e9 100644
--- a/chrome/browser/safe_browsing/download_protection/download_protection_delegate_android.cc
+++ b/chrome/browser/safe_browsing/download_protection/download_protection_delegate_android.cc
@@ -22,8 +22,12 @@
 #include "components/safe_browsing/core/common/features.h"
 #include "components/safe_browsing/core/common/proto/csd.pb.h"
 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
+#include "components/version_info/android/channel_getter.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/download_item_utils.h"
+#include "google_apis/common/api_key_request_util.h"
+#include "google_apis/google_api_keys.h"
+#include "services/network/public/cpp/resource_request.h"
 #include "url/url_constants.h"
 
 namespace safe_browsing {
@@ -202,6 +206,13 @@
   *request_proto.mutable_referring_app_info() = GetReferringAppInfoProto(info);
 }
 
+void DownloadProtectionDelegateAndroid::FinalizeResourceRequest(
+    network::ResourceRequest& resource_request) {
+  google_apis::AddAPIKeyToRequest(
+      resource_request,
+      google_apis::GetAPIKey(version_info::android::GetChannel()));
+}
+
 const GURL& DownloadProtectionDelegateAndroid::GetDownloadRequestUrl() const {
   return download_request_url_;
 }
diff --git a/chrome/browser/safe_browsing/download_protection/download_protection_delegate_android.h b/chrome/browser/safe_browsing/download_protection/download_protection_delegate_android.h
index 6733392..4e552c4 100644
--- a/chrome/browser/safe_browsing/download_protection/download_protection_delegate_android.h
+++ b/chrome/browser/safe_browsing/download_protection/download_protection_delegate_android.h
@@ -19,6 +19,10 @@
 class DownloadItem;
 }
 
+namespace network {
+struct ResourceRequest;
+}
+
 namespace safe_browsing {
 
 class ClientDownloadRequest;
@@ -35,6 +39,8 @@
                            const base::FilePath& target_path) const override;
   void PreSerializeRequest(const download::DownloadItem* item,
                            ClientDownloadRequest& request_proto) override;
+  void FinalizeResourceRequest(
+      network::ResourceRequest& resource_request) override;
   const GURL& GetDownloadRequestUrl() const override;
   net::NetworkTrafficAnnotationTag
   CompleteClientDownloadRequestTrafficAnnotation(
diff --git a/chrome/browser/supervised_user/supervised_user_verification_page.cc b/chrome/browser/supervised_user/supervised_user_verification_page.cc
index 688ee218..0c712277 100644
--- a/chrome/browser/supervised_user/supervised_user_verification_page.cc
+++ b/chrome/browser/supervised_user/supervised_user_verification_page.cc
@@ -156,9 +156,6 @@
     base::Value::Dict& load_time_data) {
   load_time_data.Set("overridable", false);
   load_time_data.Set("hide_primary_button", false);
-  load_time_data.Set("show_recurrent_error_paragraph", false);
-
-  load_time_data.Set("recurrentErrorParagraph", "");
   load_time_data.Set("openDetails", "");
   load_time_data.Set("explanationParagraph", "");
   load_time_data.Set("finalParagraph", "");
diff --git a/chrome/browser/tab_group_sync/android/java/src/org/chromium/chrome/browser/tab_group_sync/TabGroupSyncLocalToRemoteTest.java b/chrome/browser/tab_group_sync/android/java/src/org/chromium/chrome/browser/tab_group_sync/TabGroupSyncLocalToRemoteTest.java
index 1b026171..934ae03 100644
--- a/chrome/browser/tab_group_sync/android/java/src/org/chromium/chrome/browser/tab_group_sync/TabGroupSyncLocalToRemoteTest.java
+++ b/chrome/browser/tab_group_sync/android/java/src/org/chromium/chrome/browser/tab_group_sync/TabGroupSyncLocalToRemoteTest.java
@@ -51,10 +51,7 @@
 @RunWith(ChromeJUnit4ClassRunner.class)
 @DoNotBatch(reason = "TODO(b/40743432): SyncTestRule doesn't support batching.")
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
-@EnableFeatures({
-    ChromeFeatureList.TAB_GROUP_SYNC_ANDROID,
-    ChromeFeatureList.TAB_GROUP_PANE_ANDROID
-})
+@EnableFeatures({ChromeFeatureList.TAB_GROUP_SYNC_ANDROID})
 @Restriction({DeviceFormFactor.PHONE, Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE})
 public class TabGroupSyncLocalToRemoteTest {
     public SyncTestRule mSyncTestRule = new SyncTestRule();
diff --git a/chrome/browser/tab_group_sync/android/java/src/org/chromium/chrome/browser/tab_group_sync/TabGroupSyncRemoteToLocalTest.java b/chrome/browser/tab_group_sync/android/java/src/org/chromium/chrome/browser/tab_group_sync/TabGroupSyncRemoteToLocalTest.java
index d4af631..ad4996b 100644
--- a/chrome/browser/tab_group_sync/android/java/src/org/chromium/chrome/browser/tab_group_sync/TabGroupSyncRemoteToLocalTest.java
+++ b/chrome/browser/tab_group_sync/android/java/src/org/chromium/chrome/browser/tab_group_sync/TabGroupSyncRemoteToLocalTest.java
@@ -41,10 +41,7 @@
 @RunWith(ChromeJUnit4ClassRunner.class)
 @DoNotBatch(reason = "TODO(b/40743432): SyncTestRule doesn't support batching.")
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
-@EnableFeatures({
-    ChromeFeatureList.TAB_GROUP_SYNC_ANDROID,
-    ChromeFeatureList.TAB_GROUP_PANE_ANDROID
-})
+@EnableFeatures({ChromeFeatureList.TAB_GROUP_SYNC_ANDROID})
 @Restriction({DeviceFormFactor.PHONE, Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE})
 public class TabGroupSyncRemoteToLocalTest {
     private static final String TEST_URL1 = "/chrome/test/data/simple.html";
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/EmptyTabModel.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/EmptyTabModel.java
index 25559e7..a135772 100644
--- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/EmptyTabModel.java
+++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/EmptyTabModel.java
@@ -102,7 +102,7 @@
     }
 
     @Override
-    public int indexOf(Tab tab) {
+    public int indexOf(@Nullable Tab tab) {
         return INVALID_TAB_INDEX;
     }
 
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImpl.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImpl.java
index 2987c3c..a4ac7b4 100644
--- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImpl.java
+++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImpl.java
@@ -211,7 +211,7 @@
     }
 
     @Override
-    public int indexOf(Tab tab) {
+    public int indexOf(@Nullable Tab tab) {
         return mDelegateModel.indexOf(tab);
     }
 
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabGroupUtils.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabGroupUtils.java
index df72b96c4..4302946 100644
--- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabGroupUtils.java
+++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabGroupUtils.java
@@ -82,11 +82,13 @@
      * @param tabGroupModelFilter The {@link TabGroupModelFilter} to act on.
      * @param tabs The list of tabs to be merged to a group.
      * @param tabGroupMetadata The metadata used to regrouped the tabs.
+     * @param shouldApplyCollapse Whether to apply the collapsed state.
      */
     public static void regroupTabs(
             TabGroupModelFilter tabGroupModelFilter,
             List<Tab> tabs,
-            TabGroupMetadata tabGroupMetadata) {
+            TabGroupMetadata tabGroupMetadata,
+            boolean shouldApplyCollapse) {
         // 1. Extract tab group properties from the metadata.
         int rootId = tabGroupMetadata.rootId;
         Token tabGroupId = tabGroupMetadata.tabGroupId;
@@ -109,7 +111,10 @@
 
         // 4. Apply the tab group attributes (color, collapsed state, and title).
         tabGroupModelFilter.setTabGroupColor(rootId, tabGroupColor);
-        tabGroupModelFilter.setTabGroupCollapsed(rootId, tabGroupCollapsed, /* animate= */ false);
         tabGroupModelFilter.setTabGroupTitle(rootId, tabGroupTitle);
+        if (shouldApplyCollapse) {
+            tabGroupModelFilter.setTabGroupCollapsed(
+                    rootId, tabGroupCollapsed, /* animate= */ false);
+        }
     }
 }
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabGroupUtilsUnitTest.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabGroupUtilsUnitTest.java
index 4b112fa..69092c8 100644
--- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabGroupUtilsUnitTest.java
+++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabGroupUtilsUnitTest.java
@@ -7,9 +7,12 @@
 import static androidx.test.espresso.matcher.ViewMatchers.assertThat;
 
 import static org.hamcrest.CoreMatchers.equalTo;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -136,6 +139,15 @@
 
     @Test
     public void testRegroupTabs() {
+        verifyRegroupTabs(/* shouldApplyCollapse= */ true);
+    }
+
+    @Test
+    public void testRegroupTabs_CollapseStateNotApplied() {
+        verifyRegroupTabs(/* shouldApplyCollapse= */ false);
+    }
+
+    private void verifyRegroupTabs(boolean shouldApplyCollapse) {
         List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab1, mTab2, mTab3));
         TabGroupMetadata tabGroupMetadata =
                 new TabGroupMetadata(
@@ -150,7 +162,8 @@
                         /* tabGroupCollapsed= */ true,
                         /* isGroupShared= */ false,
                         /* isIncognito= */ false);
-        TabGroupUtils.regroupTabs(mTabGroupModelFilter, tabs, tabGroupMetadata);
+        TabGroupUtils.regroupTabs(
+                mTabGroupModelFilter, tabs, tabGroupMetadata, shouldApplyCollapse);
 
         for (Tab tab : tabs) {
             verify(mTabGroupModelFilter).mergeTabsToGroup(eq(tab.getId()), eq(TAB1_ID), eq(true));
@@ -158,8 +171,13 @@
             verify(tab).setRootId(TAB1_ID);
         }
         verify(mTabGroupModelFilter).setTabGroupColor(eq(TAB1_ID), eq(0));
-        verify(mTabGroupModelFilter).setTabGroupCollapsed(eq(TAB1_ID), eq(true), eq(false));
         verify(mTabGroupModelFilter).setTabGroupTitle(eq(TAB1_ID), eq(TAB_GROUP_TITLE));
+        if (shouldApplyCollapse) {
+            verify(mTabGroupModelFilter).setTabGroupCollapsed(eq(TAB1_ID), eq(true), eq(false));
+        } else {
+            verify(mTabGroupModelFilter, never())
+                    .setTabGroupCollapsed(anyInt(), anyBoolean(), anyBoolean());
+        }
     }
 
     private void createTabGroup(List<Tab> tabs, int rootId) {
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabList.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabList.java
index 1a31521..e450679 100644
--- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabList.java
+++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabList.java
@@ -71,6 +71,9 @@
         return t;
     }
 
-    /** Returns the index of the given tab in the order of the tab stack. */
-    int indexOf(Tab tab);
+    /**
+     * Returns the index of the given tab in the order of the tab stack, or {@link
+     * #INVALID_TAB_INDEX} if the tab is not found.
+     */
+    int indexOf(@Nullable Tab tab);
 }
diff --git a/chrome/browser/ui/android/signin/java/res/layout/account_picker_bottom_sheet_header.xml b/chrome/browser/ui/android/signin/java/res/layout/account_picker_bottom_sheet_header.xml
index 9acc166..ae136a00 100644
--- a/chrome/browser/ui/android/signin/java/res/layout/account_picker_bottom_sheet_header.xml
+++ b/chrome/browser/ui/android/signin/java/res/layout/account_picker_bottom_sheet_header.xml
@@ -32,7 +32,6 @@
       android:layout_height="wrap_content"
       android:layout_marginStart="24dp"
       android:layout_marginEnd="24dp"
-      android:focusable="true"
       android:gravity="center_horizontal"
       android:textAppearance="@style/TextAppearance.TextMedium.Secondary"
       app:leading="@dimen/text_size_medium_leading" />
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetView.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetView.java
index 8fb79839..01418302 100644
--- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetView.java
+++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetView.java
@@ -184,7 +184,6 @@
         }
         mCurrentViewState = state;
         View titleView = mViewFlipper.getChildAt(state).findViewById(sTitleIds[state]);
-        titleView.setFocusable(true);
         titleView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
     }
 
diff --git a/chrome/browser/ui/android/tab_model/tab_model_jni_bridge.cc b/chrome/browser/ui/android/tab_model/tab_model_jni_bridge.cc
index 77f2a11..6cbe335 100644
--- a/chrome/browser/ui/android/tab_model/tab_model_jni_bridge.cc
+++ b/chrome/browser/ui/android/tab_model/tab_model_jni_bridge.cc
@@ -197,7 +197,8 @@
     return false;
   }
   JNIEnv* env = base::android::AttachCurrentThread();
-  return Java_TabModelJniBridge_isTabInTabGroup(env, tab->GetJavaObject());
+  return Java_TabModelJniBridge_isTabInTabGroupLegacy(env,
+                                                      tab->GetJavaObject());
 }
 
 void TabModelJniBridge::AddObserver(TabModelObserver* observer) {
diff --git a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionControllerTest.java b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionControllerTest.java
index 2a949aa..77a41cd9 100644
--- a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionControllerTest.java
+++ b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionControllerTest.java
@@ -888,6 +888,98 @@
                 /* expectShowIdp= */ true);
     }
 
+    @Test
+    public void testSingleIdentifierAccounts() {
+        mMediator.showAccounts(
+                mTestEtldPlusOne,
+                Arrays.asList(mSingleIdentifierAccount, mSingleIdentifierAccountFilteredOut),
+                Arrays.asList(mIdpData),
+                /* isAutoReauthn= */ false,
+                /* newAccounts= */ Collections.EMPTY_LIST);
+
+        // Account chooser is shown.
+        assertEquals(HeaderType.SIGN_IN, mModel.get(ItemProperties.HEADER).get(TYPE));
+
+        assertEquals(2, mSheetAccountItems.size());
+        // First account has a click listener.
+        assertNotNull(mSheetAccountItems.get(0).model.get(AccountProperties.ON_CLICK_LISTENER));
+        // Second account is filtered out, so does not.
+        assertNull(mSheetAccountItems.get(1).model.get(AccountProperties.ON_CLICK_LISTENER));
+
+        View sheetContainer = mContentView.findViewById(R.id.sheet_item_list_container);
+        RecyclerView sheetItemListView = sheetContainer.findViewById(R.id.sheet_item_list);
+        assertEquals(2, sheetItemListView.getAdapter().getItemCount());
+
+        assertEquals(
+                AccountSelectionProperties.ITEM_TYPE_ACCOUNT,
+                sheetItemListView.getAdapter().getItemViewType(0));
+        View row = sheetItemListView.getChildAt(0);
+        assertEquals(row.getAlpha(), 1.f, ALPHA_COMPARISON_DELTA);
+        TextView textView = row.findViewById(R.id.title);
+        assertEquals("username", textView.getText());
+        textView = row.findViewById(R.id.description);
+        assertEquals("", textView.getText());
+        assertFalse(textView.isShown());
+
+        assertEquals(
+                AccountSelectionProperties.ITEM_TYPE_ACCOUNT,
+                sheetItemListView.getAdapter().getItemViewType(1));
+        row = sheetItemListView.getChildAt(1);
+        assertEquals(
+                row.getAlpha(),
+                AccountSelectionViewBinder.DISABLED_OPACITY,
+                ALPHA_COMPARISON_DELTA);
+        textView = row.findViewById(R.id.title);
+        assertEquals("username2", textView.getText());
+        textView = row.findViewById(R.id.description);
+        assertEquals("You can’t sign in using this account", textView.getText());
+    }
+
+    @Test
+    public void testSingleAccountWithSingleIdentifier() {
+        mMediator.showAccounts(
+                mTestEtldPlusOne,
+                Arrays.asList(mSingleIdentifierAccount),
+                Arrays.asList(mIdpData),
+                /* isAutoReauthn= */ false,
+                /* newAccounts= */ Arrays.asList(mSingleIdentifierAccount));
+
+        if (mRpMode == RpMode.PASSIVE) {
+            // Account chooser is shown.
+            assertEquals(HeaderType.SIGN_IN, mModel.get(ItemProperties.HEADER).get(TYPE));
+
+            assertEquals(1, mSheetAccountItems.size());
+
+            View sheetContainer = mContentView.findViewById(R.id.sheet_item_list_container);
+            assertTrue(sheetContainer.isShown());
+            RecyclerView sheetItemListView = sheetContainer.findViewById(R.id.sheet_item_list);
+            assertEquals(1, sheetItemListView.getAdapter().getItemCount());
+
+            assertEquals(
+                    AccountSelectionProperties.ITEM_TYPE_ACCOUNT,
+                    sheetItemListView.getAdapter().getItemViewType(0));
+            View row = sheetItemListView.getChildAt(0);
+            assertEquals(row.getAlpha(), 1.f, ALPHA_COMPARISON_DELTA);
+            TextView textView = row.findViewById(R.id.title);
+            assertEquals("username", textView.getText());
+            textView = row.findViewById(R.id.description);
+            assertEquals("", textView.getText());
+            assertFalse(textView.isShown());
+        } else {
+            // Request permission is shown.
+            assertEquals(
+                    HeaderType.REQUEST_PERMISSION_MODAL,
+                    mModel.get(ItemProperties.HEADER).get(TYPE));
+
+            View accountChip = mContentView.findViewById(R.id.account_chip);
+            assertNotNull(accountChip);
+            assertTrue(accountChip.isShown());
+
+            TextView textView = accountChip.findViewById(R.id.description);
+            assertEquals("username", textView.getText());
+        }
+    }
+
     private void pressBack() {
         if (mBottomSheetContent.handleBackPress()) return;
 
diff --git a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionJUnitTestBase.java b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionJUnitTestBase.java
index a728803d..f279c8d 100644
--- a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionJUnitTestBase.java
+++ b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionJUnitTestBase.java
@@ -154,6 +154,8 @@
     Account mFilteredOutAccount;
     Account mFilteredOutAccountWithUseDifferentAccount;
     Account mNicolasAccount;
+    Account mSingleIdentifierAccount;
+    Account mSingleIdentifierAccountFilteredOut;
 
     IdentityCredentialTokenError mTokenError;
     IdentityCredentialTokenError mTokenErrorEmptyUrl;
@@ -387,6 +389,34 @@
                         /* isFilteredOut= */ false,
                         mIdpData);
 
+        mSingleIdentifierAccount =
+                new Account(
+                        "singleid1",
+                        "",
+                        "username",
+                        "",
+                        /* secondaryDescription= */ null,
+                        /* pictureBitmap= */ null,
+                        /* circledBadgedPictureBitmap= */ null,
+                        /* isSignIn= */ false,
+                        /* isBrowserTrustedSignIn= */ false,
+                        /* isFilteredOut= */ false,
+                        mIdpData);
+
+        mSingleIdentifierAccountFilteredOut =
+                new Account(
+                        "singleid2",
+                        "",
+                        "username2",
+                        "",
+                        /* secondaryDescription= */ null,
+                        /* pictureBitmap= */ null,
+                        /* circledBadgedPictureBitmap= */ null,
+                        /* isSignIn= */ true,
+                        /* isBrowserTrustedSignIn= */ true,
+                        /* isFilteredOut= */ true,
+                        mIdpData);
+
         mNewAccountsSingleReturningAccount = Arrays.asList(mAnaAccount);
         mNewAccountsSingleNewAccount = Arrays.asList(mNewUserAccount);
         mNewAccountsMultipleAccounts = Arrays.asList(mAnaAccount, mBobAccount);
diff --git a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewBinder.java b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewBinder.java
index dd37fed..92a2f5d 100644
--- a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewBinder.java
+++ b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewBinder.java
@@ -216,15 +216,27 @@
             // shown in the Continue button instead.
             if (title != null) {
                 title.setText(
-                        account.isFilteredOut()
+                        account.isFilteredOut() && !account.getDisplayIdentifier().isEmpty()
                                 ? account.getDisplayIdentifier()
                                 : account.getDisplayName());
             }
             TextView description = view.findViewById(R.id.description);
-            description.setText(
+            String descriptionText =
                     account.isFilteredOut()
                             ? view.getContext().getString(R.string.filtered_account_message)
-                            : account.getDisplayIdentifier());
+                            : account.getDisplayIdentifier();
+            if (descriptionText.isEmpty() && title == null) {
+                // It is possible that the display identifier is empty.
+                // If we have no title, show the display name in the description.
+                descriptionText = account.getDisplayName();
+            }
+            if (descriptionText.isEmpty()) {
+                // Hide the view so that we center the remaining view(s).
+                description.setVisibility(View.GONE);
+            } else {
+                description.setText(descriptionText);
+                description.setVisibility(View.VISIBLE);
+            }
             TextView secondaryDescription = view.findViewById(R.id.secondary_description);
             // The secondary description is not shown in the account chip of active mode's
             // request permission dialog. In this case, the view is not present.
diff --git a/chrome/browser/ui/ash/gemini_app/gemini_app_interactive_uitest.cc b/chrome/browser/ui/ash/gemini_app/gemini_app_interactive_uitest.cc
index 8526c94..93f0fd8 100644
--- a/chrome/browser/ui/ash/gemini_app/gemini_app_interactive_uitest.cc
+++ b/chrome/browser/ui/ash/gemini_app/gemini_app_interactive_uitest.cc
@@ -442,7 +442,8 @@
 IN_PROC_BROWSER_TEST_P(GeminiAppInteractiveUiTest, PRE_LaunchFromAppList) {}
 
 // Verifies that the Gemini app can be launched from the app list.
-IN_PROC_BROWSER_TEST_P(GeminiAppInteractiveUiTest, LaunchFromAppList) {
+// TODO(crbug.com/408148646): Re-enable this test.
+IN_PROC_BROWSER_TEST_P(GeminiAppInteractiveUiTest, DISABLED_LaunchFromAppList) {
   // Views.
   raw_ptr<ash::AppsGridView> apps_grid_view = nullptr;
   raw_ptr<ash::AppListItemView> files_app = nullptr;
diff --git a/chrome/browser/ui/autofill/payments/BUILD.gn b/chrome/browser/ui/autofill/payments/BUILD.gn
index 4335331b..c132a4a4e 100644
--- a/chrome/browser/ui/autofill/payments/BUILD.gn
+++ b/chrome/browser/ui/autofill/payments/BUILD.gn
@@ -133,6 +133,7 @@
       "//chrome/browser/sync",
       "//chrome/browser/sync:factories",
       "//chrome/browser/ui:browser_navigator_params_headers",
+      "//chrome/browser/ui/browser_window",
       "//chrome/browser/ui/promos:utils",
       "//chrome/browser/ui/tabs:tab_strip",
       "//chrome/browser/ui/views/page_action:page_action",
@@ -142,6 +143,7 @@
       "//components/prefs",
       "//components/strings:components_strings_grit",
       "//components/sync/service",
+      "//components/tab_collections:public",
       "//components/user_prefs",
       "//components/webauthn/content/browser",
     ]
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 13457c45..6590588 100644
--- a/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client.cc
+++ b/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client.cc
@@ -98,12 +98,16 @@
 #include "chrome/browser/ui/autofill/payments/webauthn_dialog_controller_impl.h"
 #include "chrome/browser/ui/autofill/payments/webauthn_dialog_state.h"
 #include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
 #include "chrome/browser/ui/promos/ios_promos_utils.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "components/autofill/core/common/autofill_payments_features.h"
+// TODO(crbug.com/407105162): Remove nogncheck when crbug.com/40147906 is fixed.
+#include "components/tab_collections/public/tab_interface.h"  // nogncheck
 #include "components/webauthn/content/browser/internal_authenticator_impl.h"
 #endif  // BUILDFLAG(IS_ANDROID)
 
+// TODO(crbug.com/407106692): Refactor for Platform-Specific Code Separation.
 namespace autofill::payments {
 
 ChromePaymentsAutofillClient::ChromePaymentsAutofillClient(
@@ -977,6 +981,17 @@
   }
 }
 
+bool ChromePaymentsAutofillClient::IsTabModalPopup() const {
+#if !BUILDFLAG(IS_ANDROID)
+  tabs::TabInterface* const tab_interface =
+      tabs::TabInterface::MaybeGetFromContents(web_contents());
+  return tab_interface &&
+         tab_interface->GetBrowserWindowInterface()->IsTabModalPopup();
+#else
+  return false;
+#endif  // !BUILDFLAG(IS_ANDROID)
+}
+
 #if BUILDFLAG(IS_ANDROID)
 AutofillMessageController&
 ChromePaymentsAutofillClient::GetAutofillMessageController() {
diff --git a/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client.h b/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client.h
index 2e1cb56..5c141f6 100644
--- a/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client.h
+++ b/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client.h
@@ -214,6 +214,7 @@
       base::OnceCallback<void(BnplIssuer)> selected_issuer_callback,
       base::OnceClosure cancel_callback) override;
   void DismissSelectBnplIssuerDialog() override;
+  bool IsTabModalPopup() const override;
 
 #if BUILDFLAG(IS_ANDROID)
   // The AutofillMessageController is used to show a message notification
diff --git a/chrome/browser/ui/blocked_content/popup_tracker_browsertest.cc b/chrome/browser/ui/blocked_content/popup_tracker_browsertest.cc
index 952fb920..6d233b20 100644
--- a/chrome/browser/ui/blocked_content/popup_tracker_browsertest.cc
+++ b/chrome/browser/ui/blocked_content/popup_tracker_browsertest.cc
@@ -159,6 +159,7 @@
   content::WebContents* popup =
       browser()->tab_strip_model()->GetActiveWebContents();
   EXPECT_TRUE(blocked_content::PopupTracker::FromWebContents(popup));
+  content::SimulateEndOfPaintHoldingOnPrimaryMainFrame(popup);
 
   // Perform some user gestures on the page.
   content::SimulateMouseClick(popup, 0, blink::WebMouseEvent::Button::kLeft);
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index d45f8f1..1689623 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -1295,6 +1295,10 @@
   return this;
 }
 
+bool Browser::IsTabModalPopup() const {
+  return is_tab_modal_popup_;
+}
+
 void Browser::DidBecomeActive() {
   if (!is_active_) {
     is_active_ = true;
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h
index ce1e404e..b04cf08c 100644
--- a/chrome/browser/ui/browser.h
+++ b/chrome/browser/ui/browser.h
@@ -893,6 +893,12 @@
   web_app::AppBrowserController* GetAppBrowserController() override;
   std::vector<tabs::TabInterface*> GetAllTabInterfaces() override;
   Browser* GetBrowserForMigrationOnly() override;
+  bool IsTabModalPopup() const override;
+
+  // Called by BrowserView.
+  void set_is_tab_modal_popup(bool is_tab_modal_popup) {
+    is_tab_modal_popup_ = is_tab_modal_popup;
+  }
 
   // Called by BrowserView on active change for the browser.
   void DidBecomeActive();
@@ -1505,6 +1511,10 @@
   // shortly (after a PostTask).
   bool is_delete_scheduled_ = false;
 
+  // If true, the browser window was created as a tab modal pop-up. This is
+  // determined by the NavigateParams::is_tab_modal_popup.
+  bool is_tab_modal_popup_ = false;
+
 #if defined(USE_AURA)
   std::unique_ptr<OverscrollPrefManager> overscroll_pref_manager_;
 #endif
diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc
index b82a8fb..bee4f9f1 100644
--- a/chrome/browser/ui/browser_commands.cc
+++ b/chrome/browser/ui/browser_commands.cc
@@ -1362,9 +1362,9 @@
   }
 }
 
-void BookmarkCurrentTabInFolder(Browser* browser, int64_t folder_id) {
-  BookmarkModel* const model =
-      BookmarkModelFactory::GetForBrowserContext(browser->profile());
+void BookmarkCurrentTabInFolder(Browser* browser,
+                                BookmarkModel* model,
+                                int64_t folder_id) {
   GURL url;
   std::u16string title;
   if (!BookmarkCurrentTabHelper(browser, model, &url, &title)) {
diff --git a/chrome/browser/ui/browser_commands.h b/chrome/browser/ui/browser_commands.h
index 718c061..ac0a87f 100644
--- a/chrome/browser/ui/browser_commands.h
+++ b/chrome/browser/ui/browser_commands.h
@@ -32,6 +32,10 @@
 class WebContents;
 }  // namespace content
 
+namespace bookmarks {
+class BookmarkModel;
+}  // namespace bookmarks
+
 namespace chrome {
 
 // For all commands, where a tab is not specified, the active tab is assumed.
@@ -158,7 +162,9 @@
 void BookmarkCurrentTab(Browser* browser);
 // Bookmarks the current tab in the given folder and does not show the edit
 // dialog.
-void BookmarkCurrentTabInFolder(Browser* browser, int64_t folder_id);
+void BookmarkCurrentTabInFolder(Browser* browser,
+                                bookmarks::BookmarkModel* model,
+                                int64_t folder_id);
 bool CanBookmarkCurrentTab(const Browser* browser);
 void BookmarkAllTabs(Browser* browser);
 bool CanBookmarkAllTabs(const Browser* browser);
diff --git a/chrome/browser/ui/browser_navigator.cc b/chrome/browser/ui/browser_navigator.cc
index cefd4bc..d9604af 100644
--- a/chrome/browser/ui/browser_navigator.cc
+++ b/chrome/browser/ui/browser_navigator.cc
@@ -481,6 +481,7 @@
       if (params_->is_tab_modal_popup) {
         CHECK_EQ(params_->disposition, WindowOpenDisposition::NEW_POPUP);
         CHECK_NE(source_contents_, nullptr);
+        window->SetIsTabModalPopup(true);
         constrained_window::ShowModalDialog(window->GetNativeWindow(),
                                             source_contents_);
       } else {
diff --git a/chrome/browser/ui/browser_navigator_browsertest.cc b/chrome/browser/ui/browser_navigator_browsertest.cc
index 7307eee..cc5a37b 100644
--- a/chrome/browser/ui/browser_navigator_browsertest.cc
+++ b/chrome/browser/ui/browser_navigator_browsertest.cc
@@ -718,7 +718,7 @@
   params.disposition = WindowOpenDisposition::NEW_POPUP;
   params.is_tab_modal_popup = true;
   params.window_features.bounds = gfx::Rect(0, 0, 200, 200);
-  // Wait for new popup to to load and gain focus.
+  // Wait for new popup to load and gain focus.
   ui_test_utils::NavigateToURL(&params);
 
   // Add a new tab.
@@ -735,6 +735,9 @@
 
   // Verify the popup window is visible again.
   EXPECT_TRUE(params.browser->window()->IsVisible());
+
+  // Verify the popup window is set as tab model popup.
+  EXPECT_TRUE(params.browser->window()->IsTabModalPopup());
 }
 
 // This test verifies that navigating with WindowOpenDisposition = NEW_WINDOW
diff --git a/chrome/browser/ui/browser_navigator_params.h b/chrome/browser/ui/browser_navigator_params.h
index e1fe374..7ef0f33 100644
--- a/chrome/browser/ui/browser_navigator_params.h
+++ b/chrome/browser/ui/browser_navigator_params.h
@@ -235,7 +235,8 @@
       captive_portal::CaptivePortalWindowType::kNone;
 
   // Whether the browser popup is being created as a tab modal. If true,
-  // `disposition` should be NEW_POPUP.
+  // `disposition` should be NEW_POPUP. Additionally, it prevents card saving
+  // and other prompts for payments autofill enrollment.
   bool is_tab_modal_popup = false;
 
   // If false then the navigation was not initiated by a user gesture. This
diff --git a/chrome/browser/ui/browser_window.h b/chrome/browser/ui/browser_window.h
index f70be05..5c3e8484 100644
--- a/chrome/browser/ui/browser_window.h
+++ b/chrome/browser/ui/browser_window.h
@@ -256,6 +256,14 @@
   // Sets the starred state for the current tab.
   virtual void SetStarredState(bool is_starred) = 0;
 
+  // Checks if the browser popup is a tab modal popup.
+  virtual bool IsTabModalPopup() const = 0;
+
+  // Sets whether the browser popup is a tab modal popup. Tab modal popups, used
+  // by autofill features, intentionally disable save card prompts because they
+  // are not intended for saving new card details.
+  virtual void SetIsTabModalPopup(bool is_tab_modal_popup) = 0;
+
   // Called when the active tab changes.  Subclasses which implement
   // TabStripModelObserver should implement this instead of ActiveTabChanged();
   // the Browser will call this method while processing that one.
diff --git a/chrome/browser/ui/browser_window/public/browser_window_interface.h b/chrome/browser/ui/browser_window/public/browser_window_interface.h
index f2b51e7..ad7719f 100644
--- a/chrome/browser/ui/browser_window/public/browser_window_interface.h
+++ b/chrome/browser/ui/browser_window/public/browser_window_interface.h
@@ -222,6 +222,9 @@
   // //components/web_modal. See crbug.com/377820808.
   virtual void SetWebContentsBlocked(content::WebContents* web_contents,
                                      bool blocked) = 0;
+
+  // Checks if the browser popup is tab modal dialog.
+  virtual bool IsTabModalPopup() const = 0;
 };
 
 #endif  // CHROME_BROWSER_UI_BROWSER_WINDOW_PUBLIC_BROWSER_WINDOW_INTERFACE_H_
diff --git a/chrome/browser/ui/browser_window/test/mock_browser_window_interface.h b/chrome/browser/ui/browser_window/test/mock_browser_window_interface.h
index 84fd1e7..30bb7f69 100644
--- a/chrome/browser/ui/browser_window/test/mock_browser_window_interface.h
+++ b/chrome/browser/ui/browser_window/test/mock_browser_window_interface.h
@@ -81,6 +81,7 @@
               SetWebContentsBlocked,
               (content::WebContents*, bool),
               (override));
+  MOCK_METHOD(bool, IsTabModalPopup, (), (const, override));
 
   // PageNavigator methods
   MOCK_METHOD(content::WebContents*,
diff --git a/chrome/browser/ui/global_media_controls/cast_media_notification_item_unittest.cc b/chrome/browser/ui/global_media_controls/cast_media_notification_item_unittest.cc
index ddbd096a..4c27df5a 100644
--- a/chrome/browser/ui/global_media_controls/cast_media_notification_item_unittest.cc
+++ b/chrome/browser/ui/global_media_controls/cast_media_notification_item_unittest.cc
@@ -61,7 +61,8 @@
               (net::ReferrerPolicy referrer_policy,
                network::mojom::CredentialsMode credentials_mode,
                const net::HttpRequestHeaders& additional_headers,
-               const url::Origin& initiator),
+               const url::Origin& initiator,
+               bool is_same_site_request),
               (override));
   MOCK_METHOD(void,
               Start,
diff --git a/chrome/browser/ui/lens/lens_permission_bubble_controller.cc b/chrome/browser/ui/lens/lens_permission_bubble_controller.cc
index a2ff2d6..5daa35fe 100644
--- a/chrome/browser/ui/lens/lens_permission_bubble_controller.cc
+++ b/chrome/browser/ui/lens/lens_permission_bubble_controller.cc
@@ -16,6 +16,8 @@
 #include "chrome/browser/ui/browser_element_identifiers.h"
 #include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
 #include "chrome/browser/ui/lens/lens_overlay_theme_utils.h"
+#include "chrome/browser/ui/tabs/public/tab_dialog_manager.h"
+#include "chrome/browser/ui/tabs/public/tab_features.h"
 #include "chrome/grit/branded_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/theme_resources.h"
@@ -107,20 +109,26 @@
 
 std::unique_ptr<views::Widget> LensPermissionBubbleController::ShowDialogWidget(
     content::WebContents* web_contents) {
-  std::unique_ptr<views::BubbleDialogModelHost> model_host =
+  // The widget will own `model_host` through DialogDelegate.
+  views::BubbleDialogModelHost* model_host =
       views::BubbleDialogModelHost::CreateModal(
-          CreateLensPermissionDialogModel(), ui::mojom::ModalType::kChild);
+          CreateLensPermissionDialogModel(), ui::mojom::ModalType::kChild)
+          .release();
   model_host->SetOwnershipOfNewWidget(
       views::Widget::InitParams::CLIENT_OWNS_WIDGET);
 
-  // The widget will own `model_host` through DialogDelegate.
   std::unique_ptr<views::Widget> widget =
-      constrained_window::ShowWebModalDialogViewsOwned(
-          model_host.release(), web_contents,
-          views::Widget::InitParams::CLIENT_OWNS_WIDGET);
+      tab_interface_->GetTabFeatures()
+          ->tab_dialog_manager()
+          ->CreateShowDialogAndBlockTabInteraction(model_host);
   widget->MakeCloseSynchronous(
       base::BindOnce(&LensPermissionBubbleController::CloseDialogWidget,
                      base::Unretained(this)));
+
+  views::View* focused_view = model_host->GetInitiallyFocusedView();
+  CHECK(focused_view);
+  focused_view->RequestFocus();
+
   return widget;
 }
 
diff --git a/chrome/browser/ui/omnibox/chrome_omnibox_client.cc b/chrome/browser/ui/omnibox/chrome_omnibox_client.cc
index 2d82ff2..4d2a490 100644
--- a/chrome/browser/ui/omnibox/chrome_omnibox_client.cc
+++ b/chrome/browser/ui/omnibox/chrome_omnibox_client.cc
@@ -81,6 +81,7 @@
 #include "components/omnibox/common/omnibox_features.h"
 #include "components/profile_metrics/browser_profile_type.h"
 #include "components/search_engines/template_url_service.h"
+#include "components/search_engines/template_url_starter_pack_data.h"
 #include "components/sessions/content/session_tab_helper.h"
 #include "components/strings/grit/components_strings.h"
 #include "content/public/browser/devtools_agent_host.h"
@@ -345,6 +346,30 @@
   }
 }
 
+void ChromeOmniboxClient::OnKeywordModeChanged(bool entered,
+                                               const std::u16string& keyword) {
+  if (entered) {
+    // Note, entry into keyword mode is not sufficient signal to start lens and
+    // that is handled by separate explicit actions; but whenever the '@page'
+    // keyword mode is exited, lens should be closed.
+    return;
+  }
+  if (content::WebContents* web_contents = location_bar_->GetWebContents()) {
+    if (LensOverlayController* lens_controller =
+            LensOverlayController::GetController(web_contents)) {
+      if (TemplateURL* template_url =
+              GetTemplateURLService()->GetTemplateURLForKeyword(keyword)) {
+        if (template_url->starter_pack_id() ==
+            TemplateURLStarterPackData::kPage) {
+          // TODO(crbug.com/408073216): Create and use new dismissal source.
+          lens_controller->CloseUIAsync(
+              lens::LensOverlayDismissalSource::kEscapeKeyPress);
+        }
+      }
+    }
+  }
+}
+
 void ChromeOmniboxClient::MaybeShowOnFocusHatsSurvey(
     AutocompleteProviderClient* client,
     std::u16string text) {
diff --git a/chrome/browser/ui/omnibox/chrome_omnibox_client.h b/chrome/browser/ui/omnibox/chrome_omnibox_client.h
index d3431a36..38b1b67 100644
--- a/chrome/browser/ui/omnibox/chrome_omnibox_client.h
+++ b/chrome/browser/ui/omnibox/chrome_omnibox_client.h
@@ -74,6 +74,8 @@
   void OnInputStateChanged() override;
   void OnFocusChanged(OmniboxFocusState state,
                       OmniboxFocusChangeReason reason) override;
+  void OnKeywordModeChanged(bool entered,
+                            const std::u16string& keyword) override;
   void MaybeShowOnFocusHatsSurvey(AutocompleteProviderClient* client,
                                   std::u16string text) override;
   void OnResultChanged(const AutocompleteResult& result,
diff --git a/chrome/browser/ui/privacy_sandbox/privacy_sandbox_prompt_helper.cc b/chrome/browser/ui/privacy_sandbox/privacy_sandbox_prompt_helper.cc
index b3ca5f7..4f7e318 100644
--- a/chrome/browser/ui/privacy_sandbox/privacy_sandbox_prompt_helper.cc
+++ b/chrome/browser/ui/privacy_sandbox/privacy_sandbox_prompt_helper.cc
@@ -201,24 +201,14 @@
 
   // If a Privacy Sandbox prompt already exists for this browser, do not attempt
   // to open another one.
-  // Or if the handle is not being held, do not attempt to show the prompt.
   if (auto* privacy_sandbox_service =
           PrivacySandboxServiceFactory::GetForProfile(profile())) {
-    privacy_sandbox::PrivacySandboxQueueManager& queue_manager =
-        privacy_sandbox_service->GetPrivacySandboxNoticeQueueManager();
-
     if (privacy_sandbox_service->IsPromptOpenForBrowser(browser)) {
       base::UmaHistogramEnumeration(kPrivacySandboxPromptHelperEventHistogram,
                                     SettingsPrivacySandboxPromptHelperEvent::
                                         kPromptAlreadyExistsForBrowser);
       return;
     }
-
-    if (base::FeatureList::IsEnabled(
-            privacy_sandbox::kPrivacySandboxNoticeQueue) &&
-        !queue_manager.IsHoldingHandle()) {
-      return;
-    }
   }
 
   // The PrivacySandbox prompt can always fit inside a normal tabbed window due
@@ -245,6 +235,21 @@
     return;
   }
 
+  // If the handle is not being held, do not attempt to show the prompt.
+  // We want to check this constraint at the very end for histogram emitting
+  // reasons.
+  if (auto* privacy_sandbox_service =
+          PrivacySandboxServiceFactory::GetForProfile(profile())) {
+    privacy_sandbox::PrivacySandboxQueueManager& queue_manager =
+        privacy_sandbox_service->GetPrivacySandboxNoticeQueueManager();
+    if (base::FeatureList::IsEnabled(
+            privacy_sandbox::kPrivacySandboxNoticeQueue) &&
+        !queue_manager.IsHoldingHandle()) {
+      queue_manager.MaybeEmitQueueStateMetrics();
+      return;
+    }
+  }
+
   // Record the URL that the prompt was displayed over.
   uint32_t host_hash = base::Hash(navigation_handle->GetURL().IsAboutBlank()
                                       ? "about:blank"
diff --git a/chrome/browser/ui/privacy_sandbox/privacy_sandbox_queue_browsertest.cc b/chrome/browser/ui/privacy_sandbox/privacy_sandbox_queue_browsertest.cc
index 4ce9ec9..3f991586 100644
--- a/chrome/browser/ui/privacy_sandbox/privacy_sandbox_queue_browsertest.cc
+++ b/chrome/browser/ui/privacy_sandbox/privacy_sandbox_queue_browsertest.cc
@@ -20,6 +20,7 @@
 #include "components/privacy_sandbox/privacy_sandbox_features.h"
 #include "components/regional_capabilities/regional_capabilities_switches.h"
 #include "components/search_engines/search_engines_switches.h"
+#include "components/user_education/test/test_product_messaging_controller.h"
 #include "components/variations/service/variations_service.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
@@ -27,6 +28,8 @@
 #include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_delegate.h"
 
+DEFINE_LOCAL_REQUIRED_NOTICE_IDENTIFIER(kNoticeId);
+
 // This file is meant to test the general code path that causes notices to show.
 // Specifically triggering of the notice queue.
 class PrivacySandboxQueueTestNotice : public InProcessBrowserTest {
@@ -36,11 +39,9 @@
         {privacy_sandbox::kPrivacySandboxNoticeQueue}, {});
   }
 
-  void SetUpPrivacySandboxService() {
-    auto* privacy_sandbox_service =
-        PrivacySandboxServiceFactory::GetForProfile(browser()->profile());
-    privacy_sandbox_service->SetPromptDisabledForTests(false);
-    privacy_sandbox_service->ForceChromeBuildForTests(true);
+  void SetUpOnMainThread() override {
+    privacy_sandbox_service()->SetPromptDisabledForTests(false);
+    privacy_sandbox_service()->ForceChromeBuildForTests(true);
     g_browser_process->variations_service()->OverrideStoredPermanentCountry(
         "be");
     base::CommandLine::ForCurrentProcess()->RemoveSwitch(switches::kNoFirstRun);
@@ -50,6 +51,14 @@
     return dialog_widget->GetWebContentsForTesting();
   }
 
+  privacy_sandbox::PrivacySandboxQueueManager& queue_manager() {
+    return privacy_sandbox_service()->GetPrivacySandboxNoticeQueueManager();
+  }
+
+  PrivacySandboxService* privacy_sandbox_service() {
+    return PrivacySandboxServiceFactory::GetForProfile(browser()->profile());
+  }
+
   std::string element_path_ =
       "document.querySelector('privacy-sandbox-combined-dialog-app')."
       "shadowRoot.querySelector('#notice').shadowRoot.querySelector('#"
@@ -66,13 +75,6 @@
 
 // Navigate to a invalid then valid webpage. Ensure handle is held throughout.
 IN_PROC_BROWSER_TEST_F(PrivacySandboxQueueTestNotice, NoPrompt) {
-  // Set flags correctly
-  SetUpPrivacySandboxService();
-  auto* privacy_sandbox_service =
-      PrivacySandboxServiceFactory::GetForProfile(browser()->profile());
-  privacy_sandbox::PrivacySandboxQueueManager& queue_manager =
-      privacy_sandbox_service->GetPrivacySandboxNoticeQueueManager();
-
   // Navigate to invalid page.
   ASSERT_TRUE(ui_test_utils::NavigateToURLWithDisposition(
       browser(), GURL(chrome::kChromeUINewTabPageURL),
@@ -81,7 +83,7 @@
 
   // When we navigate to a page that doesn't require a prompt, we should still
   // hog handle.
-  ASSERT_TRUE(queue_manager.IsHoldingHandle());
+  ASSERT_TRUE(queue_manager().IsHoldingHandle());
 
   // Navigate to valid page.
   ASSERT_TRUE(ui_test_utils::NavigateToURLWithDisposition(
@@ -89,18 +91,11 @@
       WindowOpenDisposition::NEW_WINDOW,
       ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP));
 
-  ASSERT_TRUE(queue_manager.IsHoldingHandle());
+  ASSERT_TRUE(queue_manager().IsHoldingHandle());
 }
 
 // Navigate to a valid webpage (settings page) and click a notice. One window.
 IN_PROC_BROWSER_TEST_F(PrivacySandboxQueueTestNotice, PromptShows) {
-  // Set flags correctly.
-  SetUpPrivacySandboxService();
-  auto* privacy_sandbox_service =
-      PrivacySandboxServiceFactory::GetForProfile(browser()->profile());
-  privacy_sandbox::PrivacySandboxQueueManager& queue_manager =
-      privacy_sandbox_service->GetPrivacySandboxNoticeQueueManager();
-
   // Navigate.
   views::NamedWidgetShownWaiter waiter(
       views::test::AnyWidgetTestPasskey{},
@@ -115,7 +110,7 @@
       waiter.WaitIfNeededAndGet()->widget_delegate()->GetContentsView());
 
   // Before we click, should still be holding handle.
-  ASSERT_TRUE(queue_manager.IsHoldingHandle());
+  ASSERT_TRUE(queue_manager().IsHoldingHandle());
 
   // Click ack button.
   const std::string& code = element_path_ + ".click();";
@@ -124,19 +119,12 @@
                               1 /* world_id */));
 
   // After click, should release handle.
-  ASSERT_FALSE(queue_manager.IsHoldingHandle());
+  ASSERT_FALSE(queue_manager().IsHoldingHandle());
 }
 
 // Navigate to a valid webpage (settings page) and click a notice. Two windows.
 IN_PROC_BROWSER_TEST_F(PrivacySandboxQueueTestNotice,
                        PromptShowsMultipleWindows) {
-  // Set flags correctly.
-  SetUpPrivacySandboxService();
-  auto* privacy_sandbox_service =
-      PrivacySandboxServiceFactory::GetForProfile(browser()->profile());
-  privacy_sandbox::PrivacySandboxQueueManager& queue_manager =
-      privacy_sandbox_service->GetPrivacySandboxNoticeQueueManager();
-
   // Navigate.
   views::NamedWidgetShownWaiter waiter(
       views::test::AnyWidgetTestPasskey{},
@@ -151,7 +139,7 @@
       waiter.WaitIfNeededAndGet()->widget_delegate()->GetContentsView());
 
   // After first nav, we should be holding handle.
-  ASSERT_TRUE(queue_manager.IsHoldingHandle());
+  ASSERT_TRUE(queue_manager().IsHoldingHandle());
 
   ASSERT_TRUE(ui_test_utils::NavigateToURLWithDisposition(
       browser(), GURL(chrome::kChromeUISettingsURL),
@@ -159,7 +147,7 @@
       ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP));
 
   // After second nav, should still be holding handle.
-  ASSERT_TRUE(queue_manager.IsHoldingHandle());
+  ASSERT_TRUE(queue_manager().IsHoldingHandle());
 
   // Click ack button on one window.
   const std::string& code = element_path_ + ".click();";
@@ -168,19 +156,14 @@
                               1 /* world_id */));
 
   // After click, should release handle.
-  ASSERT_FALSE(queue_manager.IsHoldingHandle());
+  ASSERT_FALSE(queue_manager().IsHoldingHandle());
 }
 
 // Browser startup assumes we don't need a notice. Then we need a notice.
 IN_PROC_BROWSER_TEST_F(PrivacySandboxQueueTestNotice,
                        PromptNeededAtStartupThenNotAtNavigation) {
   // Set flags incorrectly so we don't need a prompt.
-  SetUpPrivacySandboxService();
-  auto* privacy_sandbox_service =
-      PrivacySandboxServiceFactory::GetForProfile(browser()->profile());
-  privacy_sandbox_service->SetPromptDisabledForTests(true);
-  privacy_sandbox::PrivacySandboxQueueManager& queue_manager =
-      privacy_sandbox_service->GetPrivacySandboxNoticeQueueManager();
+  privacy_sandbox_service()->SetPromptDisabledForTests(true);
 
   // Navigate.
   ASSERT_TRUE(ui_test_utils::NavigateToURLWithDisposition(
@@ -189,11 +172,11 @@
       ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP));
 
   // After first nav, we should not be holding handle.
-  ASSERT_FALSE(queue_manager.IsHoldingHandle());
-  ASSERT_FALSE(queue_manager.IsNoticeQueued());
+  ASSERT_FALSE(queue_manager().IsHoldingHandle());
+  ASSERT_FALSE(queue_manager().IsNoticeQueued());
 
   // Set the correct flag.
-  privacy_sandbox_service->SetPromptDisabledForTests(false);
+  privacy_sandbox_service()->SetPromptDisabledForTests(false);
 
   // Navigate again and now we want to queue and hold the handle.
   ASSERT_TRUE(ui_test_utils::NavigateToURLWithDisposition(
@@ -202,19 +185,12 @@
       ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP));
 
   // After second nav, should have been queued and holding handle.
-  ASSERT_TRUE(queue_manager.IsHoldingHandle());
+  ASSERT_TRUE(queue_manager().IsHoldingHandle());
 }
 
 // Browser startup assumes we need a notice. Then we realize we don't need it.
 IN_PROC_BROWSER_TEST_F(PrivacySandboxQueueTestNotice,
                        PromptNotNeededAtStartupThenNeededAtNavigation) {
-  // Set flags correctly.
-  SetUpPrivacySandboxService();
-  auto* privacy_sandbox_service =
-      PrivacySandboxServiceFactory::GetForProfile(browser()->profile());
-  privacy_sandbox::PrivacySandboxQueueManager& queue_manager =
-      privacy_sandbox_service->GetPrivacySandboxNoticeQueueManager();
-
   // Navigate.
   ASSERT_TRUE(ui_test_utils::NavigateToURLWithDisposition(
       browser(), GURL(chrome::kChromeUISettingsURL),
@@ -222,10 +198,10 @@
       ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP));
 
   // After first trigger, should have been queued and holding handle.
-  ASSERT_TRUE(queue_manager.IsHoldingHandle());
+  ASSERT_TRUE(queue_manager().IsHoldingHandle());
 
   // Change our mind about wanting a prompt.
-  privacy_sandbox_service->SetPromptDisabledForTests(true);
+  privacy_sandbox_service()->SetPromptDisabledForTests(true);
 
   // Navigate.
   ASSERT_TRUE(ui_test_utils::NavigateToURLWithDisposition(
@@ -234,8 +210,47 @@
       ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP));
 
   // After second nav do not hold handle.
-  ASSERT_FALSE(queue_manager.IsNoticeQueued());
-  ASSERT_FALSE(queue_manager.IsHoldingHandle());
+  ASSERT_FALSE(queue_manager().IsNoticeQueued());
+  ASSERT_FALSE(queue_manager().IsHoldingHandle());
+}
+
+// Don't allow the notice to be queued, such that the handle check fails, and we
+// can log a QueueState.
+IN_PROC_BROWSER_TEST_F(PrivacySandboxQueueTestNotice,
+                       TestNoticeQueueStateNotInQueue) {
+  base::HistogramTester histogram_tester;
+  // Suppress attempts to queue.
+  queue_manager().SetSuppressQueue(true);
+
+  // Navigate to valid page, failing the holdingHandle check.
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(), GURL(chrome::kChromeUISettingsURL),
+      WindowOpenDisposition::NEW_WINDOW, ui_test_utils::BROWSER_TEST_NO_WAIT);
+  base::RunLoop().RunUntilIdle();
+  histogram_tester.ExpectBucketCount(
+      "PrivacySandbox.Notice.NotHoldingHandle.NotInQueue",
+      /*sample=*/1, /*expected_count=*/1);
+}
+
+// Allow the notice to be queued, but add a blocking notice that doesn't allow
+// our spot in the queue to trigger. The handle check repeatedly fails, and we
+// are still in the queue.
+IN_PROC_BROWSER_TEST_F(PrivacySandboxQueueTestNotice,
+                       TestNoticeQueueStateStuckInQueue) {
+  base::HistogramTester histogram_tester;
+
+  // Add a test notice before our notice that hogs the handle.
+  user_education::test::TestNotice notice(
+      *queue_manager().GetProductMessagingController(), kNoticeId);
+
+  // Navigate to valid page, failing the holdingHandle check.
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(), GURL(chrome::kChromeUISettingsURL),
+      WindowOpenDisposition::NEW_WINDOW, ui_test_utils::BROWSER_TEST_NO_WAIT);
+  base::RunLoop().RunUntilIdle();
+  histogram_tester.ExpectBucketCount(
+      "PrivacySandbox.Notice.NotHoldingHandle.InQueue",
+      /*sample=*/1, /*expected_count=*/1);
 }
 
 class PrivacySandboxQueueTestNoticeWithSearchEngine
@@ -248,16 +263,10 @@
         switches::kIgnoreNoFirstRunForSearchEngineChoiceScreen);
   }
 
-  void SetUpPrivacySandboxServiceAndDMA() {
-    auto* privacy_sandbox_service =
-        PrivacySandboxServiceFactory::GetForProfile(browser()->profile());
+  void SetUpOnMainThread() override {
+    PrivacySandboxQueueTestNotice::SetUpOnMainThread();
     SearchEngineChoiceDialogService::SetDialogDisabledForTests(
         /*dialog_disabled=*/false);
-    privacy_sandbox_service->SetPromptDisabledForTests(false);
-    privacy_sandbox_service->ForceChromeBuildForTests(true);
-    g_browser_process->variations_service()->OverrideStoredPermanentCountry(
-        "be");
-    base::CommandLine::ForCurrentProcess()->RemoveSwitch(switches::kNoFirstRun);
   }
 
  private:
@@ -270,20 +279,13 @@
 // Navigate to a page where the DMA notice should show and ensure suppression.
 IN_PROC_BROWSER_TEST_F(PrivacySandboxQueueTestNoticeWithSearchEngine,
                        PromptSuppressed) {
-  // Set flags correctly.
-  SetUpPrivacySandboxServiceAndDMA();
-  auto* privacy_sandbox_service =
-      PrivacySandboxServiceFactory::GetForProfile(browser()->profile());
-  privacy_sandbox::PrivacySandboxQueueManager& queue_manager =
-      privacy_sandbox_service->GetPrivacySandboxNoticeQueueManager();
-
   // When we navigate to valid page for SE dialog, we should unqueue and set the
   // suppress flag.
   ASSERT_TRUE(ui_test_utils::NavigateToURLWithDisposition(
       browser(), GURL(url::kAboutBlankURL), WindowOpenDisposition::NEW_WINDOW,
       ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP));
 
-  ASSERT_FALSE(queue_manager.IsHoldingHandle());
+  ASSERT_FALSE(queue_manager().IsHoldingHandle());
 
   // Navigate again to a valid notice page.
   ASSERT_TRUE(ui_test_utils::NavigateToURLWithDisposition(
@@ -292,8 +294,8 @@
       ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP));
 
   // After second nav do not queue or hold the handle. Suppress should be true.
-  ASSERT_FALSE(queue_manager.IsNoticeQueued());
-  ASSERT_FALSE(queue_manager.IsHoldingHandle());
+  ASSERT_FALSE(queue_manager().IsNoticeQueued());
+  ASSERT_FALSE(queue_manager().IsHoldingHandle());
 }
 
 class PrivacySandboxQueueTestNoticeFeatureDisabled
@@ -311,16 +313,9 @@
 // Navigate to a page and click a button.
 IN_PROC_BROWSER_TEST_F(PrivacySandboxQueueTestNoticeFeatureDisabled,
                        ShowAndClickPrompt) {
-  // Set flags correctly.
-  SetUpPrivacySandboxService();
-  auto* privacy_sandbox_service =
-      PrivacySandboxServiceFactory::GetForProfile(browser()->profile());
-  privacy_sandbox::PrivacySandboxQueueManager& queue_manager =
-      privacy_sandbox_service->GetPrivacySandboxNoticeQueueManager();
-
   // Should not be queued after browser startup
-  ASSERT_FALSE(queue_manager.IsNoticeQueued());
-  ASSERT_FALSE(queue_manager.IsHoldingHandle());
+  ASSERT_FALSE(queue_manager().IsNoticeQueued());
+  ASSERT_FALSE(queue_manager().IsHoldingHandle());
 
   // Navigate
   views::NamedWidgetShownWaiter waiter(
@@ -336,8 +331,8 @@
       waiter.WaitIfNeededAndGet()->widget_delegate()->GetContentsView());
 
   // Before we click, should still be holding handle.
-  ASSERT_FALSE(queue_manager.IsNoticeQueued());
-  ASSERT_FALSE(queue_manager.IsHoldingHandle());
+  ASSERT_FALSE(queue_manager().IsNoticeQueued());
+  ASSERT_FALSE(queue_manager().IsHoldingHandle());
 
   // Click ack button.
   const std::string& code = element_path_ + ".click();";
@@ -346,6 +341,6 @@
                               1 /* world_id */));
 
   // After click, should release handle.
-  ASSERT_FALSE(queue_manager.IsNoticeQueued());
-  ASSERT_FALSE(queue_manager.IsHoldingHandle());
+  ASSERT_FALSE(queue_manager().IsNoticeQueued());
+  ASSERT_FALSE(queue_manager().IsHoldingHandle());
 }
diff --git a/chrome/browser/ui/startup/default_browser_prompt/default_browser_infobar_delegate.cc b/chrome/browser/ui/startup/default_browser_prompt/default_browser_infobar_delegate.cc
index 67856ad..ac54730 100644
--- a/chrome/browser/ui/startup/default_browser_prompt/default_browser_infobar_delegate.cc
+++ b/chrome/browser/ui/startup/default_browser_prompt/default_browser_infobar_delegate.cc
@@ -83,7 +83,7 @@
 
 const gfx::VectorIcon& DefaultBrowserInfoBarDelegate::GetVectorIcon() const {
   return dark_mode() ? omnibox::kProductChromeRefreshIcon
-                     : vector_icons::kProductIcon;
+                     : vector_icons::kProductRefreshIcon;
 }
 
 bool DefaultBrowserInfoBarDelegate::ShouldExpire(
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index 1686198..23d535e7 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -1492,20 +1492,19 @@
 
   std::vector<tabs::TabInterface*> split_tabs = split_tab_data->ListTabs();
 
+  for (int i = 0; i < static_cast<int>(split_tabs.size()); i++) {
+    multi_contents_view_->SetWebContentsAtIndex(split_tabs[i]->GetContents(),
+                                                i);
+  }
   const int first_split_tab_index =
       browser_->tab_strip_model()->GetIndexOfTab(split_tabs[0]);
   const int relative_active_position = active_index - first_split_tab_index;
-  multi_contents_view_->SetActivePosition(relative_active_position);
-
-  for (int i = 0; i < static_cast<int>(split_tabs.size()); i++) {
-    multi_contents_view_->SetWebContents(split_tabs[i]->GetContents(),
-                                         i == relative_active_position);
-  }
+  multi_contents_view_->SetActiveIndex(relative_active_position);
 }
 
 void BrowserView::HideSplitView() {
   CHECK(multi_contents_view_);
-  multi_contents_view_->SetWebContents(nullptr, false);
+  multi_contents_view_->CloseSplitView();
 }
 
 void BrowserView::ActivateWebContents(content::WebContents* web_contents) {
@@ -5852,6 +5851,14 @@
                  kHistoryDisclaimerBubble);
 }
 
+bool BrowserView::IsTabModalPopup() const {
+  return browser_->IsTabModalPopup();
+}
+
+void BrowserView::SetIsTabModalPopup(bool is_tab_modal_popup) {
+  browser_->set_is_tab_modal_popup(is_tab_modal_popup);
+}
+
 void BrowserView::UpdateWebAppStatusIconsVisiblity() {
   if (web_app_frame_toolbar()) {
     web_app_frame_toolbar()->UpdateStatusIconsVisibility();
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h
index b8c73749..0585993 100644
--- a/chrome/browser/ui/views/frame/browser_view.h
+++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -691,6 +691,8 @@
   void ShowIncognitoClearBrowsingDataDialog() override;
 
   void ShowIncognitoHistoryDisclaimerDialog() override;
+  bool IsTabModalPopup() const override;
+  void SetIsTabModalPopup(bool is_tab_modal_popup) override;
 
   // TabStripModelObserver:
   void OnTabStripModelChanged(
diff --git a/chrome/browser/ui/views/frame/multi_contents_view.cc b/chrome/browser/ui/views/frame/multi_contents_view.cc
index 01a1b5b..9bec5a3 100644
--- a/chrome/browser/ui/views/frame/multi_contents_view.cc
+++ b/chrome/browser/ui/views/frame/multi_contents_view.cc
@@ -39,16 +39,16 @@
     WebContentsPressedCallback inactive_view_pressed_callback)
     : browser_view_(browser_view),
       inactive_view_pressed_callback_(inactive_view_pressed_callback) {
-  start_contents_view_ = AddChildView(
-      std::make_unique<ContentsWebView>(browser_view_->GetProfile()));
-  start_contents_view_->set_is_primary_web_contents_for_window(true);
+  contents_views_.push_back(AddChildView(
+      std::make_unique<ContentsWebView>(browser_view_->GetProfile())));
+  contents_views_[0]->set_is_primary_web_contents_for_window(true);
 
   resize_area_ = AddChildView(std::make_unique<MultiContentsResizeArea>(this));
   resize_area_->SetVisible(false);
 
-  end_contents_view_ = AddChildView(
-      std::make_unique<ContentsWebView>(browser_view_->GetProfile()));
-  end_contents_view_->SetVisible(false);
+  contents_views_.push_back(AddChildView(
+      std::make_unique<ContentsWebView>(browser_view_->GetProfile())));
+  contents_views_[1]->SetVisible(false);
 
   SetProperty(views::kElementIdentifierKey, kMultiContentsViewElementId);
   SetLayoutManager(std::make_unique<views::FlexLayout>())
@@ -58,36 +58,54 @@
 MultiContentsView::~MultiContentsView() = default;
 
 ContentsWebView* MultiContentsView::GetActiveContentsView() {
-  return active_position_ == 0 ? start_contents_view_ : end_contents_view_;
+  return contents_views_[active_index_];
 }
 
 ContentsWebView* MultiContentsView::GetInactiveContentsView() {
-  return active_position_ == 0 ? end_contents_view_ : start_contents_view_;
+  int inactive_index = active_index_ == 0 ? 1 : 0;
+  return contents_views_[inactive_index];
 }
 
 bool MultiContentsView::IsInSplitView() {
   return resize_area_->GetVisible();
 }
 
-void MultiContentsView::SetWebContents(content::WebContents* web_contents,
-                                       bool active) {
-  ContentsWebView* contents_view =
-      active ? GetActiveContentsView() : GetInactiveContentsView();
-  contents_view->SetWebContents(web_contents);
-  contents_view->SetVisible(web_contents != nullptr);
+void MultiContentsView::SetWebContentsAtIndex(
+    content::WebContents* web_contents,
+    int index) {
+  CHECK(web_contents);
+  CHECK(index >= 0 && index < 2);
+  contents_views_[index]->SetWebContents(web_contents);
 
-  if (start_contents_view_->GetVisible() && end_contents_view_->GetVisible()) {
+  if (index == 1 && !contents_views_[1]->GetVisible()) {
+    contents_views_[1]->SetVisible(true);
     resize_area_->SetVisible(true);
-  } else {
-    resize_area_->SetVisible(false);
   }
 }
 
-void MultiContentsView::SetActivePosition(int position) {
-  // Position should never be less than 0 or equal to or greater than the total
+void MultiContentsView::CloseSplitView() {
+  if (!IsInSplitView()) {
+    return;
+  }
+  if (active_index_ == 1) {
+    // Move the active WebContents so that the first ContentsWebView in
+    // contents_views_ can always be visible.
+    std::iter_swap(contents_views_.begin(),
+                   contents_views_.begin() + active_index_);
+    active_index_ = 0;
+  }
+  contents_views_[1]->SetWebContents(nullptr);
+  contents_views_[1]->SetVisible(false);
+  resize_area_->SetVisible(false);
+}
+
+void MultiContentsView::SetActiveIndex(int index) {
+  // Index should never be less than 0 or equal to or greater than the total
   // number of contents views.
-  CHECK(position >= 0 && position < 2);
-  active_position_ = position;
+  CHECK(index >= 0 && index < 2);
+  // We will only activate a visible contents view.
+  CHECK(contents_views_[index]->GetVisible());
+  active_index_ = index;
   GetActiveContentsView()->set_is_primary_web_contents_for_window(true);
   GetInactiveContentsView()->set_is_primary_web_contents_for_window(false);
   // Schedule paint to be sure that the active/inactive outline is correctly
@@ -115,22 +133,20 @@
 
 void MultiContentsView::ExecuteOnEachVisibleContentsView(
     base::RepeatingCallback<void(ContentsWebView*)> callback) {
-  ContentsWebView* active_contents_view = GetActiveContentsView();
-  ContentsWebView* inactive_contents_view = GetInactiveContentsView();
-  CHECK(active_contents_view->GetVisible());
-  callback.Run(active_contents_view);
-  if (inactive_contents_view->GetVisible()) {
-    callback.Run(inactive_contents_view);
+  for (auto* contents_view : contents_views_) {
+    if (contents_view->GetVisible()) {
+      callback.Run(contents_view);
+    }
   }
 }
 
 void MultiContentsView::OnResize(int resize_amount, bool done_resizing) {
   if (!initial_start_width_on_resize_.has_value()) {
     initial_start_width_on_resize_ =
-        std::make_optional(start_contents_view_->size().width());
+        std::make_optional(contents_views_[0]->size().width());
   }
   double total_width =
-      start_contents_view_->size().width() + end_contents_view_->size().width();
+      contents_views_[0]->size().width() + contents_views_[1]->size().width();
   start_ratio_ =
       (initial_start_width_on_resize_.value() + resize_amount) / total_width;
   if (done_resizing) {
@@ -151,17 +167,19 @@
       gfx::Size(widths.resize_width, available_space.height()));
   gfx::Rect end_rect(resize_rect.top_right(),
                      gfx::Size(widths.end_width, available_space.height()));
+  float corner_radius = 0;
   if (IsInSplitView()) {
     start_rect.Inset(gfx::Insets(kSplitViewContentInset).set_right(0));
     end_rect.Inset(gfx::Insets(kSplitViewContentInset).set_left(0));
-    start_contents_view_->layer()->SetRoundedCornerRadius(
-        gfx::RoundedCornersF{kContentCornerRadius});
-    end_contents_view_->layer()->SetRoundedCornerRadius(
-        gfx::RoundedCornersF{kContentCornerRadius});
+    corner_radius = kContentCornerRadius;
   }
-  start_contents_view_->SetBoundsRect(start_rect);
+  for (auto* contents_view : contents_views_) {
+    contents_view->layer()->SetRoundedCornerRadius(
+        gfx::RoundedCornersF{corner_radius});
+  }
+  contents_views_[0]->SetBoundsRect(start_rect);
   resize_area_->SetBoundsRect(resize_rect);
-  end_contents_view_->SetBoundsRect(end_rect);
+  contents_views_[1]->SetBoundsRect(end_rect);
 }
 
 void MultiContentsView::OnPaint(gfx::Canvas* canvas) {
@@ -192,27 +210,24 @@
     canvas->DrawRoundRect(main_content_border_rect, kContentOutlineCornerRadius,
                           flags);
   };
-  draw_contents_outline(start_contents_view_);
-  draw_contents_outline(end_contents_view_);
+  for (auto* contents_view : contents_views_) {
+    draw_contents_outline(contents_view);
+  }
 }
 
 MultiContentsView::ViewWidths MultiContentsView::GetViewWidths(
     gfx::Rect available_space) {
   ViewWidths widths;
   if (IsInSplitView()) {
-    CHECK(start_contents_view_->GetVisible() &&
-          end_contents_view_->GetVisible());
+    CHECK(contents_views_[0]->GetVisible() && contents_views_[1]->GetVisible());
     widths.resize_width = resize_area_->GetPreferredSize().width();
     widths.start_width =
         start_ratio_ * (available_space.width() - widths.resize_width);
     widths.end_width =
         available_space.width() - widths.start_width - widths.resize_width;
-  } else if (start_contents_view_->GetVisible()) {
-    CHECK(!end_contents_view_->GetVisible());
-    widths.start_width = available_space.width();
   } else {
-    CHECK(end_contents_view_->GetVisible());
-    widths.end_width = available_space.width();
+    CHECK(!contents_views_[1]->GetVisible());
+    widths.start_width = available_space.width();
   }
   return ClampToMinWidth(widths);
 }
diff --git a/chrome/browser/ui/views/frame/multi_contents_view.h b/chrome/browser/ui/views/frame/multi_contents_view.h
index d500a5724..fc4cf02 100644
--- a/chrome/browser/ui/views/frame/multi_contents_view.h
+++ b/chrome/browser/ui/views/frame/multi_contents_view.h
@@ -61,14 +61,18 @@
   // Returns true if more than one WebContents is displayed.
   bool IsInSplitView();
 
-  // Assigns the given |web_contents| to a ContentsWebView. If |active| it will
-  // be assigned to the active contents view, else it will be assigned to
-  // the inactive contents view.
-  void SetWebContents(content::WebContents* web_contents, bool active);
+  // Assigns the given |web_contents| to the ContentsWebView at |index| in
+  // contents_views_. |index| must be either 0 or 1 as we currently only support
+  // two contents. If |index| is 1 and we are not currently in a split
+  // view, displays the split views.
+  void SetWebContentsAtIndex(content::WebContents* web_contents, int index);
 
-  // Sets the index of the active contents view, as relative to the inactive
-  // contents view. A value of 0 will activate start_contents_view_.
-  void SetActivePosition(int position);
+  // Preserves the active WebContents and hides the second ContentsWebView and
+  // resize handle.
+  void CloseSplitView();
+
+  // Sets the index of the active contents view within contents_views_.
+  void SetActiveIndex(int index);
 
   // Handles a mouse event prior to it being passed along to the WebContents.
   bool PreHandleMouseEvent(const blink::WebMouseEvent& event);
@@ -86,7 +90,7 @@
   void OnPaint(gfx::Canvas* canvas) override;
 
   ContentsWebView* start_contents_view_for_testing() const {
-    return start_contents_view_;
+    return contents_views_[0];
   }
 
   MultiContentsResizeArea* resize_area_for_testing() const {
@@ -94,7 +98,7 @@
   }
 
   ContentsWebView* end_contents_view_for_testing() const {
-    return end_contents_view_;
+    return contents_views_[1];
   }
 
  private:
@@ -104,26 +108,23 @@
 
   raw_ptr<BrowserView> browser_view_;
 
-  // The left contents, in LTR.
-  raw_ptr<ContentsWebView> start_contents_view_ = nullptr;
-
-  // The right contents, in LTR.
-  raw_ptr<ContentsWebView> end_contents_view_ = nullptr;
+  // Holds ContentsWebViews, when not in a split view the second ContentsWebView
+  // is not visible.
+  std::vector<ContentsWebView*> contents_views_;
 
   // The handle responsible for resizing the two contents views as relative to
   // each other.
   raw_ptr<MultiContentsResizeArea> resize_area_ = nullptr;
 
-  // The index of the active context view. A value of 0 corresponds to
-  // start_contents_.
-  int active_position_ = 0;
+  // The index in contents_views_ of the active contents view.
+  int active_index_ = 0;
 
   // Callback to be executed when the user clicks anywhere within the bounds of
   // the inactive contents view.
   WebContentsPressedCallback inactive_view_pressed_callback_;
 
-  // Current ratio of `start_contents_view_` width / overall contents view
-  // width.
+  // Current ratio of |contents_views_|'s first ContentsWebView's width /
+  // overall contents view width.
   double start_ratio_ = 0.5;
 
   // Width of `start_contents_.contents_view_` when a resize action began.
diff --git a/chrome/browser/ui/views/frame/multi_contents_view_interactive_uitest.cc b/chrome/browser/ui/views/frame/multi_contents_view_interactive_uitest.cc
index e01cac5c..7350f94 100644
--- a/chrome/browser/ui/views/frame/multi_contents_view_interactive_uitest.cc
+++ b/chrome/browser/ui/views/frame/multi_contents_view_interactive_uitest.cc
@@ -53,7 +53,7 @@
         Do([&]() {
           content::WebContents* inactive_contents =
               tab_strip_model()->GetWebContentsAt(1);
-          multi_contents_view()->SetWebContents(inactive_contents, false);
+          multi_contents_view()->SetWebContentsAtIndex(inactive_contents, 1);
         }),
         PollView(kResizeLoadObserver,
                  MultiContentsResizeArea::kMultiContentsResizeAreaElementId,
diff --git a/chrome/browser/ui/views/page_action/BUILD.gn b/chrome/browser/ui/views/page_action/BUILD.gn
index 2f018c0..10b1e5e 100644
--- a/chrome/browser/ui/views/page_action/BUILD.gn
+++ b/chrome/browser/ui/views/page_action/BUILD.gn
@@ -57,6 +57,8 @@
     "page_action_model_unittest.cc",
     "page_action_observer_unittest.cc",
     "page_action_view_unittest.cc",
+    "test_support/fake_tab_interface.cc",
+    "test_support/fake_tab_interface.h",
     "test_support/mock_page_action_model.cc",
     "test_support/mock_page_action_model.h",
     "test_support/page_action_properties.cc",
diff --git a/chrome/browser/ui/views/page_action/page_action_controller_unittest.cc b/chrome/browser/ui/views/page_action/page_action_controller_unittest.cc
index b7ead28..49e441c21 100644
--- a/chrome/browser/ui/views/page_action/page_action_controller_unittest.cc
+++ b/chrome/browser/ui/views/page_action/page_action_controller_unittest.cc
@@ -15,12 +15,15 @@
 #include "chrome/browser/ui/toolbar/toolbar_pref_names.h"
 #include "chrome/browser/ui/views/page_action/page_action_model.h"
 #include "chrome/browser/ui/views/page_action/page_action_model_observer.h"
+#include "chrome/browser/ui/views/page_action/test_support/fake_tab_interface.h"
 #include "chrome/browser/ui/views/page_action/test_support/mock_page_action_model.h"
 #include "chrome/browser/ui/views/page_action/test_support/page_action_properties.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/prefs/scoped_user_pref_update.h"
 #include "components/tab_collections/public/tab_interface.h"
 #include "content/public/test/browser_task_environment.h"
+#include "content/public/test/test_renderer_host.h"
+#include "content/public/test/web_contents_tester.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/actions/actions.h"
 #include "ui/gfx/image/image_unittest_util.h"
@@ -46,38 +49,6 @@
     ::base::ScopedObservation<PageActionModelInterface,
                               PageActionModelObserver>;
 
-class FakeTabInterface : public tabs::MockTabInterface {
- public:
-  ~FakeTabInterface() override = default;
-
-  base::CallbackListSubscription RegisterDidActivate(
-      base::RepeatingCallback<void(TabInterface*)> cb) override {
-    return activation_callbacks_.Add(cb);
-  }
-
-  base::CallbackListSubscription RegisterWillDeactivate(
-      base::RepeatingCallback<void(TabInterface*)> cb) override {
-    return deactivation_callbacks_.Add(cb);
-  }
-
-  void Activate() {
-    is_activated_ = true;
-    activation_callbacks_.Notify(this);
-  }
-
-  void Deactivate() {
-    is_activated_ = false;
-    deactivation_callbacks_.Notify(this);
-  }
-
-  bool IsActivated() const override { return is_activated_; }
-
- private:
-  bool is_activated_ = false;
-  base::RepeatingCallbackList<void(TabInterface*)> activation_callbacks_;
-  base::RepeatingCallbackList<void(TabInterface*)> deactivation_callbacks_;
-};
-
 class PageActionTestObserver : public PageActionModelObserver {
  public:
   PageActionTestObserver() = default;
@@ -115,12 +86,14 @@
   PageActionControllerTest() = default;
 
   void SetUp() override {
-    profile_ = std::make_unique<TestingProfile>();
+    test_web_contents_ =
+        content::WebContentsTester::CreateTestWebContents(&profile_, nullptr);
     pinned_actions_model_ =
-        std::make_unique<PinnedToolbarActionsModel>(profile_.get());
+        std::make_unique<PinnedToolbarActionsModel>(&profile_);
     controller_ = std::make_unique<PageActionController>(
         GetPageActionControllerTestProperties(), pinned_actions_model_.get());
-    tab_interface_ = std::make_unique<FakeTabInterface>();
+    tab_interface_ =
+        std::make_unique<FakeTabInterface>(test_web_contents_.get());
     tab_interface_->Activate();
   }
 
@@ -128,7 +101,6 @@
     actions::ActionManager::Get().ResetForTesting();
     controller_.reset();
     pinned_actions_model_.reset();
-    profile_.reset();
     tab_interface_.reset();
   }
 
@@ -136,7 +108,7 @@
   PinnedToolbarActionsModel* pinned_actions_model() {
     return pinned_actions_model_.get();
   }
-  TestingProfile* profile() { return profile_.get(); }
+  TestingProfile* profile() { return &profile_; }
 
   FakeTabInterface* tab_interface() { return tab_interface_.get(); }
 
@@ -150,9 +122,12 @@
 
  private:
   content::BrowserTaskEnvironment task_environment_;
+
+  TestingProfile profile_;
+  content::RenderViewHostTestEnabler test_render_host_factories_;
+  std::unique_ptr<content::WebContents> test_web_contents_;
   std::unique_ptr<PageActionController> controller_;
   std::unique_ptr<PinnedToolbarActionsModel> pinned_actions_model_;
-  std::unique_ptr<TestingProfile> profile_;
   std::unique_ptr<ActionItem> action_item_;
   std::unique_ptr<FakeTabInterface> tab_interface_;
 };
@@ -403,17 +378,26 @@
   PageActionControllerMockModelTest()
       : controller_(GetPageActionControllerTestProperties(),
                     /*pinned_actions_model=*/nullptr,
-                    &model_factory_) {}
+                    &model_factory_) {
+    test_web_contents_ =
+        content::WebContentsTester::CreateTestWebContents(&profile_, nullptr);
+    tab_interface_ =
+        std::make_unique<FakeTabInterface>(test_web_contents_.get());
+  }
 
   PageActionController& controller() { return controller_; }
   MockPageActionModelFactory& models() { return model_factory_; }
-  FakeTabInterface& tab_interface() { return tab_interface_; }
+  FakeTabInterface& tab_interface() { return *tab_interface_; }
 
  private:
   content::BrowserTaskEnvironment task_environment_;
+
+  TestingProfile profile_;
+  content::RenderViewHostTestEnabler test_render_host_factories_;
+  std::unique_ptr<content::WebContents> test_web_contents_;
   MockPageActionModelFactory model_factory_;
   PageActionController controller_;
-  FakeTabInterface tab_interface_;
+  std::unique_ptr<FakeTabInterface> tab_interface_;
 };
 
 TEST_F(PageActionControllerMockModelTest, SetAndClearOverrideText) {
diff --git a/chrome/browser/ui/views/page_action/page_action_interactive_uitest.cc b/chrome/browser/ui/views/page_action/page_action_interactive_uitest.cc
index 02da774a..f33d156 100644
--- a/chrome/browser/ui/views/page_action/page_action_interactive_uitest.cc
+++ b/chrome/browser/ui/views/page_action/page_action_interactive_uitest.cc
@@ -39,6 +39,12 @@
   return page_action->size() == page_action->GetMinimumSize();
 }
 
+bool IsIconCentered(PageActionView* page_action) {
+  const auto* const image_container = page_action->GetImageContainerView();
+  return image_container->x() ==
+         page_action->width() - image_container->bounds().right();
+}
+
 void EnsurePageActionEnabled(actions::ActionId action_id) {
   auto* action = actions::ActionManager::Get().FindAction(action_id);
   CHECK(action);
@@ -46,6 +52,60 @@
   action->SetVisible(true);
 }
 
+MATCHER(IsChipExpanded, "Check if the chip is expanded") {
+  if (arg == nullptr) {
+    *result_listener << "Page action is null";
+    return false;
+  }
+  if (!IsLabelVisible(arg)) {
+    *result_listener << "Label is not visible";
+    return false;
+  }
+  if (IsAtMinimumSize(arg)) {
+    *result_listener << "Chip is at minimum size, Size: "
+                     << arg->size().ToString();
+    return false;
+  }
+  if (arg->is_animating_label()) {
+    *result_listener << "Page action is animating";
+    return false;
+  }
+  if (IsIconCentered(arg)) {
+    *result_listener << "Chip is centered, Insets: "
+                     << arg->GetInsets().ToString();
+    return false;
+  }
+
+  return true;
+}
+
+MATCHER(IsChipCollapsed, "Check if the chip is collapsed") {
+  if (arg == nullptr) {
+    *result_listener << "Page action is null";
+    return false;
+  }
+  if (IsLabelVisible(arg)) {
+    *result_listener << "Label is visible";
+    return false;
+  }
+  if (!IsAtMinimumSize(arg)) {
+    *result_listener << "Chip is not at minimum size, Size: "
+                     << arg->size().ToString();
+    return false;
+  }
+  if (arg->is_animating_label()) {
+    *result_listener << "Page action is animating";
+    return false;
+  }
+  if (!IsIconCentered(arg)) {
+    *result_listener << "Chip is not centered, Insets: "
+                     << arg->GetInsets().ToString();
+    return false;
+  }
+
+  return true;
+}
+
 class PageActionUiTestBase {
  public:
   PageActionUiTestBase() {
@@ -189,16 +249,14 @@
   ShowTestSuggestionChip();
   FastForwardAnimation(view);
 
-  EXPECT_TRUE(IsLabelVisible(view));
-  EXPECT_FALSE(IsAtMinimumSize(view));
+  EXPECT_THAT(view, IsChipExpanded());
 
   AdjustAvailableSpace(kReducedSpaceTextLength);
 
   ShowTestSuggestionChip();
   FastForwardAnimation(view);
 
-  EXPECT_FALSE(IsLabelVisible(view));
-  EXPECT_TRUE(IsAtMinimumSize(view));
+  EXPECT_THAT(view, IsChipCollapsed());
 }
 
 // Tests that increasing available space from reduced to full restores the
@@ -212,15 +270,14 @@
   ShowTestSuggestionChip();
   FastForwardAnimation(view);
 
-  EXPECT_FALSE(IsLabelVisible(view));
+  EXPECT_THAT(view, IsChipCollapsed());
 
   AdjustAvailableSpace(kFullSpaceTextLength);
 
   ShowTestSuggestionChip();
   FastForwardAnimation(view);
 
-  EXPECT_TRUE(IsLabelVisible(view));
-  EXPECT_FALSE(IsAtMinimumSize(view));
+  EXPECT_THAT(view, IsChipExpanded());
 }
 
 // Tests that transitioning from full available space to reduced and then back
@@ -234,24 +291,21 @@
   ShowTestSuggestionChip();
   FastForwardAnimation(view);
 
-  EXPECT_TRUE(IsLabelVisible(view));
-  EXPECT_FALSE(IsAtMinimumSize(view));
+  EXPECT_THAT(view, IsChipExpanded());
 
   AdjustAvailableSpace(kReducedSpaceTextLength);
 
   ShowTestSuggestionChip();
   FastForwardAnimation(view);
 
-  EXPECT_FALSE(IsLabelVisible(view));
-  EXPECT_TRUE(IsAtMinimumSize(view));
+  EXPECT_THAT(view, IsChipCollapsed());
 
   AdjustAvailableSpace(kFullSpaceTextLength);
 
   ShowTestSuggestionChip();
   FastForwardAnimation(view);
 
-  EXPECT_TRUE(IsLabelVisible(view));
-  EXPECT_FALSE(IsAtMinimumSize(view));
+  EXPECT_THAT(view, IsChipExpanded());
 }
 
 // Tests that starting with reduced space, moving to full space, and then
@@ -273,16 +327,14 @@
   ShowTestSuggestionChip();
   FastForwardAnimation(view);
 
-  EXPECT_TRUE(IsLabelVisible(view));
-  EXPECT_FALSE(IsAtMinimumSize(view));
+  EXPECT_THAT(view, IsChipExpanded());
 
   AdjustAvailableSpace(kReducedSpaceTextLength);
 
   ShowTestSuggestionChip();
   FastForwardAnimation(view);
 
-  EXPECT_FALSE(IsLabelVisible(view));
-  EXPECT_TRUE(IsAtMinimumSize(view));
+  EXPECT_THAT(view, IsChipCollapsed());
 }
 
 // Tests that calling ShowPageAction on a page action results in an icon-only
@@ -294,8 +346,7 @@
 
   PageActionView* view = GetTestPageActionView();
 
-  EXPECT_FALSE(IsLabelVisible(view));
-  EXPECT_TRUE(IsAtMinimumSize(view));
+  EXPECT_THAT(view, IsChipCollapsed());
 }
 
 // Tests that once a page action is shown as an icon-only view, it remains
@@ -307,13 +358,11 @@
 
   PageActionView* view = GetTestPageActionView();
 
-  EXPECT_FALSE(IsLabelVisible(view));
-  EXPECT_TRUE(IsAtMinimumSize(view));
+  EXPECT_THAT(view, IsChipCollapsed());
 
   AdjustAvailableSpace(kReducedSpaceTextLength);
 
-  EXPECT_FALSE(IsLabelVisible(view));
-  EXPECT_TRUE(IsAtMinimumSize(view));
+  EXPECT_THAT(view, IsChipCollapsed());
 
   AdjustAvailableSpace(kFullSpaceTextLength);
 
diff --git a/chrome/browser/ui/views/page_action/page_action_observer_unittest.cc b/chrome/browser/ui/views/page_action/page_action_observer_unittest.cc
index 5fa137a..c399f46 100644
--- a/chrome/browser/ui/views/page_action/page_action_observer_unittest.cc
+++ b/chrome/browser/ui/views/page_action/page_action_observer_unittest.cc
@@ -8,6 +8,7 @@
 #include "chrome/browser/ui/views/page_action/page_action_controller.h"
 #include "chrome/browser/ui/views/page_action/page_action_model.h"
 #include "chrome/browser/ui/views/page_action/page_action_model_observer.h"
+#include "chrome/browser/ui/views/page_action/test_support/fake_tab_interface.h"
 #include "chrome/browser/ui/views/page_action/test_support/mock_page_action_model.h"
 #include "chrome/browser/ui/views/page_action/test_support/page_action_properties.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -76,10 +77,11 @@
 class PageActionObserverTest : public ::testing::Test {
  public:
   void SetUp() override {
+    tab_ = std::make_unique<FakeTabInterface>(/*web_content=*/nullptr);
     model_factory_ = std::make_unique<FakePageActionModelFactory>();
     controller_ = std::make_unique<PageActionController>(
         GetPageActionControllerTestProperties(), nullptr, model_factory_.get());
-    controller_->Initialize(tab_, {kTestPageActionId});
+    controller_->Initialize(*tab_, {kTestPageActionId});
   }
 
   void TearDown() override {
@@ -93,7 +95,7 @@
 
  private:
   MockPageActionObserver observer_;
-  tabs::MockTabInterface tab_;
+  std::unique_ptr<FakeTabInterface> tab_;
   std::unique_ptr<FakePageActionModelFactory> model_factory_;
   std::unique_ptr<PageActionController> controller_;
 };
diff --git a/chrome/browser/ui/views/page_action/page_action_view.cc b/chrome/browser/ui/views/page_action/page_action_view.cc
index 63c6656e..7f2846a4 100644
--- a/chrome/browser/ui/views/page_action/page_action_view.cc
+++ b/chrome/browser/ui/views/page_action/page_action_view.cc
@@ -17,6 +17,7 @@
 #include "ui/color/color_id.h"
 #include "ui/gfx/animation/slide_animation.h"
 #include "ui/gfx/font_list.h"
+#include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/views/animation/ink_drop.h"
 #include "ui/views/view_class_properties.h"
@@ -47,6 +48,7 @@
   SetUseTonalColorsWhenExpanded(true);
   SetBackgroundVisibility(BackgroundVisibility::kWithLabel);
   UpdateBorder();
+  SetExpandedLabelAdditionalInsets(views::Inset1D(4, 8));
 
   label_visibility_changed_subscription_ =
       label()->AddVisibleChangedCallback(base::BindRepeating(
@@ -124,26 +126,11 @@
   View::ViewHierarchyChanged(details);
   if (details.is_add && details.child == this) {
     UpdateIconImage();
-    UpdateBorder();
   }
 }
 
 void PageActionView::UpdateBorder() {
-  gfx::Insets insets = icon_insets_;
-  if (IsChipVisible()) {
-    constexpr int kInsetsLeftPaddingMax = 4;
-    constexpr int kInsetsRightPaddingMax = 8;
-
-    // Set the padding according to the progress of the expand/collapse
-    // animation.
-    const int left_padding = GetWidthBetween(0, kInsetsLeftPaddingMax);
-    const int right_padding = GetWidthBetween(0, kInsetsRightPaddingMax);
-    insets += gfx::Insets().set_left_right(left_padding, right_padding);
-  }
-
-  if (GetInsets() != insets) {
-    SetBorder(views::CreateEmptyBorder(insets));
-  }
+  SetBorder(views::CreateEmptyBorder(icon_insets_));
 }
 
 bool PageActionView::ShouldShowSeparator() const {
@@ -217,7 +204,6 @@
 
 void PageActionView::OnLabelVisibilityChanged() {
   UpdateBackground();
-  UpdateBorder();
   UpdateLabelColors();
   UpdateIconImage();
   chip_visibility_changed_callbacks_.Notify(this);
diff --git a/chrome/browser/ui/views/page_action/page_action_view_unittest.cc b/chrome/browser/ui/views/page_action/page_action_view_unittest.cc
index f4d9022..751a802 100644
--- a/chrome/browser/ui/views/page_action/page_action_view_unittest.cc
+++ b/chrome/browser/ui/views/page_action/page_action_view_unittest.cc
@@ -343,29 +343,6 @@
             view_icon_size());
 }
 
-// Test that UpdateBorder adjusts the insets based on label visibility.
-TEST_F(PageActionViewTest, UpdateBorderAdjustsInsets) {
-  EXPECT_CALL(*model(), GetVisible()).WillRepeatedly(Return(true));
-  EXPECT_CALL(*model(), GetShowSuggestionChip()).WillRepeatedly(Return(true));
-  EXPECT_CALL(*model(), GetText()).WillRepeatedly(ReturnRef(kTestText));
-  page_action_view()->OnPageActionModelChanged(*model());
-  const gfx::Insets initial_insets = page_action_view()->GetInsets();
-
-  page_action_view()->UpdateBorder();
-  const gfx::Insets insets_with_chip = page_action_view()->GetInsets();
-
-  EXPECT_EQ(initial_insets, insets_with_chip);
-
-  EXPECT_CALL(*model(), GetShowSuggestionChip()).WillRepeatedly(Return(false));
-  page_action_view()->OnPageActionModelChanged(*model());
-
-  page_action_view()->UpdateBorder();
-  const gfx::Insets insets_without_chip = page_action_view()->GetInsets();
-
-  EXPECT_NE(initial_insets, insets_without_chip);
-  EXPECT_NE(insets_with_chip, insets_without_chip);
-}
-
 // Test that UpdateIconImage() correctly handles ImageModels created without a
 // vector icon
 TEST_F(PageActionViewTest, UpdateIconImageHandlesDifferentImageTypes) {
@@ -566,31 +543,6 @@
   EXPECT_NE(page_action_view()->GetBackground(), nullptr);
 }
 
-TEST_F(PageActionViewAnimationTest, BorderInsetsScaleWithAnimationProgress) {
-  gfx::Animation::SetPrefersReducedMotionForTesting(false);
-  ASSERT_FALSE(gfx::Animation::PrefersReducedMotion());
-  EXPECT_CALL(*model(), GetShouldAnimateChip()).WillRepeatedly(Return(true));
-
-  // Record the min and max insets.
-  // The test will compare insets mid-animation to these values.
-  SetInitialChipVisibility(false);
-  const gfx::Insets min_insets = page_action_view()->GetInsets();
-  SetInitialChipVisibility(true);
-  const gfx::Insets max_insets = page_action_view()->GetInsets();
-  ASSERT_LT(min_insets.width(), max_insets.width());
-
-  ExtendAnimations();
-  EXPECT_CALL(*model(), GetShowSuggestionChip()).WillRepeatedly(Return(false));
-  page_action_view()->OnPageActionModelChanged(*model());
-
-  // Fast forward the animation to halfway.
-  // The insets should be somewhere between the min and max insets.
-  FastForwardAnimation(0.5);
-  const gfx::Insets curr_insets = page_action_view()->GetInsets();
-  EXPECT_LT(curr_insets.width(), max_insets.width());
-  EXPECT_GT(curr_insets.width(), min_insets.width());
-}
-
 TEST_F(PageActionViewAnimationTest, AnimationsDisabled) {
   gfx::Animation::SetPrefersReducedMotionForTesting(false);
   ASSERT_FALSE(gfx::Animation::PrefersReducedMotion());
diff --git a/chrome/browser/ui/views/page_action/test_support/fake_tab_interface.cc b/chrome/browser/ui/views/page_action/test_support/fake_tab_interface.cc
new file mode 100644
index 0000000..b48e5e1
--- /dev/null
+++ b/chrome/browser/ui/views/page_action/test_support/fake_tab_interface.cc
@@ -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.
+
+#include "chrome/browser/ui/views/page_action/test_support/fake_tab_interface.h"
+
+#include "content/public/browser/web_contents.h"
+
+namespace page_actions {
+
+FakeTabInterface::FakeTabInterface(content::WebContents* contents)
+    : contents_(contents) {}
+
+FakeTabInterface::~FakeTabInterface() = default;
+
+base::CallbackListSubscription FakeTabInterface::RegisterDidActivate(
+    base::RepeatingCallback<void(TabInterface*)> cb) {
+  return activation_callbacks_.Add(cb);
+}
+
+base::CallbackListSubscription FakeTabInterface::RegisterWillDeactivate(
+    base::RepeatingCallback<void(TabInterface*)> cb) {
+  return deactivation_callbacks_.Add(cb);
+}
+
+void FakeTabInterface::Activate() {
+  is_activated_ = true;
+  activation_callbacks_.Notify(this);
+}
+
+void FakeTabInterface::Deactivate() {
+  is_activated_ = false;
+  deactivation_callbacks_.Notify(this);
+}
+
+bool FakeTabInterface::IsActivated() const {
+  return is_activated_;
+}
+
+}  // namespace page_actions
diff --git a/chrome/browser/ui/views/page_action/test_support/fake_tab_interface.h b/chrome/browser/ui/views/page_action/test_support/fake_tab_interface.h
new file mode 100644
index 0000000..3ec2308
--- /dev/null
+++ b/chrome/browser/ui/views/page_action/test_support/fake_tab_interface.h
@@ -0,0 +1,41 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_PAGE_ACTION_TEST_SUPPORT_FAKE_TAB_INTERFACE_H_
+#define CHROME_BROWSER_UI_VIEWS_PAGE_ACTION_TEST_SUPPORT_FAKE_TAB_INTERFACE_H_
+
+#include "base/callback_list.h"
+#include "chrome/browser/ui/tabs/test/mock_tab_interface.h"
+
+namespace content {
+class WebContents;
+}
+
+namespace page_actions {
+
+class FakeTabInterface : public tabs::MockTabInterface {
+ public:
+  explicit FakeTabInterface(content::WebContents* contents);
+  ~FakeTabInterface() override;
+
+  // tabs::MockTabInterface
+  bool IsActivated() const override;
+  base::CallbackListSubscription RegisterDidActivate(
+      base::RepeatingCallback<void(TabInterface*)> cb) override;
+  base::CallbackListSubscription RegisterWillDeactivate(
+      base::RepeatingCallback<void(TabInterface*)> cb) override;
+
+  void Activate();
+  void Deactivate();
+
+ private:
+  raw_ptr<content::WebContents> contents_;
+  bool is_activated_ = false;
+  base::RepeatingCallbackList<void(TabInterface*)> activation_callbacks_;
+  base::RepeatingCallbackList<void(TabInterface*)> deactivation_callbacks_;
+};
+
+}  // namespace page_actions
+
+#endif  // CHROME_BROWSER_UI_VIEWS_PAGE_ACTION_TEST_SUPPORT_FAKE_TAB_INTERFACE_H_
diff --git a/chrome/browser/ui/views/page_info/page_info_ad_personalization_content_view.cc b/chrome/browser/ui/views/page_info/page_info_ad_personalization_content_view.cc
index 747b9be..936b6ce 100644
--- a/chrome/browser/ui/views/page_info/page_info_ad_personalization_content_view.cc
+++ b/chrome/browser/ui/views/page_info/page_info_ad_personalization_content_view.cc
@@ -91,6 +91,8 @@
   description_label->SetMultiLine(true);
   description_label->SetEnabledColor(kColorPageInfoForeground);
   description_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+  description_label->SetID(
+      PageInfoViewFactory::VIEW_ID_PAGE_INFO_AD_PERSONALIZATION_LABEL);
   // TODO(crbug.com/40244046): Figure out why without additional horizontal
   // margin the size is being calculated incorrectly and the topics labels are
   // being cut off.
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc
index 6fc8175..e48c477 100644
--- a/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc
+++ b/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc
@@ -43,6 +43,7 @@
 #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/location_bar/location_icon_view.h"
+#include "chrome/browser/ui/views/page_info/page_info_ad_personalization_content_view.h"
 #include "chrome/browser/ui/views/page_info/page_info_cookies_content_view.h"
 #include "chrome/browser/ui/views/page_info/page_info_permission_content_view.h"
 #include "chrome/browser/ui/views/page_info/page_info_view_factory.h"
@@ -279,6 +280,13 @@
     return presenter;
   }
 
+  void SetAdPersonalizationInfo(
+      const PageInfoUI::AdPersonalizationInfo& identity_info) {
+    auto* presenter = GetPresenter();
+    EXPECT_TRUE(presenter->ui_for_testing());
+    presenter->ui_for_testing()->SetAdPersonalizationInfo(identity_info);
+  }
+
   void SetPageInfoBubbleIdentityInfo(
       const PageInfoUI::IdentityInfo& identity_info) {
     auto* presenter = GetPresenter();
@@ -898,6 +906,46 @@
           u" " + l10n_util::GetStringUTF16(IDS_LEARN_MORE));
 }
 
+IN_PROC_BROWSER_TEST_F(PageInfoBubbleViewBrowserTest, AdPrivacyStrings) {
+  base::UserActionTester user_actions_stats;
+  net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
+  https_server.AddDefaultHandlers(
+      base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
+  ASSERT_TRUE(https_server.Start());
+
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(
+      browser(), https_server.GetURL("/simple.html")));
+
+  // Setup the bogus ad personalization info.
+  PageInfoUI::AdPersonalizationInfo info;
+  info.has_joined_user_to_interest_group = true;
+
+  auto* pscs = content_settings::PageSpecificContentSettings::GetForFrame(
+      browser()
+          ->tab_strip_model()
+          ->GetActiveWebContents()
+          ->GetPrimaryMainFrame());
+  pscs->OnTopicAccessed(
+      url::Origin::Create(GURL("https://a.test")), false,
+      privacy_sandbox::CanonicalTopic(browsing_topics::Topic(1), 1));
+
+  OpenPageInfoBubble(browser());
+
+  SetAdPersonalizationInfo(info);
+
+  views::View* button =
+      GetView(PageInfoViewFactory::VIEW_ID_PAGE_INFO_AD_PERSONALIZATION_BUTTON);
+  PerformMouseClickOnView(button);
+
+  auto* label = PageInfoBubbleView::GetPageInfoBubbleForTesting()->GetViewByID(
+      PageInfoViewFactory::VIEW_ID_PAGE_INFO_AD_PERSONALIZATION_LABEL);
+  ASSERT_TRUE(label);
+
+  EXPECT_EQ(user_actions_stats.GetActionCount(
+                "PageInfo.AdPersonalization.OpenedWithTopics"),
+            1);
+}
+
 IN_PROC_BROWSER_TEST_F(PageInfoBubbleViewBrowserTest, UnwantedSoftwareStrings) {
   net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
   https_server.AddDefaultHandlers(
diff --git a/chrome/browser/ui/views/page_info/page_info_main_view.cc b/chrome/browser/ui/views/page_info/page_info_main_view.cc
index 9979f07f..467ec0e 100644
--- a/chrome/browser/ui/views/page_info/page_info_main_view.cc
+++ b/chrome/browser/ui/views/page_info/page_info_main_view.cc
@@ -677,7 +677,7 @@
 
 std::unique_ptr<views::View> PageInfoMainView::CreateAdPersonalizationButton() {
   auto ads_personalization_button = std::make_unique<RichHoverButton>(
-      base::BindRepeating(&PageInfoNavigationHandler::OpenCookiesPage,
+      base::BindRepeating(&PageInfoNavigationHandler::OpenAdPersonalizationPage,
                           base::Unretained(navigation_handler_)),
       PageInfoViewFactory::GetImageModel(vector_icons::kAdsClickIcon),
       l10n_util::GetStringUTF16(IDS_PAGE_INFO_AD_PRIVACY_HEADER),
diff --git a/chrome/browser/ui/views/page_info/page_info_view_factory.h b/chrome/browser/ui/views/page_info/page_info_view_factory.h
index 78a15398..818e474 100644
--- a/chrome/browser/ui/views/page_info/page_info_view_factory.h
+++ b/chrome/browser/ui/views/page_info/page_info_view_factory.h
@@ -58,6 +58,7 @@
     VIEW_ID_PAGE_INFO_PERMISSION_VIEW,
     VIEW_ID_PAGE_INFO_SECURITY_SUMMARY_LABEL,
     VIEW_ID_PAGE_INFO_SECURITY_DETAILS_LABEL,
+    VIEW_ID_PAGE_INFO_AD_PERSONALIZATION_LABEL,
     VIEW_ID_PAGE_INFO_BACK_BUTTON,
     VIEW_ID_PAGE_INFO_CLOSE_BUTTON,
     VIEW_ID_PAGE_INFO_CURRENT_VIEW,
diff --git a/chrome/browser/ui/web_applications/test/web_app_navigation_browsertest.cc b/chrome/browser/ui/web_applications/test/web_app_navigation_browsertest.cc
index 875e689..69d1d96826 100644
--- a/chrome/browser/ui/web_applications/test/web_app_navigation_browsertest.cc
+++ b/chrome/browser/ui/web_applications/test/web_app_navigation_browsertest.cc
@@ -153,6 +153,7 @@
       rel.c_str());
   ASSERT_TRUE(content::ExecJs(web_contents, script));
 
+  content::SimulateEndOfPaintHoldingOnPrimaryMainFrame(web_contents);
   content::SimulateMouseClick(web_contents, modifiers, button);
 }
 
diff --git a/chrome/browser/ui/webui/ntp/new_tab_ui_browsertest.cc b/chrome/browser/ui/webui/ntp/new_tab_ui_browsertest.cc
index 85ad5b5..1970e9a 100644
--- a/chrome/browser/ui/webui/ntp/new_tab_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/ntp/new_tab_ui_browsertest.cc
@@ -4,8 +4,6 @@
 
 #include <stddef.h>
 
-#include <string_view>
-
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "chrome/browser/ui/browser.h"
@@ -32,11 +30,12 @@
 static bool had_console_errors = false;
 
 bool HandleMessage(int severity,
-                   std::string_view file,
+                   const char* file,
                    int line,
                    size_t message_start,
                    const std::string& str) {
-  if (severity == logging::LOGGING_ERROR && file == "CONSOLE") {
+  if (severity == logging::LOGGING_ERROR && file &&
+      file == std::string("CONSOLE")) {
     had_console_errors = true;
   }
   return false;
diff --git a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks.mojom b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks.mojom
index ad12ee34..fb0bb87b 100644
--- a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks.mojom
+++ b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks.mojom
@@ -40,17 +40,46 @@
   kCount = 2,
 };
 
+
+// Representation of a Bookmark node to be used by the renderer for display.
+// Nodes are mapped using the the `id` and `parent_id`, any actions or
+// modifications to the nodes needs to be communicated using those ids.
+struct BookmarksTreeNode {
+  string id;
+  string parent_id;
+  uint32 index;
+  string title;
+
+  // Non-null for page nodes.
+  string? url;
+  // Non-null for folder nodes.
+  array<BookmarksTreeNode>? children;
+
+  double? date_added;
+  double? date_last_used;
+};
+
 // Used by the Read Later WebUI page (for the side panel) to bootstrap
 // bidirectional communication.
+// Also initializes the `page` remote that allows communication from the browser
+// to the renderer.
 interface BookmarksPageHandlerFactory {
   // The WebUI calls this method when the page is first initialized.
-  CreateBookmarksPageHandler(pending_receiver<BookmarksPageHandler> handler);
+  CreateBookmarksPageHandler(pending_remote<BookmarksPage> page,
+                             pending_receiver<BookmarksPageHandler> handler);
 };
 
 // Browser-side handler for requests from WebUI page.
+// Folder parent ID should use string IDs as it can represent merged nodes.
+// Regular ID (non merged folder or url) can be directly passed as int64, it
+// can also support string based IDs.
 interface BookmarksPageHandler {
   // Bookmarks the current active tab in the given folder.
-  BookmarkCurrentTabInFolder(int64 folder_id);
+  BookmarkCurrentTabInFolder(string folder_id);
+
+  // Creates a folder in `folder_id` at the first position with `title`.
+  // Returns the id of the newly created node.
+  CreateFolder(string folder_id, string title) => (string new_folder_id);
 
   // Opens the edit bookmark dialog.
   ExecuteEditCommand(array<int64> node_ids, ActionSource source);
@@ -96,6 +125,25 @@
                ui.mojom.ClickModifiers click_modifiers,
                ActionSource source);
 
+  // Triggers the undo from the BookmarkModel.
+  Undo();
+
+  // Renames the bookmark with `node_id` with `new_title`. The id should map to
+  // a regular non permanent node as those are the only ones that can be
+  // renamed.
+  RenameBookmark(int64 node_id, string new_title);
+
+  // Moves the bookmark with `node_id` into the `folder_id` folder.
+  // `folder_id` can be a merged Side Panel ID. `node_id` should map to a
+  // regular non permanent node.
+  MoveBookmark(int64 node_id, string folder_id);
+
+  // Removes the boomkarks with id in `node_ids`. All bookmarks are expected to
+  // map to a regular non permanent node. If some of the nodes are folders, it
+  // will remove all children as well.
+  // Result callback is called when all nodes are removed, it contains no data.
+  RemoveBookmarks(array<int64> node_ids) => ();
+
   // Called when the sort option has been updated and the profile pref should be
   // updated.
   SetSortOrder(SortOrder sort_order);
@@ -113,4 +161,25 @@
 
   // Notify the backend that the UI is ready to be shown.
   ShowUI();
+
+  // Requests all non empty permanent nodes in a merged view (local and account
+  // nodes are merged into one).
+  // The `id` of those nodes will be the local storage id node.
+  GetAllBookmarks() => (array<BookmarksTreeNode> nodes);
+};
+
+// Called from C++ to TS. (Browser -> Renderer)
+interface BookmarksPage {
+  // Send the information of the newly added node to the Ui.
+  OnBookmarkNodeAdded(BookmarksTreeNode node);
+  // Send all the node ids that were removed to the Ui.
+  OnBookmarkNodesRemoved(array<string> node_ids);
+  // Send the list of children ids of `folder_id` after a reorder event.
+  OnBookmarkParentFolderChildrenReordered(string folder_id,
+                                          array<string> children_ordered_ids);
+  // Send the node index of a moved element: old and new Ui indices.
+  OnBookmarkNodeMoved(string old_parent_index, uint32 old_node_index,
+                      string new_parent_index, uint32 new_node_index);
+  // Send the new information of the bookmark.
+  OnBookmarkNodeChanged(string id, string new_title, string new_url);
 };
diff --git a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_page_handler.cc b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_page_handler.cc
index be05b3cb..3deb30dcf 100644
--- a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_page_handler.cc
+++ b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_page_handler.cc
@@ -4,12 +4,23 @@
 
 #include "chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_page_handler.h"
 
+#include <algorithm>
+#include <iterator>
+#include <optional>
+
 #include "base/memory/ptr_util.h"
 #include "base/memory/raw_ptr.h"
 #include "base/metrics/user_metrics.h"
 #include "base/metrics/user_metrics_action.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/to_string.h"
+#include "base/strings/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/bookmarks/bookmark_merged_surface_service.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
+#include "chrome/browser/bookmarks/bookmark_parent_folder.h"
+#include "chrome/browser/bookmarks/bookmark_parent_folder_children.h"
+#include "chrome/browser/bookmarks/managed_bookmark_service_factory.h"
 #include "chrome/browser/commerce/shopping_service_factory.h"
 #include "chrome/browser/prefs/incognito_mode_prefs.h"
 #include "chrome/browser/profiles/profile.h"
@@ -25,15 +36,20 @@
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/webui/bookmarks/bookmark_prefs.h"
 #include "chrome/browser/ui/webui/commerce/shopping_list_context_menu_controller.h"
+#include "chrome/browser/ui/webui/side_panel/bookmarks/bookmarks.mojom.h"
 #include "chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.h"
 #include "chrome/browser/ui/webui/side_panel/reading_list/reading_list_ui.h"
+#include "chrome/browser/undo/bookmark_undo_service_factory.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/bookmarks/browser/bookmark_model.h"
 #include "components/bookmarks/browser/bookmark_node.h"
 #include "components/bookmarks/browser/bookmark_utils.h"
+#include "components/bookmarks/browser/scoped_group_bookmark_actions.h"
+#include "components/bookmarks/managed/managed_bookmark_service.h"
 #include "components/prefs/pref_service.h"
 #include "components/profile_metrics/browser_profile_type.h"
 #include "components/strings/grit/components_strings.h"
+#include "components/undo/bookmark_undo_service.h"
 #include "mojo/public/cpp/bindings/message.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/mojom/window_open_disposition.mojom.h"
@@ -175,22 +191,219 @@
                                  shopping_list_controller);
 }
 
+// Temporary helper function for `GetPermanentFolderSidePanelID`.
+std::string GetPermanentFolderStringId(
+    const bookmarks::BookmarkNode* permanent_node) {
+  if (!permanent_node) {
+    return "-1";
+  }
+
+  CHECK(permanent_node->is_permanent_node());
+  return base::ToString(permanent_node->id());
+}
+
+// TODO(crbug.com/380806881): Currently returns the local node to align with the
+// resources passed in `BookmarksSidePanelUI` and to keep all operations on
+// local nodes work as intended. When the migration of all parent node id
+// computation support the merged node, then a neutral fixed Id can be used to
+// represent the permanent merged folders.
+std::string GetPermanentFolderSidePanelID(
+    const BookmarkMergedSurfaceService& bookmark_merged_surface,
+    BookmarkParentFolder::PermanentFolderType folder_type) {
+  const bookmarks::BookmarkModel* bookmark_model =
+      bookmark_merged_surface.bookmark_model();
+  CHECK(bookmark_model);
+
+  switch (folder_type) {
+    case BookmarkParentFolder::PermanentFolderType::kBookmarkBarNode:
+      return GetPermanentFolderStringId(bookmark_model->bookmark_bar_node());
+    case BookmarkParentFolder::PermanentFolderType::kOtherNode:
+      return GetPermanentFolderStringId(bookmark_model->other_node());
+    case BookmarkParentFolder::PermanentFolderType::kMobileNode:
+      return GetPermanentFolderStringId(bookmark_model->mobile_node());
+    case BookmarkParentFolder::PermanentFolderType::kManagedNode:
+      const bookmarks::ManagedBookmarkService* managed_bookmark_service =
+          bookmark_merged_surface.managed_bookmark_service();
+      const bookmarks::BookmarkNode* managed_node =
+          managed_bookmark_service ? managed_bookmark_service->managed_node()
+                                   : nullptr;
+      return GetPermanentFolderStringId(managed_node);
+  }
+}
+
+// Returns the correct ID of the folder used in Ui. Can either return itself if
+// it is a regular folder, or return the merged Id if it is a permanent folder
+// (that are merged in the Ui).
+std::string GetFolderSidePanelID(
+    const BookmarkMergedSurfaceService& bookmark_merged_surface,
+    const BookmarkParentFolder& folder) {
+  std::optional<BookmarkParentFolder::PermanentFolderType> folder_type =
+      folder.as_permanent_folder();
+  if (folder_type.has_value()) {
+    return GetPermanentFolderSidePanelID(bookmark_merged_surface,
+                                         folder_type.value());
+  }
+
+  return base::ToString(folder.as_non_permanent_folder()->id());
+}
+
+// Will return `std::nullopt` if `side_panel_id` does not correspond to a
+// permanent node special ID or is not an actual int64 id. Invalid inputs should
+// result in no-ops.
+std::optional<BookmarkParentFolder> GetBookmarkParentFolderFromSidePanel(
+    const BookmarkMergedSurfaceService& bookmark_merged_surface,
+    const std::string& side_panel_id) {
+  // TODO(crbug.com/380806881): Checks for permanent folder IDs when fixed Side
+  // Panel IDs will be implemented. It should simplify the checks here.
+  if (side_panel_id ==
+      GetPermanentFolderSidePanelID(
+          bookmark_merged_surface,
+          BookmarkParentFolder::PermanentFolderType::kBookmarkBarNode)) {
+    return BookmarkParentFolder::BookmarkBarFolder();
+  }
+  if (side_panel_id ==
+      GetPermanentFolderSidePanelID(
+          bookmark_merged_surface,
+          BookmarkParentFolder::PermanentFolderType::kOtherNode)) {
+    return BookmarkParentFolder::OtherFolder();
+  }
+  if (side_panel_id ==
+      GetPermanentFolderSidePanelID(
+          bookmark_merged_surface,
+          BookmarkParentFolder::PermanentFolderType::kMobileNode)) {
+    return BookmarkParentFolder::MobileFolder();
+  }
+  if (side_panel_id ==
+      GetPermanentFolderSidePanelID(
+          bookmark_merged_surface,
+          BookmarkParentFolder::PermanentFolderType::kManagedNode)) {
+    return BookmarkParentFolder::ManagedFolder();
+  }
+
+  int64_t folder_id;
+  // Conversion check validity.
+  if (!base::StringToInt64(side_panel_id, &folder_id)) {
+    if (mojo::IsInMessageDispatch()) {
+      mojo::ReportBadMessage(
+          "Unsupported conversion: side_panel_id should either be a permanent "
+          "merged node ID or represent an int64 id value");
+    }
+    return std::nullopt;
+  }
+
+  return BookmarkParentFolder::FromFolderNode(bookmarks::GetBookmarkNodeByID(
+      bookmark_merged_surface.bookmark_model(), folder_id));
+}
+
+std::vector<side_panel::mojom::BookmarksTreeNodePtr> ConstructMojoChildNodes(
+    const BookmarkMergedSurfaceService& bookmark_merged_surface,
+    const BookmarkParentFolder& parent,
+    const BookmarkParentFolderChildren& children);
+
+side_panel::mojom::BookmarksTreeNodePtr ConstructMojoNode(
+    const BookmarkMergedSurfaceService& bookmark_merged_surface,
+    const BookmarkParentFolder& parent,
+    const bookmarks::BookmarkNode* node,
+    bool with_children) {
+  side_panel::mojom::BookmarksTreeNodePtr mojo_node =
+      side_panel::mojom::BookmarksTreeNode::New();
+  mojo_node->title = base::UTF16ToUTF8(node->GetTitle());
+  mojo_node->id = base::ToString(node->id());
+  mojo_node->parent_id = GetFolderSidePanelID(bookmark_merged_surface, parent);
+  mojo_node->index = bookmark_merged_surface.GetIndexOf(node);
+  mojo_node->date_added = node->date_added().InSecondsFSinceUnixEpoch();
+  mojo_node->date_last_used = node->date_last_used().InSecondsFSinceUnixEpoch();
+  if (node->is_folder()) {
+    if (with_children) {
+      const BookmarkParentFolder& sub_parent =
+          BookmarkParentFolder::FromFolderNode(node);
+      mojo_node->children = ConstructMojoChildNodes(
+          bookmark_merged_surface, sub_parent,
+          bookmark_merged_surface.GetChildren(sub_parent));
+    }
+  } else {
+    mojo_node->url = node->url().spec();
+  }
+
+  return mojo_node;
+}
+
+std::vector<side_panel::mojom::BookmarksTreeNodePtr> ConstructMojoChildNodes(
+    const BookmarkMergedSurfaceService& bookmark_merged_surface,
+    const BookmarkParentFolder& parent,
+    const BookmarkParentFolderChildren& children) {
+  std::vector<side_panel::mojom::BookmarksTreeNodePtr> mojo_nodes;
+  for (const bookmarks::BookmarkNode* node : children) {
+    mojo_nodes.push_back(ConstructMojoNode(bookmark_merged_surface, parent,
+                                           node, /*with_children=*/true));
+  }
+  return mojo_nodes;
+}
+
 }  // namespace
 
 BookmarksPageHandler::BookmarksPageHandler(
     mojo::PendingReceiver<side_panel::mojom::BookmarksPageHandler> receiver,
-    BookmarksSidePanelUI* bookmarks_ui)
-    : receiver_(this, std::move(receiver)), bookmarks_ui_(bookmarks_ui) {}
-
-BookmarksPageHandler::~BookmarksPageHandler() = default;
-
-void BookmarksPageHandler::BookmarkCurrentTabInFolder(int64_t folder_id) {
+    mojo::PendingRemote<side_panel::mojom::BookmarksPage> page,
+    BookmarksSidePanelUI* bookmarks_ui,
+    BookmarkMergedSurfaceService* bookmark_merged_surface)
+    : receiver_(this, std::move(receiver)),
+      page_(std::move(page)),
+      bookmarks_ui_(bookmarks_ui),
+      bookmark_merged_surface_(bookmark_merged_surface) {
+  CHECK(bookmark_merged_surface_);
   Browser* browser = chrome::FindLastActive();
   if (!browser) {
     return;
   }
 
-  chrome::BookmarkCurrentTabInFolder(browser, folder_id);
+  scoped_bookmark_merged_service_observation_.Observe(bookmark_merged_surface_);
+}
+
+BookmarksPageHandler::~BookmarksPageHandler() = default;
+
+void BookmarksPageHandler::BookmarkCurrentTabInFolder(
+    const std::string& folder_id) {
+  Browser* browser = chrome::FindLastActive();
+  if (!browser) {
+    return;
+  }
+
+  std::optional<BookmarkParentFolder> parent =
+      GetBookmarkParentFolderFromSidePanel(*bookmark_merged_surface_,
+                                           folder_id);
+  if (!parent) {
+    return;
+  }
+  chrome::BookmarkCurrentTabInFolder(
+      browser, bookmark_merged_surface_->bookmark_model(),
+      bookmark_merged_surface_->GetDefaultParentForNewNodes(*parent)->id());
+}
+
+void BookmarksPageHandler::CreateFolder(const std::string& folder_id,
+                                        const std::string& title,
+                                        CreateFolderCallback callback) {
+  Browser* browser = chrome::FindLastActive();
+  if (!browser) {
+    return;
+  }
+
+  std::optional<BookmarkParentFolder> parent =
+      GetBookmarkParentFolderFromSidePanel(*bookmark_merged_surface_,
+                                           folder_id);
+  if (!parent) {
+    std::move(callback).Run("");
+    return;
+  }
+  const bookmarks::BookmarkNode* parent_node =
+      bookmark_merged_surface_->GetDefaultParentForNewNodes(*parent);
+
+  bookmarks::BookmarkModel* model = bookmark_merged_surface_->bookmark_model();
+  const bookmarks::BookmarkNode* new_folder =
+      model->AddFolder(parent_node, /*index=*/0, base::UTF8ToUTF16(title));
+  model->SetDateFolderModified(parent_node, base::Time::Now());
+
+  std::move(callback).Run(base::ToString(new_folder->id()));
 }
 
 void BookmarksPageHandler::ExecuteOpenInNewTabCommand(
@@ -274,10 +487,8 @@
     return;
   }
 
-  bookmarks::BookmarkModel* bookmark_model =
-      BookmarkModelFactory::GetForBrowserContext(browser->profile());
-  const bookmarks::BookmarkNode* bookmark_node =
-      bookmarks::GetBookmarkNodeByID(bookmark_model, node_id);
+  const bookmarks::BookmarkNode* bookmark_node = bookmarks::GetBookmarkNodeByID(
+      bookmark_merged_surface_->bookmark_model(), node_id);
   if (!bookmark_node) {
     return;
   }
@@ -297,6 +508,77 @@
       profile_metrics::GetBrowserProfileType(browser->profile()));
 }
 
+void BookmarksPageHandler::Undo() {
+  Browser* browser = chrome::FindLastActive();
+  if (!browser) {
+    return;
+  }
+
+  BookmarkUndoServiceFactory::GetForProfile(browser->profile())
+      ->undo_manager()
+      ->Undo();
+}
+
+void BookmarksPageHandler::RenameBookmark(int64_t node_id,
+                                          const std::string& new_title) {
+  bookmarks::BookmarkModel* model = bookmark_merged_surface_->bookmark_model();
+  const bookmarks::BookmarkNode* node_to_rename =
+      bookmarks::GetBookmarkNodeByID(model, node_id);
+  if (!node_to_rename) {
+    return;
+  }
+
+  // Using extensions metrics recording as this action was previously done
+  // through the extensions API.
+  model->SetTitle(node_to_rename, base::UTF8ToUTF16(new_title),
+                  bookmarks::metrics::BookmarkEditSource::kExtension);
+}
+
+void BookmarksPageHandler::MoveBookmark(int64_t node_id,
+                                        const std::string& folder_id) {
+  Browser* browser = chrome::FindLastActive();
+  if (!browser) {
+    return;
+  }
+
+  std::optional<BookmarkParentFolder> parent =
+      GetBookmarkParentFolderFromSidePanel(*bookmark_merged_surface_,
+                                           folder_id);
+  if (!parent) {
+    return;
+  }
+
+  const bookmarks::BookmarkNode* node_to_move = bookmarks::GetBookmarkNodeByID(
+      bookmark_merged_surface_->bookmark_model(), node_id);
+  bookmark_merged_surface_->Move(
+      node_to_move, *parent,
+      bookmark_merged_surface_->GetChildrenCount(*parent), browser);
+}
+
+void BookmarksPageHandler::RemoveBookmarks(const std::vector<int64_t>& node_ids,
+                                           RemoveBookmarksCallback callback) {
+  bookmarks::BookmarkModel* model = bookmark_merged_surface_->bookmark_model();
+  bookmarks::ScopedGroupBookmarkActions group_deletes(model);
+  for (int64_t node_id : node_ids) {
+    const bookmarks::BookmarkNode* node_to_remove =
+        bookmarks::GetBookmarkNodeByID(model, node_id);
+    // TODO(crbug.com/407986687): Investigate if this is the correct behavior.
+    // This fixes the issue when `node_ids` contain both parent and children at
+    // the same time. This is possible when using the compact view with tree
+    // view. Undo may not be working as expected.
+    if (!node_to_remove) {
+      continue;
+    }
+    // Using extensions metrics recording as this action was previously done
+    // through the extensions API.
+    model->Remove(node_to_remove,
+                  bookmarks::metrics::BookmarkEditSource::kExtension,
+                  FROM_HERE);
+  }
+
+  std::move(callback).Run();
+}
+
 void BookmarksPageHandler::SetSortOrder(
     side_panel::mojom::SortOrder sort_order) {
   Browser* browser = chrome::FindLastActive();
@@ -350,3 +632,159 @@
     embedder->ShowUI();
   }
 }
+
+void BookmarksPageHandler::BookmarkMergedSurfaceServiceLoaded() {
+  if (get_all_bookmarks_callback_) {
+    SendAllBookmarks(std::move(get_all_bookmarks_callback_));
+  }
+}
+
+void BookmarksPageHandler::GetAllBookmarks(GetAllBookmarksCallback callback) {
+  if (!bookmark_merged_surface_->loaded()) {
+    // Temporarily store the resulting callback to be executed upon bookmarks
+    // load.
+    get_all_bookmarks_callback_ = std::move(callback);
+    return;
+  }
+
+  SendAllBookmarks(std::move(callback));
+}
+
+void BookmarksPageHandler::SendAllBookmarks(GetAllBookmarksCallback callback) {
+  CHECK(bookmark_merged_surface_->loaded());
+
+  const std::vector<BookmarkParentFolder> permanent_folders{
+      BookmarkParentFolder::BookmarkBarFolder(),
+      BookmarkParentFolder::OtherFolder(),
+      BookmarkParentFolder::MobileFolder(),
+      BookmarkParentFolder::ManagedFolder(),
+  };
+
+  std::vector<side_panel::mojom::BookmarksTreeNodePtr> mojo_nodes;
+  int permanent_folder_side_panel_index = 0;
+  // Prepare all non empty permanent nodes using a merged view.
+  for (const BookmarkParentFolder& folder : permanent_folders) {
+    const auto& underlying_nodes =
+        bookmark_merged_surface_->GetUnderlyingNodes(folder);
+    CHECK(!underlying_nodes.empty());
+
+    // TODO(crbug.com/401176689): This causes the Mobile/ManagedBookmark folders
+    // not to be pushed if empty. Upon sign in/sync event, if the Mobile
+    // Bookmarks gets populated while the SidePanel is showing, the added node
+    // would not find its parent in the displayed nodes.
+    // This would apply to all folders that are not showing visible if empty.
+    bool any_visible = std::ranges::any_of(
+        underlying_nodes,
+        [](const bookmarks::BookmarkNode* node) { return node->IsVisible(); });
+    if (!any_visible) {
+      continue;
+    }
+
+    // TODO(crbug.com/380806881): Temporarily relies on the fact that the last
+    // node is the local one, because the Ui does assumptions on the local
+    // permanent IDs to perform some special operations on the permanent
+    // folders.
+    // This allows existing usages of local node manipulation to keep working
+    // properly during the transition of all the calls.
+    // Once the migration of all the calls to the merged mapping computation is
+    // done, we would be able to introduce a new Side Panel ID system for merged
+    // permanent folders IDs to stop relying on the assumption that the merged
+    // Id is the local Id node.
+    const bookmarks::BookmarkNode* local_node = underlying_nodes.back();
+
+    side_panel::mojom::BookmarksTreeNodePtr mojo_node =
+        side_panel::mojom::BookmarksTreeNode::New();
+    mojo_node->title = base::UTF16ToUTF8(local_node->GetTitle());
+    std::optional<BookmarkParentFolder::PermanentFolderType> folder_type =
+        folder.as_permanent_folder();
+    CHECK(folder_type.has_value());
+    mojo_node->id = GetPermanentFolderSidePanelID(*bookmark_merged_surface_,
+                                                  folder_type.value());
+    mojo_node->parent_id = base::ToString(local_node->parent()->id());
+    mojo_node->index = permanent_folder_side_panel_index++;
+    mojo_node->children =
+        ConstructMojoChildNodes(*bookmark_merged_surface_, folder,
+                                bookmark_merged_surface_->GetChildren(folder));
+
+    // Given that this node represents a merge of two folders, we compute the
+    // max of the nodes for each attribute.
+    mojo_node->date_added =
+        (*std::max_element(underlying_nodes.begin(), underlying_nodes.end(),
+                           [](const bookmarks::BookmarkNode* first,
+                              const bookmarks::BookmarkNode* second) {
+                             return first->date_added() > second->date_added();
+                           }))
+            ->date_added()
+            .InSecondsFSinceUnixEpoch();
+    mojo_node->date_last_used =
+        (*std::max_element(underlying_nodes.begin(), underlying_nodes.end(),
+                           [](const bookmarks::BookmarkNode* first,
+                              const bookmarks::BookmarkNode* second) {
+                             return first->date_last_used() >
+                                    second->date_last_used();
+                           }))
+            ->date_last_used()
+            .InSecondsFSinceUnixEpoch();
+
+    mojo_nodes.push_back(std::move(mojo_node));
+  }
+
+  std::move(callback).Run(std::move(mojo_nodes));
+}
+
+void BookmarksPageHandler::BookmarkNodeAdded(const BookmarkParentFolder& parent,
+                                             size_t index) {
+  const bookmarks::BookmarkNode* added_node =
+      bookmark_merged_surface_->GetNodeAtIndex(parent, index);
+  // `with_children` false here because `BookmarkNodeAdded` will be called for
+  // every child node as well.
+  page_->OnBookmarkNodeAdded(ConstructMojoNode(
+      *bookmark_merged_surface_, parent, added_node, /*with_children=*/false));
+}
+
+void BookmarksPageHandler::BookmarkNodesRemoved(
+    const BookmarkParentFolder& parent,
+    const base::flat_set<const bookmarks::BookmarkNode*>& nodes) {
+  std::vector<std::string> mojo_node_ids;
+  std::ranges::transform(nodes, std::back_inserter(mojo_node_ids),
+                         [](const bookmarks::BookmarkNode* node) {
+                           return base::ToString(node->id());
+                         });
+  page_->OnBookmarkNodesRemoved(std::move(mojo_node_ids));
+}
+
+void BookmarksPageHandler::BookmarkParentFolderChildrenReordered(
+    const BookmarkParentFolder& folder) {
+  std::string folder_id =
+      GetFolderSidePanelID(*bookmark_merged_surface_, folder);
+  std::vector<std::string> mojo_children_ordered_ids;
+  for (const bookmarks::BookmarkNode* child :
+       bookmark_merged_surface_->GetChildren(folder)) {
+    mojo_children_ordered_ids.push_back(base::ToString(child->id()));
+  }
+  page_->OnBookmarkParentFolderChildrenReordered(folder_id,
+                                                 mojo_children_ordered_ids);
+}
+
+void BookmarksPageHandler::BookmarkNodeMoved(
+    const BookmarkParentFolder& old_parent,
+    size_t old_index,
+    const BookmarkParentFolder& new_parent,
+    size_t new_index) {
+  page_->OnBookmarkNodeMoved(
+      GetFolderSidePanelID(*bookmark_merged_surface_, old_parent), old_index,
+      GetFolderSidePanelID(*bookmark_merged_surface_, new_parent), new_index);
+}
+
+void BookmarksPageHandler::BookmarkNodeChanged(
+    const bookmarks::BookmarkNode* node) {
+  page_->OnBookmarkNodeChanged(base::ToString(node->id()),
+                               base::UTF16ToUTF8(node->GetTitle()),
+                               node->is_url() ? node->url().spec() : "");
+}
+
+std::string GetFolderSidePanelIDForTesting(
+    const BookmarkMergedSurfaceService& bookmark_merged_surface,
+    const BookmarkParentFolder& folder) {
+  return GetFolderSidePanelID(bookmark_merged_surface, folder);
+}
diff --git a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_page_handler.h b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_page_handler.h
index 0a470ab..2459ae18 100644
--- a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_page_handler.h
+++ b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_page_handler.h
@@ -6,23 +6,34 @@
 #define CHROME_BROWSER_UI_WEBUI_SIDE_PANEL_BOOKMARKS_BOOKMARKS_PAGE_HANDLER_H_
 
 #include "base/memory/raw_ptr.h"
+#include "base/scoped_observation.h"
+#include "chrome/browser/bookmarks/bookmark_merged_surface_service_observer.h"
 #include "chrome/browser/ui/webui/side_panel/bookmarks/bookmarks.mojom.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
 
 class BookmarksSidePanelUI;
+class BookmarkMergedSurfaceService;
 
-class BookmarksPageHandler : public side_panel::mojom::BookmarksPageHandler {
+class BookmarksPageHandler : public side_panel::mojom::BookmarksPageHandler,
+                             public BookmarkMergedSurfaceServiceObserver {
  public:
+  // `bookmark_merged_surface` must not be null and must outlive this object.
   explicit BookmarksPageHandler(
       mojo::PendingReceiver<side_panel::mojom::BookmarksPageHandler> receiver,
-      BookmarksSidePanelUI* bookmarks_ui);
+      mojo::PendingRemote<side_panel::mojom::BookmarksPage> page,
+      BookmarksSidePanelUI* bookmarks_ui,
+      BookmarkMergedSurfaceService* bookmark_merged_surface);
   BookmarksPageHandler(const BookmarksPageHandler&) = delete;
   BookmarksPageHandler& operator=(const BookmarksPageHandler&) = delete;
   ~BookmarksPageHandler() override;
 
   // side_panel::mojom::BookmarksPageHandler:
-  void BookmarkCurrentTabInFolder(int64_t folder_id) override;
+  void BookmarkCurrentTabInFolder(const std::string& folder_id) override;
+  void CreateFolder(const std::string& folder_id,
+                    const std::string& title,
+                    CreateFolderCallback callback) override;
   void ExecuteOpenInNewTabCommand(
       const std::vector<int64_t>& node_ids,
       side_panel::mojom::ActionSource source) override;
@@ -54,16 +65,59 @@
                     int32_t parent_folder_depth,
                     ui::mojom::ClickModifiersPtr click_modifiers,
                     side_panel::mojom::ActionSource source) override;
+  void Undo() override;
+  void RenameBookmark(int64_t node_id, const std::string& new_title) override;
+  void MoveBookmark(int64_t node_id, const std::string& folder_id) override;
+  void RemoveBookmarks(const std::vector<int64_t>& node_ids,
+                       RemoveBookmarksCallback callback) override;
   void SetSortOrder(side_panel::mojom::SortOrder sort_order) override;
   void SetViewType(side_panel::mojom::ViewType view_type) override;
   void ShowContextMenu(const std::string& id,
                        const gfx::Point& point,
                        side_panel::mojom::ActionSource source) override;
   void ShowUI() override;
+  void GetAllBookmarks(GetAllBookmarksCallback callback) override;
+
+  // BookmarkMergedSurfaceServiceObserver:
+  void BookmarkMergedSurfaceServiceLoaded() override;
+  void BookmarkNodeAdded(const BookmarkParentFolder& parent,
+                         size_t index) override;
+  void BookmarkNodesRemoved(
+      const BookmarkParentFolder& parent,
+      const base::flat_set<const bookmarks::BookmarkNode*>& nodes) override;
+  void BookmarkNodeMoved(const BookmarkParentFolder& old_parent,
+                         size_t old_index,
+                         const BookmarkParentFolder& new_parent,
+                         size_t new_index) override;
+  void BookmarkNodeChanged(const bookmarks::BookmarkNode* node) override;
+  void BookmarkNodeFaviconChanged(
+      const bookmarks::BookmarkNode* node) override {}
+  void BookmarkParentFolderChildrenReordered(
+      const BookmarkParentFolder& folder) override;
+  void BookmarkAllUserNodesRemoved() override {}
 
  private:
+  // Compute and sends all the bookmark through the input `callback`,
+  // redirecting the values to the TS side.
+  void SendAllBookmarks(GetAllBookmarksCallback callback);
+
   mojo::Receiver<side_panel::mojom::BookmarksPageHandler> receiver_;
+  mojo::Remote<side_panel::mojom::BookmarksPage> page_;
   raw_ptr<BookmarksSidePanelUI> bookmarks_ui_ = nullptr;
+  raw_ptr<BookmarkMergedSurfaceService> bookmark_merged_surface_ = nullptr;
+
+  // This value is needed when the request from the Ui comes in before the
+  // bookmarks are loaded. The callback will be executed upon bookmark load in
+  // this case.
+  GetAllBookmarksCallback get_all_bookmarks_callback_;
+
+  base::ScopedObservation<BookmarkMergedSurfaceService,
+                          BookmarkMergedSurfaceServiceObserver>
+      scoped_bookmark_merged_service_observation_{this};
 };
 
+std::string GetFolderSidePanelIDForTesting(
+    const BookmarkMergedSurfaceService& merged_surface_bookmarks,
+    const BookmarkParentFolder& folder);
+
 #endif  // CHROME_BROWSER_UI_WEBUI_SIDE_PANEL_BOOKMARKS_BOOKMARKS_PAGE_HANDLER_H_
diff --git a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_page_handler_unittest.cc b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_page_handler_unittest.cc
index de8f94c..d8f8cf3 100644
--- a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_page_handler_unittest.cc
+++ b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_page_handler_unittest.cc
@@ -6,37 +6,212 @@
 
 #include <memory>
 
+#include "base/functional/bind.h"
+#include "base/run_loop.h"
+#include "base/strings/to_string.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/mock_callback.h"
+#include "chrome/browser/bookmarks/bookmark_merged_surface_service.h"
+#include "chrome/browser/bookmarks/bookmark_test_utils.h"
 #include "chrome/browser/ui/webui/bookmarks/bookmark_prefs.h"
+#include "chrome/browser/ui/webui/side_panel/bookmarks/bookmarks.mojom.h"
 #include "chrome/test/base/browser_with_test_window_test.h"
-#include "components/bookmarks/common/bookmark_pref_names.h"
+#include "components/bookmarks/browser/bookmark_model.h"
+#include "components/bookmarks/browser/bookmark_node.h"
+#include "components/bookmarks/managed/managed_bookmark_service.h"
+#include "components/bookmarks/test/bookmark_test_helpers.h"
+#include "components/bookmarks/test/test_bookmark_client.h"
+#include "components/signin/public/base/signin_switches.h"
+#include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
 
-class TestBookmarksPageHandler : public BookmarksPageHandler {
+using bookmarks::test::AddNodesFromModelString;
+using ::testing::Contains;
+using ::testing::ElementsAre;
+using ::testing::SizeIs;
+using ::testing::UnorderedElementsAre;
+
+// Compares a `side_panel::mojom::BookmarksTreeNodePtr` (arg) with a
+// `bookmarks::BookmarkNode` (node) by comparing their `id` and the ids of their
+// children recursively.
+// Note: the matching node `arg` may contain more children than the expected
+// `node` since it could be the representation of a merged node. Therefore we
+// only make sure that `node`'s children are a subset of `arg`'s children if
+// `arg` actually contains any children.
+MATCHER_P2(MatchesNode, node, service, "") {
+  const std::string expected_id =
+      node->is_folder()
+          ? GetFolderSidePanelIDForTesting(
+                *service, BookmarkParentFolder::FromFolderNode(node))
+          : base::ToString(node->id());
+
+  if (arg->id != expected_id) {
+    return false;
+  }
+
+  // If the matching node has no children, then expected node shouldn't as well.
+  if (!arg->children.has_value() || arg->children->empty()) {
+    return node->children().empty();
+  }
+
+  // The expected node should have its children contained in the matching node
+  // with the same id.
+  for (const auto& child : node->children()) {
+    EXPECT_THAT(arg->children.value(),
+                Contains(MatchesNode(child.get(), service)))
+        << "Some child nodes of '" << node->GetTitle()
+        << "' are not contained in the matching node with the same id.";
+  }
+
+  return true;
+}
+
+class MockBookmarksPage : public side_panel::mojom::BookmarksPage {
  public:
-  TestBookmarksPageHandler()
-      : BookmarksPageHandler(
-            mojo::PendingReceiver<side_panel::mojom::BookmarksPageHandler>(),
-            static_cast<BookmarksSidePanelUI*>(nullptr)) {}
+  MockBookmarksPage() = default;
+  ~MockBookmarksPage() override = default;
+
+  mojo::PendingRemote<side_panel::mojom::BookmarksPage> BindAndGetRemote() {
+    DCHECK(!receiver_.is_bound());
+    return receiver_.BindNewPipeAndPassRemote();
+  }
+
+  void FlushForTesting() { receiver_.FlushForTesting(); }
+
+  void Reset() { receiver_.reset(); }
+
+  MOCK_METHOD(void,
+              OnBookmarkNodeAdded,
+              (side_panel::mojom::BookmarksTreeNodePtr));
+  MOCK_METHOD(void, OnBookmarkNodesRemoved, (const std::vector<std::string>&));
+  MOCK_METHOD(void,
+              OnBookmarkParentFolderChildrenReordered,
+              (const std::string&, const std::vector<std::string>&));
+  MOCK_METHOD(void,
+              OnBookmarkNodeMoved,
+              (const std::string&, uint32_t, const std::string&, uint32_t));
+  MOCK_METHOD(void,
+              OnBookmarkNodeChanged,
+              (const std::string&, const std::string&, const std::string&));
+
+ private:
+  mojo::Receiver<side_panel::mojom::BookmarksPage> receiver_{this};
+};
+
+// Helper class to handle the return value of
+// `BookmarksPageHandler::CreateFolder()` through a callback. It resets
+// internally after retrieving the results so that it can be used multiple times
+// within the same instance.
+class CreateFolderFunctionHelper {
+ public:
+  std::string GetResultWhenReady() {
+    if (!result_) {
+      run_loop_.Run();
+    }
+
+    return ClearAndReturnResult();
+  }
+
+  void OnCreateFolderResult(const std::string& result) {
+    result_ = result;
+
+    if (run_loop_.running()) {
+      run_loop_.Quit();
+    }
+  }
+
+ private:
+  std::string ClearAndReturnResult() {
+    CHECK(result_.has_value());
+    std::string ret_value = result_.value();
+    result_.reset();
+    return ret_value;
+  }
+
+  std::optional<std::string> result_;
+  base::RunLoop run_loop_;
 };
 
 class BookmarksPageHandlerTest : public BrowserWithTestWindowTest {
  public:
   void SetUp() override {
     BrowserWithTestWindowTest::SetUp();
-    handler_ = std::make_unique<TestBookmarksPageHandler>();
+    CreateHandler();
+    LoadBookmarkModel();
   }
 
   void TearDown() override {
-    handler_.reset();
+    ClearHandler();
     BrowserWithTestWindowTest::TearDown();
   }
 
-  TestBookmarksPageHandler* handler() { return handler_.get(); }
+  BookmarksPageHandler* handler() { return handler_.get(); }
+  bookmarks::BookmarkModel* model() { return bookmark_model_.get(); }
+  bookmarks::ManagedBookmarkService* managed_bookmark_service() {
+    return managed_bookmark_service_.get();
+  }
+  BookmarkMergedSurfaceService* service() {
+    return bookmark_merged_service_.get();
+  }
+  testing::NiceMock<MockBookmarksPage>& mock_bookmarks_page() {
+    return mock_bookmarks_page_;
+  }
+
+  void CreateHandler(int managed_bookmarks_count = 0) {
+    CHECK(!handler_);
+
+    prefs_ = std::make_unique<sync_preferences::TestingPrefServiceSyncable>();
+
+    managed_bookmark_service_ =
+        CreateManagedBookmarkService(prefs_.get(), managed_bookmarks_count);
+    bookmark_model_ = std::make_unique<bookmarks::BookmarkModel>(
+        std::make_unique<TestBookmarkClientWithManagedService>(
+            managed_bookmark_service_.get()));
+
+    bookmark_merged_service_ = std::make_unique<BookmarkMergedSurfaceService>(
+        bookmark_model_.get(), managed_bookmark_service_.get());
+
+    handler_ = std::make_unique<BookmarksPageHandler>(
+        mojo::PendingReceiver<side_panel::mojom::BookmarksPageHandler>(),
+        mock_bookmarks_page_.BindAndGetRemote(),
+        /*bookmarks_ui=*/nullptr, bookmark_merged_service_.get());
+  }
+
+  void LoadBookmarkModel() {
+    bookmark_model_->LoadEmptyForTest();
+    bookmark_merged_service_->LoadForTesting({});
+  }
+
+  void ClearHandler() {
+    handler_.reset();
+    mock_bookmarks_page_.Reset();
+    bookmark_merged_service_.reset();
+    bookmark_model_.reset();
+    managed_bookmark_service_.reset();
+    prefs_.reset();
+  }
+
+  int64_t GetBookmarkIdFromString(const std::string& string_id) {
+    int64_t bookmark_id;
+    CHECK(base::StringToInt64(string_id, &bookmark_id));
+    return bookmark_id;
+  }
 
  private:
-  std::unique_ptr<TestBookmarksPageHandler> handler_;
+  std::unique_ptr<sync_preferences::TestingPrefServiceSyncable> prefs_;
+
+  std::unique_ptr<bookmarks::ManagedBookmarkService> managed_bookmark_service_;
+  std::unique_ptr<bookmarks::BookmarkModel> bookmark_model_;
+  std::unique_ptr<BookmarkMergedSurfaceService> bookmark_merged_service_;
+
+  testing::NiceMock<MockBookmarksPage> mock_bookmarks_page_;
+
+  std::unique_ptr<BookmarksPageHandler> handler_;
+
+  base::test::ScopedFeatureList scoped_feature_list_{
+      switches::kSyncEnableBookmarksInTransportMode};
 };
 
 TEST_F(BookmarksPageHandlerTest, SetSortOrder) {
@@ -57,4 +232,426 @@
       static_cast<int>(view_type));
 }
 
+TEST_F(BookmarksPageHandlerTest, GetAllBookmarksOnBookmarkModelLoaded) {
+  // Reset the handler so that the model is not already loaded. Load it
+  // explicitly late.
+  ClearHandler();
+  CreateHandler();
+
+  base::MockCallback<BookmarksPageHandler::GetAllBookmarksCallback>
+      mock_callback;
+
+  EXPECT_CALL(mock_callback, Run(testing::_)).Times(0);
+  handler()->GetAllBookmarks(mock_callback.Get());
+
+  testing::Mock::VerifyAndClearExpectations(&mock_callback);
+
+  EXPECT_CALL(mock_callback, Run(testing::_)).Times(1);
+  LoadBookmarkModel();
+}
+
+TEST_F(BookmarksPageHandlerTest,
+       GetAllBookmarksContentWithEmptyPermanentNodes) {
+  const bookmarks::BookmarkNode* bookmark_bar = model()->bookmark_bar_node();
+  const bookmarks::BookmarkNode* other_node = model()->other_node();
+
+  base::MockCallback<BookmarksPageHandler::GetAllBookmarksCallback>
+      mock_callback;
+  EXPECT_CALL(mock_callback, Run(testing::_))
+      .WillOnce([&](const std::vector<side_panel::mojom::BookmarksTreeNodePtr>&
+                        nodes) {
+        // Total count: 2 - BookmarkBar + Other node (even if empty).
+        EXPECT_THAT(nodes, SizeIs(2));
+        // Bookmark is empty but still pushed.
+        ASSERT_TRUE(bookmark_bar->children().empty());
+        EXPECT_THAT(nodes, Contains(MatchesNode(bookmark_bar, service())));
+        // Other node is empty but still pushed.
+        ASSERT_TRUE(other_node->children().empty());
+        EXPECT_THAT(nodes, Contains(MatchesNode(other_node, service())));
+      });
+  handler()->GetAllBookmarks(mock_callback.Get());
+}
+
+TEST_F(BookmarksPageHandlerTest, GetAllBookmarksContentWithAllNodes) {
+  // Clears the handler to recreate it with the managed bookmarks.
+  ClearHandler();
+  CreateHandler(/*managed_bookmarks_count=*/10);
+  LoadBookmarkModel();
+
+  const bookmarks::BookmarkNode* bookmark_bar = model()->bookmark_bar_node();
+  AddNodesFromModelString(model(), bookmark_bar, "1 2 ");
+  const bookmarks::BookmarkNode* other_node = model()->other_node();
+  AddNodesFromModelString(model(), other_node, "3 f1:[ 4 5 ]");
+
+  const bookmarks::BookmarkNode* mobile_node = model()->mobile_node();
+  AddNodesFromModelString(model(), mobile_node, "6 f2:[ 7 8 ]");
+
+  const bookmarks::BookmarkNode* managed_node =
+      managed_bookmark_service()->managed_node();
+
+  base::MockCallback<BookmarksPageHandler::GetAllBookmarksCallback>
+      mock_callback;
+  EXPECT_CALL(mock_callback, Run(testing::_))
+      .WillOnce([&](const std::vector<side_panel::mojom::BookmarksTreeNodePtr>&
+                        nodes) {
+        // Total count: 4 - BookmarkBar + Other node + Mobile node + Managed.
+        EXPECT_THAT(nodes, SizeIs(4));
+        EXPECT_THAT(nodes, Contains(MatchesNode(bookmark_bar, service())));
+        EXPECT_THAT(nodes, Contains(MatchesNode(other_node, service())));
+        EXPECT_THAT(nodes, Contains(MatchesNode(mobile_node, service())));
+        EXPECT_THAT(nodes, Contains(MatchesNode(managed_node, service())));
+      });
+  handler()->GetAllBookmarks(mock_callback.Get());
+}
+
+TEST_F(BookmarksPageHandlerTest, GetAllBookmarksContentWithAccountNodes) {
+  model()->CreateAccountPermanentFolders();
+
+  const bookmarks::BookmarkNode* bookmark_bar = model()->bookmark_bar_node();
+  AddNodesFromModelString(model(), bookmark_bar, "1 2 ");
+
+  const bookmarks::BookmarkNode* account_bookmark_bar =
+      model()->account_bookmark_bar_node();
+  AddNodesFromModelString(model(), account_bookmark_bar, "a1 a2 ");
+
+  const bookmarks::BookmarkNode* other_node = model()->other_node();
+  AddNodesFromModelString(model(), other_node, "3 4 ");
+
+  const bookmarks::BookmarkNode* account_other_node =
+      model()->account_other_node();
+  AddNodesFromModelString(model(), account_other_node, "a3 a4 ");
+
+  const bookmarks::BookmarkNode* account_mobile_node =
+      model()->account_mobile_node();
+  AddNodesFromModelString(model(), account_mobile_node, "a5 ");
+  const bookmarks::BookmarkNode* mobile_node = model()->mobile_node();
+
+  base::MockCallback<BookmarksPageHandler::GetAllBookmarksCallback>
+      mock_callback;
+  EXPECT_CALL(mock_callback, Run(testing::_))
+      .WillOnce([&](const std::vector<side_panel::mojom::BookmarksTreeNodePtr>&
+                        nodes) {
+        // Total count: 3 - BookmarkBar (Merged) + Other node (Merged) + Mobile.
+        EXPECT_THAT(nodes, SizeIs(3));
+        // Both `bookmark_bar` and `account_bookmark_bar` are merged into one.
+        EXPECT_THAT(nodes, Contains(MatchesNode(bookmark_bar, service())));
+        EXPECT_THAT(nodes,
+                    Contains(MatchesNode(account_bookmark_bar, service())));
+        // Both `other_node` and `account_other_node` are merged into one.
+        EXPECT_THAT(nodes, Contains(MatchesNode(other_node, service())));
+        EXPECT_THAT(nodes,
+                    Contains(MatchesNode(account_other_node, service())));
+        // Both `mobile_node` and `account_mobile_node` are merged into one.
+        // Even if `mobile_node` is empty, it is still represented since there
+        // are at least one total mobile node.
+        EXPECT_THAT(nodes,
+                    Contains(MatchesNode(account_mobile_node, service())));
+        ASSERT_TRUE(mobile_node->children().empty());
+        EXPECT_THAT(nodes, Contains(MatchesNode(mobile_node, service())));
+      });
+  handler()->GetAllBookmarks(mock_callback.Get());
+}
+
+TEST_F(BookmarksPageHandlerTest, OnBookmarkNodeAdded) {
+  const std::string expected_bookmark_side_panel_id =
+      GetFolderSidePanelIDForTesting(*service(),
+                                     BookmarkParentFolder::BookmarkBarFolder());
+
+  // Make sure that nodes added directly to the bookmark_bar folder have the
+  // correct parent id computed for the side panel.
+  EXPECT_CALL(mock_bookmarks_page(), OnBookmarkNodeAdded(testing::_))
+      .Times(3)
+      .WillRepeatedly([&](side_panel::mojom::BookmarksTreeNodePtr mojo_node) {
+        EXPECT_EQ(expected_bookmark_side_panel_id, mojo_node->parent_id);
+      });
+  AddNodesFromModelString(model(), model()->bookmark_bar_node(), "1 2 3 ");
+  mock_bookmarks_page().FlushForTesting();
+  testing::Mock::VerifyAndClearExpectations(&mock_bookmarks_page());
+
+  // When adding a folder, only the folder should have this side panel id as the
+  // parent id, sub elements should just have the new folder as parent id.
+  EXPECT_CALL(mock_bookmarks_page(), OnBookmarkNodeAdded(testing::_))
+      .Times(3)
+      .WillRepeatedly([&](side_panel::mojom::BookmarksTreeNodePtr mojo_node) {
+        if (mojo_node->url.has_value()) {
+          EXPECT_NE(expected_bookmark_side_panel_id, mojo_node->parent_id);
+        } else {
+          // Folder but should not have children as it will be sent with
+          // separate notification.
+          EXPECT_FALSE(mojo_node->children.has_value());
+          EXPECT_EQ(expected_bookmark_side_panel_id, mojo_node->parent_id);
+        }
+      });
+  AddNodesFromModelString(model(), model()->bookmark_bar_node(), "f1:[ 4 5 ]");
+  mock_bookmarks_page().FlushForTesting();
+  testing::Mock::VerifyAndClearExpectations(&mock_bookmarks_page());
+
+  model()->CreateAccountPermanentFolders();
+  // Permanent nodes do not trigger a notification.
+  EXPECT_CALL(mock_bookmarks_page(), OnBookmarkNodeAdded(testing::_)).Times(0);
+  mock_bookmarks_page().FlushForTesting();
+  testing::Mock::VerifyAndClearExpectations(&mock_bookmarks_page());
+
+  // Adding direct children to the account node should also have the side panel
+  // bookmark bar id as their parent id.
+  EXPECT_CALL(mock_bookmarks_page(), OnBookmarkNodeAdded(testing::_))
+      .Times(2)
+      .WillRepeatedly([&](side_panel::mojom::BookmarksTreeNodePtr mojo_node) {
+        EXPECT_EQ(expected_bookmark_side_panel_id, mojo_node->parent_id);
+      });
+  AddNodesFromModelString(model(), model()->account_bookmark_bar_node(),
+                          "a1 a2 ");
+  mock_bookmarks_page().FlushForTesting();
+}
+
+TEST_F(BookmarksPageHandlerTest, OnBookmarkNodesRemoved) {
+  model()->CreateAccountPermanentFolders();
+
+  const bookmarks::BookmarkNode* other_node = model()->other_node();
+  const bookmarks::BookmarkNode* account_other_node =
+      model()->account_other_node();
+
+  AddNodesFromModelString(model(), other_node, "1 2:[ 3 ]");
+  AddNodesFromModelString(model(), account_other_node, "4 5 6 ");
+
+  const bookmarks::BookmarkNode* folder_in_other =
+      other_node->children()[1].get();
+  ASSERT_TRUE(folder_in_other->is_folder());
+
+  // Only folder id expected; without its children ids.
+  EXPECT_CALL(mock_bookmarks_page(),
+              OnBookmarkNodesRemoved(
+                  UnorderedElementsAre(base::ToString(folder_in_other->id()))));
+  model()->Remove(folder_in_other,
+                  bookmarks::metrics::BookmarkEditSource::kOther, FROM_HERE);
+  mock_bookmarks_page().FlushForTesting();
+  testing::Mock::VerifyAndClearExpectations(&mock_bookmarks_page());
+
+  const bookmarks::BookmarkNode* first_account_node =
+      account_other_node->children()[1].get();
+  ASSERT_TRUE(first_account_node->is_url());
+
+  EXPECT_CALL(mock_bookmarks_page(),
+              OnBookmarkNodesRemoved(UnorderedElementsAre(
+                  base::ToString(first_account_node->id()))));
+  model()->Remove(first_account_node,
+                  bookmarks::metrics::BookmarkEditSource::kOther, FROM_HERE);
+  mock_bookmarks_page().FlushForTesting();
+  testing::Mock::VerifyAndClearExpectations(&mock_bookmarks_page());
+
+  // 2 remaining nodes in `account_other_node`.
+  EXPECT_CALL(
+      mock_bookmarks_page(),
+      OnBookmarkNodesRemoved(UnorderedElementsAre(
+          base::ToString(account_other_node->children()[0].get()->id()),
+          base::ToString(account_other_node->children()[1].get()->id()))));
+  model()->RemoveAccountPermanentFolders();
+  mock_bookmarks_page().FlushForTesting();
+}
+
+TEST_F(BookmarksPageHandlerTest,
+       OnBookmarkParentFolderChildrenReorderedFromLocalNode) {
+  model()->CreateAccountPermanentFolders();
+
+  const bookmarks::BookmarkNode* other_node = model()->other_node();
+  const bookmarks::BookmarkNode* account_other_node =
+      model()->account_other_node();
+
+  AddNodesFromModelString(model(), other_node, "2 1:[ 3 ]");
+  std::string first_other_node_id =
+      base::ToString(other_node->children()[0].get()->id());
+  std::string second_other_node_id =
+      base::ToString(other_node->children()[1].get()->id());
+  AddNodesFromModelString(model(), account_other_node, "5 4 ");
+  std::string first_account_other_node_id =
+      base::ToString(account_other_node->children()[0].get()->id());
+  std::string second_account_other_node_id =
+      base::ToString(account_other_node->children()[1].get()->id());
+
+  // All merged nodes are part of the notification, but only local nodes are
+  // reorderd.
+  EXPECT_CALL(
+      mock_bookmarks_page(),
+      OnBookmarkParentFolderChildrenReordered(
+          base::ToString(other_node->id()),
+          ElementsAre(first_account_other_node_id, second_account_other_node_id,
+                      second_other_node_id, first_other_node_id)));
+  // Sort local nodes.
+  model()->SortChildren(other_node);
+  mock_bookmarks_page().FlushForTesting();
+}
+
+TEST_F(BookmarksPageHandlerTest,
+       OnBookmarkParentFolderChildrenReorderedFromAccountNode) {
+  model()->CreateAccountPermanentFolders();
+
+  const bookmarks::BookmarkNode* other_node = model()->other_node();
+  const bookmarks::BookmarkNode* account_other_node =
+      model()->account_other_node();
+
+  AddNodesFromModelString(model(), other_node, "2 1:[ 3 ]");
+  std::string first_other_node_id =
+      base::ToString(other_node->children()[0].get()->id());
+  std::string second_other_node_id =
+      base::ToString(other_node->children()[1].get()->id());
+  AddNodesFromModelString(model(), account_other_node, "5 4 ");
+  std::string first_account_other_node_id =
+      base::ToString(account_other_node->children()[0].get()->id());
+  std::string second_account_other_node_id =
+      base::ToString(account_other_node->children()[1].get()->id());
+
+  // All merged nodes are part of the notification, but only account nodes are
+  // reorderd.
+  EXPECT_CALL(
+      mock_bookmarks_page(),
+      OnBookmarkParentFolderChildrenReordered(
+          base::ToString(other_node->id()),
+          ElementsAre(second_account_other_node_id, first_account_other_node_id,
+                      first_other_node_id, second_other_node_id)));
+  // Sort account nodes.
+  model()->SortChildren(account_other_node);
+  mock_bookmarks_page().FlushForTesting();
+}
+
+TEST_F(BookmarksPageHandlerTest, OnBookmarkNodeMoved) {
+  base::test::ScopedFeatureList scoped_feature_list{
+      switches::kSyncEnableBookmarksInTransportMode};
+
+  model()->CreateAccountPermanentFolders();
+
+  const bookmarks::BookmarkNode* other_node = model()->other_node();
+  const bookmarks::BookmarkNode* account_bookmark_bar_node =
+      model()->account_bookmark_bar_node();
+
+  AddNodesFromModelString(model(), other_node, "2 1:[ 3 ]");
+  const bookmarks::BookmarkNode* node_to_move = other_node->children()[0].get();
+  AddNodesFromModelString(model(), account_bookmark_bar_node, "5 4 ");
+
+  EXPECT_CALL(mock_bookmarks_page(),
+              OnBookmarkNodeMoved(
+                  GetFolderSidePanelIDForTesting(
+                      *service(), BookmarkParentFolder::OtherFolder()),
+                  testing::_,
+                  GetFolderSidePanelIDForTesting(
+                      *service(), BookmarkParentFolder::BookmarkBarFolder()),
+                  testing::_));
+
+  model()->Move(node_to_move, account_bookmark_bar_node, 0);
+  mock_bookmarks_page().FlushForTesting();
+}
+
+TEST_F(BookmarksPageHandlerTest, BookmarkCurrentTabInFolder) {
+  // Adds tab content that will be used to be bookmarked.
+  AddTab(browser(), GURL("http://www.google.com/"));
+
+  const bookmarks::BookmarkNode* other_node = model()->other_node();
+  ASSERT_TRUE(other_node->children().empty());
+
+  // Using side panel id, merged node between local and account nodes.
+  std::string other_side_panel_id = GetFolderSidePanelIDForTesting(
+      *service(), BookmarkParentFolder::OtherFolder());
+  handler()->BookmarkCurrentTabInFolder(other_side_panel_id);
+  // Without account nodes, the local node is the default one for merged nodes.
+  EXPECT_EQ(1u, other_node->children().size());
+
+  // Initiates the account nodes.
+  model()->CreateAccountPermanentFolders();
+  const bookmarks::BookmarkNode* account_other_node =
+      model()->account_other_node();
+  ASSERT_TRUE(account_other_node->children().empty());
+
+  // Account node is now the default one.
+  handler()->BookmarkCurrentTabInFolder(other_side_panel_id);
+  EXPECT_EQ(1u, account_other_node->children().size());
+  EXPECT_EQ(1u, other_node->children().size());
+
+  // Creating a non merged folder.
+  const bookmarks::BookmarkNode* new_folder =
+      model()->AddFolder(other_node, 0, u"New Local Folder");
+  ASSERT_TRUE(new_folder->children().empty());
+  ASSERT_EQ(2u, other_node->children().size());
+  // A non meregd folder is directly given as input and impacted.
+  handler()->BookmarkCurrentTabInFolder(base::ToString(new_folder->id()));
+  EXPECT_EQ(1u, new_folder->children().size());
+  EXPECT_EQ(1u, account_other_node->children().size());
+  EXPECT_EQ(2u, other_node->children().size());
+}
+
+TEST_F(BookmarksPageHandlerTest, CreateFolder) {
+  CreateFolderFunctionHelper helper;
+  const std::string folder_title = "new_folder_title";
+
+  const bookmarks::BookmarkNode* other_node = model()->other_node();
+  ASSERT_TRUE(other_node->children().empty());
+
+  // Using side panel id, merged node between local and account nodes.
+  std::string other_side_panel_id = GetFolderSidePanelIDForTesting(
+      *service(), BookmarkParentFolder::OtherFolder());
+  handler()->CreateFolder(
+      other_side_panel_id, folder_title,
+      base::BindOnce(&CreateFolderFunctionHelper::OnCreateFolderResult,
+                     base::Unretained(&helper)));
+  std::string added_local_folder_id = helper.GetResultWhenReady();
+  // Without account nodes, the local node is the default one for merged nodes.
+  ASSERT_EQ(1u, other_node->children().size());
+  EXPECT_EQ(GetBookmarkIdFromString(added_local_folder_id),
+            other_node->children()[0].get()->id());
+
+  // Initiates the account nodes.
+  model()->CreateAccountPermanentFolders();
+  const bookmarks::BookmarkNode* account_other_node =
+      model()->account_other_node();
+  ASSERT_TRUE(account_other_node->children().empty());
+  // Account node is now the default one.
+  handler()->CreateFolder(
+      other_side_panel_id, folder_title,
+      base::BindOnce(&CreateFolderFunctionHelper::OnCreateFolderResult,
+                     base::Unretained(&helper)));
+  std::string added_account_folder_id = helper.GetResultWhenReady();
+  ASSERT_EQ(1u, account_other_node->children().size());
+  EXPECT_EQ(GetBookmarkIdFromString(added_account_folder_id),
+            account_other_node->children()[0].get()->id());
+  EXPECT_EQ(1u, other_node->children().size());
+
+  // Creating a non merged folder.
+  const bookmarks::BookmarkNode* new_folder =
+      model()->AddFolder(other_node, 0, u"New Local Folder");
+  ASSERT_TRUE(new_folder->children().empty());
+  ASSERT_EQ(2u, other_node->children().size());
+  // A non meregd folder is directly given as input and impacted.
+  handler()->CreateFolder(
+      base::ToString(new_folder->id()), folder_title,
+      base::BindOnce(&CreateFolderFunctionHelper::OnCreateFolderResult,
+                     base::Unretained(&helper)));
+  std::string added_regular_folder_id = helper.GetResultWhenReady();
+  ASSERT_EQ(1u, new_folder->children().size());
+  EXPECT_EQ(GetBookmarkIdFromString(added_regular_folder_id),
+            new_folder->children()[0].get()->id());
+  EXPECT_EQ(1u, account_other_node->children().size());
+  EXPECT_EQ(2u, other_node->children().size());
+}
+
+// Should test any handler function that accepts a string as node ID.
+// Making sure that the test does not crash and has no effect.
+TEST_F(BookmarksPageHandlerTest, HandlerWithInvalidInputs) {
+  const std::string invalid_id_string = "random_invalid_id";
+  model()->CreateAccountPermanentFolders();
+
+  ASSERT_FALSE(model()->HasBookmarks());
+
+  handler()->BookmarkCurrentTabInFolder(invalid_id_string);
+
+  EXPECT_FALSE(model()->HasBookmarks());
+
+  CreateFolderFunctionHelper helper;
+  handler()->CreateFolder(
+      invalid_id_string, "folder_title",
+      base::BindOnce(&CreateFolderFunctionHelper::OnCreateFolderResult,
+                     base::Unretained(&helper)));
+  std::string result = helper.GetResultWhenReady();
+  EXPECT_TRUE(result.empty());
+
+  EXPECT_FALSE(model()->HasBookmarks());
+}
+
 }  // namespace
diff --git a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.cc b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.cc
index 2608789..668f51aa 100644
--- a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.cc
+++ b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/bookmarks/bookmark_merged_surface_service_factory.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/bookmarks/managed_bookmark_service_factory.h"
 #include "chrome/browser/browser_features.h"
@@ -309,9 +310,12 @@
 }
 
 void BookmarksSidePanelUI::CreateBookmarksPageHandler(
+    mojo::PendingRemote<side_panel::mojom::BookmarksPage> page,
     mojo::PendingReceiver<side_panel::mojom::BookmarksPageHandler> receiver) {
-  bookmarks_page_handler_ =
-      std::make_unique<BookmarksPageHandler>(std::move(receiver), this);
+  bookmarks_page_handler_ = std::make_unique<BookmarksPageHandler>(
+      std::move(receiver), std::move(page), this,
+      BookmarkMergedSurfaceServiceFactory::GetForProfile(
+          Profile::FromWebUI(web_ui())));
 }
 
 void BookmarksSidePanelUI::CreateShoppingServiceHandler(
diff --git a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.h b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.h
index bc4efb4..c5643219 100644
--- a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.h
+++ b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.h
@@ -91,6 +91,7 @@
  private:
   // side_panel::mojom::BookmarksPageHandlerFactory:
   void CreateBookmarksPageHandler(
+      mojo::PendingRemote<side_panel::mojom::BookmarksPage> page,
       mojo::PendingReceiver<side_panel::mojom::BookmarksPageHandler> receiver)
       override;
 
diff --git a/chrome/browser/web_applications/os_integration/mac/web_app_shortcut_copier_mac.mm b/chrome/browser/web_applications/os_integration/mac/web_app_shortcut_copier_mac.mm
index 4d31e20d..5f8308b 100644
--- a/chrome/browser/web_applications/os_integration/mac/web_app_shortcut_copier_mac.mm
+++ b/chrome/browser/web_applications/os_integration/mac/web_app_shortcut_copier_mac.mm
@@ -10,7 +10,7 @@
 
 #include "base/apple/bundle_locations.h"
 #include "base/apple/foundation_util.h"
-#include "base/apple/mach_port_rendezvous.h"
+#include "base/apple/mach_port_rendezvous_mac.h"
 #include "base/base_paths.h"
 #include "base/command_line.h"
 #include "base/debug/leak_annotations.h"
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt
index 5dfde9f..815932af 100644
--- a/chrome/build/android-arm64.pgo.txt
+++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@
-chrome-android64-main-1743683860-63e1120b8ae53d4bfe273cbf3324bdf587c0e252-98600920dcf44881ae63f76b909cc390bfc7a53b.profdata
+chrome-android64-main-1743694520-71bc4d113b1728c64b03949dc9a613ab0634f2b4-d9b13ffe206771188d7cd24287e2b5771f154d10.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index d4785e0..ea8dcfea 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1743681583-5369662539b315f2599ad5c5b43f41a8480a60e0-b0c950decbb2c51b8e18cffd2daf446745dc5642.profdata
+chrome-mac-arm-main-1743695934-834524764624a7dfbe485d955bda13cb155ed57d-d0ea5acf1b288b4217a694511748b508823d07f4.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index cf1a2941..6646e9bc 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1743659957-eb39706b69ef97fd4e764ef74331981eef0004c8-126fdbc28ded6dc63b3d1ed0c6ac08aa41642402.profdata
+chrome-mac-main-1743681583-01bcc09b016011f58654feb27349940f801e5028-b0c950decbb2c51b8e18cffd2daf446745dc5642.profdata
diff --git a/chrome/build/win-arm64.pgo.txt b/chrome/build/win-arm64.pgo.txt
index f68d6c3..f201e02 100644
--- a/chrome/build/win-arm64.pgo.txt
+++ b/chrome/build/win-arm64.pgo.txt
@@ -1 +1 @@
-chrome-win-arm64-main-1743659957-36b2304f2afe9bf7f7261237f607f2755db42ab2-126fdbc28ded6dc63b3d1ed0c6ac08aa41642402.profdata
+chrome-win-arm64-main-1743681583-a9ffc9c4259ed1c9053514ca3f548dcdd3ff209a-b0c950decbb2c51b8e18cffd2daf446745dc5642.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index bf39dc4..b1332b2 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1743670773-e6818bdfe2c122a56af46a5c5ca68c120968e89c-ee01e088f5ece0a0a44ad879ef57ea5306902f84.profdata
+chrome-win64-main-1743681583-3db3ab12f6a03a81238a09635db753126ec689c0-b0c950decbb2c51b8e18cffd2daf446745dc5642.profdata
diff --git a/chrome/common/logging_chrome.cc b/chrome/common/logging_chrome.cc
index 839c132..b9d56421 100644
--- a/chrome/common/logging_chrome.cc
+++ b/chrome/common/logging_chrome.cc
@@ -110,7 +110,7 @@
 // Assertion handler for logging errors that occur when dialogs are
 // silenced.  To record a new error, pass the log string associated
 // with that error in the str parameter.
-NOINLINE void SilentRuntimeAssertHandler(std::string_view file,
+NOINLINE void SilentRuntimeAssertHandler(const char* file,
                                          int line,
                                          std::string_view message,
                                          std::string_view stack_trace) {
diff --git a/chrome/release_scripts b/chrome/release_scripts
index 6f89544..2948009 160000
--- a/chrome/release_scripts
+++ b/chrome/release_scripts
@@ -1 +1 @@
-Subproject commit 6f895445ad5a137f98d68ad25783f953e3713d52
+Subproject commit 29480092413e128bbd9e417c36760d759556930c
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 3e62358..7029b4f 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -7547,6 +7547,8 @@
       "../browser/bookmarks/bookmark_merged_surface_service_unittest.cc",
       "../browser/bookmarks/bookmark_parent_folder_children_unittest.cc",
       "../browser/bookmarks/bookmark_parent_folder_unittest.cc",
+      "../browser/bookmarks/bookmark_test_utils.cc",
+      "../browser/bookmarks/bookmark_test_utils.h",
       "../browser/bookmarks/permanent_folder_ordering_tracker_unittest.cc",
       "../browser/browser_commands_unittest.cc",
       "../browser/browsing_data/chrome_browsing_data_lifetime_manager_unittest.cc",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/HubBaseStation.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/HubBaseStation.java
index 835038dd..a6c9a938 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/HubBaseStation.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/HubBaseStation.java
@@ -30,7 +30,6 @@
 import org.chromium.base.test.transit.ViewElement;
 import org.chromium.base.test.transit.ViewSpec;
 import org.chromium.chrome.browser.ChromeTabbedActivity;
-import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.hub.PaneId;
 import org.chromium.chrome.browser.hub.R;
 import org.chromium.chrome.browser.layouts.LayoutType;
@@ -82,16 +81,9 @@
         elements.declareView(HUB_MENU_BUTTON);
 
         // TODO(crbug.com/386819654): Add a member of type ViewElement representing tab group pane
-        if (ChromeFeatureList.sTabGroupPaneAndroid.isEnabled()) {
-            mRegularTabsButton = elements.declareView(REGULAR_TOGGLE_TAB_BUTTON);
-            if (mIncognitoTabsExist) {
-                mIncognitoTabsButton = elements.declareView(INCOGNITO_TOGGLE_TAB_BUTTON);
-            }
-        } else {
-            if (mIncognitoTabsExist) {
-                mRegularTabsButton = elements.declareView(REGULAR_TOGGLE_TAB_BUTTON);
-                mIncognitoTabsButton = elements.declareView(INCOGNITO_TOGGLE_TAB_BUTTON);
-            }
+        mRegularTabsButton = elements.declareView(REGULAR_TOGGLE_TAB_BUTTON);
+        if (mIncognitoTabsExist) {
+            mIncognitoTabsButton = elements.declareView(INCOGNITO_TOGGLE_TAB_BUTTON);
         }
 
         elements.declareEnterCondition(
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/RegularTabSwitcherStation.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/RegularTabSwitcherStation.java
index c2f05ce90..9272f32b 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/RegularTabSwitcherStation.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/RegularTabSwitcherStation.java
@@ -12,7 +12,6 @@
 import org.chromium.base.test.transit.Elements;
 import org.chromium.base.test.transit.ViewElementMatchesCondition;
 import org.chromium.base.test.transit.ViewSpec;
-import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.hub.PaneId;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.test.R;
@@ -44,11 +43,9 @@
     @Override
     public void declareElements(Elements.Builder elements) {
         super.declareElements(elements);
-        if (ChromeFeatureList.sTabGroupPaneAndroid.isEnabled() || mIncognitoTabsExist) {
-            assert mRegularTabsButton != null;
-            elements.declareEnterCondition(
-                    new ViewElementMatchesCondition(mRegularTabsButton, isSelected()));
-        }
+        assert mRegularTabsButton != null;
+        elements.declareEnterCondition(
+                new ViewElementMatchesCondition(mRegularTabsButton, isSelected()));
         if (!mRegularTabsExist) {
             elements.declareView(EMPTY_STATE_TEXT);
         }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/suggestions/mostvisited/FakeMostVisitedSites.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/suggestions/mostvisited/FakeMostVisitedSites.java
index 2d3587434..7ba9333 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/suggestions/mostvisited/FakeMostVisitedSites.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/suggestions/mostvisited/FakeMostVisitedSites.java
@@ -53,7 +53,7 @@
     }
 
     @Override
-    public boolean queryCustomLink(GURL keyUrl) {
+    public boolean hasCustomLink(GURL keyUrl) {
         // TODO (crbug.com/397421764): Implement when needed by tests.
         return false;
     }
@@ -118,9 +118,9 @@
     }
 
     /**
-     * Sets new tile suggestion data, generating dummy data for the missing properties.
+     * Sets new tile suggestion data, generating fake data for the missing properties.
      *
-     * If there is an observer it will be notified and the call has to be made on the UI thread.
+     * <p>If there is an observer it will be notified and the call has to be made on the UI thread.
      *
      * @param urls The URLs of the site suggestions.
      * @see #setTileSuggestions(SiteSuggestion[])
diff --git a/chrome/test/base/ash/web_ui_browser_test.cc b/chrome/test/base/ash/web_ui_browser_test.cc
index 27c9fedb..71cb380f 100644
--- a/chrome/test/base/ash/web_ui_browser_test.cc
+++ b/chrome/test/base/ash/web_ui_browser_test.cc
@@ -65,11 +65,12 @@
 
 // Intercepts all log messages.
 bool LogHandler(int severity,
-                std::string_view file,
+                const char* file,
                 int line,
                 size_t message_start,
                 const std::string& str) {
-  if (severity == logging::LOGGING_ERROR && file == "CONSOLE") {
+  if (severity == logging::LOGGING_ERROR && file &&
+      std::string("CONSOLE") == file) {
     g_error_messages.Get().push_back(str);
   }
 
diff --git a/chrome/test/base/test_browser_window.cc b/chrome/test/base/test_browser_window.cc
index 934d8c3..1293b29 100644
--- a/chrome/test/base/test_browser_window.cc
+++ b/chrome/test/base/test_browser_window.cc
@@ -454,6 +454,14 @@
 void TestBrowserWindow::NotifyNewBadgeFeatureUsed(
     const base::Feature& feature) {}
 
+bool TestBrowserWindow::IsTabModalPopup() const {
+  return is_tab_modal_popup_;
+}
+
+void TestBrowserWindow::SetIsTabModalPopup(bool is_tab_modal_popup) {
+  is_tab_modal_popup_ = is_tab_modal_popup;
+}
+
 user_education::FeaturePromoController*
 TestBrowserWindow::SetFeaturePromoController(
     std::unique_ptr<user_education::FeaturePromoController>
diff --git a/chrome/test/base/test_browser_window.h b/chrome/test/base/test_browser_window.h
index b5535cd0..4964327 100644
--- a/chrome/test/base/test_browser_window.h
+++ b/chrome/test/base/test_browser_window.h
@@ -271,6 +271,8 @@
   user_education::DisplayNewBadge MaybeShowNewBadgeFor(
       const base::Feature& new_badge_feature) override;
   void NotifyNewBadgeFeatureUsed(const base::Feature& feature) override;
+  bool IsTabModalPopup() const override;
+  void SetIsTabModalPopup(bool is_tab_modal_popup) override;
 
   // Sets the controller returned by GetFeaturePromoController().
   // Deletes the existing one, if any.
@@ -331,6 +333,7 @@
   bool is_active_ = false;
   bool is_closed_ = false;
   bool is_tab_strip_editable_ = true;
+  bool is_tab_modal_popup_ = false;
 
   std::unique_ptr<user_education::FeaturePromoController>
       feature_promo_controller_;
diff --git a/chrome/test/chromedriver/logging.cc b/chrome/test/chromedriver/logging.cc
index 02c4f48..9dac4b1e 100644
--- a/chrome/test/chromedriver/logging.cc
+++ b/chrome/test/chromedriver/logging.cc
@@ -16,7 +16,6 @@
 #include <array>
 #include <cmath>
 #include <memory>
-#include <string_view>
 #include <utility>
 
 #include "base/command_line.h"
@@ -120,7 +119,7 @@
 }
 
 bool HandleLogMessage(int severity,
-                      std::string_view file,
+                      const char* file,
                       int line,
                       size_t message_start,
                       const std::string& str) {
diff --git a/chrome/test/data/webui/bookmarks/router_test.ts b/chrome/test/data/webui/bookmarks/router_test.ts
index c97e8b0..3ce810b 100644
--- a/chrome/test/data/webui/bookmarks/router_test.ts
+++ b/chrome/test/data/webui/bookmarks/router_test.ts
@@ -54,8 +54,8 @@
     store.data.selectedFolder = '2';
     store.notifyObservers();
     await microtasksFinished();
-
     assertEquals('chrome://bookmarks/?id=2', window.location.href);
+
     store.data.selectedFolder = '1';
     store.notifyObservers();
     await microtasksFinished();
@@ -86,6 +86,68 @@
   });
 });
 
+suite('<bookmarks-router-account-and-local>', function() {
+  let store: TestStore;
+
+  function navigateTo(route: string) {
+    window.history.replaceState({}, '', route);
+    window.dispatchEvent(new CustomEvent('popstate'));
+  }
+
+  setup(function() {
+    document.body.innerHTML = window.trustedTypes!.emptyHTML;
+    const nodes = testTree(
+        createFolder('1', [createItem('11', {syncing: true})], {
+          syncing: true,
+          folderType: chrome.bookmarks.FolderType.BOOKMARKS_BAR,
+        }),
+        createFolder('2', [createItem('21', {syncing: false})], {
+          syncing: false,
+          folderType: chrome.bookmarks.FolderType.BOOKMARKS_BAR,
+        }));
+    store = new TestStore({
+      nodes: nodes,
+      folderOpenState: getAllFoldersOpenState(nodes),
+      selectedFolder: 'account_heading',
+      search: {
+        term: '',
+      },
+    });
+    store.replaceSingleton();
+
+    const router = new BookmarksRouter();
+    router.initialize();
+  });
+
+  test('selected folder updates from route', function() {
+    navigateTo('/?id=local_heading');
+    const action = store.lastAction as SelectFolderAction;
+    assertEquals('select-folder', action.name);
+    assertEquals('local_heading', action.id);
+  });
+
+  test('route updates from ID', async function() {
+    store.data.selectedFolder = '2';
+    store.notifyObservers();
+    await microtasksFinished();
+    assertEquals('chrome://bookmarks/?id=2', window.location.href);
+
+    store.data.selectedFolder = 'account_heading';
+    store.notifyObservers();
+    await microtasksFinished();
+    // Selecting account bookmarks root clears route.
+    assertEquals('chrome://bookmarks/', window.location.href);
+  });
+
+  test('account bookmarks root selected with empty route', function() {
+    navigateTo('/?id=2');
+    navigateTo('/');
+    const action = store.lastAction as SelectFolderAction;
+    assertEquals('select-folder', action.name);
+    assertEquals('account_heading', action.id);
+  });
+});
+
 suite('URL preload', function() {
   let testBookmarksApiProxy: TestBookmarksApiProxy;
 
diff --git a/chrome/test/data/webui/bookmarks/test_util.ts b/chrome/test/data/webui/bookmarks/test_util.ts
index 795be489..4e199efa 100644
--- a/chrome/test/data/webui/bookmarks/test_util.ts
+++ b/chrome/test/data/webui/bookmarks/test_util.ts
@@ -39,7 +39,7 @@
         id: id,
         children: children,
         title: '',
-        syncing: true,
+        syncing: config?.syncing ?? true,
       },
       config || {});
 
@@ -76,7 +76,7 @@
         id: id,
         title: '',
         url: 'http://www.google.com/',
-        syncing: true,
+        syncing: config?.syncing ?? true,
       },
       config || {});
 }
diff --git a/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_context_menu_test.ts b/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_context_menu_test.ts
index 7897d4e..0917c6d 100644
--- a/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_context_menu_test.ts
+++ b/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_context_menu_test.ts
@@ -4,6 +4,7 @@
 
 import 'chrome://bookmarks-side-panel.top-chrome/power_bookmarks_context_menu.js';
 
+import type {BookmarksTreeNode} from 'chrome://bookmarks-side-panel.top-chrome/bookmarks.mojom-webui.js';
 import {BookmarksApiProxyImpl} from 'chrome://bookmarks-side-panel.top-chrome/bookmarks_api_proxy.js';
 import type {PowerBookmarksContextMenuElement} from 'chrome://bookmarks-side-panel.top-chrome/power_bookmarks_context_menu.js';
 import {PowerBookmarksService} from 'chrome://bookmarks-side-panel.top-chrome/power_bookmarks_service.js';
@@ -20,38 +21,54 @@
   let delegate: TestPowerBookmarksDelegate;
   let service: PowerBookmarksService;
 
-  const folders: chrome.bookmarks.BookmarkTreeNode[] = [
+  const allBookmarks: BookmarksTreeNode[] = [
     {
       id: '2',
       parentId: '0',
+      index: 0,
       title: 'Other Bookmarks',
+      url: null,
+      dateAdded: null,
+      dateLastUsed: null,
       children: [
         {
           id: '3',
           parentId: '2',
+          index: 0,
           title: 'First child bookmark',
           url: 'http://child/bookmark/1/',
           dateAdded: 1,
+          dateLastUsed: null,
+          children: null,
         },
         {
           id: '4',
           parentId: '2',
+          index: 1,
           title: 'Second child bookmark',
           url: 'http://child/bookmark/2/',
           dateAdded: 3,
+          dateLastUsed: null,
+          children: null,
         },
         {
           id: '5',
           parentId: '2',
           title: 'Child folder',
+          index: 3,
           dateAdded: 2,
+          url: null,
+          dateLastUsed: null,
           children: [
             {
               id: '6',
               parentId: '5',
+              index: 0,
               title: 'Nested bookmark',
               url: 'http://nested/bookmark/',
               dateAdded: 4,
+              dateLastUsed: null,
+              children: null,
             },
           ],
         },
@@ -63,7 +80,7 @@
     document.body.innerHTML = window.trustedTypes!.emptyHTML;
 
     bookmarksApi = new TestBookmarksApiProxy();
-    bookmarksApi.setFolders(structuredClone(folders));
+    bookmarksApi.setAllBookmarks(allBookmarks);
     BookmarksApiProxyImpl.setInstance(bookmarksApi);
 
     delegate = new TestPowerBookmarksDelegate();
diff --git a/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_drag_manager_test.ts b/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_drag_manager_test.ts
index 8d79b8ba..c5c854a 100644
--- a/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_drag_manager_test.ts
+++ b/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_drag_manager_test.ts
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 
+import type {BookmarksTreeNode} from 'chrome://bookmarks-side-panel.top-chrome/bookmarks.mojom-webui.js';
 import {BookmarksApiProxyImpl} from 'chrome://bookmarks-side-panel.top-chrome/bookmarks_api_proxy.js';
 import {DROP_POSITION_ATTR, DropPosition, PowerBookmarksDragManager} from 'chrome://bookmarks-side-panel.top-chrome/power_bookmarks_drag_manager.js';
 import {PowerBookmarksListElement} from 'chrome://bookmarks-side-panel.top-chrome/power_bookmarks_list.js';
@@ -14,39 +15,54 @@
 
 suite('SidePanelPowerBookmarkDragManagerTest', () => {
   let delegate: PowerBookmarksListElement;
-
-  const folders: chrome.bookmarks.BookmarkTreeNode[] = [
+  const allBookmarks: BookmarksTreeNode[] = [
     {
       id: '2',
       parentId: '0',
+      index: 0,
       title: 'Other Bookmarks',
+      url: null,
+      dateAdded: null,
+      dateLastUsed: null,
       children: [
         {
           id: '3',
           parentId: '2',
+          index: 0,
           title: 'First child bookmark',
           url: 'http://child/bookmark/1/',
           dateAdded: 1,
+          dateLastUsed: null,
+          children: null,
         },
         {
           id: '4',
           parentId: '2',
+          index: 1,
           title: 'Second child bookmark',
           url: 'http://child/bookmark/2/',
           dateAdded: 3,
+          dateLastUsed: null,
+          children: null,
         },
         {
           id: '5',
           parentId: '2',
+          index: 2,
           title: 'Child folder',
+          url: null,
           dateAdded: 2,
+          dateLastUsed: null,
           children: [
             {
               id: '6',
               parentId: '5',
+              index: 0,
               title: 'Nested bookmark',
               url: 'http://nested/bookmark/',
               dateAdded: 4,
+              dateLastUsed: null,
+              children: null,
             },
           ],
         },
@@ -62,7 +78,7 @@
     document.body.innerHTML = window.trustedTypes!.emptyHTML;
 
     const bookmarksApi = new TestBookmarksApiProxy();
-    bookmarksApi.setFolders(structuredClone(folders));
+    bookmarksApi.setAllBookmarks(allBookmarks);
     BookmarksApiProxyImpl.setInstance(bookmarksApi);
 
     loadTimeData.overrideValues({
@@ -73,7 +89,7 @@
     new PowerBookmarksDragManager(delegate);
     document.body.appendChild(delegate);
 
-    await bookmarksApi.whenCalled('getFolders');
+    await bookmarksApi.whenCalled('getAllBookmarks');
     await flushTasks();
   });
 
diff --git a/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_edit_dialog_test.ts b/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_edit_dialog_test.ts
index f67ae05..b8a16195 100644
--- a/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_edit_dialog_test.ts
+++ b/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_edit_dialog_test.ts
@@ -4,6 +4,7 @@
 
 import 'chrome://bookmarks-side-panel.top-chrome/power_bookmarks_edit_dialog.js';
 
+import type {BookmarksTreeNode} from 'chrome://bookmarks-side-panel.top-chrome/bookmarks.mojom-webui.js';
 import {BookmarksApiProxyImpl} from 'chrome://bookmarks-side-panel.top-chrome/bookmarks_api_proxy.js';
 import type {PowerBookmarksEditDialogElement} from 'chrome://bookmarks-side-panel.top-chrome/power_bookmarks_edit_dialog.js';
 import {PowerBookmarksService} from 'chrome://bookmarks-side-panel.top-chrome/power_bookmarks_service.js';
@@ -21,47 +22,65 @@
   let bookmarksApi: TestBookmarksApiProxy;
   let delegate: TestPowerBookmarksDelegate;
   let service: PowerBookmarksService;
-
-  const folders: chrome.bookmarks.BookmarkTreeNode[] = [
+  const allBookmarks: BookmarksTreeNode[] = [
     {
       id: '2',
       parentId: '0',
+      index: 0,
       title: 'Other Bookmarks',
+      url: null,
+      dateAdded: null,
+      dateLastUsed: null,
       children: [
         {
           id: '3',
           parentId: '2',
+          index: 0,
           title: 'First child bookmark',
           url: 'http://child/bookmark/1/',
           dateAdded: 1,
+          dateLastUsed: null,
+          children: null,
         },
         {
           id: '4',
           parentId: '2',
+          index: 1,
           title: 'Second child bookmark',
           url: 'http://child/bookmark/2/',
           dateAdded: 3,
+          dateLastUsed: null,
+          children: null,
         },
         {
           id: '5',
           parentId: '2',
+          index: 2,
           title: 'Child folder',
+          url: null,
           dateAdded: 2,
+          dateLastUsed: null,
           children: [
             {
               id: '6',
               parentId: '5',
+              index: 0,
               title: 'Nested bookmark',
               url: 'http://nested/bookmark/',
               dateAdded: 4,
+              dateLastUsed: null,
+              children: null,
             },
           ],
         },
         {
-          id: '6',
+          id: '7',
           parentId: '2',
+          index: 3,
           title: 'Child folder 2',
+          url: null,
           dateAdded: 1,
+          dateLastUsed: null,
           children: [],
         },
       ],
@@ -72,7 +91,7 @@
     document.body.innerHTML = window.trustedTypes!.emptyHTML;
 
     bookmarksApi = new TestBookmarksApiProxy();
-    bookmarksApi.setFolders(structuredClone(folders));
+    bookmarksApi.setAllBookmarks(allBookmarks);
     BookmarksApiProxyImpl.setInstance(bookmarksApi);
 
     delegate = new TestPowerBookmarksDelegate();
diff --git a/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_list_test.ts b/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_list_test.ts
index e7af1ce..f592f0c 100644
--- a/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_list_test.ts
+++ b/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_list_test.ts
@@ -5,6 +5,7 @@
 import 'chrome://bookmarks-side-panel.top-chrome/power_bookmarks_list.js';
 
 import {ActionSource, SortOrder, ViewType} from 'chrome://bookmarks-side-panel.top-chrome/bookmarks.mojom-webui.js';
+import type {BookmarksTreeNode} from 'chrome://bookmarks-side-panel.top-chrome/bookmarks.mojom-webui.js';
 import {BookmarksApiProxyImpl} from 'chrome://bookmarks-side-panel.top-chrome/bookmarks_api_proxy.js';
 import type {PowerBookmarkRowElement} from 'chrome://bookmarks-side-panel.top-chrome/power_bookmark_row.js';
 import {NESTED_BOOKMARKS_BASE_MARGIN, NESTED_BOOKMARKS_MARGIN_PER_DEPTH} from 'chrome://bookmarks-side-panel.top-chrome/power_bookmark_row.js';
@@ -25,48 +26,68 @@
 import {fakeMetricsPrivate} from 'chrome://webui-test/metrics_test_support.js';
 import {flushTasks, waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
 import {TestMock} from 'chrome://webui-test/test_mock.js';
-import {eventToPromise} from 'chrome://webui-test/test_util.js';
+import {eventToPromise, microtasksFinished} from 'chrome://webui-test/test_util.js';
 
 import {TestBookmarksApiProxy} from './test_bookmarks_api_proxy.js';
 
-const FOLDERS: chrome.bookmarks.BookmarkTreeNode[] = [
+const FOLDERS: BookmarksTreeNode[] = [
   {
     id: '1',
     parentId: '0',
+    index: 0,
     title: 'Bookmarks Bar',
+    url: null,
+    dateAdded: null,
+    dateLastUsed: null,
     children: [],
   },
   {
     id: '2',
     parentId: '0',
     title: 'Other Bookmarks',
+    index: 1,
+    url: null,
+    dateAdded: null,
+    dateLastUsed: null,
     children: [
       {
         id: '3',
         parentId: '2',
+        index: 0,
         title: 'First child bookmark',
         url: 'http://child/bookmark/1/',
         dateAdded: 1,
+        dateLastUsed: null,
+        children: null,
       },
       {
         id: '4',
         parentId: '2',
+        index: 1,
         title: 'Second child bookmark',
         url: 'http://child/bookmark/2/',
         dateAdded: 3,
+        dateLastUsed: null,
+        children: null,
       },
       {
         id: '5',
         parentId: '2',
+        index: 2,
         title: 'Child folder',
+        url: null,
         dateAdded: 2,
+        dateLastUsed: null,
         children: [
           {
             id: '6',
             parentId: '5',
+            index: 0,
             title: 'Nested bookmark',
             url: 'http://nested/bookmark/',
             dateAdded: 4,
+            dateLastUsed: null,
+            children: null,
           },
         ],
       },
@@ -103,6 +124,11 @@
         '#addCurrentTabButton')!;
   }
 
+  function getAddNewFolderButton() {
+    return powerBookmarksList.shadowRoot!.querySelector<CrButtonElement>(
+        '.new-folder-row')!;
+  }
+
   function getBookmarkWithId(id: string): chrome.bookmarks.BookmarkTreeNode|
       undefined {
     return getBookmarks().find((bookmark) => bookmark.id === id);
@@ -174,7 +200,7 @@
     parentElement.appendChild(powerBookmarksList);
     document.body.appendChild(parentElement);
 
-    await bookmarksApi.whenCalled('getFolders');
+    await bookmarksApi.whenCalled('getAllBookmarks');
     await waitAfterNextRender(powerBookmarksList);
     flush();
   }
@@ -185,7 +211,7 @@
     metrics = fakeMetricsPrivate();
 
     bookmarksApi = new TestBookmarksApiProxy();
-    bookmarksApi.setFolders(structuredClone(FOLDERS));
+    bookmarksApi.setAllBookmarks(structuredClone(FOLDERS));
     BookmarksApiProxyImpl.setInstance(bookmarksApi);
 
     priceTrackingProxy.reset();
@@ -227,11 +253,11 @@
   });
 
   test('GetsAndShowsTopLevelBookmarks', () => {
-    assertEquals(1, bookmarksApi.getCallCount('getFolders'));
+    assertEquals(1, bookmarksApi.getCallCount('getAllBookmarks'));
     assertEquals(FOLDERS[1]!.children!.length + 1, getBookmarks().length);
   });
 
-  test('RebuildsKeyboardNavigationOnCreated', async () => {
+  test('RebuildsKeyboardNavigationOnBoomkmarkNodeAdded', async () => {
     await flushTasks();
 
     assertEquals(
@@ -242,14 +268,17 @@
         JSON.stringify(
             ['bookmark-1', 'bookmark-5', 'bookmark-4', 'bookmark-3']));
 
-    bookmarksApi.callbackRouter.onCreated.callListeners('999', {
+    bookmarksApi.callbackRouterRemote.onBookmarkNodeAdded({
       id: '999',
       title: 'New bookmark of current url',
       index: 0,
       parentId: FOLDERS[1]!.id,
-      url: powerBookmarksList.getCurrentUrlForTesting(),
+      url: powerBookmarksList.getCurrentUrlForTesting()!,
+      children: null,
+      dateAdded: null,
+      dateLastUsed: null,
     });
-
+    await microtasksFinished();
     await flushTasks();
 
     assertEquals(
@@ -277,8 +306,7 @@
         JSON.stringify(
             ['bookmark-1', 'bookmark-5', 'bookmark-4', 'bookmark-3']));
 
-    bookmarksApi.callbackRouter.onRemoved.callListeners('4');
-
+    bookmarksApi.callbackRouterRemote.onBookmarkNodesRemoved(['4']);
     await flushTasks();
     await waitAfterNextRender(powerBookmarksList);
 
@@ -302,13 +330,15 @@
             ['bookmark-1', 'bookmark-5', 'bookmark-4', 'bookmark-3']));
 
     const movedBookmark = FOLDERS[1]!.children![2]!.children![0]!;
-    bookmarksApi.callbackRouter.onMoved.callListeners(movedBookmark.id, {
-      index: 0,
-      parentId: FOLDERS[1]!.id,                   // Moving to other bookmarks.
-      oldParentId: FOLDERS[1]!.children![2]!.id,  // Moving from child folder.
-      oldIndex: 0,
-    });
-
+    assertTrue(!!movedBookmark);
+    bookmarksApi.callbackRouterRemote.onBookmarkNodeMoved(
+        /*oldParentId=*/ FOLDERS[1]!.children![2]!
+            .id,  // Moving from child folder.
+        /*oldIndex=*/ 0,
+        /*parentId=*/ FOLDERS[1]!.id,  // Moving to other bookmarks.
+        /*index=*/ 0,
+    );
+    await microtasksFinished();
     await flushTasks();
 
     assertEquals(
@@ -371,11 +401,9 @@
 
   test('UpdatesChangedBookmarks', async () => {
     const changedBookmark = FOLDERS[1]!.children![0]!;
-    bookmarksApi.callbackRouter.onChanged.callListeners(changedBookmark.id, {
-      title: 'New title',
-      url: 'http://new/url',
-    });
-    flush();
+    bookmarksApi.callbackRouterRemote.onBookmarkNodeChanged(
+        changedBookmark.id, 'New title', 'http://new/url');
+    await flushTasks();
 
     const bookmark = getBookmarkWithId('3');
     assertTrue(!!bookmark);
@@ -396,20 +424,16 @@
     assertEquals(0, getBookmarks().length);
 
     const changedBookmark = FOLDERS[1]!.children![0]!;
-    bookmarksApi.callbackRouter.onChanged.callListeners(changedBookmark.id, {
-      title: 'abcdef',
-      url: 'http://new/url',
-    });
-    flush();
+    bookmarksApi.callbackRouterRemote.onBookmarkNodeChanged(
+        changedBookmark.id, 'abcdef', 'http://new/url');
+    await flushTasks();
 
     // Bookmark matches search term and should display.
     assertEquals(1, getBookmarks().length);
 
-    bookmarksApi.callbackRouter.onChanged.callListeners(changedBookmark.id, {
-      title: 'New title',
-      url: 'http://new/url',
-    });
-    flush();
+    bookmarksApi.callbackRouterRemote.onBookmarkNodeChanged(
+        changedBookmark.id, 'New title', 'http://new/url');
+    await flushTasks();
 
     // Bookmark no longer matches search term and should not display.
     assertEquals(0, getBookmarks().length);
@@ -421,59 +445,81 @@
     assertFalse(btn.disabled);
   });
 
-  test('UpdatesAddTabButton', () => {
-    bookmarksApi.callbackRouter.onCreated.callListeners('999', {
+  test('UpdatesAddTabButton', async () => {
+    bookmarksApi.callbackRouterRemote.onBookmarkNodeAdded({
       id: '999',
       title: 'New bookmark of current url',
       index: 0,
       parentId: FOLDERS[1]!.id,
-      url: powerBookmarksList.getCurrentUrlForTesting(),
+      url: powerBookmarksList.getCurrentUrlForTesting()!,
+      children: null,
+      dateAdded: null,
+      dateLastUsed: null,
     });
-    flush();
+    await flushTasks();
 
     let btn = getAddTabButton();
     assertTrue(btn.disabled);
 
-    bookmarksApi.callbackRouter.onRemoved.callListeners('999');
-    flush();
+    bookmarksApi.callbackRouterRemote.onBookmarkNodesRemoved(['999']);
+    await flushTasks();
 
     btn = getAddTabButton();
     assertFalse(btn.disabled);
   });
 
-  test('AddsCreatedBookmark', () => {
-    bookmarksApi.callbackRouter.onCreated.callListeners('999', {
+  test('AddNewFolderClicked', async () => {
+    const addNewFolderButton = getAddNewFolderButton();
+    assertTrue(!!addNewFolderButton);
+    assertFalse(addNewFolderButton.disabled);
+
+    addNewFolderButton.click();
+    await bookmarksApi.whenCalled('createFolder');
+  });
+
+  test('AddsCreatedBookmark', async () => {
+    bookmarksApi.callbackRouterRemote.onBookmarkNodeAdded({
       id: '999',
       title: 'New bookmark',
       index: 0,
       parentId: FOLDERS[1]!.id,
       url: 'http://new/bookmark',
+      children: null,
+      dateAdded: null,
+      dateLastUsed: null,
     });
-    flush();
+    await flushTasks();
 
     const bookmarks = getBookmarks();
     assertEquals(5, bookmarks.length);
   });
 
-  test('AddsCreatedBookmarkForNewFolder', () => {
+  test('AddsCreatedBookmarkForNewFolder', async () => {
     // Create a new folder without a children array.
-    bookmarksApi.callbackRouter.onCreated.callListeners('1000', {
+    bookmarksApi.callbackRouterRemote.onBookmarkNodeAdded({
       id: '1000',
       title: 'New folder',
       index: 0,
       parentId: FOLDERS[1]!.id,
+      url: null,
+      children: null,
+      dateAdded: null,
+      dateLastUsed: null,
     });
-    flush();
+    await flushTasks();
 
     // Create a new bookmark within that folder.
-    bookmarksApi.callbackRouter.onCreated.callListeners('1001', {
+    bookmarksApi.callbackRouterRemote.onBookmarkNodeAdded({
       id: '1001',
       title: 'New bookmark in new folder',
       index: 0,
       parentId: '1000',
       url: 'http://google.com',
+      children: null,
+      dateAdded: null,
+      dateLastUsed: null,
     });
-    flush();
+    await flushTasks();
 
     const bookmarks = getBookmarks();
     assertEquals(5, bookmarks.length);
@@ -491,14 +537,17 @@
     assertEquals(1, getBookmarksInList(0).length);
     assertEquals(3, getBookmarksInList(1).length);
 
-    bookmarksApi.callbackRouter.onCreated.callListeners('123', {
+    bookmarksApi.callbackRouterRemote.onBookmarkNodeAdded({
       id: '123',
       title: 'New bookmark',
       index: 0,
       parentId: '5',
       url: 'http://new/bookmark',
+      children: null,
+      dateAdded: null,
+      dateLastUsed: null,
     });
-    flush();
+    await flushTasks();
 
     // New bookmark matches search term and is under active folder, gets
     // displayed in primary list
@@ -506,28 +555,34 @@
     assertEquals(2, getBookmarksInList(0).length);
     assertEquals(3, getBookmarksInList(1).length);
 
-    bookmarksApi.callbackRouter.onCreated.callListeners('456', {
+    bookmarksApi.callbackRouterRemote.onBookmarkNodeAdded({
       id: '456',
       title: 'foo',
       index: 0,
       parentId: FOLDERS[1]!.id,
       url: 'http://foo',
+      children: null,
+      dateAdded: null,
+      dateLastUsed: null,
     });
-    flush();
+    await flushTasks();
 
     // New bookmark does not match search term, doesn't get displayed
     assertFalse(!!getBookmarkWithId('456'));
     assertEquals(2, getBookmarksInList(0).length);
     assertEquals(3, getBookmarksInList(1).length);
 
-    bookmarksApi.callbackRouter.onCreated.callListeners('789', {
+    bookmarksApi.callbackRouterRemote.onBookmarkNodeAdded({
       id: '789',
       title: 'Bookmark',
       index: 0,
       parentId: FOLDERS[1]!.id,
       url: 'http://bookmark',
+      children: null,
+      dateAdded: null,
+      dateLastUsed: null,
     });
-    flush();
+    await flushTasks();
 
     // New bookmark matches search term and is not under active folder, gets
     // displayed in secondary list
@@ -536,15 +591,17 @@
     assertEquals(4, getBookmarksInList(1).length);
   });
 
-  test('MovesBookmarks', () => {
+  test('MovesBookmarks', async () => {
     const movedBookmark = FOLDERS[1]!.children![2]!.children![0]!;
-    bookmarksApi.callbackRouter.onMoved.callListeners(movedBookmark.id, {
-      index: 0,
-      parentId: FOLDERS[1]!.id,                   // Moving to other bookmarks.
-      oldParentId: FOLDERS[1]!.children![2]!.id,  // Moving from child folder.
-      oldIndex: 0,
-    });
-    flush();
+    assertTrue(!!movedBookmark);
+    bookmarksApi.callbackRouterRemote.onBookmarkNodeMoved(
+        /*oldParentId=*/ FOLDERS[1]!.children![2]!
+            .id,  // Moving from child folder.
+        /*oldIndex=*/ 0,
+        /*parentId=*/ FOLDERS[1]!.id,  // Moving to other bookmarks.
+        /*index=*/ 0,
+    );
+    await flushTasks();
 
     const bookmarks = getBookmarks();
     assertEquals(5, bookmarks.length);
@@ -554,24 +611,29 @@
     assertEquals(0, childFolder.children!.length);
   });
 
-  test('MovesBookmarksIntoNewFolder', () => {
+  test('MovesBookmarksIntoNewFolder', async () => {
     // Create a new folder without a children array.
-    bookmarksApi.callbackRouter.onCreated.callListeners('1000', {
+    bookmarksApi.callbackRouterRemote.onBookmarkNodeAdded({
       id: '1000',
       title: 'New folder',
       index: 0,
       parentId: FOLDERS[1]!.id,
+      url: null,
+      children: null,
+      dateAdded: null,
+      dateLastUsed: null,
     });
-    flush();
+    await flushTasks();
 
     const movedBookmark = FOLDERS[1]!.children![2]!.children![0]!;
-    bookmarksApi.callbackRouter.onMoved.callListeners(movedBookmark.id, {
-      index: 0,
-      parentId: '1000',
-      oldParentId: FOLDERS[1]!.children![2]!.id,
-      oldIndex: 0,
-    });
-    flush();
+    assertTrue(!!movedBookmark);
+    bookmarksApi.callbackRouterRemote.onBookmarkNodeMoved(
+        /*oldParentId=*/ FOLDERS[1]!.children![2]!.id,
+        /*oldIndex=*/ 0,
+        /*parentId=*/ '1000',
+        /*index=*/ 0,
+    );
+    await flushTasks();
 
     const newFolder = getBookmarkWithId('1000');
     assertTrue(!!newFolder);
@@ -588,26 +650,27 @@
 
     const movedBookmark = getBookmarkWithId('6');
     assertTrue(!!movedBookmark);
-    bookmarksApi.callbackRouter.onMoved.callListeners(movedBookmark.id, {
-      index: 0,
-      parentId: FOLDERS[1]!.id,                   // Moving to other bookmarks.
-      oldParentId: FOLDERS[1]!.children![2]!.id,  // Moving from child folder.
-      oldIndex: 0,
-    });
-    flush();
+    bookmarksApi.callbackRouterRemote.onBookmarkNodeMoved(
+        /*oldParentId=*/ FOLDERS[1]!.children![2]!
+            .id,  // Moving from child folder.
+        /*oldIndex=*/ 0,
+        /*parentId=*/ FOLDERS[1]!.id,  // Moving to other bookmarks.
+        /*index=*/ 0,
+    );
+    await flushTasks();
 
     // Moved bookmark is no longer in active folder, should move from primary
     // to secondary list.
     assertEquals(0, getBookmarksInList(0).length);
     assertEquals(4, getBookmarksInList(1).length);
 
-    bookmarksApi.callbackRouter.onMoved.callListeners(movedBookmark.id, {
-      index: 0,
-      parentId: FOLDERS[1]!.children![2]!.id,  // Moving to child folder.
-      oldParentId: FOLDERS[1]!.id,             // Moving from other bookmarks.
-      oldIndex: 0,
-    });
-    flush();
+    bookmarksApi.callbackRouterRemote.onBookmarkNodeMoved(
+        /*oldParentId=*/ FOLDERS[1]!.id,  // Moving from other bookmarks.
+        /*oldIndex=*/ 0,
+        /*parentId=*/ FOLDERS[1]!.children![2]!.id,  // Moving to child folder.
+        /*index=*/ 0,
+    );
+    await flushTasks();
 
     // Moved bookmark is now in active folder, should move from secondary
     // to primary list.
@@ -615,11 +678,11 @@
     assertEquals(3, getBookmarksInList(1).length);
   });
 
-  test('RemovesBookmark', () => {
+  test('RemovesBookmark', async () => {
     const originalShownBookmarkCount = getBookmarks().length;
 
-    bookmarksApi.callbackRouter.onRemoved.callListeners('3');
-    flush();
+    bookmarksApi.callbackRouterRemote.onBookmarkNodesRemoved(['3']);
+    await flushTasks();
 
     const removedBookmark = getBookmarkWithId('3');
     assertTrue(!removedBookmark);
@@ -948,7 +1011,7 @@
     parentElement.appendChild(powerBookmarksList);
     document.body.appendChild(parentElement);
 
-    await bookmarksApi.whenCalled('getFolders');
+    await bookmarksApi.whenCalled('getAllBookmarks');
     await waitAfterNextRender(powerBookmarksList);
     flush();
   }
@@ -957,7 +1020,7 @@
     document.body.innerHTML = window.trustedTypes!.emptyHTML;
 
     bookmarksApi = new TestBookmarksApiProxy();
-    bookmarksApi.setFolders(structuredClone(FOLDERS));
+    bookmarksApi.setAllBookmarks(structuredClone(FOLDERS));
     BookmarksApiProxyImpl.setInstance(bookmarksApi);
 
     priceTrackingProxy.reset();
@@ -1107,7 +1170,7 @@
     parentElement.appendChild(powerBookmarksList);
     document.body.appendChild(parentElement);
 
-    await bookmarksApi.whenCalled('getFolders');
+    await bookmarksApi.whenCalled('getAllBookmarks');
     await waitAfterNextRender(powerBookmarksList);
     flush();
   }
@@ -1116,7 +1179,7 @@
     document.body.innerHTML = window.trustedTypes!.emptyHTML;
 
     bookmarksApi = new TestBookmarksApiProxy();
-    bookmarksApi.setFolders(structuredClone(FOLDERS));
+    bookmarksApi.setAllBookmarks(structuredClone(FOLDERS));
     BookmarksApiProxyImpl.setInstance(bookmarksApi);
 
     priceTrackingProxy.reset();
diff --git a/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_service_test.ts b/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_service_test.ts
index 5cdada1..9bfa2f4 100644
--- a/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_service_test.ts
+++ b/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_service_test.ts
@@ -5,6 +5,7 @@
 import 'chrome://bookmarks-side-panel.top-chrome/power_bookmarks_list.js';
 
 import type {BookmarkProductInfo} from '//resources/cr_components/commerce/shared.mojom-webui.js';
+import type {BookmarksTreeNode} from 'chrome://bookmarks-side-panel.top-chrome/bookmarks.mojom-webui.js';
 import {BookmarksApiProxyImpl} from 'chrome://bookmarks-side-panel.top-chrome/bookmarks_api_proxy.js';
 import {PowerBookmarksService} from 'chrome://bookmarks-side-panel.top-chrome/power_bookmarks_service.js';
 import {ShoppingServiceBrowserProxyImpl} from 'chrome://resources/cr_components/commerce/shopping_service_browser_proxy.js';
@@ -12,7 +13,7 @@
 import {PageImageServiceHandlerRemote} from 'chrome://resources/cr_components/page_image_service/page_image_service.mojom-webui.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {PluralStringProxyImpl} from 'chrome://resources/js/plural_string_proxy.js';
-import {assertEquals} from 'chrome://webui-test/chai_assert.js';
+import {assertDeepEquals, assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
 import {TestMock} from 'chrome://webui-test/test_mock.js';
 import {TestPluralStringProxy} from 'chrome://webui-test/test_plural_string_proxy.js';
@@ -58,40 +59,54 @@
   let imageServiceHandler: TestMock<PageImageServiceHandlerRemote>&
       PageImageServiceHandlerRemote;
 
-  const folders: chrome.bookmarks.BookmarkTreeNode[] = [
+  const folders: BookmarksTreeNode[] = [
     {
       id: '2',
       parentId: '0',
+      index: 0,
       title: 'Other Bookmarks',
+      url: null,
+      dateAdded: null,
+      dateLastUsed: null,
       children: [
         {
           id: '3',
           parentId: '2',
+          index: 0,
           title: 'First child bookmark',
           url: 'http://child/bookmark/1/',
           dateAdded: 1,
           dateLastUsed: 4,
+          children: null,
         },
         {
           id: '4',
           parentId: '2',
+          index: 1,
           title: 'Second child bookmark',
           url: 'http://child/bookmark/2/',
           dateAdded: 3,
           dateLastUsed: 3,
+          children: null,
         },
         {
           id: '5',
           parentId: '2',
+          index: 2,
           title: 'Child folder',
+          url: null,
           dateAdded: 2,
+          dateLastUsed: null,
           children: [
             {
               id: '6',
               parentId: '5',
+              index: 0,
               title: 'Nested bookmark',
               url: 'http://nested/bookmark/',
               dateAdded: 4,
+              dateLastUsed: null,
+              children: null,
             },
           ],
         },
@@ -101,61 +116,84 @@
 
   // More complex folder structure, including a more extensive hierarchy and
   // inverted dateAdded between parents/children. Not used by default in tests.
-  const complexFolders: chrome.bookmarks.BookmarkTreeNode[] = [
+  const complexAllBookmarks: BookmarksTreeNode[] = [
     {
       id: '2',
       parentId: '0',
+      index: 0,
       title: 'Other Bookmarks',
+      url: null,
+      dateAdded: null,
+      dateLastUsed: null,
       children: [
         {
           id: '3',
           parentId: '2',
+          index: 0,
           title: 'Child folder',
+          url: null,
           dateAdded: 4,
+          dateLastUsed: null,
           children: [
             {
               id: '7',
               parentId: '3',
+              index: 0,
               title: 'Nested bookmark',
               url: 'http://nested/bookmark/',
               dateAdded: 1,
               dateLastUsed: 10,
+              children: null,
             },
           ],
         },
         {
           id: '4',
           parentId: '2',
+          index: 1,
           title: 'Child folder',
+          url: null,
           dateAdded: 2,
+          dateLastUsed: null,
           children: [
             {
               id: '8',
               parentId: '4',
+              index: 0,
               title: 'Nested bookmark',
               url: 'http://nested/bookmark/',
               dateAdded: 5,
               dateLastUsed: 6,
+              children: null,
             },
           ],
         },
         {
           id: '5',
           parentId: '2',
+          index: 2,
           title: 'Child folder',
+          url: null,
           dateAdded: 6,
+          dateLastUsed: null,
           children: [
             {
               id: '10',
               parentId: '5',
+              index: 0,
               title: 'Child folder',
+              url: null,
               dateAdded: 8,
+              dateLastUsed: null,
               children: [
                 {
                   id: '13',
                   parentId: '10',
+                  index: 0,
                   title: 'Nested folder',
+                  url: null,
                   dateAdded: 0,
+                  dateLastUsed: null,
                   children: [],
                 },
               ],
@@ -165,22 +203,30 @@
         {
           id: '6',
           parentId: '2',
+          index: 3,
           title: 'Child folder',
+          url: null,
           dateAdded: 3,
+          dateLastUsed: null,
           children: [
             {
               id: '12',
               parentId: '6',
+              index: 0,
               title: 'Child folder',
+              url: null,
               dateAdded: 3,
+              dateLastUsed: null,
               children: [
                 {
                   id: '14',
                   parentId: '12',
+                  index: 0,
                   title: 'Nested bookmark',
                   url: 'http://nested/bookmark/',
                   dateAdded: 9,
                   dateLastUsed: 1,
+                  children: null,
                 },
               ],
             },
@@ -194,7 +240,7 @@
     document.body.innerHTML = window.trustedTypes!.emptyHTML;
 
     bookmarksApi = new TestBookmarksApiProxy();
-    bookmarksApi.setFolders(structuredClone(folders));
+    bookmarksApi.setAllBookmarks(folders);
     BookmarksApiProxyImpl.setInstance(bookmarksApi);
 
     shoppingServiceApi = new TestShoppingServiceApiProxy();
@@ -265,7 +311,7 @@
   });
 
   test('SortsByNewestWithComplexDescendants', async () => {
-    bookmarksApi.setFolders(structuredClone(complexFolders));
+    bookmarksApi.setAllBookmarks(complexAllBookmarks);
     service.startListening();
 
     await delegate.whenCalled('onBookmarksLoaded');
@@ -287,7 +333,7 @@
   });
 
   test('SortsByOldestWithComplexDescendants', async () => {
-    bookmarksApi.setFolders(structuredClone(complexFolders));
+    bookmarksApi.setAllBookmarks(complexAllBookmarks);
     service.startListening();
 
     await delegate.whenCalled('onBookmarksLoaded');
@@ -309,7 +355,7 @@
   });
 
   test('SortsByLastOpenedWithComplexDescendants', async () => {
-    bookmarksApi.setFolders(structuredClone(complexFolders));
+    bookmarksApi.setAllBookmarks(complexAllBookmarks);
     service.startListening();
 
     await delegate.whenCalled('onBookmarksLoaded');
@@ -338,44 +384,51 @@
     assertEquals(sortedBookmarks[2]!.id, '3');
   });
 
-  test('CallsOnBookmarkChanged', () => {
+  test('CallsOnBookmarkChanged', async () => {
     const changedBookmark = folders[0]!.children![0]!;
-    bookmarksApi.callbackRouter.onChanged.callListeners(changedBookmark.id, {
-      title: 'New title',
-      url: 'http://new/url',
-    });
+    bookmarksApi.callbackRouterRemote.onBookmarkNodeChanged(
+        changedBookmark.id, 'New title', 'http://new/url');
+    await flushTasks();
 
     assertEquals(delegate.getCallCount('onBookmarkChanged'), 1);
   });
 
-  test('CallsOnBookmarkCreated', () => {
-    bookmarksApi.callbackRouter.onCreated.callListeners('999', {
+  test('CallsOnBookmarkAdded', async () => {
+    bookmarksApi.callbackRouterRemote.onBookmarkNodeAdded({
       id: '999',
       title: 'New bookmark',
       index: 0,
       parentId: folders[0]!.id,
       url: 'http://new/bookmark',
+      children: null,
+      dateAdded: null,
+      dateLastUsed: null,
     });
+    await flushTasks();
 
-    assertEquals(delegate.getCallCount('onBookmarkCreated'), 1);
+    assertEquals(delegate.getCallCount('onBookmarkAdded'), 1);
   });
 
-  test('CallsOnBookmarkMoved', () => {
+  test('CallsOnBookmarkMoved', async () => {
     const movedBookmark = folders[0]!.children![2]!.children![0]!;
-    bookmarksApi.callbackRouter.onMoved.callListeners(movedBookmark.id, {
-      index: 0,
-      parentId: folders[0]!.id,                   // Moving to other bookmarks.
-      oldParentId: folders[0]!.children![2]!.id,  // Moving from child folder.
-      oldIndex: 0,
-    });
+    assertTrue(!!movedBookmark);
+    bookmarksApi.callbackRouterRemote.onBookmarkNodeMoved(
+        /*oldParentId=*/ folders[0]!.children![2]!
+            .id,  // Moving from child folder.
+        /*oldIndex=*/ 0,
+        /*parentId=*/ folders[0]!.id,  // Moving to other bookmarks.
+        /*index=*/ 0,
+    );
+    await flushTasks();
 
     assertEquals(delegate.getCallCount('onBookmarkMoved'), 1);
   });
 
-  test('CallsOnBookmarkRemoved', () => {
-    bookmarksApi.callbackRouter.onRemoved.callListeners('4');
+  test('CallsOnBookmarkNodesRemoved', async () => {
+    bookmarksApi.callbackRouterRemote.onBookmarkNodesRemoved(['3', '4']);
+    await flushTasks();
 
-    assertEquals(delegate.getCallCount('onBookmarkRemoved'), 1);
+    assertEquals(delegate.getCallCount('onBookmarkRemoved'), 2);
   });
 
   test('FindsBookmarkWithId', () => {
@@ -407,4 +460,19 @@
     await flushTasks();
     assertEquals(imageServiceHandler.getCallCount('getPageImageUrl'), 3);
   });
+
+  test('OnBookmarkParentFolderChildrenReordered', async () => {
+    const folder = service.findBookmarkWithId('2')!;
+    const b3 = service.findBookmarkWithId('3')!;
+    const b4 = service.findBookmarkWithId('4')!;
+    const b5 = service.findBookmarkWithId('5')!;
+
+    assertDeepEquals(folder.children!, [b3, b4, b5]);
+
+    bookmarksApi.callbackRouterRemote.onBookmarkParentFolderChildrenReordered(
+        '2', ['4', '5', '3']);
+    await flushTasks();
+
+    assertDeepEquals(folder.children!, [b4, b5, b3]);
+  });
 });
diff --git a/chrome/test/data/webui/side_panel/bookmarks/test_bookmarks_api_proxy.ts b/chrome/test/data/webui/side_panel/bookmarks/test_bookmarks_api_proxy.ts
index d1bcc58..cc0db1a 100644
--- a/chrome/test/data/webui/side_panel/bookmarks/test_bookmarks_api_proxy.ts
+++ b/chrome/test/data/webui/side_panel/bookmarks/test_bookmarks_api_proxy.ts
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import type {ActionSource, SortOrder, ViewType} from 'chrome://bookmarks-side-panel.top-chrome/bookmarks.mojom-webui.js';
+import type {ActionSource, BookmarksPageRemote, BookmarksTreeNode, SortOrder, ViewType} from 'chrome://bookmarks-side-panel.top-chrome/bookmarks.mojom-webui.js';
+import {BookmarksPageCallbackRouter} from 'chrome://bookmarks-side-panel.top-chrome/bookmarks.mojom-webui.js';
 import type {BookmarksApiProxy} from 'chrome://bookmarks-side-panel.top-chrome/bookmarks_api_proxy.js';
 import type {ClickModifiers} from 'chrome://resources/mojo/ui/base/mojom/window_open_disposition.mojom-webui.js';
 import {FakeChromeEvent} from 'chrome://webui-test/fake_chrome_event.js';
@@ -10,13 +11,11 @@
 
 export class TestBookmarksApiProxy extends TestBrowserProxy implements
     BookmarksApiProxy {
-  private folders_: chrome.bookmarks.BookmarkTreeNode[] = [];
+  private allBookmarks_: BookmarksTreeNode[] = [];
+  pageCallbackRouter: BookmarksPageCallbackRouter;
+  callbackRouterRemote: BookmarksPageRemote;
+
   callbackRouter: {
-    onChanged: FakeChromeEvent,
-    onChildrenReordered: FakeChromeEvent,
-    onCreated: FakeChromeEvent,
-    onMoved: FakeChromeEvent,
-    onRemoved: FakeChromeEvent,
     onTabActivated: FakeChromeEvent,
     onTabUpdated: FakeChromeEvent,
   };
@@ -24,10 +23,8 @@
   constructor() {
     super([
       'getActiveUrl',
-      'getFolders',
       'bookmarkCurrentTabInFolder',
       'openBookmark',
-      'cutBookmark',
       'contextMenuOpenBookmarkInNewTab',
       'contextMenuOpenBookmarkInNewWindow',
       'contextMenuOpenBookmarkInIncognitoWindow',
@@ -37,28 +34,26 @@
       'contextMenuAddToBookmarksBar',
       'contextMenuRemoveFromBookmarksBar',
       'contextMenuDelete',
-      'copyBookmark',
       'createFolder',
       'editBookmarks',
       'deleteBookmarks',
-      'pasteToBookmark',
       'renameBookmark',
       'setSortOrder',
       'setViewType',
       'showContextMenu',
       'showUi',
       'undo',
+      'getAllBookmarks',
     ]);
 
     this.callbackRouter = {
-      onChanged: new FakeChromeEvent(),
-      onChildrenReordered: new FakeChromeEvent(),
-      onCreated: new FakeChromeEvent(),
-      onMoved: new FakeChromeEvent(),
-      onRemoved: new FakeChromeEvent(),
       onTabActivated: new FakeChromeEvent(),
       onTabUpdated: new FakeChromeEvent(),
     };
+
+    this.pageCallbackRouter = new BookmarksPageCallbackRouter();
+    this.callbackRouterRemote =
+        this.pageCallbackRouter.$.bindNewPipeAndPassRemote();
   }
 
   getActiveUrl() {
@@ -66,11 +61,6 @@
     return Promise.resolve('http://www.test.com');
   }
 
-  getFolders() {
-    this.methodCalled('getFolders');
-    return Promise.resolve(this.folders_);
-  }
-
   bookmarkCurrentTabInFolder() {
     this.methodCalled('bookmarkCurrentTabInFolder');
   }
@@ -81,10 +71,6 @@
     this.methodCalled('openBookmark', id, depth, clickModifiers, source);
   }
 
-  setFolders(folders: chrome.bookmarks.BookmarkTreeNode[]) {
-    this.folders_ = folders;
-  }
-
   contextMenuOpenBookmarkInNewTab(ids: string[], source: ActionSource) {
     this.methodCalled('contextMenuOpenBookmarkInNewTab', ids, source);
   }
@@ -128,9 +114,9 @@
   }
 
   createFolder(parentId: string, title: string):
-      Promise<chrome.bookmarks.BookmarkTreeNode> {
+      Promise<{newFolderId: string}> {
     this.methodCalled('createFolder', parentId, title);
-    return Promise.resolve({id: '0', title: 'foo'});
+    return Promise.resolve({newFolderId: '0'});
   }
 
   cutBookmark(id: string) {
@@ -176,4 +162,13 @@
   undo() {
     this.methodCalled('undo');
   }
+
+  setAllBookmarks(allBookmarks: BookmarksTreeNode[]) {
+    this.allBookmarks_ = allBookmarks;
+  }
+
+  getAllBookmarks(): Promise<{nodes: BookmarksTreeNode[]}> {
+    this.methodCalled('getAllBookmarks');
+    return Promise.resolve({nodes: this.allBookmarks_});
+  }
 }
diff --git a/chrome/test/data/webui/side_panel/bookmarks/test_power_bookmarks_delegate.ts b/chrome/test/data/webui/side_panel/bookmarks/test_power_bookmarks_delegate.ts
index bb1dec8b..816c6e3 100644
--- a/chrome/test/data/webui/side_panel/bookmarks/test_power_bookmarks_delegate.ts
+++ b/chrome/test/data/webui/side_panel/bookmarks/test_power_bookmarks_delegate.ts
@@ -12,7 +12,7 @@
       'setImageUrl',
       'onBookmarksLoaded',
       'onBookmarkChanged',
-      'onBookmarkCreated',
+      'onBookmarkAdded',
       'onBookmarkMoved',
       'onBookmarkRemoved',
       'getTrackedProductInfos',
@@ -34,14 +34,14 @@
     this.methodCalled('onBookmarksLoaded');
   }
 
-  onBookmarkChanged(id: string, changedInfo: chrome.bookmarks.ChangeInfo) {
-    this.methodCalled('onBookmarkChanged', id, changedInfo);
+  onBookmarkChanged(id: string) {
+    this.methodCalled('onBookmarkChanged', id);
   }
 
-  onBookmarkCreated(
+  onBookmarkAdded(
       bookmark: chrome.bookmarks.BookmarkTreeNode,
       parent: chrome.bookmarks.BookmarkTreeNode) {
-    this.methodCalled('onBookmarkCreated', bookmark, parent);
+    this.methodCalled('onBookmarkAdded', bookmark, parent);
   }
 
   onBookmarkMoved(
diff --git a/chromecast/starboard/chromecast/BUILD.gn b/chromecast/starboard/chromecast/BUILD.gn
index ae81dd8..2dc95dfd 100644
--- a/chromecast/starboard/chromecast/BUILD.gn
+++ b/chromecast/starboard/chromecast/BUILD.gn
@@ -9,6 +9,7 @@
   cast_test_group("starboard_adapter_tests") {
     tests = [
       "//chromecast/starboard/chromecast/events:starboard_event_source_test",
+      "//chromecast/starboard/chromecast/starboard_adapter:cast_starboard_api_adapter_test",
     ]
   }
 }
diff --git a/chromecast/starboard/chromecast/starboard_adapter/BUILD.gn b/chromecast/starboard/chromecast/starboard_adapter/BUILD.gn
index b965381..eb2d960a 100644
--- a/chromecast/starboard/chromecast/starboard_adapter/BUILD.gn
+++ b/chromecast/starboard/chromecast/starboard_adapter/BUILD.gn
@@ -4,6 +4,7 @@
 
 import("//chromecast/chromecast.gni")
 import("//chromecast/starboard/starboard.gni")
+import("//testing/test.gni")
 
 config("public_config") {
   include_dirs =
@@ -22,7 +23,10 @@
 
 source_set("starboard_adapter_static") {
   sources = []
-  public_deps = [ ":starboard_adapter_public" ]
+  public_deps = [
+    ":starboard_adapter_public",
+    "//base",
+  ]
 
   if (remove_starboard_headers) {
     sources += [ "src/cast_starboard_api_adapter_dummy.cc" ]
@@ -31,10 +35,7 @@
       "src/cast_starboard_api_adapter_impl.cc",
       "src/cast_starboard_api_adapter_impl.h",
     ]
-    public_deps += [
-      "//chromecast/starboard/chromecast/starboard_cast_api",
-      "//chromecast/starboard/chromecast/starboard_cast_dummy:cast_starboard_api",
-    ]
+    public_deps += [ "//chromecast/starboard/chromecast/starboard_cast_api" ]
   }
 
   # TODO(riazantsevv@): To implement this in a better way.
@@ -44,9 +45,29 @@
 if (starboard_graphics_is_shared) {
   shared_library("starboard_adapter") {
     public_deps = [ ":starboard_adapter_static" ]
+    if (!remove_starboard_headers) {
+      public_deps += [ "//chromecast/starboard/chromecast/starboard_cast_dummy:cast_starboard_api" ]
+    }
   }
 } else {
   source_set("starboard_adapter") {
     public_deps = [ ":starboard_adapter_static" ]
+    if (!remove_starboard_headers) {
+      public_deps += [ "//chromecast/starboard/chromecast/starboard_cast_dummy:cast_starboard_api" ]
+    }
+  }
+}
+
+if (!remove_starboard_headers) {
+  test("cast_starboard_api_adapter_test") {
+    sources = [ "src/cast_starboard_api_adapter_test.cc" ]
+    deps = [
+      ":starboard_adapter_static",
+      "//base/test:run_all_unittests",
+      "//base/test:test_support",
+      "//chromecast/starboard/chromecast/starboard_cast_api",
+      "//testing/gmock",
+      "//testing/gtest",
+    ]
   }
 }
diff --git a/chromecast/starboard/chromecast/starboard_adapter/public/cast_starboard_api_adapter.h b/chromecast/starboard/chromecast/starboard_adapter/public/cast_starboard_api_adapter.h
index 5be3284f..ee2aec8 100644
--- a/chromecast/starboard/chromecast/starboard_adapter/public/cast_starboard_api_adapter.h
+++ b/chromecast/starboard/chromecast/starboard_adapter/public/cast_starboard_api_adapter.h
@@ -26,22 +26,20 @@
 // which is a C-style interface implemented in an external library. The primary
 // purpose of CastStarboardApiAdapter is to managage the lifecycle of the
 // external library, which expects to always be initialized before use and only
-// have a single instance.
+// have a single instance. The API is only guaranteed to be initialized if
+// there are non-zero subscribers.
 class __attribute__((visibility("default"))) CastStarboardApiAdapter {
  public:
   static CastStarboardApiAdapter* GetInstance();
 
   virtual ~CastStarboardApiAdapter() = default;
 
-  // Ensures that the CastStarboardApi is initialized. Callers should invoke
-  // this before any other functions.
-  virtual bool EnsureInitialized() = 0;
-
   // When Starboard events occur, `callback` will be called with `context`, an
   // integer corresponding to the SbEventType, and a void* containing the data
   // for the event (which may be null, since some events do not contain data).
   // The `callback` must be thread safe, i.e. it will not automatically be
-  // posted to the same thread on which Subscribe was called.
+  // posted to the same thread on which Subscribe was called. The `callback`
+  // may be `nullptr` if the consumer does not wish to receive callbacks.
   virtual void Subscribe(void* context,
                          void (*callback)(void* context,
                                           const SbEvent* event)) = 0;
diff --git a/chromecast/starboard/chromecast/starboard_adapter/src/cast_starboard_api_adapter_impl.cc b/chromecast/starboard/chromecast/starboard_adapter/src/cast_starboard_api_adapter_impl.cc
index c0c6a18d..c6f9c82 100644
--- a/chromecast/starboard/chromecast/starboard_adapter/src/cast_starboard_api_adapter_impl.cc
+++ b/chromecast/starboard/chromecast/starboard_adapter/src/cast_starboard_api_adapter_impl.cc
@@ -4,6 +4,10 @@
 
 #include "cast_starboard_api_adapter_impl.h"
 
+#include "base/at_exit.h"
+#include "base/functional/bind.h"
+#include "base/logging.h"
+
 // TODO(b/333961720): remove all the macros in this file and split the impl into
 // two different classes: one for SB 15+, one for older versions of starboard.
 // Only include the relevant one in the BUILD.gn file.
@@ -14,27 +18,55 @@
 #endif  // SB_API_VERSION >= 15
 
 namespace chromecast {
+
 namespace {
-CastStarboardApiAdapterImpl* GetImpl() {
-  static CastStarboardApiAdapterImpl* starboard_adapter =
-      new CastStarboardApiAdapterImpl();
-  return starboard_adapter;
+
+CastStarboardApiAdapterImpl* g_instance = nullptr;
+std::mutex g_instance_mutex;
+
+void DeleteInstance() {
+  std::unique_lock<std::mutex> lock(g_instance_mutex);
+  if (g_instance) {
+    delete g_instance;
+  }
 }
+
 }  // namespace
 
 CastStarboardApiAdapter* CastStarboardApiAdapter::GetInstance() {
-  return GetImpl();
+  // Perform a lazy check, if this is already initialized we can skip checking
+  // inits.
+  if (!g_instance) {
+    // If we do not have an instance, we must re-validate once we have acquired
+    // the mutex that it was not already constructed.
+    std::unique_lock<std::mutex> lock(g_instance_mutex);
+    // The instance is assigned by the class's constructor.
+    if (!g_instance) {
+      new CastStarboardApiAdapterImpl();
+
+      // Since OzonePlatform* is always orphaned, a handle to CastStarboardApi
+      // is still held by CastEglPlatformStarboard rather than being cleaned up
+      // by the last Unsubscribe. Artificially clean it up at process exit.
+      base::AtExitManager::RegisterTask(base::BindOnce(DeleteInstance));
+    }
+  }
+
+  return g_instance;
 }
 
-#if SB_API_VERSION >= 15
 CastStarboardApiAdapterImpl::CastStarboardApiAdapterImpl()
-    : init_f_(init_p_.get_future()), initialized_(false) {}
-#else   // SB_API_VERSION >=15
-CastStarboardApiAdapterImpl::CastStarboardApiAdapterImpl()
-    : initialized_(false) {}
-#endif  // SB_API_VERSION >= 15
+    : initialized_(false) {
+  CHECK(!g_instance);
+  g_instance = this;
+}
 
-CastStarboardApiAdapterImpl::~CastStarboardApiAdapterImpl() {}
+CastStarboardApiAdapterImpl::~CastStarboardApiAdapterImpl() {
+  if (initialized_) {
+    Release();
+  }
+
+  g_instance = nullptr;
+}
 
 SbEglNativeDisplayType CastStarboardApiAdapterImpl::GetEglNativeDisplayType() {
   return SB_EGL_DEFAULT_DISPLAY;
@@ -42,10 +74,9 @@
 
 // static
 void CastStarboardApiAdapterImpl::SbEventHandle(const SbEvent* event) {
-  GetImpl()->SbEventHandleInternal(event);
+  g_instance->SbEventHandleInternal(event);
 }
 
-#if SB_API_VERSION >= 15
 void CastStarboardApiAdapterImpl::SbEventHandleInternal(const SbEvent* event) {
   // If multiple instances of Starboard become supported, |event->window| may
   // need to be checked here for some types before propagating.
@@ -53,59 +84,68 @@
     case kSbEventTypeStart:
       init_p_.set_value(true);
       break;
+    case kSbEventTypeStop:
+      init_p_.set_value(false);
+      break;
     default:
       for (const auto p : subscribers_) {
-        p.second(p.first, event);
+        if (p.second) {
+          p.second(p.first, event);
+        }
       }
       break;
   }
 }
-#else   // SB_API_VERSION >=15
-void CastStarboardApiAdapterImpl::SbEventHandleInternal(const SbEvent* event) {
-  std::lock_guard<decltype(lock_)> lock(lock_);
-  for (const auto p : subscribers_) {
-    p.second(p.first, event);
-  }
-}
-#endif  // SB_API_VERSION >= 15
+
+void CastStarboardApiAdapterImpl::Initialize() {
+  init_p_ = {};
 
 #if SB_API_VERSION >= 15
-bool CastStarboardApiAdapterImpl::EnsureInitialized() {
-  std::lock_guard<decltype(lock_)> lock(lock_);
-  if (initialized_) {
-    return true;
-  }
-
   sb_main_ = std::make_unique<std::thread>(
       &SbRunStarboardMain, /*argc=*/0, /*argv=*/nullptr,
       &CastStarboardApiAdapterImpl::SbEventHandle);
   sb_main_->detach();
-  initialized_ = init_f_.get();
-  return initialized_;
-}
 #else   // SB_API_VERSION >=15
-bool CastStarboardApiAdapterImpl::EnsureInitialized() {
-  std::lock_guard<decltype(lock_)> lock(lock_);
-  if (initialized_) {
-    return true;
-  }
-
   CastStarboardApiInitialize(/*argc=*/0, /*argv=*/nullptr,
                              &CastStarboardApiAdapterImpl::SbEventHandle);
-  initialized_ = true;
-  return true;
-}
 #endif  // SB_API_VERSION >= 15
+  init_f_ = init_p_.get_future();
+  initialized_ = init_f_.get();
+}
+
+void CastStarboardApiAdapterImpl::Release() {
+  {
+    std::lock_guard<decltype(lock_)> lock(lock_);
+    subscribers_.clear();
+  }
+
+  init_p_ = {};
+#if SB_API_VERSION >= 15
+  SbSystemRequestStop(0);
+#else   // SB_API_VERSION >=15
+  CastStarboardApiFinalize();
+#endif  // SB_API_VERSION >= 15
+  init_f_ = init_p_.get_future();
+  initialized_ = init_f_.get();
+}
 
 void CastStarboardApiAdapterImpl::Subscribe(void* context,
                                             CastStarboardApiAdapterImplCB cb) {
   std::lock_guard<decltype(lock_)> lock(lock_);
+  if (!initialized_) {
+    Initialize();
+  }
   subscribers_.insert({context, cb});
 }
 
 void CastStarboardApiAdapterImpl::Unsubscribe(void* context) {
-  std::lock_guard<decltype(lock_)> lock(lock_);
-  subscribers_.erase(context);
+  {
+    std::lock_guard<decltype(lock_)> lock(lock_);
+    subscribers_.erase(context);
+  }
+  // Defer Release() until the destructor is called.
+  // This helps simplify the complexity around Unsubscribe and AtExit calls
+  // calling at the same time.
 }
 
 SbWindow CastStarboardApiAdapterImpl::GetWindow(
diff --git a/chromecast/starboard/chromecast/starboard_adapter/src/cast_starboard_api_adapter_impl.h b/chromecast/starboard/chromecast/starboard_adapter/src/cast_starboard_api_adapter_impl.h
index 1b8917ac..fe8a334 100644
--- a/chromecast/starboard/chromecast/starboard_adapter/src/cast_starboard_api_adapter_impl.h
+++ b/chromecast/starboard/chromecast/starboard_adapter/src/cast_starboard_api_adapter_impl.h
@@ -5,13 +5,10 @@
 #ifndef CHROMECAST_STARBOARD_CHROMECAST_STARBOARD_ADAPTER_SRC_CAST_STARBOARD_API_ADAPTER_IMPL_H_
 #define CHROMECAST_STARBOARD_CHROMECAST_STARBOARD_ADAPTER_SRC_CAST_STARBOARD_API_ADAPTER_IMPL_H_
 
-#include <mutex>
-#include <unordered_map>
-
-#if SB_API_VERSION >= 15
 #include <future>
+#include <mutex>
 #include <thread>
-#endif  // SB_API_VERSION >= 15
+#include <unordered_map>
 
 #include "chromecast/starboard/chromecast/starboard_adapter/public/cast_starboard_api_adapter.h"
 
@@ -34,9 +31,10 @@
 
  private:
   void SbEventHandleInternal(const SbEvent* event);
+  void Initialize();
+  void Release();
 
   // CastStarboardApiAdapter implementation:
-  bool EnsureInitialized() override;
   void Subscribe(void* context,
                  CastStarboardApiAdapterImplCB callback) override;
   void Unsubscribe(void* context) override;
@@ -45,9 +43,9 @@
 
 #if SB_API_VERSION >= 15
   std::unique_ptr<std::thread> sb_main_;
+#endif  // SB_API_VERSION >= 15
   std::promise<bool> init_p_;
   std::future<bool> init_f_;
-#endif  // SB_API_VERSION >= 15
   SbWindow window_ = kSbWindowInvalid;
   std::mutex lock_;
   bool initialized_;
diff --git a/chromecast/starboard/chromecast/starboard_adapter/src/cast_starboard_api_adapter_test.cc b/chromecast/starboard/chromecast/starboard_adapter/src/cast_starboard_api_adapter_test.cc
new file mode 100644
index 0000000..fea119e0
--- /dev/null
+++ b/chromecast/starboard/chromecast/starboard_adapter/src/cast_starboard_api_adapter_test.cc
@@ -0,0 +1,149 @@
+// 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 "base/at_exit.h"
+#include "base/test/task_environment.h"
+#include "chromecast/starboard/chromecast/starboard_adapter/src/cast_starboard_api_adapter_impl.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if SB_API_VERSION >= 15
+#include <starboard/event.h>
+#else  // SB_API_VERSION >=15
+#include <cast_starboard_api.h>
+#endif  // SB_API_VERSION >= 15
+
+#include <atomic>
+#include <thread>
+
+class MockCastStarboardApi {
+ public:
+#if SB_API_VERSION >= 15
+  MOCK_METHOD(int,
+              SbRunStarboardMain,
+              (int argc, char** argv, SbEventHandleCallback callback));
+  MOCK_METHOD(void, SbSystemRequestStop, (int error_level));
+#else
+  MOCK_METHOD(int,
+              CastStarboardApiInitialize,
+              (int argc, char** argv, SbEventHandleCB callback));
+  MOCK_METHOD(void, CastStarboardApiFinalize, ());
+#endif
+  MOCK_METHOD(SbWindow, SbWindowCreate, (const SbWindowOptions* options));
+};
+
+MockCastStarboardApi* g_mock_cast_starboard_api = nullptr;
+
+#if SB_API_VERSION >= 15
+int SbRunStarboardMain(int argc, char** argv, SbEventHandleCallback callback) {
+  return g_mock_cast_starboard_api->SbRunStarboardMain(argc, argv, callback);
+}
+
+void SbSystemRequestStop(int error_level) {
+  g_mock_cast_starboard_api->SbSystemRequestStop(error_level);
+}
+#else   // SB_API_VERSION >= 15
+
+int CastStarboardApiInitialize(int argc,
+                               char** argv,
+                               SbEventHandleCB callback) {
+  return g_mock_cast_starboard_api->CastStarboardApiInitialize(argc, argv,
+                                                               callback);
+}
+
+void CastStarboardApiFinalize() {
+  g_mock_cast_starboard_api->CastStarboardApiFinalize();
+}
+#endif  // SB_API_VERSION >= 15
+
+SbWindow SbWindowCreate(const SbWindowOptions* options) {
+  return g_mock_cast_starboard_api->SbWindowCreate(options);
+}
+
+namespace chromecast {
+namespace {
+
+using ::testing::_;
+
+class CastStarboardApiAdapterTest : public ::testing::Test {
+ public:
+  CastStarboardApiAdapterTest() {
+    g_mock_cast_starboard_api = &cast_starboard_api_;
+    fake_start_.type = kSbEventTypeStart;
+    fake_stop_.type = kSbEventTypeStop;
+  }
+
+ protected:
+  MockCastStarboardApi cast_starboard_api_;
+  SbEvent fake_start_;
+  SbEvent fake_stop_;
+};
+
+TEST_F(CastStarboardApiAdapterTest, ConcurrentGetsAndRelease) {
+  constexpr int num_threads = 10;
+  std::atomic_int32_t instance_id{0};
+  std::atomic_int32_t subscriber_count{0};
+  std::atomic_bool thread_ready_flag;
+  // Init/Main and Finalize/Stop should onnly be called once, but
+  // due to the way the adapter is implemented, if the code under test
+  // is executed multiple times, and we do not send the expected
+  // Start/Stop signals, the tests will hang waiting on a future to
+  // complete.
+#if SB_API_VERSION >= 15
+  SbEventHandleCallback sb_callback;
+  EXPECT_CALL(cast_starboard_api_, SbRunStarboardMain(_, _, _))
+      .Times(1)
+      .WillRepeatedly(
+          [&](int argc, char** argv, SbEventHandleCallback callback) {
+            sb_callback = callback;
+            sb_callback(&fake_start_);
+            return 0;
+          });
+  EXPECT_CALL(cast_starboard_api_, SbSystemRequestStop(0))
+      .Times(1)
+      .WillRepeatedly([&]() { sb_callback(&fake_stop_); });
+#else
+  SbEventHandleCB sb_callback;
+  EXPECT_CALL(cast_starboard_api_, CastStarboardApiInitialize(_, _, _))
+      .Times(1)
+      .WillRepeatedly([&](int argc, char** argv, SbEventHandleCB callback) {
+        sb_callback = callback;
+        sb_callback(&fake_start_);
+        return 0;
+      });
+  EXPECT_CALL(cast_starboard_api_, CastStarboardApiFinalize())
+      .Times(1)
+      .WillRepeatedly([&]() { sb_callback(&fake_stop_); });
+#endif
+
+  auto thread_body = [&]() {
+    // Busy loop until all threads are init so we can have as much overlap as
+    // possible on the following code paths.
+    while (!thread_ready_flag.load(std::memory_order_relaxed)) {
+    }
+    auto* instance = CastStarboardApiAdapter::GetInstance();
+    auto* id = reinterpret_cast<void*>(static_cast<uintptr_t>((instance_id++)));
+    instance->Subscribe(id, nullptr);
+    subscriber_count.fetch_add(1, std::memory_order_relaxed);
+    // Spin until all subscribers have init. we're only testing for races with
+    // Initialize/Release, not interleavings currently.
+    while (subscriber_count.load(std::memory_order_relaxed) != num_threads) {
+    }
+    instance->Unsubscribe(id);
+  };
+  std::vector<std::thread> threads;
+  for (int i = 0; i < num_threads; ++i) {
+    threads.push_back(std::thread(thread_body));
+  }
+  thread_ready_flag.store(true, std::memory_order_relaxed);
+  for (auto& thread : threads) {
+    thread.join();
+  }
+  // Force any atexit calls to run now, while we have the mock objects around.
+  // Without a manual call, this will occur outside of the test block.
+  base::AtExitManager::ProcessCallbacksNow();
+}
+
+}  // namespace
+}  // namespace chromecast
diff --git a/chromecast/starboard/chromecast/starboard_cast_dummy/cast_starboard_api_dummy.cc b/chromecast/starboard/chromecast/starboard_cast_dummy/cast_starboard_api_dummy.cc
index a40c7e0..ec3cf32 100644
--- a/chromecast/starboard/chromecast/starboard_cast_dummy/cast_starboard_api_dummy.cc
+++ b/chromecast/starboard/chromecast/starboard_cast_dummy/cast_starboard_api_dummy.cc
@@ -13,13 +13,29 @@
 #endif  // SB_API_VERSION < 15
 
 #if SB_API_VERSION >= 15
+namespace {
+SbEventHandleCallback g_callback = nullptr;
+}
+
 int SbRunStarboardMain(int argc, char** argv, SbEventHandleCallback callback) {
+  g_callback = callback;
   SbEvent* fake_start = new SbEvent;
   fake_start->type = kSbEventTypeStart;
-  callback(fake_start);
+  g_callback(fake_start);
   return 0;
 }
+
+void SbSystemRequestStop(int error_level) {
+  SbEvent* fake_stop = new SbEvent;
+  fake_stop->type = kSbEventTypeStop;
+  g_callback(fake_stop);
+  g_callback = nullptr;
+}
 #else  // SB_API_VERSION >= 15
+namespace {
+SbEventHandleCB g_callback = nullptr;
+}
+
 int StarboardMain(int argc, char** argv) {
   return 0;
 }
@@ -27,13 +43,19 @@
 int CastStarboardApiInitialize(int argc,
                                char** argv,
                                SbEventHandleCB callback) {
+  g_callback = callback;
   SbEvent* fake_start = new SbEvent;
   fake_start->type = kSbEventTypeStart;
-  callback(fake_start);
+  g_callback(fake_start);
   return 0;
 }
 
-void CastStarboardApiFinalize() {}
+void CastStarboardApiFinalize() {
+  SbEvent* fake_stop = new SbEvent;
+  fake_stop->type = kSbEventTypeStop;
+  g_callback(fake_stop);
+  g_callback = nullptr;
+}
 
 #endif  // SB_API_VERSION >= 15
 
diff --git a/chromecast/starboard/graphics/cast_egl_platform_starboard.cc b/chromecast/starboard/graphics/cast_egl_platform_starboard.cc
index 8e5eade..0d44ced 100644
--- a/chromecast/starboard/graphics/cast_egl_platform_starboard.cc
+++ b/chromecast/starboard/graphics/cast_egl_platform_starboard.cc
@@ -31,24 +31,28 @@
  public:
   CastEglPlatformStarboard()
 #if !BUILDFLAG(REMOVE_STARBOARD_HEADERS)
-      : sb_adapter_(CastStarboardApiAdapter::GetInstance())
-#endif
+      : sb_adapter_(CastStarboardApiAdapter::GetInstance()) {
+    sb_adapter_->Subscribe(this, nullptr);
+  }
+#else
   {
   }
+#endif
 
   const int* GetEGLSurfaceProperties(const int* desired) override {
     return desired;
   }
 
-  ~CastEglPlatformStarboard() override {}
+  ~CastEglPlatformStarboard() override {
+#if !BUILDFLAG(REMOVE_STARBOARD_HEADERS)
+    sb_adapter_->Unsubscribe(this);
+#endif
+  }
 
   bool InitializeHardware() override {
 #if BUILDFLAG(REMOVE_STARBOARD_HEADERS)
     return false;
 #else
-    if (!sb_adapter_->EnsureInitialized()) {
-      return false;
-    }
     graphics_lib_ =
         dlopen(kGraphicsLibraryName, RTLD_NOW | RTLD_LOCAL | RTLD_DEEPBIND);
     if (!graphics_lib_) {
diff --git a/chromecast/starboard/media/media/starboard_api_wrapper_base.cc b/chromecast/starboard/media/media/starboard_api_wrapper_base.cc
index f3206e8b..fe8c79b 100644
--- a/chromecast/starboard/media/media/starboard_api_wrapper_base.cc
+++ b/chromecast/starboard/media/media/starboard_api_wrapper_base.cc
@@ -216,11 +216,25 @@
 }  // namespace
 
 StarboardApiWrapperBase::StarboardApiWrapperBase() = default;
-StarboardApiWrapperBase::~StarboardApiWrapperBase() = default;
+
+StarboardApiWrapperBase::~StarboardApiWrapperBase() {
+  if (initialized_) {
+    initialized_ = false;
+    chromecast::CastStarboardApiAdapter::GetInstance()->Unsubscribe(this);
+  }
+}
 
 bool StarboardApiWrapperBase::EnsureInitialized() {
-  return chromecast::CastStarboardApiAdapter::GetInstance()
-      ->EnsureInitialized();
+  // TODO: crbug.com/357265940 - The Starboard API is only explicitly subscriber
+  // in one thread. Currently, CastMediaStarboard will use the Starboard API to
+  // check MIME type compatibility in another process.
+  if (!initialized_) {
+    initialized_ = true;
+    chromecast::CastStarboardApiAdapter::GetInstance()->Subscribe(this,
+                                                                  nullptr);
+  }
+
+  return initialized_;
 }
 
 void* StarboardApiWrapperBase::CreatePlayer(
diff --git a/chromecast/starboard/media/media/starboard_api_wrapper_base.h b/chromecast/starboard/media/media/starboard_api_wrapper_base.h
index cd68c9d..6cf8556 100644
--- a/chromecast/starboard/media/media/starboard_api_wrapper_base.h
+++ b/chromecast/starboard/media/media/starboard_api_wrapper_base.h
@@ -104,6 +104,9 @@
       SbPlayer player,
       SbMediaType sample_type,
       base::span<const SbPlayerSampleInfo> sample_infos) = 0;
+
+  // Tracks whether |EnsureInitialized| was called.
+  bool initialized_ = false;
 };
 
 }  // namespace media
diff --git a/chromeos/ash/components/multidevice/logging/logging.cc b/chromeos/ash/components/multidevice/logging/logging.cc
index 844ea6d..2670a785 100644
--- a/chromeos/ash/components/multidevice/logging/logging.cc
+++ b/chromeos/ash/components/multidevice/logging/logging.cc
@@ -34,20 +34,19 @@
   const std::string string_from_stream = stream_.str();
   auto* log_buffer = LogBuffer::GetInstance();
   CHECK(log_buffer);
-  log_buffer->AddLogMessage(
-      LogBuffer::LogMessage(string_from_stream, base::Time::Now(),
-                            std::string(file_), line_, severity_));
+  log_buffer->AddLogMessage(LogBuffer::LogMessage(
+      string_from_stream, base::Time::Now(), file_.data(), line_, severity_));
 
   // Don't emit VERBOSE-level logging to the standard logging system unless
   // verbose logging is enabled for the source file.
   if (severity_ <= logging::LOGGING_VERBOSE &&
-      logging::GetVlogLevelHelper(file_) <= 0) {
+      logging::GetVlogLevelHelper(file_.data(), file_.size()) <= 0) {
     return;
   }
 
   // The destructor of |log_message| also creates a log for the standard logging
   // system.
-  logging::LogMessage log_message(file_, line_, severity_);
+  logging::LogMessage log_message(file_.data(), line_, severity_);
   log_message.stream() << string_from_stream;
 }
 
diff --git a/chromeos/ash/components/multidevice/logging/logging.h b/chromeos/ash/components/multidevice/logging/logging.h
index d4dd63b..0ffbf1c 100644
--- a/chromeos/ash/components/multidevice/logging/logging.h
+++ b/chromeos/ash/components/multidevice/logging/logging.h
@@ -21,10 +21,10 @@
 // Examples:
 //   PA_LOG(INFO) << "Waiting for " << x << " pending requests.";
 //   PA_LOG(ERROR) << "Request failed: " << error_string;
-#define PA_LOG(severity)                                             \
-  ash::multidevice::ScopedLogMessage(                                \
-      std::string_view(__FILE__, std::size(__FILE__) - 1), __LINE__, \
-      logging::LOGGING_##severity)                                   \
+#define PA_LOG(severity)                                         \
+  ash::multidevice::ScopedLogMessage(                            \
+      std::string_view(__FILE__, std::size(__FILE__)), __LINE__, \
+      logging::LOGGING_##severity)                               \
       .stream()
 
 // Disables all logging while in scope. Intended to be called only from test
diff --git a/chromeos/ash/components/multidevice/logging/logging_unittest.cc b/chromeos/ash/components/multidevice/logging/logging_unittest.cc
index ce43456..13aa9b0 100644
--- a/chromeos/ash/components/multidevice/logging/logging_unittest.cc
+++ b/chromeos/ash/components/multidevice/logging/logging_unittest.cc
@@ -6,8 +6,6 @@
 
 #include <stddef.h>
 
-#include <string_view>
-
 #include "base/lazy_instance.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/strings/string_number_conversions.h"
@@ -28,7 +26,7 @@
 base::LazyInstance<std::vector<std::string>>::DestructorAtExit g_standard_logs =
     LAZY_INSTANCE_INITIALIZER;
 bool HandleStandardLogMessage(int severity,
-                              std::string_view file,
+                              const char* file,
                               int line,
                               size_t message_start,
                               const std::string& str) {
diff --git a/chromeos/ash/components/quick_start/logging.cc b/chromeos/ash/components/quick_start/logging.cc
index ec2da71..ea13a41 100644
--- a/chromeos/ash/components/quick_start/logging.cc
+++ b/chromeos/ash/components/quick_start/logging.cc
@@ -26,7 +26,7 @@
 ScopedLogMessage::~ScopedLogMessage() {
   if (ShouldEmitToStandardLog()) {
     // Create a log for the standard logging system.
-    logging::LogMessage log_message(file_, line_, severity_);
+    logging::LogMessage log_message(file_.data(), line_, severity_);
     log_message.stream() << stream_.str();
   }
 }
@@ -37,7 +37,7 @@
   // - The Vlog Level for |file_| is at least 1
   // - The --quick-start-verbose-logging switch is enabled
   return severity_ > logging::LOGGING_VERBOSE ||
-         logging::GetVlogLevelHelper(file_) > 0 ||
+         logging::GetVlogLevelHelper(file_.data(), file_.size()) > 0 ||
          base::CommandLine::ForCurrentProcess()->HasSwitch(
              kQuickStartVerboseLoggingSwitch);
 }
diff --git a/chromeos/ash/components/quick_start/logging_unittest.cc b/chromeos/ash/components/quick_start/logging_unittest.cc
index c8a2c7b..fadacf3 100644
--- a/chromeos/ash/components/quick_start/logging_unittest.cc
+++ b/chromeos/ash/components/quick_start/logging_unittest.cc
@@ -2,16 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromeos/ash/components/quick_start/logging.h"
-
 #include <stddef.h>
 
-#include <string_view>
-
 #include "base/command_line.h"
 #include "base/no_destructor.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+#include "chromeos/ash/components/quick_start/logging.h"
+
 namespace ash::quick_start {
 
 namespace {
@@ -29,7 +27,7 @@
 }
 
 bool HandleStandardLogMessage(int severity,
-                              std::string_view file,
+                              const char* file,
                               int line,
                               size_t message_start,
                               const std::string& str) {
diff --git a/chromeos/ash/components/quick_start/quick_start_requests.cc b/chromeos/ash/components/quick_start/quick_start_requests.cc
index f54b243..86eb5a2 100644
--- a/chromeos/ash/components/quick_start/quick_start_requests.cc
+++ b/chromeos/ash/components/quick_start/quick_start_requests.cc
@@ -135,14 +135,13 @@
 }
 
 std::unique_ptr<QuickStartMessage> BuildAssertionRequestMessage(
-    std::array<uint8_t, crypto::kSHA256Length> client_data_hash) {
+    base::span<const uint8_t, crypto::hash::kSha256Size> client_data_hash) {
   cbor::Value request = GenerateGetAssertionRequest(client_data_hash);
   std::vector<uint8_t> ctap_request_command =
       CBOREncodeGetAssertionRequest(std::move(request));
 
-  std::unique_ptr<QuickStartMessage> message =
-      std::make_unique<QuickStartMessage>(
-          QuickStartMessageType::kSecondDeviceAuthPayload);
+  auto message = std::make_unique<QuickStartMessage>(
+      QuickStartMessageType::kSecondDeviceAuthPayload);
 
   message->GetPayload()->Set(FIDO_MESSAGE_KEY,
                              base::Base64Encode(ctap_request_command));
@@ -151,9 +150,8 @@
 
 std::unique_ptr<QuickStartMessage> BuildGetInfoRequestMessage() {
   std::vector<uint8_t> ctap_request_command({kAuthenticatorGetInfoCommand});
-  std::unique_ptr<QuickStartMessage> message =
-      std::make_unique<QuickStartMessage>(
-          QuickStartMessageType::kSecondDeviceAuthPayload);
+  auto message = std::make_unique<QuickStartMessage>(
+      QuickStartMessageType::kSecondDeviceAuthPayload);
   message->GetPayload()->Set(FIDO_MESSAGE_KEY,
                              base::Base64Encode(ctap_request_command));
   return message;
@@ -162,9 +160,8 @@
 std::unique_ptr<QuickStartMessage> BuildRequestWifiCredentialsMessage(
     uint64_t session_id,
     std::string& shared_secret) {
-  std::unique_ptr<QuickStartMessage> message =
-      std::make_unique<QuickStartMessage>(
-          QuickStartMessageType::kQuickStartPayload);
+  auto message = std::make_unique<QuickStartMessage>(
+      QuickStartMessageType::kQuickStartPayload);
   message->GetPayload()->Set(kRequestWifiKey, true);
   std::string shared_secret_str(shared_secret.begin(), shared_secret.end());
   std::string shared_secret_base64 = base::Base64Encode(shared_secret_str);
@@ -174,7 +171,7 @@
 }
 
 cbor::Value GenerateGetAssertionRequest(
-    std::array<uint8_t, crypto::kSHA256Length> client_data_hash) {
+    base::span<const uint8_t, crypto::hash::kSha256Size> client_data_hash) {
   url::Origin origin = url::Origin::Create(GURL(kOrigin));
   cbor::Value::MapValue cbor_map;
   cbor_map.insert_or_assign(cbor::Value(0x01), cbor::Value(kRelyingPartyId));
@@ -203,32 +200,28 @@
 
 std::unique_ptr<QuickStartMessage> BuildNotifySourceOfUpdateMessage(
     uint64_t session_id,
-    const base::span<uint8_t, 32> shared_secret) {
-  std::unique_ptr<QuickStartMessage> message =
-      std::make_unique<QuickStartMessage>(
-          QuickStartMessageType::kQuickStartPayload);
+    base::span<const uint8_t, 32> shared_secret) {
+  auto message = std::make_unique<QuickStartMessage>(
+      QuickStartMessageType::kQuickStartPayload);
   message->GetPayload()->Set(kNotifySourceOfUpdateMessageKey, true);
 
-  std::string shared_secret_str(shared_secret.begin(), shared_secret.end());
-  std::string shared_secret_base64 = base::Base64Encode(shared_secret_str);
-  message->GetPayload()->Set(kSharedSecretKey, shared_secret_base64);
+  message->GetPayload()->Set(kSharedSecretKey,
+                             base::Base64Encode(shared_secret));
   message->GetPayload()->Set(kSessionIdKey, base::NumberToString(session_id));
 
   return message;
 }
 
 std::unique_ptr<QuickStartMessage> BuildBootstrapStateCancelMessage() {
-  std::unique_ptr<QuickStartMessage> message =
-      std::make_unique<QuickStartMessage>(
-          QuickStartMessageType::kBootstrapState);
+  auto message = std::make_unique<QuickStartMessage>(
+      QuickStartMessageType::kBootstrapState);
   message->GetPayload()->Set(kBootstrapStateKey, kBootstrapStateCancel);
   return message;
 }
 
 std::unique_ptr<QuickStartMessage> BuildBootstrapStateCompleteMessage() {
-  std::unique_ptr<QuickStartMessage> message =
-      std::make_unique<QuickStartMessage>(
-          QuickStartMessageType::kBootstrapState);
+  auto message = std::make_unique<QuickStartMessage>(
+      QuickStartMessageType::kBootstrapState);
   message->GetPayload()->Set(kBootstrapStateKey, kBootstrapStateComplete);
 
   // TODO(b/332603236): Remove postTransferAction payload when new device info
diff --git a/chromeos/ash/components/quick_start/quick_start_requests.h b/chromeos/ash/components/quick_start/quick_start_requests.h
index bd6f091..e51a1b1 100644
--- a/chromeos/ash/components/quick_start/quick_start_requests.h
+++ b/chromeos/ash/components/quick_start/quick_start_requests.h
@@ -9,7 +9,7 @@
 #include <string>
 
 #include "components/cbor/values.h"
-#include "crypto/sha2.h"
+#include "crypto/hash.h"
 #include "quick_start_message.h"
 
 namespace ash::quick_start::requests {
@@ -17,7 +17,7 @@
 std::unique_ptr<QuickStartMessage> BuildBootstrapOptionsRequest();
 
 std::unique_ptr<QuickStartMessage> BuildAssertionRequestMessage(
-    std::array<uint8_t, crypto::kSHA256Length> client_data_hash);
+    base::span<const uint8_t, crypto::hash::kSha256Size> client_data_hash);
 
 std::unique_ptr<QuickStartMessage> BuildGetInfoRequestMessage();
 
@@ -28,11 +28,11 @@
 std::vector<uint8_t> CBOREncodeGetAssertionRequest(const cbor::Value& request);
 
 cbor::Value GenerateGetAssertionRequest(
-    std::array<uint8_t, crypto::kSHA256Length> client_data_hash);
+    base::span<const uint8_t, crypto::hash::kSha256Size> client_data_hash);
 
 std::unique_ptr<QuickStartMessage> BuildNotifySourceOfUpdateMessage(
     uint64_t session_id,
-    const base::span<uint8_t, 32> shared_secret);
+    base::span<const uint8_t, 32> shared_secret);
 
 std::unique_ptr<QuickStartMessage> BuildBootstrapStateCancelMessage();
 
diff --git a/chromeos/ash/components/quick_start/quick_start_requests_unittest.cc b/chromeos/ash/components/quick_start/quick_start_requests_unittest.cc
index b97d8bdc..98b0c7c 100644
--- a/chromeos/ash/components/quick_start/quick_start_requests_unittest.cc
+++ b/chromeos/ash/components/quick_start/quick_start_requests_unittest.cc
@@ -5,13 +5,19 @@
 #include "chromeos/ash/components/quick_start/quick_start_requests.h"
 
 #include "components/cbor/reader.h"
+#include "crypto/hash.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using ash::quick_start::requests::CBOREncodeGetAssertionRequest;
 using ash::quick_start::requests::GenerateGetAssertionRequest;
 
 namespace {
-const char kTestClientDataString[] = "test_client_data";
+// Used as a dummy client data hash when constructing test requests.
+const std::array<uint8_t, crypto::hash::kSha256Size> kTestClientDataHash = {
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
+    0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
+    0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+};
 }  // namespace
 
 class QuickStartRequestTest : public testing::Test {
@@ -26,15 +32,16 @@
 };
 
 TEST_F(QuickStartRequestTest, GenerateGetAssertionRequest_ValidChallenge) {
-  std::array<uint8_t, crypto::kSHA256Length> client_data_hash;
-  crypto::SHA256HashString(kTestClientDataString, client_data_hash.data(),
-                           client_data_hash.size());
-  cbor::Value request = GenerateGetAssertionRequest(client_data_hash);
+  cbor::Value request = GenerateGetAssertionRequest(kTestClientDataHash);
   ASSERT_TRUE(request.is_map());
   const cbor::Value::MapValue& request_map = request.GetMap();
   // CBOR Index 0x01 stores the relying_party_id for the GetAssertionRequest.
   EXPECT_EQ(request_map.find(cbor::Value(0x01))->second.GetString(),
             "google.com");
+  // CBOR Index 0x02 stores the client data hash.
+  EXPECT_EQ(base::as_byte_span(
+                request_map.find(cbor::Value(0x02))->second.GetBytestring()),
+            kTestClientDataHash);
   // CBOR Index 0x05 stores the options for the GetAssertionRequest.
   const cbor::Value::MapValue& options_map =
       request_map.find(cbor::Value(0x05))->second.GetMap();
@@ -47,10 +54,7 @@
 }
 
 TEST_F(QuickStartRequestTest, CBOREncodeGetAssertionRequest) {
-  std::array<uint8_t, crypto::kSHA256Length> client_data_hash;
-  crypto::SHA256HashString(kTestClientDataString, client_data_hash.data(),
-                           client_data_hash.size());
-  cbor::Value request = GenerateGetAssertionRequest(client_data_hash);
+  cbor::Value request = GenerateGetAssertionRequest(kTestClientDataHash);
   std::vector<uint8_t> cbor_encoded_request =
       CBOREncodeGetAssertionRequest(std::move(request));
   std::optional<cbor::Value> cbor;
diff --git a/chromeos/ash/services/device_sync/cryptauth_feature_status_getter_impl_unittest.cc b/chromeos/ash/services/device_sync/cryptauth_feature_status_getter_impl_unittest.cc
index de46089..4eee3f92 100644
--- a/chromeos/ash/services/device_sync/cryptauth_feature_status_getter_impl_unittest.cc
+++ b/chromeos/ash/services/device_sync/cryptauth_feature_status_getter_impl_unittest.cc
@@ -168,7 +168,7 @@
                   batch_get_feature_statuses_request_->device_ids().begin(),
                   batch_get_feature_statuses_request_->device_ids().end()));
     EXPECT_EQ(GetAllCryptAuthFeatureTypeStrings(),
-              base::flat_set<std::string>(
+              base::flat_set<std::string_view>(
                   batch_get_feature_statuses_request_->feature_types().begin(),
                   batch_get_feature_statuses_request_->feature_types().end()));
   }
diff --git a/chromeos/ash/services/device_sync/cryptauth_feature_type.cc b/chromeos/ash/services/device_sync/cryptauth_feature_type.cc
index 3abb0b3..33829a3 100644
--- a/chromeos/ash/services/device_sync/cryptauth_feature_type.cc
+++ b/chromeos/ash/services/device_sync/cryptauth_feature_type.cc
@@ -8,7 +8,7 @@
 #include "base/base64url.h"
 #include "base/containers/flat_map.h"
 #include "base/no_destructor.h"
-#include "crypto/sha2.h"
+#include "crypto/hash.h"
 
 namespace ash {
 
@@ -186,10 +186,10 @@
   return *enabled_set;
 }
 
-const base::flat_set<std::string>& GetAllCryptAuthFeatureTypeStrings() {
-  static const base::NoDestructor<base::flat_set<std::string>>
+const base::flat_set<std::string_view>& GetAllCryptAuthFeatureTypeStrings() {
+  static const base::NoDestructor<base::flat_set<std::string_view>>
       feature_string_set([] {
-        base::flat_set<std::string> feature_string_set;
+        base::flat_set<std::string_view> feature_string_set;
         for (CryptAuthFeatureType feature_type : GetAllCryptAuthFeatureTypes())
           feature_string_set.insert(CryptAuthFeatureTypeToString(feature_type));
 
@@ -198,7 +198,8 @@
   return *feature_string_set;
 }
 
-const char* CryptAuthFeatureTypeToString(CryptAuthFeatureType feature_type) {
+std::string_view CryptAuthFeatureTypeToString(
+    CryptAuthFeatureType feature_type) {
   switch (feature_type) {
     case CryptAuthFeatureType::kBetterTogetherHostSupported:
       return kBetterTogetherHostSupportedString;
@@ -268,7 +269,7 @@
 }
 
 std::optional<CryptAuthFeatureType> CryptAuthFeatureTypeFromString(
-    const std::string& feature_type_string) {
+    std::string_view feature_type_string) {
   if (feature_type_string == kBetterTogetherHostSupportedString)
     return CryptAuthFeatureType::kBetterTogetherHostSupported;
   if (feature_type_string == kBetterTogetherHostEnabledString)
@@ -337,15 +338,15 @@
   return std::nullopt;
 }
 
-// Computes the base64url-encoded, SHA-256 8-byte hash of the
-// CryptAuthFeatureType string.
+// For a given CryptAuthFeatureType, return the base64url encoding of the first
+// 8 bytes of the SHA-256 of its string representation.
 std::string CryptAuthFeatureTypeToGcmHash(CryptAuthFeatureType feature_type) {
-  std::string hash_8_bytes(8, 0);
-  crypto::SHA256HashString(CryptAuthFeatureTypeToString(feature_type),
-                           std::data(hash_8_bytes), 8u);
+  auto hash = crypto::hash::Sha256(
+      base::as_byte_span(CryptAuthFeatureTypeToString(feature_type)));
 
   std::string hash_base64url;
-  base::Base64UrlEncode(hash_8_bytes, base::Base64UrlEncodePolicy::OMIT_PADDING,
+  base::Base64UrlEncode(base::span(hash).first(8u),
+                        base::Base64UrlEncodePolicy::OMIT_PADDING,
                         &hash_base64url);
 
   return hash_base64url;
diff --git a/chromeos/ash/services/device_sync/cryptauth_feature_type.h b/chromeos/ash/services/device_sync/cryptauth_feature_type.h
index ca853b3..5590884 100644
--- a/chromeos/ash/services/device_sync/cryptauth_feature_type.h
+++ b/chromeos/ash/services/device_sync/cryptauth_feature_type.h
@@ -101,15 +101,16 @@
 const base::flat_set<CryptAuthFeatureType>& GetAllCryptAuthFeatureTypes();
 const base::flat_set<CryptAuthFeatureType>& GetSupportedCryptAuthFeatureTypes();
 const base::flat_set<CryptAuthFeatureType>& GetEnabledCryptAuthFeatureTypes();
-const base::flat_set<std::string>& GetAllCryptAuthFeatureTypeStrings();
+const base::flat_set<std::string_view>& GetAllCryptAuthFeatureTypeStrings();
 
 // Provides a unique mapping between each CryptAuthFeatureType enum value and
 // the corresponding string used in the protos and understood by CryptAuth.
 // CryptAuthFeatureTypeFromString returns null if |feature_type_string| does not
 // map to a known CryptAuthFeatureType.
-const char* CryptAuthFeatureTypeToString(CryptAuthFeatureType feature_type);
+std::string_view CryptAuthFeatureTypeToString(
+    CryptAuthFeatureType feature_type);
 std::optional<CryptAuthFeatureType> CryptAuthFeatureTypeFromString(
-    const std::string& feature_type_string);
+    std::string_view feature_type_string);
 
 // Provides a unique mapping between a CryptAuthFeatureType and its
 // corresponding encoded hash value that CryptAuth sends in GCM messages.
diff --git a/chromeos/ash/services/device_sync/cryptauth_group_private_key_sharer_impl.cc b/chromeos/ash/services/device_sync/cryptauth_group_private_key_sharer_impl.cc
index 10dcc43..984d3f95 100644
--- a/chromeos/ash/services/device_sync/cryptauth_group_private_key_sharer_impl.cc
+++ b/chromeos/ash/services/device_sync/cryptauth_group_private_key_sharer_impl.cc
@@ -2,11 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifdef UNSAFE_BUFFERS_BUILD
-// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
-#pragma allow_unsafe_buffers
-#endif
-
 #include "chromeos/ash/services/device_sync/cryptauth_group_private_key_sharer_impl.h"
 
 #include <utility>
@@ -14,13 +9,14 @@
 #include "base/functional/bind.h"
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_functions.h"
+#include "base/numerics/byte_conversions.h"
 #include "chromeos/ash/components/multidevice/logging/logging.h"
 #include "chromeos/ash/services/device_sync/async_execution_time_metrics_logger.h"
 #include "chromeos/ash/services/device_sync/cryptauth_client.h"
 #include "chromeos/ash/services/device_sync/cryptauth_ecies_encryptor_impl.h"
 #include "chromeos/ash/services/device_sync/cryptauth_key.h"
 #include "chromeos/ash/services/device_sync/cryptauth_task_metrics_logger.h"
-#include "crypto/sha2.h"
+#include "crypto/hash.h"
 
 namespace ash {
 
@@ -67,15 +63,9 @@
 // The first 8 bytes of the SHA-256 hash of |str|, converted into a 64-bit
 // signed integer in little-endian order. This format is chosen to be consistent
 // with the CryptAuth backend implementation.
-int64_t CalculateInt64Sha256Hash(const std::string& str) {
-  uint8_t hash_bytes[sizeof(int64_t)];
-  crypto::SHA256HashString(str, hash_bytes, sizeof(hash_bytes));
-
-  int64_t hash_int64 = 0;
-  for (size_t i = 0; i < 8u; ++i)
-    hash_int64 |= static_cast<int64_t>(hash_bytes[i]) << (i * 8);
-
-  return hash_int64;
+int64_t CalculateInt64Sha256Hash(std::string_view str) {
+  auto hash = crypto::hash::Sha256(base::as_byte_span(str));
+  return base::I64FromLittleEndian(base::span<const uint8_t>(hash).first<8u>());
 }
 
 void RecordGroupPrivateKeyEncryptionMetrics(
diff --git a/chromeos/ash/services/device_sync/cryptauth_group_private_key_sharer_impl_unittest.cc b/chromeos/ash/services/device_sync/cryptauth_group_private_key_sharer_impl_unittest.cc
index 720eb01..10294eae 100644
--- a/chromeos/ash/services/device_sync/cryptauth_group_private_key_sharer_impl_unittest.cc
+++ b/chromeos/ash/services/device_sync/cryptauth_group_private_key_sharer_impl_unittest.cc
@@ -28,7 +28,6 @@
 #include "chromeos/ash/services/device_sync/proto/cryptauth_common.pb.h"
 #include "chromeos/ash/services/device_sync/proto/cryptauth_devicesync.pb.h"
 #include "chromeos/ash/services/device_sync/proto/cryptauth_v2_test_util.h"
-#include "crypto/sha2.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace ash {
diff --git a/chromeos/ash/services/device_sync/cryptauth_key.cc b/chromeos/ash/services/device_sync/cryptauth_key.cc
index e9bc17f..2185078e 100644
--- a/chromeos/ash/services/device_sync/cryptauth_key.cc
+++ b/chromeos/ash/services/device_sync/cryptauth_key.cc
@@ -6,7 +6,7 @@
 
 #include "base/base64url.h"
 #include "chromeos/ash/services/device_sync/value_string_encoding.h"
-#include "crypto/sha2.h"
+#include "crypto/hash.h"
 
 namespace ash::device_sync {
 
@@ -21,9 +21,9 @@
 const char kPrivateKeyDictKey[] = "private_key";
 
 // Returns the base64url-encoded SHA256 hash of the input string.
-std::string CreateHandle(const std::string& string_to_hash) {
+std::string CreateHandle(std::string_view str) {
   std::string handle;
-  base::Base64UrlEncode(crypto::SHA256HashString(string_to_hash),
+  base::Base64UrlEncode(crypto::hash::Sha256(base::as_byte_span(str)),
                         base::Base64UrlEncodePolicy::INCLUDE_PADDING, &handle);
   return handle;
 }
diff --git a/clank b/clank
index 984675d..84a854a 160000
--- a/clank
+++ b/clank
@@ -1 +1 @@
-Subproject commit 984675d15dc0687e5e725ec195196357fd0bc765
+Subproject commit 84a854a1fe9a948b8df14dc5e236cd9df9f23984
diff --git a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding.cc b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding.cc
index c8ac862..b4fa314 100644
--- a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding.cc
+++ b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding.cc
@@ -757,7 +757,7 @@
   std::vector<AutofillField*> upload_fields(form.fields().size());
   std::ranges::transform(form.fields(), upload_fields.begin(),
                          &std::unique_ptr<AutofillField>::get);
-  EncodeFormFieldsForUpload(form, &*options.encoder, options.fields,
+  EncodeFormFieldsForUpload(form, options.encoder.get(), options.fields,
                             upload_fields, &upload);
   std::vector<AutofillUploadContents> uploads = {std::move(upload)};
 
@@ -790,7 +790,7 @@
                               (*subform_begin)->renderer_form_id();
                      });
     // SAFETY: The iterators are from the same container.
-    EncodeFormFieldsForUpload(form, &*options.encoder, options.fields,
+    EncodeFormFieldsForUpload(form, options.encoder.get(), options.fields,
                               UNSAFE_BUFFERS({subform_begin, subform_end}),
                               &uploads.back());
     subform_begin = subform_end;
diff --git a/components/autofill/core/browser/data_model/addresses/address.cc b/components/autofill/core/browser/data_model/addresses/address.cc
index 4d818af..40e5057 100644
--- a/components/autofill/core/browser/data_model/addresses/address.cc
+++ b/components/autofill/core/browser/data_model/addresses/address.cc
@@ -136,8 +136,8 @@
     if (!current_value.empty()) {
       AreStringTokenEquivalent(value, Root()->GetValueForType(type))
           ? Root()->SetValueForType(ADDRESS_HOME_STREET_ADDRESS, value, status)
-          : Root()->SetValueForTypeAndResetSubstructure(
-                ADDRESS_HOME_STREET_ADDRESS, value, status);
+          : Root()->SetValueForType(ADDRESS_HOME_STREET_ADDRESS, value, status,
+                                    /*invalidate_child_nodes=*/true);
       return;
     }
   }
diff --git a/components/autofill/core/browser/data_model/addresses/autofill_structured_address_component.cc b/components/autofill/core/browser/data_model/addresses/autofill_structured_address_component.cc
index c8f2f3e..84a28bc5 100644
--- a/components/autofill/core/browser/data_model/addresses/autofill_structured_address_component.cc
+++ b/components/autofill/core/browser/data_model/addresses/autofill_structured_address_component.cc
@@ -339,7 +339,8 @@
 bool AddressComponent::SetValueForType(
     FieldType field_type,
     const std::u16string& value,
-    const VerificationStatus& verification_status) {
+    const VerificationStatus& verification_status,
+    bool invalidate_child_nodes) {
   AddressComponent* node_for_type = GetNodeForType(field_type);
   if (!node_for_type || node_for_type->IsValueReadOnly()) {
     return false;
@@ -348,22 +349,9 @@
       ? node_for_type->SetValue(value, verification_status)
       : node_for_type->SetValueForOtherSupportedType(field_type, value,
                                                      verification_status);
-  return true;
-}
-
-bool AddressComponent::SetValueForTypeAndResetSubstructure(
-    FieldType field_type,
-    const std::u16string& value,
-    const VerificationStatus& verification_status) {
-  AddressComponent* node_for_type = GetNodeForType(field_type);
-  if (!node_for_type) {
-    return false;
+  if (invalidate_child_nodes) {
+    node_for_type->UnsetSubcomponents();
   }
-  node_for_type->GetStorageType() == field_type
-      ? node_for_type->SetValue(value, verification_status)
-      : node_for_type->SetValueForOtherSupportedType(field_type, value,
-                                                     verification_status);
-  node_for_type->UnsetSubcomponents();
   return true;
 }
 
diff --git a/components/autofill/core/browser/data_model/addresses/autofill_structured_address_component.h b/components/autofill/core/browser/data_model/addresses/autofill_structured_address_component.h
index 21156f4..563fbc6 100644
--- a/components/autofill/core/browser/data_model/addresses/autofill_structured_address_component.h
+++ b/components/autofill/core/browser/data_model/addresses/autofill_structured_address_component.h
@@ -223,18 +223,15 @@
   // Sets the value corresponding to the storage type of this AddressComponent.
   virtual void SetValue(std::u16string value, VerificationStatus status);
 
-  // Wrapper function around
-  // SetValueForTypeIfPossible(/*invalidate_child_nodes=*/false);
+  // Sets the value for the specified field type.
+  // - If `invalidate_child_nodes` is false (default), checks if the node is
+  //   read-only.
+  // - If `invalidate_child_nodes` is true, ignores read-only status and clears
+  //   child nodes after setting.
   bool SetValueForType(FieldType field_type,
                        const std::u16string& value,
-                       const VerificationStatus& status);
-
-  // Wrapper function around
-  // SetValueForTypeIfPossible(/*invalidate_child_nodes=*/true);
-  // TODO(crbug.com/40266145): Remove and merge with SetValueForType.
-  bool SetValueForTypeAndResetSubstructure(FieldType field_type,
-                                           const std::u16string& value,
-                                           const VerificationStatus& status);
+                       const VerificationStatus& status,
+                       bool invalidate_child_nodes = false);
 
   // Sets the value to an empty string, marks it unassigned and sets the
   // verification status to |kNoStatus|.
diff --git a/components/autofill/core/browser/data_model/addresses/autofill_structured_address_component_unittest.cc b/components/autofill/core/browser/data_model/addresses/autofill_structured_address_component_unittest.cc
index 8fd8cf0..4b0656b 100644
--- a/components/autofill/core/browser/data_model/addresses/autofill_structured_address_component_unittest.cc
+++ b/components/autofill/core/browser/data_model/addresses/autofill_structured_address_component_unittest.cc
@@ -295,8 +295,9 @@
   TestCompoundNameAddressComponent compound_name;
   EXPECT_TRUE(compound_name.SetValueForType(NAME_FIRST, u"First1-First2",
                                             VerificationStatus::kObserved));
-  EXPECT_TRUE(compound_name.SetValueForTypeAndResetSubstructure(
-      NAME_MIDDLE, u"Middle", VerificationStatus::kObserved));
+  EXPECT_TRUE(compound_name.SetValueForType(NAME_MIDDLE, u"Middle",
+                                            VerificationStatus::kObserved,
+                                            /*invalidate_child_nodes=*/true));
   EXPECT_TRUE(compound_name.SetValueForType(NAME_LAST, u"LAST",
                                             VerificationStatus::kObserved));
   EXPECT_TRUE(compound_name.CompleteFullTree());
@@ -1179,8 +1180,9 @@
   EXPECT_EQ(compound_component.GetValueForType(NAME_LAST), last_name);
 
   // Change the value of FULL_NAME and invalidate all child and ancestor nodes.
-  compound_component.SetValueForTypeAndResetSubstructure(
-      NAME_FULL, u"Oh' Brian", VerificationStatus::kObserved);
+  compound_component.SetValueForType(NAME_FULL, u"Oh' Brian",
+                                     VerificationStatus::kObserved,
+                                     /*invalidate_child_nodes=*/true);
   EXPECT_EQ(compound_component.GetValueForType(CREDIT_CARD_NAME_FULL),
             full_name);
   EXPECT_EQ(compound_component.GetValueForType(NAME_FIRST), std::u16string());
diff --git a/components/autofill/core/browser/data_model/addresses/contact_info.cc b/components/autofill/core/browser/data_model/addresses/contact_info.cc
index fe0b19ac5..0638499 100644
--- a/components/autofill/core/browser/data_model/addresses/contact_info.cc
+++ b/components/autofill/core/browser/data_model/addresses/contact_info.cc
@@ -177,8 +177,8 @@
         ? GetRootForType(type.GetStorableType())
               ->SetValueForType(type.GetStorableType(), value, status)
         : GetRootForType(type.GetStorableType())
-              ->SetValueForTypeAndResetSubstructure(type.GetStorableType(),
-                                                    value, status);
+              ->SetValueForType(type.GetStorableType(), value, status,
+                                /*invalidate_child_nodes=*/true);
     return true;
   }
   SetRawInfoWithVerificationStatus(type.GetStorableType(), value, status);
diff --git a/components/autofill/core/browser/data_model/valuables/loyalty_card.cc b/components/autofill/core/browser/data_model/valuables/loyalty_card.cc
index 2acceaa..435f02ec 100644
--- a/components/autofill/core/browser/data_model/valuables/loyalty_card.cc
+++ b/components/autofill/core/browser/data_model/valuables/loyalty_card.cc
@@ -14,12 +14,14 @@
                          std::string merchant_name,
                          std::string program_name,
                          GURL program_logo,
-                         std::string loyalty_card_number)
+                         std::string loyalty_card_number,
+                         std::vector<GURL> merchant_domains)
     : id_(std::move(id)),
       merchant_name_(std::move(merchant_name)),
       program_name_(std::move(program_name)),
       program_logo_(std::move(program_logo)),
-      loyalty_card_number_(std::move(loyalty_card_number)) {}
+      loyalty_card_number_(std::move(loyalty_card_number)),
+      merchant_domains_(std::move(merchant_domains)) {}
 
 LoyaltyCard::LoyaltyCard(const LoyaltyCard&) = default;
 LoyaltyCard::LoyaltyCard(LoyaltyCard&&) = default;
diff --git a/components/autofill/core/browser/data_model/valuables/loyalty_card.h b/components/autofill/core/browser/data_model/valuables/loyalty_card.h
index a11dd59a..0deef0d 100644
--- a/components/autofill/core/browser/data_model/valuables/loyalty_card.h
+++ b/components/autofill/core/browser/data_model/valuables/loyalty_card.h
@@ -19,7 +19,8 @@
               std::string merchant_name,
               std::string program_name,
               GURL program_logo,
-              std::string loyalty_card_number);
+              std::string loyalty_card_number,
+              std::vector<GURL> merchant_domains);
 
   LoyaltyCard(const LoyaltyCard&);
   LoyaltyCard(LoyaltyCard&&);
@@ -53,6 +54,13 @@
     loyalty_card_number_ = loyalty_card_number;
   }
 
+  const std::vector<GURL>& merchant_domains() const {
+    return merchant_domains_;
+  }
+  void set_merchant_domains(std::vector<GURL> merchant_domains) {
+    merchant_domains_ = std::move(merchant_domains);
+  }
+
   // Checks if this loyalty card is valid. A valid loyalty card contains a
   // non-empty loyalty card id and a logo URL which should be either empty or
   // valid.
@@ -76,6 +84,9 @@
 
   // The loyalty card text code.
   std::string loyalty_card_number_;
+
+  // The list of merchant domains associated to this card.
+  std::vector<GURL> merchant_domains_;
 };
 
 }  // namespace autofill
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 50fa65b..d71aab4f 100644
--- a/components/autofill/core/browser/form_import/form_data_importer.cc
+++ b/components/autofill/core/browser/form_import/form_data_importer.cc
@@ -216,6 +216,27 @@
   });
 }
 
+bool ShouldProcessExtractedCreditCard(
+    const raw_ref<AutofillClient>& client,
+    FormDataImporter::CreditCardImportType credit_card_import_type) {
+  // Processing should not occur if the current window is a tab modal pop-up, as
+  // no credit card save or feature enrollment should happen in this case.
+  if (base::FeatureList::IsEnabled(
+          features::kAutofillSkipSaveCardForTabModalPopup) &&
+      client->GetPaymentsAutofillClient()->IsTabModalPopup()) {
+    return false;
+  }
+
+  // If there is no `credit_card_import_type` from form extraction, the
+  // extracted card is not a viable candidate for processing.
+  if (credit_card_import_type ==
+      FormDataImporter::CreditCardImportType::kNoCard) {
+    return false;
+  }
+
+  return true;
+}
+
 }  // namespace
 
 FormDataImporter::ExtractedFormData::ExtractedFormData() = default;
@@ -276,11 +297,11 @@
       preliminary_imported_address_profiles);
 
   bool cc_prompt_potentially_shown = false;
-  if (credit_card_import_type_ != CreditCardImportType::kNoCard) {
-    // Only check IsCreditCardUploadEnabled() if payment method autofill is
-    // enabled and a credit card was extracted from the form, in order to
-    // prevent the metrics it logs from being diluted by cases where payment
-    // method autofill is off or there was no credit card to process.
+  if (ShouldProcessExtractedCreditCard(client_, credit_card_import_type_)) {
+    // Only check IsCreditCardUploadEnabled() if conditions that enable
+    // processing of the extracted credit card are true, in order to prevent
+    // the metrics it logs from being diluted by cases where extracted credit
+    // cards should not be processed or there was no credit card to process.
     bool credit_card_upload_enabled =
         credit_card_save_manager_->IsCreditCardUploadEnabled();
     cc_prompt_potentially_shown = ProcessExtractedCreditCard(
diff --git a/components/autofill/core/browser/form_import/form_data_importer_test_api.h b/components/autofill/core/browser/form_import/form_data_importer_test_api.h
index 9eea5d63..2885f4b 100644
--- a/components/autofill/core/browser/form_import/form_data_importer_test_api.h
+++ b/components/autofill/core/browser/form_import/form_data_importer_test_api.h
@@ -113,6 +113,15 @@
     return fdi_->fetched_card_instrument_id_;
   }
 
+  void ImportAndProcessFormData(const FormStructure& submitted_form,
+                                bool profile_autofill_enabled,
+                                bool payment_methods_autofill_enabled,
+                                ukm::SourceId ukm_source_id) {
+    fdi_->ImportAndProcessFormData(submitted_form, profile_autofill_enabled,
+                                   payment_methods_autofill_enabled,
+                                   ukm_source_id);
+  }
+
  private:
   const raw_ref<FormDataImporter> fdi_;
 };
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 087484e..3413d53 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
@@ -4030,6 +4030,64 @@
   EXPECT_EQ(observed_field_types.size(), 1u);
 }
 
+class SkipSaveCardInFormDataImporterTest
+    : public FormDataImporterTest,
+      public testing::WithParamInterface<bool> {
+ public:
+  SkipSaveCardInFormDataImporterTest() {
+    feature_list_.InitWithFeatureState(
+        features::kAutofillSkipSaveCardForTabModalPopup,
+        IsSkipSaveCardEnabled());
+  }
+  bool IsSkipSaveCardEnabled() { return GetParam(); }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+INSTANTIATE_TEST_SUITE_P(All,
+                         SkipSaveCardInFormDataImporterTest,
+                         ::testing::Bool());
+
+// Test that save card functionality is skipped for tab modal popup only when
+// kAutofillSkipSaveCardForTabModalPopup is enabled; otherwise, the card saving
+// functionality is started.
+TEST_P(SkipSaveCardInFormDataImporterTest,
+       ImportAndProcessFormData_TabModalPopup) {
+  std::unique_ptr<FormStructure> form_structure =
+      ConstructDefaultCreditCardFormStructure();
+  test_api(form_data_importer())
+      .set_credit_card_import_type(
+          FormDataImporter::CreditCardImportType::kServerCard);
+  payments_client().set_is_tab_model_popup(true);
+
+  EXPECT_CALL(credit_card_save_manager(), ProceedWithSavingIfApplicable)
+      .Times(IsSkipSaveCardEnabled() ? 0 : 1);
+
+  test_api(form_data_importer())
+      .ImportAndProcessFormData(
+          *form_structure, /*profile_autofill_enabled=*/true,
+          /*payment_methods_autofill_enabled=*/true, ukm_source_id());
+}
+
+// Test that save card functionality is initiated for non tab modal popups.
+TEST_P(SkipSaveCardInFormDataImporterTest,
+       ImportAndProcessFormData_StartSaveCardFlow) {
+  std::unique_ptr<FormStructure> form_structure =
+      ConstructDefaultCreditCardFormStructure();
+  test_api(form_data_importer())
+      .set_credit_card_import_type(
+          FormDataImporter::CreditCardImportType::kServerCard);
+
+  EXPECT_CALL(credit_card_save_manager(), ProceedWithSavingIfApplicable)
+      .Times(1);
+
+  test_api(form_data_importer())
+      .ImportAndProcessFormData(
+          *form_structure, /*profile_autofill_enabled=*/true,
+          /*payment_methods_autofill_enabled=*/true, ukm_source_id());
+}
+
 // Test case for credit card extraction.
 class FormDataImporterTest_ExtractCreditCardFromForm
     : public FormDataImporterTest {
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 4b7eca1..18a5973 100644
--- a/components/autofill/core/browser/foundations/browser_autofill_manager_unittest.cc
+++ b/components/autofill/core/browser/foundations/browser_autofill_manager_unittest.cc
@@ -183,6 +183,7 @@
 
 constexpr Suggestion::Icon kAddressEntryIcon = Suggestion::Icon::kAccount;
 constexpr char kPlusAddress[] = "plus+remote@plus.plus";
+constexpr char kEllipsisDotSeparator[] = "\u2022";
 
 // Action `SaveArgElementsTo<k>(pointer)` saves the value pointed to by the
 // `k`th (0-based) argument of the mock function by moving it to `*pointer`.
@@ -204,13 +205,22 @@
   return !BUILDFLAG(IS_IOS);
 }
 
+bool ShouldUseNewFopDisplay() {
+#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
+  return false;
+#else
+  return base::FeatureList::IsEnabled(
+      features::kAutofillEnableNewFopDisplayDesktop);
+#endif
+}
+
 // The number of obfuscation dots we use as a prefix when showing a credit
 // card's last four.
 int ObfuscationLengthForCreditCardLastFourDigits() {
 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
   return 2;
 #else
-  return 4;
+  return ShouldUseNewFopDisplay() ? 2 : 4;
 #endif
 }
 
@@ -226,7 +236,13 @@
       {Suggestion::Text(card.ObfuscatedNumberWithVisibleLastFourDigits(
           ObfuscationLengthForCreditCardLastFourDigits()))}};
 #else
-  if (ShouldSplitCardNameAndLastFourDigitsForMetadata()) {
+  if (ShouldUseNewFopDisplay()) {
+    suggestion_labels = {
+        {Suggestion::Text(card.NetworkAndLastFourDigits(
+             ObfuscationLengthForCreditCardLastFourDigits())),
+         Suggestion::Text(u"•"),
+         Suggestion::Text(card.AbbreviatedExpirationDateForDisplay(false))}};
+  } else if (ShouldSplitCardNameAndLastFourDigitsForMetadata()) {
     // First label contains card name details and second label contains
     // obfuscated last four.
     suggestion_labels = {
@@ -260,18 +276,44 @@
           : nickname;
   std::string obfuscated_card_digits = test::ObfuscatedCardDigitsAsUTF8(
       last_four, ObfuscationLengthForCreditCardLastFourDigits());
+  std::string network_and_last_four =
+      base::StrCat({base::UTF16ToUTF8(CreditCard::NetworkForDisplay(network)),
+                    std::string("  "), obfuscated_card_digits});
+  std::vector<std::vector<Suggestion::Text>> network_last_four_and_exp_labels =
+      std::vector<std::vector<Suggestion::Text>>{
+          {Suggestion::Text(base::UTF8ToUTF16(network_and_last_four)),
+           Suggestion::Text(u"•"),
+           Suggestion::Text(base::UTF8ToUTF16(expiration_date_label))}};
   if (type == CREDIT_CARD_NUMBER) {
+    if (ShouldUseNewFopDisplay()) {
+      if (!nickname.empty()) {
+        return Suggestion(
+            /*main_text=*/nickname,
+            /*labels=*/network_last_four_and_exp_labels, icon,
+            SuggestionType::kCreditCardEntry);
+      } else {
+        std::vector<std::string> minor_texts = {kEllipsisDotSeparator,
+                                                expiration_date_label};
+        return Suggestion(
+            /*main_text=*/network_and_last_four,
+            /*minor_text_labels=*/minor_texts,
+            /*label=*/"", icon, SuggestionType::kCreditCardEntry);
+      }
+    }
     if (ShouldSplitCardNameAndLastFourDigitsForMetadata()) {
       std::vector<std::string> minor_text = {obfuscated_card_digits};
       return Suggestion(
-          /*main_text=*/network_or_nickname, minor_text,
+          /*main_text=*/network_or_nickname,
+          /*minor_text_labels=*/minor_text,
           /*label=*/expiration_date_label, icon,
           SuggestionType::kCreditCardEntry);
     } else {
 #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
-      // We use a longer label on desktop platforms.
-      expiration_date_label =
-          std::string("Expires on ") + expiration_date_label;
+      if (!ShouldUseNewFopDisplay()) {
+        // We use a longer label on desktop platforms.
+        expiration_date_label =
+            std::string("Expires on ") + expiration_date_label;
+      }
 #endif
       return Suggestion(
           /*main_text=*/base::StrCat(
@@ -286,6 +328,8 @@
       // The label is formatted as either "••••1234" or "••1234".
       labels.push_back(
           {Suggestion::Text(base::UTF8ToUTF16(obfuscated_card_digits))});
+    } else if (ShouldUseNewFopDisplay()) {
+      labels = network_last_four_and_exp_labels;
     } else if (ShouldSplitCardNameAndLastFourDigitsForMetadata()) {
       // The label is formatted as "Product Description/Nickname/Network
       // ••••1234".
@@ -1847,7 +1891,6 @@
   autofill_field->set_autofilled_type(autofill_field->Type().GetStorableType());
 
   OnAskForValuesToFill(form, firstname_field);
-#if !BUILDFLAG(IS_IOS)
   // Test that we sent the right values to the external delegate.
   external_delegate()->CheckSuggestions(
       firstname_field.global_id(),
@@ -1857,15 +1900,6 @@
                   SuggestionType::kAddressFieldByFieldFilling),
        CreateSeparator(), CreateUndoOrClearFormSuggestion(),
        CreateManageAddressesSuggestion()});
-#else
-  // Test that we sent the right values to the external delegate.
-  external_delegate()->CheckSuggestions(
-      firstname_field.global_id(),
-      {Suggestion("Elvis", "3734 Elvis Presley Blvd.", kAddressEntryIcon,
-                  SuggestionType::kAddressEntry),
-       CreateSeparator(), CreateUndoOrClearFormSuggestion(),
-       CreateManageAddressesSuggestion()});
-#endif  // !BUILDFLAG(IS_IOS)
 }
 
 // Test that we return no suggestions when the form has no relevant fields.
@@ -1978,7 +2012,15 @@
     : public BrowserAutofillManagerTest,
       public testing::WithParamInterface<bool> {
  public:
-  BrowserAutofillManagerTestForMetadataCardSuggestions()  = default;
+  BrowserAutofillManagerTestForMetadataCardSuggestions() {
+#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
+    feature_flags_.InitAndEnableFeature(
+        features::kAutofillEnableNewFopDisplayDesktop);
+#endif
+  }
+
+ private:
+  base::test::ScopedFeatureList feature_flags_;
 };
 
 INSTANTIATE_TEST_SUITE_P(All,
@@ -3044,7 +3086,6 @@
   autofill_field->set_autofilled_type(autofill_field->Type().GetStorableType());
   field.set_value(u"Elvis");
   OnAskForValuesToFill(form, field);
-#if !BUILDFLAG(IS_IOS)
   // Test that we sent the right values to the external delegate.
   external_delegate()->CheckSuggestions(
       field.global_id(),
@@ -3054,15 +3095,6 @@
                   SuggestionType::kAddressFieldByFieldFilling),
        CreateSeparator(), CreateUndoOrClearFormSuggestion(),
        CreateManageAddressesSuggestion()});
-#else
-  // Test that we sent the right values to the external delegate.
-  external_delegate()->CheckSuggestions(
-      field.global_id(),
-      {Suggestion("Elvis", "3734 Elvis Presley Blvd.", kAddressEntryIcon,
-                  SuggestionType::kAddressEntry),
-       CreateSeparator(), CreateUndoOrClearFormSuggestion(),
-       CreateManageAddressesSuggestion()});
-#endif  // !BUILDFLAG(IS_IOS)
 }
 #endif  // !BUILDFLAG(IS_ANDROID)
 
@@ -7303,7 +7335,12 @@
   BrowserAutofillManagerTestForSharingNickname()
       : local_nickname_(GetParam().local_nickname),
         server_nickname_(GetParam().server_nickname),
-        expected_nickname_(GetParam().expected_nickname) {}
+        expected_nickname_(GetParam().expected_nickname) {
+#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
+    feature_flags_.InitAndEnableFeature(
+        features::kAutofillEnableNewFopDisplayDesktop);
+#endif
+  }
 
   CreditCard GetLocalCard() {
     CreditCard local_card("287151C8-6AB1-487C-9095-28E80BE5DA15",
@@ -7335,7 +7372,7 @@
     return masked_server_card;
   }
 
-  base::test::ScopedFeatureList card_metadata_flags_;
+  base::test::ScopedFeatureList feature_flags_;
   std::string local_nickname_;
   std::string server_nickname_;
   std::string expected_nickname_;
diff --git a/components/autofill/core/browser/payments/payments_autofill_client.cc b/components/autofill/core/browser/payments/payments_autofill_client.cc
index 5fab001a..392011e 100644
--- a/components/autofill/core/browser/payments/payments_autofill_client.cc
+++ b/components/autofill/core/browser/payments/payments_autofill_client.cc
@@ -257,4 +257,8 @@
 
 void PaymentsAutofillClient::DismissSelectBnplIssuerDialog() {}
 
+bool PaymentsAutofillClient::IsTabModalPopup() const {
+  return false;
+}
+
 }  // namespace autofill::payments
diff --git a/components/autofill/core/browser/payments/payments_autofill_client.h b/components/autofill/core/browser/payments/payments_autofill_client.h
index 31823712..c0bd5e08a 100644
--- a/components/autofill/core/browser/payments/payments_autofill_client.h
+++ b/components/autofill/core/browser/payments/payments_autofill_client.h
@@ -582,6 +582,9 @@
 
   // Dismiss the issuer selection dialog for BNPL.
   virtual void DismissSelectBnplIssuerDialog();
+
+  // Checks if the browser popup is a tab modal popup.
+  virtual bool IsTabModalPopup() const;
 };
 
 }  // namespace payments
diff --git a/components/autofill/core/browser/payments/test_payments_autofill_client.cc b/components/autofill/core/browser/payments/test_payments_autofill_client.cc
index 87a7ed9..000778d 100644
--- a/components/autofill/core/browser/payments/test_payments_autofill_client.cc
+++ b/components/autofill/core/browser/payments/test_payments_autofill_client.cc
@@ -220,6 +220,10 @@
   return false;
 }
 
+bool TestPaymentsAutofillClient::IsTabModalPopup() const {
+  return is_tab_model_popup_;
+}
+
 #if !BUILDFLAG(IS_IOS)
 std::unique_ptr<webauthn::InternalAuthenticator>
 TestPaymentsAutofillClient::CreateCreditCardInternalAuthenticator(
diff --git a/components/autofill/core/browser/payments/test_payments_autofill_client.h b/components/autofill/core/browser/payments/test_payments_autofill_client.h
index cb94aa22..74282207 100644
--- a/components/autofill/core/browser/payments/test_payments_autofill_client.h
+++ b/components/autofill/core/browser/payments/test_payments_autofill_client.h
@@ -110,6 +110,7 @@
       base::WeakPtr<TouchToFillDelegate> delegate,
       base::span<const CreditCard> cards_to_suggest,
       base::span<const Suggestion> suggestions) override;
+  bool IsTabModalPopup() const override;
 #if !BUILDFLAG(IS_IOS)
   std::unique_ptr<webauthn::InternalAuthenticator>
   CreateCreditCardInternalAuthenticator(AutofillDriver* driver) override;
@@ -193,6 +194,10 @@
     return unmask_authenticator_selection_dialog_shown_;
   }
 
+  void set_is_tab_model_popup(bool is_tab_model_popup) {
+    is_tab_model_popup_ = is_tab_model_popup;
+  }
+
 #if BUILDFLAG(IS_ANDROID)
   // Set up a mock to simulate successful mandatory reauth when autofilling
   // payment methods.
@@ -220,6 +225,8 @@
   // True if LoadRiskData() was called, false otherwise.
   bool risk_data_loaded_ = false;
 
+  bool is_tab_model_popup_ = false;
+
   AutofillProgressDialogType autofill_progress_dialog_type_ =
       AutofillProgressDialogType::kServerCardUnmaskProgressDialog;
 
diff --git a/components/autofill/core/browser/suggestions/payments/payments_suggestion_generator.cc b/components/autofill/core/browser/suggestions/payments/payments_suggestion_generator.cc
index 0b181f5..2ceaa5d 100644
--- a/components/autofill/core/browser/suggestions/payments/payments_suggestion_generator.cc
+++ b/components/autofill/core/browser/suggestions/payments/payments_suggestion_generator.cc
@@ -63,6 +63,7 @@
 namespace {
 
 constexpr uint64_t kCentsPerDollar = 100;
+constexpr char16_t kEllipsisDotSeparator[] = u"\u2022";
 
 Suggestion CreateSeparator() {
   Suggestion suggestion;
@@ -128,12 +129,21 @@
   return {};
 }
 
+bool ShouldUseNewFopDisplay() {
+#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
+  return false;
+#else
+  return base::FeatureList::IsEnabled(
+      features::kAutofillEnableNewFopDisplayDesktop);
+#endif
+}
+
 int GetObfuscationLength() {
 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
   // On Android and iOS, the obfuscation length is 2.
   return 2;
 #else
-  return 4;
+  return ShouldUseNewFopDisplay() ? 2 : 4;
 #endif
 }
 
@@ -271,12 +281,22 @@
   }
 
   if (trigger_field_type == CREDIT_CARD_NUMBER) {
+    if (ShouldUseNewFopDisplay()) {
+      std::optional<std::u16string> identifier =
+          credit_card.CardIdentifierForAutofillDisplay(nickname);
+      if (identifier.has_value()) {
+        return create_text(*identifier);
+      } else {
+        return create_text(
+            credit_card.NetworkAndLastFourDigits(GetObfuscationLength()),
+            credit_card.AbbreviatedExpirationDateForDisplay(false));
+      }
+    }
     if (ShouldSplitCardNameAndLastFourDigits()) {
       return create_text(credit_card.CardNameForAutofillDisplay(nickname),
                          credit_card.ObfuscatedNumberWithVisibleLastFourDigits(
                              GetObfuscationLength()));
     }
-
     return create_text(credit_card.CardNameAndLastFourDigits(
         nickname, GetObfuscationLength()));
   }
@@ -366,6 +386,18 @@
         credit_card.GetInfo(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, app_locale))}};
 #else
     std::vector<std::vector<Suggestion::Text>> labels;
+
+    // If the main text is the card's nickname or product description,
+    // the network, last four digits, and expiration date must be displayed
+    // separately in another row.
+    if (ShouldUseNewFopDisplay() && !suggestion.main_text.value.empty() &&
+        suggestion.minor_texts.empty()) {
+      labels.push_back({Suggestion::Text(credit_card.NetworkAndLastFourDigits(
+                            GetObfuscationLength())),
+                        Suggestion::Text(kEllipsisDotSeparator),
+                        Suggestion::Text(credit_card.GetInfo(
+                            CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, app_locale))});
+    }
     std::optional<Suggestion::Text> benefit_label =
         GetCreditCardBenefitSuggestionLabel(credit_card, client);
     if (benefit_label) {
@@ -389,10 +421,13 @@
         }
       }
     }
-    labels.push_back({Suggestion::Text(
-        ShouldSplitCardNameAndLastFourDigits()
-            ? credit_card.GetInfo(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, app_locale)
-            : credit_card.DescriptiveExpiration(app_locale))});
+    if (!ShouldUseNewFopDisplay()) {
+      labels.push_back({Suggestion::Text(
+          ShouldSplitCardNameAndLastFourDigits()
+              ? credit_card.GetInfo(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR,
+                                    app_locale)
+              : credit_card.DescriptiveExpiration(app_locale))});
+    }
     suggestion.labels = std::move(labels);
 #endif  // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
     return;
@@ -431,6 +466,15 @@
     return;
   }
 
+  if (ShouldUseNewFopDisplay()) {
+    suggestion.labels = {{Suggestion::Text(credit_card.NetworkAndLastFourDigits(
+                              GetObfuscationLength())),
+                          Suggestion::Text(kEllipsisDotSeparator),
+                          Suggestion::Text(credit_card.GetInfo(
+                              CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, app_locale))}};
+    return;
+  }
+
   if (ShouldSplitCardNameAndLastFourDigits()) {
     // Format the label as "Product Description/Nickname/Network  ••••1234".
     // If the card name is too long, it will be truncated from the tail.
@@ -543,16 +587,31 @@
     suggestion.labels = {};
     std::optional<Suggestion::Text> benefit_label =
         GetCreditCardBenefitSuggestionLabel(credit_card, client);
+    if (ShouldUseNewFopDisplay() && suggestion.minor_texts.empty()) {
+      // minor_texts empty means that the card has either nickname or
+      // product description, so add network and last four digits as a
+      // separate label.
+      suggestion.labels = {{Suggestion::Text(
+          credit_card.NetworkAndLastFourDigits(GetObfuscationLength()))}};
+    }
     if (benefit_label && client.GetPersonalDataManager()
                              .payments_data_manager()
                              .IsCardEligibleForBenefits(credit_card)) {
-      suggestion.labels.push_back({*benefit_label});
+      // For the new-FOP display feature, when the merchant opts out
+      // (that is, the suggestion is not acceptable), the benefit is not
+      // shown because a merchant opt-out message will be displayed instead.
+      if (!ShouldUseNewFopDisplay() || suggestion.IsAcceptable()) {
+        suggestion.labels.push_back({*benefit_label});
+      }
     }
   }
-  if (suggestion.IsAcceptable()) {
+  // For the new-FOP display feature, a virtual card label will not be added
+  // as it will be shown as a badge.
+  if (!ShouldUseNewFopDisplay() && suggestion.IsAcceptable()) {
     suggestion.labels.push_back(
         std::vector<Suggestion::Text>{Suggestion::Text(virtual_card_label)});
-  } else {
+  }
+  if (!suggestion.IsAcceptable()) {
     suggestion.labels.push_back(std::vector<Suggestion::Text>{
         Suggestion::Text(virtual_card_disabled_label)});
   }
@@ -803,7 +862,11 @@
       credit_card, client, trigger_field_type);
   suggestion.main_text = std::move(main_text);
   if (!minor_text.value.empty()) {
-    suggestion.minor_texts = {std::move(minor_text)};
+    if (ShouldUseNewFopDisplay()) {
+      suggestion.minor_texts.emplace_back(kEllipsisDotSeparator,
+                                          Suggestion::Text::IsPrimary(true));
+    }
+    suggestion.minor_texts.emplace_back(std::move(minor_text));
   }
   SetSuggestionLabelsForCard(credit_card, client, trigger_field_type,
                              metadata_logging_context, suggestion);
diff --git a/components/autofill/core/browser/suggestions/payments/payments_suggestion_generator_unittest.cc b/components/autofill/core/browser/suggestions/payments/payments_suggestion_generator_unittest.cc
index cc9e484..f8e1f412 100644
--- a/components/autofill/core/browser/suggestions/payments/payments_suggestion_generator_unittest.cc
+++ b/components/autofill/core/browser/suggestions/payments/payments_suggestion_generator_unittest.cc
@@ -77,6 +77,11 @@
 using ::testing::UnorderedElementsAre;
 using ::testing::UnorderedElementsAreArray;
 
+#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
+// A dot ("•") separator.
+inline constexpr char16_t kEllipsisDotSeparator[] = u"\u2022";
+#endif  // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
+
 Matcher<Suggestion> EqualLabels(
     const std::vector<std::vector<Suggestion::Text>>& suggestion_objects) {
   return Field(&Suggestion::labels, suggestion_objects);
@@ -326,7 +331,8 @@
         /*enabled_features=*/
         {features::kAutofillEnableCardBenefitsForAmericanExpress,
          features::kAutofillEnableCardBenefitsForBmo,
-         features::kAutofillEnableCardBenefitsIph},
+         features::kAutofillEnableCardBenefitsIph,
+         features::kAutofillEnableNewFopDisplayDesktop},
         /*disabled_features=*/{});
 
     std::u16string benefit_description;
@@ -422,17 +428,13 @@
 #if !BUILDFLAG(IS_ANDROID)
 // Checks that for FPAN suggestions that the benefit description is displayed.
 TEST_P(AutofillCreditCardBenefitsLabelTest, BenefitSuggestionLabel_Fpan) {
-  EXPECT_THAT(
-      CreateCreditCardSuggestionForTest(card(), *autofill_client(),
-                                        CREDIT_CARD_NUMBER,
-                                        /*virtual_card_option=*/false,
-                                        /*card_linked_offer_available=*/false)
-          .labels,
-      ElementsAre(
-          std::vector<Suggestion::Text>{
-              Suggestion::Text(expected_benefit_text())},
-          std::vector<Suggestion::Text>{Suggestion::Text(card().GetInfo(
-              CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, /*app_locale=*/"en-US"))}));
+  EXPECT_THAT(CreateCreditCardSuggestionForTest(
+                  card(), *autofill_client(), CREDIT_CARD_NUMBER,
+                  /*virtual_card_option=*/false,
+                  /*card_linked_offer_available=*/false)
+                  .labels,
+              ElementsAre(std::vector<Suggestion::Text>{
+                  Suggestion::Text(expected_benefit_text())}));
 }
 
 // Checks that feature is set to display the credit card benefit IPH for
@@ -492,21 +494,36 @@
 }
 
 // Checks that for virtual cards suggestion the benefit description is shown
-// with a virtual card label appended.
+// as a label.
 TEST_P(AutofillCreditCardBenefitsLabelTest,
        BenefitSuggestionLabel_VirtualCard) {
+  EXPECT_THAT(CreateCreditCardSuggestionForTest(
+                  card(), *autofill_client(), CREDIT_CARD_NUMBER,
+                  /*virtual_card_option=*/true,
+                  /*card_linked_offer_available=*/false)
+                  .labels,
+              ElementsAre(std::vector<Suggestion::Text>{
+                  Suggestion::Text(expected_benefit_text())}));
+}
+
+// Checks that for merchant opt-out virtual cards suggestion the benefit
+// description is not shown.
+TEST_P(AutofillCreditCardBenefitsLabelTest,
+       BenefitSuggestionLabel_VirtualCard_MerchantOptOut) {
+  CreditCard virtual_card = CreditCard::CreateVirtualCard(card());
+  ON_CALL(*static_cast<MockAutofillOptimizationGuide*>(
+              autofill_client()->GetAutofillOptimizationGuide()),
+          ShouldBlockFormFieldSuggestion)
+      .WillByDefault(testing::Return(true));
   EXPECT_THAT(
-      CreateCreditCardSuggestionForTest(card(), *autofill_client(),
+      CreateCreditCardSuggestionForTest(virtual_card, *autofill_client(),
                                         CREDIT_CARD_NUMBER,
                                         /*virtual_card_option=*/true,
                                         /*card_linked_offer_available=*/false)
           .labels,
-      ElementsAre(
-          std::vector<Suggestion::Text>{
-              Suggestion::Text(expected_benefit_text())},
-          std::vector<Suggestion::Text>{
-              Suggestion::Text(l10n_util::GetStringUTF16(
-                  IDS_AUTOFILL_VIRTUAL_CARD_SUGGESTION_OPTION_VALUE))}));
+      ElementsAre(std::vector<Suggestion::Text>{
+          Suggestion::Text(l10n_util::GetStringUTF16(
+              IDS_AUTOFILL_VIRTUAL_CARD_DISABLED_SUGGESTION_OPTION_VALUE))}));
 }
 
 // Checks that for credit card suggestions with eligible benefits, the
@@ -538,6 +555,135 @@
   }
   autofill_client()->set_last_committed_primary_main_frame_url(
       GURL("https://random-url.com"));
+  Suggestion suggestion = CreateCreditCardSuggestionForTest(
+      card(), *autofill_client(), CREDIT_CARD_NUMBER,
+      /*virtual_card_option=*/false,
+      /*card_linked_offer_available=*/false);
+
+  // Merchant benefit description is not returned.
+  EXPECT_TRUE(suggestion.labels.empty());
+}
+
+// Checks that the category benefit description is not displayed for suggestions
+// where the webpage's category in the optimization guide is different from the
+// benefit's applicable category.
+TEST_P(AutofillCreditCardBenefitsLabelTest,
+       BenefitSuggestionLabelNotDisplayed_CategoryIsDifferent) {
+  if (!std::holds_alternative<CreditCardCategoryBenefit>(GetBenefit())) {
+    GTEST_SKIP() << "This test should not run for non-category benefits.";
+  }
+
+  ON_CALL(*static_cast<MockAutofillOptimizationGuide*>(
+              autofill_client()->GetAutofillOptimizationGuide()),
+          AttemptToGetEligibleCreditCardBenefitCategory)
+      .WillByDefault(testing::Return(
+          CreditCardCategoryBenefit::BenefitCategory::kUnknownBenefitCategory));
+  Suggestion suggestion = CreateCreditCardSuggestionForTest(
+      card(), *autofill_client(), CREDIT_CARD_NUMBER,
+      /*virtual_card_option=*/false,
+      /*card_linked_offer_available=*/false);
+
+  // Category benefit description is not returned.
+  EXPECT_TRUE(suggestion.labels.empty());
+}
+
+// Checks that the benefit description is not displayed when benefit suggestions
+// are disabled for the given card and url.
+TEST_P(AutofillCreditCardBenefitsLabelTest,
+       BenefitSuggestionLabelNotDisplayed_BlockedUrl) {
+  ON_CALL(*static_cast<MockAutofillOptimizationGuide*>(
+              autofill_client()->GetAutofillOptimizationGuide()),
+          ShouldBlockBenefitSuggestionLabelsForCardAndUrl)
+      .WillByDefault(testing::Return(true));
+  Suggestion suggestion = CreateCreditCardSuggestionForTest(
+      card(), *autofill_client(), CREDIT_CARD_NUMBER,
+      /*virtual_card_option=*/false,
+      /*card_linked_offer_available=*/false);
+
+  // Benefit description is not returned.
+  EXPECT_TRUE(suggestion.labels.empty());
+}
+
+// Checks that for FPAN suggestions that the benefit description is displayed.
+TEST_P(AutofillCreditCardBenefitsLabelTest,
+       BenefitSuggestionLabel_Fpan_NewFopDisplayOff) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndDisableFeature(
+      features::kAutofillEnableNewFopDisplayDesktop);
+  EXPECT_THAT(
+      CreateCreditCardSuggestionForTest(card(), *autofill_client(),
+                                        CREDIT_CARD_NUMBER,
+                                        /*virtual_card_option=*/false,
+                                        /*card_linked_offer_available=*/false)
+          .labels,
+      ElementsAre(
+          std::vector<Suggestion::Text>{
+              Suggestion::Text(expected_benefit_text())},
+          std::vector<Suggestion::Text>{Suggestion::Text(card().GetInfo(
+              CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, /*app_locale=*/"en-US"))}));
+}
+
+// Checks that for virtual cards suggestion the benefit description is shown
+// with a virtual card label appended.
+TEST_P(AutofillCreditCardBenefitsLabelTest,
+       BenefitSuggestionLabel_VirtualCard_NewFopDisplayOff) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndDisableFeature(
+      features::kAutofillEnableNewFopDisplayDesktop);
+
+  EXPECT_THAT(
+      CreateCreditCardSuggestionForTest(card(), *autofill_client(),
+                                        CREDIT_CARD_NUMBER,
+                                        /*virtual_card_option=*/true,
+                                        /*card_linked_offer_available=*/false)
+          .labels,
+      ElementsAre(
+          std::vector<Suggestion::Text>{
+              Suggestion::Text(expected_benefit_text())},
+          std::vector<Suggestion::Text>{
+              Suggestion::Text(l10n_util::GetStringUTF16(
+                  IDS_AUTOFILL_VIRTUAL_CARD_SUGGESTION_OPTION_VALUE))}));
+}
+
+// Checks that for merchant opt-out virtual cards suggestion the benefit
+// description is not shown.
+TEST_P(AutofillCreditCardBenefitsLabelTest,
+       BenefitSuggestionLabel_VirtualCard_MerchantOptOut_NewFopDisplayOff) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndDisableFeature(
+      features::kAutofillEnableNewFopDisplayDesktop);
+  CreditCard virtual_card = CreditCard::CreateVirtualCard(card());
+  ON_CALL(*static_cast<MockAutofillOptimizationGuide*>(
+              autofill_client()->GetAutofillOptimizationGuide()),
+          ShouldBlockFormFieldSuggestion)
+      .WillByDefault(testing::Return(true));
+  EXPECT_THAT(
+      CreateCreditCardSuggestionForTest(virtual_card, *autofill_client(),
+                                        CREDIT_CARD_NUMBER,
+                                        /*virtual_card_option=*/true,
+                                        /*card_linked_offer_available=*/false)
+          .labels,
+      ElementsAre(
+          std::vector<Suggestion::Text>{
+              Suggestion::Text(expected_benefit_text())},
+          std::vector<
+              Suggestion::Text>{Suggestion::Text(l10n_util::GetStringUTF16(
+              IDS_AUTOFILL_VIRTUAL_CARD_DISABLED_SUGGESTION_OPTION_VALUE))}));
+}
+
+// Checks that the merchant benefit description is not displayed for suggestions
+// where the webpage's URL is different from the benefit's applicable URL.
+TEST_P(
+    AutofillCreditCardBenefitsLabelTest,
+    BenefitSuggestionLabelNotDisplayed_MerchantUrlIsDifferent_NewFopDisplayOff) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndDisableFeature(
+      features::kAutofillEnableNewFopDisplayDesktop);
+  if (!std::holds_alternative<CreditCardMerchantBenefit>(GetBenefit())) {
+    GTEST_SKIP() << "This test should not run for non-merchant benefits.";
+  }
+  autofill_client()->set_last_committed_primary_main_frame_url(
+      GURL("https://random-url.com"));
   // Merchant benefit description is not returned.
   EXPECT_THAT(
       CreateCreditCardSuggestionForTest(card(), *autofill_client(),
@@ -552,8 +698,12 @@
 // Checks that the category benefit description is not displayed for suggestions
 // where the webpage's category in the optimization guide is different from the
 // benefit's applicable category.
-TEST_P(AutofillCreditCardBenefitsLabelTest,
-       BenefitSuggestionLabelNotDisplayed_CategoryIsDifferent) {
+TEST_P(
+    AutofillCreditCardBenefitsLabelTest,
+    BenefitSuggestionLabelNotDisplayed_CategoryIsDifferent_NewFopDisplayOff) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndDisableFeature(
+      features::kAutofillEnableNewFopDisplayDesktop);
   if (!std::holds_alternative<CreditCardCategoryBenefit>(GetBenefit())) {
     GTEST_SKIP() << "This test should not run for non-category benefits.";
   }
@@ -578,7 +728,10 @@
 // Checks that the benefit description is not displayed when benefit suggestions
 // are disabled for the given card and url.
 TEST_P(AutofillCreditCardBenefitsLabelTest,
-       BenefitSuggestionLabelNotDisplayed_BlockedUrl) {
+       BenefitSuggestionLabelNotDisplayed_BlockedUrl_NewFopDisplayOff) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndDisableFeature(
+      features::kAutofillEnableNewFopDisplayDesktop);
   ON_CALL(*static_cast<MockAutofillOptimizationGuide*>(
               autofill_client()->GetAutofillOptimizationGuide()),
           ShouldBlockBenefitSuggestionLabelsForCardAndUrl)
@@ -2056,7 +2209,19 @@
 // This class helps test the credit card contents that are displayed in
 // Autofill suggestions. It covers suggestions on Desktop/Android dropdown,
 // and on Android keyboard accessory.
-using AutofillCreditCardSuggestionContentTest = PaymentsSuggestionGeneratorTest;
+class AutofillCreditCardSuggestionContentTest
+    : public PaymentsSuggestionGeneratorTest {
+ public:
+  AutofillCreditCardSuggestionContentTest() {
+    feature_list_metadata_.InitAndEnableFeature(
+        features::kAutofillEnableNewFopDisplayDesktop);
+  }
+
+  ~AutofillCreditCardSuggestionContentTest() override = default;
+
+ private:
+  base::test::ScopedFeatureList feature_list_metadata_;
+};
 
 // Verify that the suggestion's texts are populated correctly for a virtual card
 // suggestion when the cardholder name field is focused.
@@ -2106,24 +2271,20 @@
               EqualLabels({{CreditCard::GetObfuscatedStringForCardDigits(
                   /*obfuscation_length=*/2, u"1111")}}));
 #else
-  // There should be 1 lines of labels with 2 columns:
-  // 1. Card name "Visa".
-  // 2. obfuscated last 4 digits "....1111".
-  ASSERT_EQ(virtual_card_name_field_suggestion.labels.size(), 2U);
-  ASSERT_EQ(virtual_card_name_field_suggestion.labels[0].size(), 2U);
-  EXPECT_EQ(virtual_card_name_field_suggestion.labels[0][0].value, u"Visa");
-  EXPECT_EQ(virtual_card_name_field_suggestion.labels[0][1].value,
-            CreditCard::GetObfuscatedStringForCardDigits(
-                /*obfuscation_length=*/4, u"1111"));
+  // There should be 1 lines of labels with 3 columns:
+  // 1. Card Network + last 4 digits.
+  // 2. A dot ("•") separator.
+  // 3. Expiration date.
+  EXPECT_THAT(
+      virtual_card_name_field_suggestion,
+      EqualLabels(
+          {{server_card.NetworkAndLastFourDigits(/*obfuscation_length=*/2),
+            kEllipsisDotSeparator,
+            server_card.AbbreviatedExpirationDateForDisplay(false)}}));
 #endif
   EXPECT_EQ(virtual_card_name_field_suggestion.IsAcceptable(), true);
   EXPECT_EQ(virtual_card_name_field_suggestion.iph_metadata.feature,
             &feature_engagement::kIPHAutofillVirtualCardSuggestionFeature);
-#if !BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_ANDROID)
-  ASSERT_EQ(virtual_card_name_field_suggestion.labels[1].size(), 1U);
-  EXPECT_EQ(virtual_card_name_field_suggestion.labels[1][0].value,
-            u"Virtual card");
-#endif
 }
 
 // Verify that the suggestion's texts are populated correctly for a virtual card
@@ -2158,11 +2319,14 @@
             CreditCard::GetObfuscatedStringForCardDigits(
                 /*obfuscation_length=*/2, u"1111"));
 #else
-  // Card name and the obfuscated last four digits are shown separately.
-  EXPECT_EQ(virtual_card_number_field_suggestion.main_text.value, u"Visa");
+  // For Desktop, display the card name and the last 4 digits, followed
+  // by a dot separator and expiration date.
+  EXPECT_EQ(virtual_card_number_field_suggestion.main_text.value,
+            server_card.NetworkAndLastFourDigits(/*obfuscation_length=*/2));
   EXPECT_EQ(virtual_card_number_field_suggestion.minor_texts[0].value,
-            CreditCard::GetObfuscatedStringForCardDigits(
-                /*obfuscation_length=*/4, u"1111"));
+            kEllipsisDotSeparator);
+  EXPECT_EQ(virtual_card_number_field_suggestion.minor_texts[1].value,
+            server_card.AbbreviatedExpirationDateForDisplay(false));
 #endif
   EXPECT_EQ(virtual_card_number_field_suggestion.IsAcceptable(), true);
   EXPECT_EQ(virtual_card_number_field_suggestion.iph_metadata.feature,
@@ -2170,10 +2334,6 @@
 #if BUILDFLAG(IS_ANDROID)
   // For the keyboard accessory, there is no label.
   ASSERT_TRUE(virtual_card_number_field_suggestion.labels.empty());
-// For Desktop dropdown, "Virtual card" is the label.
-#elif !BUILDFLAG(IS_IOS)
-  EXPECT_THAT(virtual_card_number_field_suggestion,
-              EqualLabels({{u"Virtual card"}}));
 #endif
 }
 
@@ -2205,14 +2365,14 @@
               EqualLabels({{CreditCard::GetObfuscatedStringForCardDigits(
                   /*obfuscation_length=*/2, u"1111")}}));
 #else
-  // For Desktop/Android, the label is "CardName  ....1111". Card name and
-  // last four are shown separately.
-  ASSERT_EQ(real_card_name_field_suggestion.labels.size(), 1U);
-  ASSERT_EQ(real_card_name_field_suggestion.labels[0].size(), 2U);
-  EXPECT_EQ(real_card_name_field_suggestion.labels[0][0].value, u"Visa");
-  EXPECT_EQ(real_card_name_field_suggestion.labels[0][1].value,
-            CreditCard::GetObfuscatedStringForCardDigits(
-                /*obfuscation_length=*/4, u"1111"));
+  // For Desktop, the label is "Visa ..1111 • 02/29". Network name and
+  // last four followed by expiration date.
+  EXPECT_THAT(
+      real_card_name_field_suggestion,
+      EqualLabels(
+          {{server_card.NetworkAndLastFourDigits(/*obfuscation_length=*/2),
+            kEllipsisDotSeparator,
+            server_card.AbbreviatedExpirationDateForDisplay(false)}}));
 #endif
 }
 
@@ -2236,26 +2396,36 @@
       base::StrCat({u"Visa  ", CreditCard::GetObfuscatedStringForCardDigits(
                                    /*obfuscation_length=*/2, u"1111")}));
   EXPECT_TRUE(real_card_number_field_suggestion.minor_texts.empty());
-#elif BUILDFLAG(IS_ANDROID)
-  // For Android, split the first line and populate the card name and
-  // the last 4 digits separately.
-  EXPECT_EQ(real_card_number_field_suggestion.main_text.value, u"Visa");
-  EXPECT_EQ(real_card_number_field_suggestion.minor_texts[0].value,
-            CreditCard::GetObfuscatedStringForCardDigits(2, u"1111"));
-#else
-  // For Desktop, split the first line and populate the card name and
-  // the last 4 digits separately.
-  EXPECT_EQ(real_card_number_field_suggestion.main_text.value, u"Visa");
-  EXPECT_EQ(real_card_number_field_suggestion.minor_texts[0].value,
-            CreditCard::GetObfuscatedStringForCardDigits(4, u"1111"));
-#endif
-
   // The label is the expiration date formatted as mm/yy.
   EXPECT_THAT(
       real_card_number_field_suggestion,
       EqualLabels(
           {{base::StrCat({base::UTF8ToUTF16(test::NextMonth()), u"/",
                           base::UTF8ToUTF16(test::NextYear().substr(2))})}}));
+#elif BUILDFLAG(IS_ANDROID)
+  // For Android, split the first line and populate the card name and
+  // the last 4 digits separately.
+  EXPECT_EQ(real_card_number_field_suggestion.main_text.value, u"Visa");
+  EXPECT_EQ(real_card_number_field_suggestion.minor_texts[0].value,
+            CreditCard::GetObfuscatedStringForCardDigits(2, u"1111"));
+  // The label is the expiration date formatted as mm/yy.
+  EXPECT_THAT(
+      real_card_number_field_suggestion,
+      EqualLabels(
+          {{base::StrCat({base::UTF8ToUTF16(test::NextMonth()), u"/",
+                          base::UTF8ToUTF16(test::NextYear().substr(2))})}}));
+#else
+  // For Desktop, display the card name and the last 4 digits, followed
+  // by a dot separator and expiration date.
+  EXPECT_EQ(real_card_number_field_suggestion.main_text.value,
+            server_card.NetworkAndLastFourDigits(/*obfuscation_length=*/2));
+  EXPECT_EQ(real_card_number_field_suggestion.minor_texts[0].value,
+            kEllipsisDotSeparator);
+  EXPECT_EQ(real_card_number_field_suggestion.minor_texts[1].value,
+            server_card.AbbreviatedExpirationDateForDisplay(false));
+  // The label is empty.
+  EXPECT_TRUE(real_card_number_field_suggestion.labels.empty());
+#endif
 }
 
 // Verify that the suggestion's texts are populated correctly for a local and
@@ -2452,9 +2622,139 @@
                         IDS_AUTOFILL_VIRTUAL_CARD_SUGGESTION_OPTION_VALUE) +
                     u" • " + card_type + u" " + obfuscated_number}}));
 }
-
 #endif  // BUILDFLAG(IS_IOS)
 
+#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
+// Verify that the suggestion's texts are populated correctly for a virtual card
+// suggestion when the cardholder name field is focused.
+TEST_F(
+    AutofillCreditCardSuggestionContentTest,
+    CreateCreditCardSuggestion_VirtualCardMetadata_NameField_NewFopDisplayOff) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndDisableFeature(
+      features::kAutofillEnableNewFopDisplayDesktop);
+  CreditCard server_card = CreateServerCard();
+
+  // Name field suggestion for virtual cards.
+  Suggestion virtual_card_name_field_suggestion =
+      CreateCreditCardSuggestionForTest(server_card, *autofill_client(),
+                                        CREDIT_CARD_NAME_FULL,
+                                        /*virtual_card_option=*/true,
+                                        /*card_linked_offer_available=*/false);
+
+  // On other platforms, the cardholder name is shown on the first line.
+  EXPECT_EQ(virtual_card_name_field_suggestion.main_text.value,
+            u"Elvis Presley");
+  EXPECT_TRUE(virtual_card_name_field_suggestion.minor_texts.empty());
+
+  // There should be 1 lines of labels with 2 columns:
+  // 1. Card name "Visa".
+  // 2. obfuscated last 4 digits "....1111".
+  ASSERT_EQ(virtual_card_name_field_suggestion.labels.size(), 2U);
+  ASSERT_EQ(virtual_card_name_field_suggestion.labels[0].size(), 2U);
+  EXPECT_EQ(virtual_card_name_field_suggestion.labels[0][0].value, u"Visa");
+  EXPECT_EQ(virtual_card_name_field_suggestion.labels[0][1].value,
+            CreditCard::GetObfuscatedStringForCardDigits(
+                /*obfuscation_length=*/4, u"1111"));
+  EXPECT_EQ(virtual_card_name_field_suggestion.IsAcceptable(), true);
+  EXPECT_EQ(virtual_card_name_field_suggestion.iph_metadata.feature,
+            &feature_engagement::kIPHAutofillVirtualCardSuggestionFeature);
+  ASSERT_EQ(virtual_card_name_field_suggestion.labels[1].size(), 1U);
+  EXPECT_EQ(virtual_card_name_field_suggestion.labels[1][0].value,
+            u"Virtual card");
+}
+
+// Verify that the suggestion's texts are populated correctly for a virtual card
+// suggestion when the card number field is focused.
+TEST_F(
+    AutofillCreditCardSuggestionContentTest,
+    CreateCreditCardSuggestion_VirtualCardMetadata_NumberField_NewFopDisplayOff) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndDisableFeature(
+      features::kAutofillEnableNewFopDisplayDesktop);
+  CreditCard server_card = CreateServerCard();
+
+  // Card number field suggestion for virtual cards.
+  Suggestion virtual_card_number_field_suggestion =
+      CreateCreditCardSuggestionForTest(server_card, *autofill_client(),
+                                        CREDIT_CARD_NUMBER,
+                                        /*virtual_card_option=*/true,
+                                        /*card_linked_offer_available=*/false);
+
+  // Card name and the obfuscated last four digits are shown separately.
+  EXPECT_EQ(virtual_card_number_field_suggestion.main_text.value, u"Visa");
+  EXPECT_EQ(virtual_card_number_field_suggestion.minor_texts[0].value,
+            CreditCard::GetObfuscatedStringForCardDigits(
+                /*obfuscation_length=*/4, u"1111"));
+  EXPECT_EQ(virtual_card_number_field_suggestion.IsAcceptable(), true);
+  EXPECT_EQ(virtual_card_number_field_suggestion.iph_metadata.feature,
+            &feature_engagement::kIPHAutofillVirtualCardSuggestionFeature);
+  EXPECT_THAT(virtual_card_number_field_suggestion,
+              EqualLabels({{u"Virtual card"}}));
+}
+
+// Verify that the suggestion's texts are populated correctly for a masked
+// server card suggestion when the cardholder name field is focused.
+TEST_F(
+    AutofillCreditCardSuggestionContentTest,
+    CreateCreditCardSuggestion_MaskedServerCardMetadata_NameField_NewFopDisplayOff) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndDisableFeature(
+      features::kAutofillEnableNewFopDisplayDesktop);
+  CreditCard server_card = CreateServerCard();
+
+  // Name field suggestion for non-virtual cards.
+  Suggestion real_card_name_field_suggestion =
+      CreateCreditCardSuggestionForTest(server_card, *autofill_client(),
+                                        CREDIT_CARD_NAME_FULL,
+                                        /*virtual_card_option=*/false,
+                                        /*card_linked_offer_available=*/false);
+
+  // Only the name is displayed on the first line.
+  EXPECT_EQ(real_card_name_field_suggestion.main_text.value, u"Elvis Presley");
+  EXPECT_TRUE(real_card_name_field_suggestion.minor_texts.empty());
+  // Card network and last four are shown separately.
+  ASSERT_EQ(real_card_name_field_suggestion.labels.size(), 1U);
+  ASSERT_EQ(real_card_name_field_suggestion.labels[0].size(), 2U);
+  EXPECT_EQ(real_card_name_field_suggestion.labels[0][0].value, u"Visa");
+  EXPECT_EQ(real_card_name_field_suggestion.labels[0][1].value,
+            CreditCard::GetObfuscatedStringForCardDigits(
+                /*obfuscation_length=*/4, u"1111"));
+}
+
+// Verify that the suggestion's texts are populated correctly for a masked
+// server card suggestion when the card number field is focused.
+TEST_F(
+    AutofillCreditCardSuggestionContentTest,
+    CreateCreditCardSuggestion_MaskedServerCardMetadata_NumberField_NewFopDisplayOff) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndDisableFeature(
+      features::kAutofillEnableNewFopDisplayDesktop);
+  CreditCard server_card = CreateServerCard();
+
+  // Card number field suggestion for non-virtual cards.
+  Suggestion real_card_number_field_suggestion =
+      CreateCreditCardSuggestionForTest(server_card, *autofill_client(),
+                                        CREDIT_CARD_NUMBER,
+                                        /*virtual_card_option=*/false,
+                                        /*card_linked_offer_available=*/false);
+
+  // Split the first line and populate the card name and the last 4 digits
+  // separately.
+  EXPECT_EQ(real_card_number_field_suggestion.main_text.value, u"Visa");
+  EXPECT_EQ(real_card_number_field_suggestion.minor_texts[0].value,
+            CreditCard::GetObfuscatedStringForCardDigits(4, u"1111"));
+
+  // The label is the expiration date formatted as mm/yy.
+  EXPECT_THAT(
+      real_card_number_field_suggestion,
+      EqualLabels(
+          {{base::StrCat({base::UTF8ToUTF16(test::NextMonth()), u"/",
+                          base::UTF8ToUTF16(test::NextYear().substr(2))})}}));
+}
+
+#endif  // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
+
 // The boolean param denotes if merchant has opted out of VCN.
 class AutofillCreditCardSuggestionContentVcnMerchantOptOutTest
     : public AutofillCreditCardSuggestionContentTest,
@@ -2529,6 +2829,124 @@
             CreditCard::GetObfuscatedStringForCardDigits(
                 /*obfuscation_length=*/2, u"4444"));
 #else
+  // Desktop: There should be one line for network and last four, and one line
+  // if merchant opt-out virtual card text.
+  ASSERT_EQ(virtual_card_name_field_suggestion.labels.size(),
+            is_merchant_opted_out() ? 2U : 1U);
+  if (is_merchant_opted_out()) {
+    EXPECT_THAT(
+        virtual_card_name_field_suggestion,
+        EqualLabels(
+            {{server_card.NetworkAndLastFourDigits(/*obfuscation_length=*/2),
+              kEllipsisDotSeparator,
+              server_card.AbbreviatedExpirationDateForDisplay(false)},
+             {l10n_util::GetStringUTF16(expected_message_id())}}));
+  } else {
+    EXPECT_THAT(
+        virtual_card_name_field_suggestion,
+        EqualLabels(
+            {{server_card.NetworkAndLastFourDigits(/*obfuscation_length=*/2),
+              kEllipsisDotSeparator,
+              server_card.AbbreviatedExpirationDateForDisplay(false)}}));
+  }
+#endif
+}
+
+// Verify that the suggestion's texts are populated correctly for a virtual
+// card suggestion when the card number field is focused based on if
+// merchant accepts virtual cards.
+TEST_P(
+    AutofillCreditCardSuggestionContentVcnMerchantOptOutTest,
+    CreateCreditCardSuggestion_VirtualCardMetadata_MerchantOptOut_NumberField) {
+  CreditCard server_card = test::GetVirtualCard();
+
+  // Card number field suggestion for virtual cards.
+  Suggestion virtual_card_number_field_suggestion =
+      CreateCreditCardSuggestionForTest(server_card, *autofill_client(),
+                                        CREDIT_CARD_NUMBER,
+                                        /*virtual_card_option=*/true,
+                                        /*card_linked_offer_available=*/false);
+
+  // `IsAcceptable()` returns false only when flag is enabled and merchant has
+  // opted out of VCN.
+  EXPECT_EQ(virtual_card_number_field_suggestion.IsAcceptable(),
+            !is_merchant_opted_out());
+  // `HasDeactivatedStyle()` returns true only when merchant has opted out of
+  // VCN.
+  EXPECT_EQ(virtual_card_number_field_suggestion.HasDeactivatedStyle(),
+            is_merchant_opted_out());
+  EXPECT_EQ(
+      virtual_card_number_field_suggestion.iph_metadata.feature,
+      virtual_card_number_field_suggestion.HasDeactivatedStyle()
+          ? &feature_engagement::
+                kIPHAutofillDisabledVirtualCardSuggestionFeature
+          : &feature_engagement::kIPHAutofillVirtualCardSuggestionFeature);
+
+#if BUILDFLAG(IS_ANDROID)
+  // In Android, when filling card number, the labels are removed.
+  ASSERT_TRUE(virtual_card_number_field_suggestion.labels.empty());
+#elif BUILDFLAG(IS_IOS)
+  // In iOS, when filling card number, only the expiration date will be shown.
+  ASSERT_EQ(virtual_card_number_field_suggestion.labels.size(), 1U);
+  EXPECT_EQ(virtual_card_number_field_suggestion.labels[0].size(), 1U);
+  EXPECT_NE(virtual_card_number_field_suggestion.labels[0][0].value,
+            l10n_util::GetStringUTF16(expected_message_id()));
+#else
+  // Desktop, the label should be one-line message if it's merchant opt out.
+  EXPECT_EQ(virtual_card_number_field_suggestion.labels.size(),
+            is_merchant_opted_out() ? 1U : 0U);
+#endif
+}
+
+// Verify that the suggestion's texts are populated correctly for a virtual
+// card suggestion when the cardholder name field is focused based on if
+// merchant accepts virtual cards.
+TEST_P(
+    AutofillCreditCardSuggestionContentVcnMerchantOptOutTest,
+    CreateCreditCardSuggestion_VirtualCardMetadata_MerchantOptOut_NameField_NewFopDisplayOff) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndDisableFeature(
+      features::kAutofillEnableNewFopDisplayDesktop);
+  CreditCard server_card = test::GetVirtualCard();
+
+  // Name field suggestion for virtual cards.
+  Suggestion virtual_card_name_field_suggestion =
+      CreateCreditCardSuggestionForTest(server_card, *autofill_client(),
+                                        CREDIT_CARD_NAME_FULL,
+                                        /*virtual_card_option=*/true,
+                                        /*card_linked_offer_available=*/false);
+
+  // `IsAcceptable()` returns false only when merchant has opted out of VCN.
+  EXPECT_EQ(virtual_card_name_field_suggestion.IsAcceptable(),
+            !is_merchant_opted_out());
+
+  // `HasDeactivatedStyle()` returns true only when merchant has opted out of
+  // VCN.
+  EXPECT_EQ(virtual_card_name_field_suggestion.HasDeactivatedStyle(),
+            is_merchant_opted_out());
+  EXPECT_EQ(
+      virtual_card_name_field_suggestion.iph_metadata.feature,
+      virtual_card_name_field_suggestion.HasDeactivatedStyle()
+          ? &feature_engagement::
+                kIPHAutofillDisabledVirtualCardSuggestionFeature
+          : &feature_engagement::kIPHAutofillVirtualCardSuggestionFeature);
+#if BUILDFLAG(IS_ANDROID)
+  // Android: There should be only 1 line of label: obfuscated last 4 digits
+  // "..4444".
+  EXPECT_THAT(virtual_card_name_field_suggestion,
+              EqualLabels({{CreditCard::GetObfuscatedStringForCardDigits(
+                  /*obfuscation_length=*/2, u"4444")}}));
+#elif BUILDFLAG(IS_IOS)
+  // iOS: In dropdown, there should be one line, with the value equal to
+  // obfuscated last four digits. And in AdjustVirtualCardSuggestionContent
+  // we would make minor text the value, and set main text as the virtual card
+  // label.
+  ASSERT_EQ(virtual_card_name_field_suggestion.labels.size(), 1U);
+  ASSERT_EQ(virtual_card_name_field_suggestion.labels[0].size(), 1U);
+  EXPECT_EQ(virtual_card_name_field_suggestion.labels[0][0].value,
+            CreditCard::GetObfuscatedStringForCardDigits(
+                /*obfuscation_length=*/2, u"4444"));
+#else
   // Desktop: There should be two lines, where first line is the card number
   // and second line is the virtual card text.
   ASSERT_EQ(virtual_card_name_field_suggestion.labels.size(), 2U);
@@ -2543,7 +2961,10 @@
 // merchant accepts virtual cards.
 TEST_P(
     AutofillCreditCardSuggestionContentVcnMerchantOptOutTest,
-    CreateCreditCardSuggestion_VirtualCardMetadata_MerchantOptOut_NumberField) {
+    CreateCreditCardSuggestion_VirtualCardMetadata_MerchantOptOut_NumberField_NewFopDisplayOff) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndDisableFeature(
+      features::kAutofillEnableNewFopDisplayDesktop);
   CreditCard server_card = test::GetVirtualCard();
 
   // Card number field suggestion for virtual cards.
diff --git a/components/autofill/core/browser/test_utils/valuables_data_test_utils.cc b/components/autofill/core/browser/test_utils/valuables_data_test_utils.cc
index b34e72c..d69d08db 100644
--- a/components/autofill/core/browser/test_utils/valuables_data_test_utils.cc
+++ b/components/autofill/core/browser/test_utils/valuables_data_test_utils.cc
@@ -15,14 +15,15 @@
       /*loyalty_card_id=*/ValuableId("loyalty_card_id_1"),
       /*merchant_name=*/"Deutsche Bahn", /*program_name=*/"BahnBonus",
       /*program_logo=*/GURL("https://empty.url.com"),
-      /*loyalty_card_number=*/"1234");
+      /*loyalty_card_number=*/"1234", {GURL("https://domain.example")});
 }
 
 LoyaltyCard CreateLoyaltyCard2() {
   return LoyaltyCard(/*loyalty_card_id=*/ValuableId("loyalty_card_id_2"),
                      /*merchant_name=*/"Lidl", /*program_name=*/"CustomerCard",
                      /*program_logo=*/GURL("https://empty.url.com"),
-                     /*loyalty_card_number=*/"4321");
+                     /*loyalty_card_number=*/"4321",
+                     {GURL("https://domain.example")});
 }
 
 }  // namespace autofill::test
diff --git a/components/autofill/core/browser/webdata/valuables/valuable_sync_bridge_unittest.cc b/components/autofill/core/browser/webdata/valuables/valuable_sync_bridge_unittest.cc
index fad029d..e62a9505 100644
--- a/components/autofill/core/browser/webdata/valuables/valuable_sync_bridge_unittest.cc
+++ b/components/autofill/core/browser/webdata/valuables/valuable_sync_bridge_unittest.cc
@@ -42,7 +42,7 @@
 LoyaltyCard TestLoyaltyCard(std::string_view id) {
   return LoyaltyCard(ValuableId(std::string(id)), "merchant_name",
                      "program_name", GURL("http://foobar.com/logo.png"),
-                     "card_number");
+                     "card_number", {GURL("https://domain.example")});
 }
 
 std::vector<LoyaltyCard> ExtractLoyaltyCardsFromDataBatch(
@@ -283,6 +283,7 @@
   loyalty_card->mutable_program_logo()->assign("program_logo");
   loyalty_card->mutable_merchant_name()->assign("merchant_name");
   loyalty_card->mutable_loyalty_card_number()->assign("card_number");
+  *loyalty_card->add_merchant_domains() = "https://www.domain.example";
 
   EXPECT_EQ(bridge()
                 .TrimAllSupportedFieldsFromRemoteSpecifics(specifics)
@@ -309,6 +310,7 @@
   loyalty_card->mutable_program_logo()->assign("program_logo");
   loyalty_card->mutable_merchant_name()->assign("merchant_name");
   loyalty_card->mutable_loyalty_card_number()->assign("card_number");
+  *loyalty_card->add_merchant_domains() = "https://www.domain.example";
 
   EXPECT_EQ(bridge()
                 .TrimAllSupportedFieldsFromRemoteSpecifics(
diff --git a/components/autofill/core/browser/webdata/valuables/valuables_sync_util.cc b/components/autofill/core/browser/webdata/valuables/valuables_sync_util.cc
index 02498a5f..06d9bd2 100644
--- a/components/autofill/core/browser/webdata/valuables/valuables_sync_util.cc
+++ b/components/autofill/core/browser/webdata/valuables/valuables_sync_util.cc
@@ -22,6 +22,10 @@
   loyalty_card->set_program_name(card.program_name());
   loyalty_card->set_program_logo(card.program_logo().possibly_invalid_spec());
   loyalty_card->set_loyalty_card_number(card.loyalty_card_number());
+  for (const GURL& merchant_domain : card.merchant_domains()) {
+    *loyalty_card->add_merchant_domains() = merchant_domain.spec();
+  }
+
   return specifics;
 }
 
@@ -29,11 +33,13 @@
     const AutofillValuableSpecifics& specifics) {
   // Since the specifics are guaranteed to be valid by `IsEntityDataValid()`,
   // the conversion will succeed.
-  return LoyaltyCard(ValuableId(specifics.id()),
-                     specifics.loyalty_card().merchant_name(),
-                     specifics.loyalty_card().program_name(),
-                     GURL(specifics.loyalty_card().program_logo()),
-                     specifics.loyalty_card().loyalty_card_number());
+  const auto& repeated_domains = specifics.loyalty_card().merchant_domains();
+  std::vector<GURL> domains(repeated_domains.begin(), repeated_domains.end());
+  return LoyaltyCard(
+      ValuableId(specifics.id()), specifics.loyalty_card().merchant_name(),
+      specifics.loyalty_card().program_name(),
+      GURL(specifics.loyalty_card().program_logo()),
+      specifics.loyalty_card().loyalty_card_number(), std::move(domains));
 }
 
 std::unique_ptr<syncer::EntityData> CreateEntityDataFromLoyaltyCard(
@@ -66,6 +72,7 @@
   trimmed_specifics.mutable_loyalty_card()->clear_program_name();
   trimmed_specifics.mutable_loyalty_card()->clear_program_logo();
   trimmed_specifics.mutable_loyalty_card()->clear_loyalty_card_number();
+  trimmed_specifics.mutable_loyalty_card()->clear_merchant_domains();
   trimmed_specifics.clear_valuable_data();
   return trimmed_specifics;
 }
diff --git a/components/autofill/core/browser/webdata/valuables/valuables_sync_util_unittest.cc b/components/autofill/core/browser/webdata/valuables/valuables_sync_util_unittest.cc
index d6e168eff..da81dad 100644
--- a/components/autofill/core/browser/webdata/valuables/valuables_sync_util_unittest.cc
+++ b/components/autofill/core/browser/webdata/valuables/valuables_sync_util_unittest.cc
@@ -21,7 +21,7 @@
 LoyaltyCard TestLoyaltyCard(std::string_view id = kId1) {
   return LoyaltyCard(ValuableId(std::string(id)), "merchant_name",
                      "program_name", GURL("http://foobar.com/logo.png"),
-                     "number");
+                     "number", {GURL("https://domain.example")});
 }
 
 sync_pb::AutofillValuableSpecifics TestLoyaltyCardSpecifics(
@@ -37,6 +37,7 @@
   loyalty_card->set_program_name("program_name");
   loyalty_card->set_program_logo(std::string(program_logo));
   loyalty_card->set_loyalty_card_number("number");
+  *loyalty_card->add_merchant_domains() = "https://domain.example";
   return specifics;
 }
 
@@ -55,6 +56,12 @@
   EXPECT_EQ(card.program_logo(), specifics.loyalty_card().program_logo());
   EXPECT_EQ(card.loyalty_card_number(),
             specifics.loyalty_card().loyalty_card_number());
+  ASSERT_EQ(card.merchant_domains().size(),
+            (size_t)specifics.loyalty_card().merchant_domains().size());
+  for (size_t i = 0; i < card.merchant_domains().size(); i++) {
+    EXPECT_EQ(card.merchant_domains()[i],
+              specifics.loyalty_card().merchant_domains(i));
+  }
 }
 
 TEST_F(LoyaltyCardSyncUtilTest, CreateEntityDataFromLoyaltyCard) {
@@ -72,6 +79,12 @@
   EXPECT_EQ(card.program_logo(), specifics.loyalty_card().program_logo());
   EXPECT_EQ(card.loyalty_card_number(),
             specifics.loyalty_card().loyalty_card_number());
+  ASSERT_EQ(card.merchant_domains().size(),
+            (size_t)specifics.loyalty_card().merchant_domains().size());
+  for (size_t i = 0; i < card.merchant_domains().size(); i++) {
+    EXPECT_EQ(card.merchant_domains()[i],
+              specifics.loyalty_card().merchant_domains(i));
+  }
 }
 
 TEST_F(LoyaltyCardSyncUtilTest, CreateAutofillLoyaltyCardFromSpecifics) {
diff --git a/components/autofill/core/browser/webdata/valuables/valuables_table.cc b/components/autofill/core/browser/webdata/valuables/valuables_table.cc
index 94839f0..7bf7e77c 100644
--- a/components/autofill/core/browser/webdata/valuables/valuables_table.cc
+++ b/components/autofill/core/browser/webdata/valuables/valuables_table.cc
@@ -7,6 +7,7 @@
 #include <optional>
 #include <string_view>
 
+#include "base/strings/strcat.h"
 #include "components/autofill/core/browser/data_model/valuables/loyalty_card.h"
 #include "components/autofill/core/browser/data_model/valuables/valuable_types.h"
 #include "components/autofill/core/browser/webdata/autofill_table_utils.h"
@@ -26,16 +27,45 @@
 constexpr std::string_view kLoyaltyCardProgramLogo = "program_logo";
 constexpr std::string_view kLoyaltyCardNumber = "loyalty_card_number";
 
+constexpr std::string_view kLoyaltyCardMerchantDomainTable =
+    "loyalty_card_merchant_domain";
+constexpr std::string_view kMerchantDomain = "merchant_domain";
+
+// Returns the merchant domains for the loyalty card identified by
+// `loyalty_card_id`.
+std::vector<GURL> GetMerchantDomainsForLoyaltyCardId(
+    sql::Database* db,
+    const ValuableId& loyalty_card_id) {
+  std::vector<GURL> merchant_domains;
+  sql::Statement s_card_merchant_domain;
+  SelectBuilder(db, s_card_merchant_domain, kLoyaltyCardMerchantDomainTable,
+                {kLoyaltyCardId, kMerchantDomain},
+                base::StrCat({"WHERE ", kLoyaltyCardId, " = ?"}));
+  s_card_merchant_domain.BindString(0, loyalty_card_id.value());
+  while (s_card_merchant_domain.Step()) {
+    const std::string merchant_domain = s_card_merchant_domain.ColumnString(1);
+    if (!merchant_domain.empty()) {
+      merchant_domains.emplace_back(merchant_domain);
+    }
+  }
+  return merchant_domains;
+}
+
 // Expects that `s` is pointing to a query result containing `kLoyaltyCardId`,
 // `kLoyaltyCardMerchantName`, `kLoyaltyCardProgramName`,
-// `kLoyaltyCardProgramLogo` and `kUnmaskedLoyaltyCardSuffix` in that order.
+// `kLoyaltyCardProgramLogo` and `kLoyaltyCardNumber` in that order.
 // Constructs a `LoyaltyCard` from that data.
-std::optional<LoyaltyCard> LoyaltyCardFromStatement(sql::Statement& s) {
-  LoyaltyCard card(/*loyalty_card_id=*/ValuableId(s.ColumnString(0)),
-                   /*merchant_name=*/s.ColumnString(1),
-                   /*program_name=*/s.ColumnString(2),
-                   /*program_logo=*/GURL(s.ColumnStringView(3)),
-                   /*loyalty_card_number=*/s.ColumnString(4));
+std::optional<LoyaltyCard> LoyaltyCardFromStatement(sql::Database* db,
+                                                    sql::Statement& s) {
+  ValuableId loyalty_card_id = ValuableId(s.ColumnString(0));
+  LoyaltyCard card(
+      /*loyalty_card_id=*/loyalty_card_id,
+      /*merchant_name=*/s.ColumnString(1),
+      /*program_name=*/s.ColumnString(2),
+      /*program_logo=*/GURL(s.ColumnStringView(3)),
+      /*loyalty_card_number=*/s.ColumnString(4),
+      /*merchant_domains=*/
+      GetMerchantDomainsForLoyaltyCardId(db, loyalty_card_id));
   // Ignore invalid loyalty cards, for more information see
   // `LoyaltyCard::IsValid()`. Loyalty cards coming from sync should be valid,
   // so this situation should not happen.
@@ -63,7 +93,7 @@
 }
 
 bool ValuablesTable::CreateTablesIfNecessary() {
-  return InitLoyaltyCardsTable();
+  return InitLoyaltyCardsTable() && InitLoyaltyCardMerchantDomainTable();
 }
 
 bool ValuablesTable::InitLoyaltyCardsTable() {
@@ -75,6 +105,12 @@
                                  {kLoyaltyCardNumber, "TEXT NOT NULL"}});
 }
 
+bool ValuablesTable::InitLoyaltyCardMerchantDomainTable() {
+  return CreateTableIfNotExists(
+      db(), kLoyaltyCardMerchantDomainTable,
+      {{kLoyaltyCardId, "VARCHAR"}, {kMerchantDomain, "VARCHAR"}});
+}
+
 bool ValuablesTable::MigrateToVersion138() {
   // This is the legacy table name, which existed before and was renamed.
   const std::string kLoyaltyCardTable = "loyalty_card";
@@ -111,7 +147,8 @@
        kLoyaltyCardProgramLogo, kLoyaltyCardNumber});
   std::vector<LoyaltyCard> result;
   while (query.Step()) {
-    if (auto loyalty_card = LoyaltyCardFromStatement(query)) {
+    if (std::optional<LoyaltyCard> loyalty_card =
+            LoyaltyCardFromStatement(db(), query)) {
       result.emplace_back(std::move(*loyalty_card));
     }
   }
@@ -122,6 +159,7 @@
     const std::vector<LoyaltyCard>& loyalty_cards) const {
   // Remove the existing set of loyalty cards.
   bool response = Delete(db(), kLoyaltyCardsTable);
+  response &= Delete(db(), kLoyaltyCardMerchantDomainTable);
 
   sql::Statement insert_cards;
   InsertBuilder(
@@ -145,6 +183,17 @@
     insert_cards.BindString(index++, loyalty_card.loyalty_card_number());
     response &= insert_cards.Run();
     insert_cards.Reset(/*clear_bound_vars=*/true);
+
+    for (const GURL& merchant_domain : loyalty_card.merchant_domains()) {
+      // Insert new loyalty_card_merchant_domain values.
+      sql::Statement insert_card_merchant_domains;
+      InsertBuilder(db(), insert_card_merchant_domains,
+                    kLoyaltyCardMerchantDomainTable,
+                    {kLoyaltyCardId, kMerchantDomain}, /*or_replace=*/true);
+      insert_card_merchant_domains.BindString(0, loyalty_card.id().value());
+      insert_card_merchant_domains.BindString(1, merchant_domain.spec());
+      response &= insert_card_merchant_domains.Run();
+    }
   }
   return response;
 }
@@ -156,10 +205,10 @@
       db(), query, kLoyaltyCardsTable,
       {kLoyaltyCardId, kLoyaltyCardMerchantName, kLoyaltyCardProgramName,
        kLoyaltyCardProgramLogo, kLoyaltyCardNumber},
-      "WHERE loyalty_card_id=?");
+      base::StrCat({"WHERE ", kLoyaltyCardId, " = ?"}));
   query.BindString(0, loyalty_card_id.value());
   if (query.is_valid() && query.Step()) {
-    return LoyaltyCardFromStatement(query);
+    return LoyaltyCardFromStatement(db(), query);
   }
   return std::nullopt;
 }
diff --git a/components/autofill/core/browser/webdata/valuables/valuables_table.h b/components/autofill/core/browser/webdata/valuables/valuables_table.h
index 4a1c570..fd36cd7 100644
--- a/components/autofill/core/browser/webdata/valuables/valuables_table.h
+++ b/components/autofill/core/browser/webdata/valuables/valuables_table.h
@@ -31,6 +31,16 @@
 //   program_logo         The url of the logo icon for the card.
 //   loyalty_card_number  A string representation of the unmasked loyalty card
 //                        number suffix.
+// -----------------------------------------------------------------------------
+// loyalty_card_merchant_domain
+//                      Contains the mapping of merchant domains and card linked
+//                      offers.
+//
+//   loyalty_card_id    Identifies the relevant loyalty card. Matches the
+//                      `loyalty_card_id` in the loyalty_cards table.
+//   merchant_domain    List of full origins for merchant websites on which
+//                      this card would apply.
+// -----------------------------------------------------------------------------
 class ValuablesTable : public WebDatabaseTable {
  public:
   ValuablesTable();
@@ -68,6 +78,7 @@
 
  private:
   bool InitLoyaltyCardsTable();
+  bool InitLoyaltyCardMerchantDomainTable();
 
   // Renames the database table from `loyalty_card` to `loyalty_cards` and
   // renames the following columns:
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc
index 105dd43..dc7c1f1 100644
--- a/components/autofill/core/common/autofill_features.cc
+++ b/components/autofill/core/common/autofill_features.cc
@@ -284,7 +284,7 @@
 // TODO(crbug.com/339543182): Remove when launched.
 BASE_FEATURE(kAutofillAddressFieldSwapping,
              "AutofillAddressFieldSwapping",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+             base::FEATURE_ENABLED_BY_DEFAULT);
 
 // When enabled, address field swapping suggestions will not include a
 // suggestion matching the field's current value. This decreases noises in the
diff --git a/components/autofill/core/common/autofill_payments_features.cc b/components/autofill/core/common/autofill_payments_features.cc
index e1bd758a..dfca54b 100644
--- a/components/autofill/core/common/autofill_payments_features.cc
+++ b/components/autofill/core/common/autofill_payments_features.cc
@@ -226,6 +226,12 @@
              base::FEATURE_ENABLED_BY_DEFAULT);
 #endif
 
+// Kill switch, when enabled, will prevent the display of the save card bubble
+// within a tab modal pop-up window.
+BASE_FEATURE(kAutofillSkipSaveCardForTabModalPopup,
+             "AutofillSkipSaveCardForTabModalPopup",
+             base::FEATURE_ENABLED_BY_DEFAULT);
+
 // When enabled, adds a timeout on the network request for Unmask requests.
 BASE_FEATURE(kAutofillUnmaskCardRequestTimeout,
              "AutofillUnmaskCardRequestTimeout",
diff --git a/components/autofill/core/common/autofill_payments_features.h b/components/autofill/core/common/autofill_payments_features.h
index 148ec53..1605a35 100644
--- a/components/autofill/core/common/autofill_payments_features.h
+++ b/components/autofill/core/common/autofill_payments_features.h
@@ -93,6 +93,8 @@
 COMPONENT_EXPORT(AUTOFILL)
 BASE_DECLARE_FEATURE(kAutofillShowManualFillForVirtualCards);
 #endif
+COMPONENT_EXPORT(AUTOFILL)
+BASE_DECLARE_FEATURE(kAutofillSkipSaveCardForTabModalPopup);
 #if BUILDFLAG(IS_ANDROID)
 COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillSyncEwalletAccounts);
 #endif
diff --git a/components/autofill/ios/browser/resources/autofill_controller.js b/components/autofill/ios/browser/resources/autofill_controller.js
index 373bee54..33d718cf 100644
--- a/components/autofill/ios/browser/resources/autofill_controller.js
+++ b/components/autofill/ios/browser/resources/autofill_controller.js
@@ -5,7 +5,7 @@
 import * as fill_constants from '//components/autofill/ios/form_util/resources/fill_constants.js';
 import {isTextAreaElement} from '//components/autofill/ios/form_util/resources/fill_element_inference_util.js';
 import {getFrameId} from '//ios/web/public/js_messaging/resources/frame_id.js';
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 import {isTextField, sendWebKitMessage, trim} from '//ios/web/public/js_messaging/resources/utils.js';
 
 
@@ -132,7 +132,7 @@
  *     empty if no match.
  */
 function getUnownedIframes() {
-  return Array.from(gCrWeb.form.getIframeElements(document))
+  return Array.from(gCrWebLegacy.form.getIframeElements(document))
       .filter(e => !e.closest('form'));
 }
 
@@ -152,7 +152,7 @@
   const numEditableUnownedElements =
       countEditableElements_(unownedControlElements);
   const iframeElements =
-      gCrWeb.autofill_form_features.isAutofillAcrossIframesEnabled() ?
+      gCrWebLegacy.autofill_form_features.isAutofillAcrossIframesEnabled() ?
       getUnownedIframes() :
       [];
   if (numEditableUnownedElements > 0 || iframeElements.length > 0) {
@@ -467,7 +467,7 @@
   // Returns true if the child frames can be extracted.
   const canExtractChildFrames = () =>
       numFramesSeen <= fill_constants.MAX_EXTRACTABLE_FRAMES ||
-      !gCrWeb.autofill_form_features.isAutofillAcrossIframesThrottlingEnabled();
+      !gCrWebLegacy.autofill_form_features.isAutofillAcrossIframesThrottlingEnabled();
 
   for (let formIndex = 0; formIndex < webForms.length; ++formIndex) {
     /** @type {HTMLFormElement} */
@@ -476,7 +476,7 @@
         __gCrWeb.autofill.extractAutofillableElementsInForm(formElement);
     const numEditableElements = countEditableElements_(controlElements);
     const hasChildFrames =
-        gCrWeb.autofill_form_features.isAutofillAcrossIframesEnabled() ?
+        gCrWebLegacy.autofill_form_features.isAutofillAcrossIframesEnabled() ?
         formElement.getElementsByTagName('iframe').length > 0 :
         false;
 
diff --git a/components/autofill/ios/browser/resources/suggestion_controller.ts b/components/autofill/ios/browser/resources/suggestion_controller.ts
index 0d12626..df41e1a 100644
--- a/components/autofill/ios/browser/resources/suggestion_controller.ts
+++ b/components/autofill/ios/browser/resources/suggestion_controller.ts
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 
 /**
  * @fileoverview Installs suggestion management functions on the
@@ -294,7 +294,7 @@
  * @return The element if found, otherwise null.
  */
 function getFormElement(formName: string, fieldName: string): Element|null {
-  const form = gCrWeb.form.getFormElementFromIdentifier(formName);
+  const form = gCrWebLegacy.form.getFormElementFromIdentifier(formName);
   if (!form) {
     return null;
   }
@@ -387,7 +387,7 @@
   };
 }
 
-gCrWeb.suggestion = {
+gCrWebLegacy.suggestion = {
   getNextElementInTabOrder,
   getPreviousElementInTabOrder,
   selectNextElement,
diff --git a/components/autofill/ios/form_util/resources/autofill_form_features.ts b/components/autofill/ios/form_util/resources/autofill_form_features.ts
index b7f3f27f..f33e340 100644
--- a/components/autofill/ios/form_util/resources/autofill_form_features.ts
+++ b/components/autofill/ios/form_util/resources/autofill_form_features.ts
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 
 /**
  * @fileoverview Contains feature flag state for behavior relating to Autofill
@@ -119,9 +119,9 @@
   return autofillCorrectUserEditedBitInParsedField;
 }
 
-// Expose globally via `gCrWeb` instead of `export` to ensure state (feature
+// Expose globally via `gCrWebLegacy` instead of `export` to ensure state (feature
 // on/off) is maintained across imports.
-gCrWeb.autofill_form_features = {
+gCrWebLegacy.autofill_form_features = {
   setAutofillAcrossIframes,
   isAutofillAcrossIframesEnabled,
   setAutofillAcrossIframesThrottling,
diff --git a/components/autofill/ios/form_util/resources/child_frame_registration_lib.ts b/components/autofill/ios/form_util/resources/child_frame_registration_lib.ts
index 36fbb3a..3cbfe91 100644
--- a/components/autofill/ios/form_util/resources/child_frame_registration_lib.ts
+++ b/components/autofill/ios/form_util/resources/child_frame_registration_lib.ts
@@ -9,7 +9,7 @@
 
 import {CHILD_FRAME_REMOTE_TOKEN_ATTRIBUTE} from '//components/autofill/ios/form_util/resources/fill_constants.js';
 import {getFrameId} from '//ios/web/public/js_messaging/resources/frame_id.js';
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 import {generateRandomId, sendWebKitMessage} from '//ios/web/public/js_messaging/resources/utils.js';
 
 /**
@@ -99,7 +99,7 @@
  * @param {MessageEvent} payload The data sent via postMessage.
  */
 function processChildFrameMessage(payload: MessageEvent): void {
-  if (!gCrWeb.autofill_form_features.isAutofillAcrossIframesEnabled()) {
+  if (!gCrWebLegacy.autofill_form_features.isAutofillAcrossIframesEnabled()) {
     return;
   }
   const command: unknown = payload.data?.command;
@@ -131,18 +131,18 @@
  *      cached or a freshly generated one.
  */
 function getRemoteIdForFrame(frame: HTMLIFrameElement): string {
-  if (!gCrWeb.hasOwnProperty('remoteFrameIdRegistrar')) {
-    gCrWeb.remoteFrameIdRegistrar = new Map();
+  if (!gCrWebLegacy.hasOwnProperty('remoteFrameIdRegistrar')) {
+    gCrWebLegacy.remoteFrameIdRegistrar = new Map();
   }
 
   // Return the cached remote token if the frame was already registered.
-  if (gCrWeb.remoteFrameIdRegistrar.has(frame)) {
-    return gCrWeb.remoteFrameIdRegistrar.get(frame);
+  if (gCrWebLegacy.remoteFrameIdRegistrar.has(frame)) {
+    return gCrWebLegacy.remoteFrameIdRegistrar.get(frame);
   }
 
   // Otherwise, create a remote ID for the frame and cache it.
   const remoteId: string = generateRandomId();
-  gCrWeb.remoteFrameIdRegistrar.set(frame, remoteId);
+  gCrWebLegacy.remoteFrameIdRegistrar.set(frame, remoteId);
   return remoteId;
 }
 
@@ -200,7 +200,7 @@
   return remoteFrameId;
 }
 
-gCrWeb.remoteFrameRegistration = {
+gCrWebLegacy.remoteFrameRegistration = {
   processChildFrameMessage,
   registerChildFrame,
   registerSelfWithRemoteToken,
diff --git a/components/autofill/ios/form_util/resources/child_frame_registration_test.ts b/components/autofill/ios/form_util/resources/child_frame_registration_test.ts
index 5c3f224..259de3e 100644
--- a/components/autofill/ios/form_util/resources/child_frame_registration_test.ts
+++ b/components/autofill/ios/form_util/resources/child_frame_registration_test.ts
@@ -7,7 +7,7 @@
  * Requires functions in child_frame_registration_lib.ts.
  */
 
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 
 /**
  * Calls registerChildFrame on each frame in the document. This is a convenience
@@ -17,13 +17,13 @@
 function registerAllChildFrames(): string[] {
   const ids: string[] = [];
   for (const frame of document.getElementsByTagName('iframe')) {
-    ids.push(gCrWeb.remoteFrameRegistration.registerChildFrame(
+    ids.push(gCrWebLegacy.remoteFrameRegistration.registerChildFrame(
         (frame as HTMLIFrameElement)));
   }
   return ids;
 }
 
 window.addEventListener(
-    'message', gCrWeb.remoteFrameRegistration.processChildFrameMessage);
+    'message', gCrWebLegacy.remoteFrameRegistration.processChildFrameMessage);
 
-gCrWeb.remoteFrameRegistration.registerAllChildFrames = registerAllChildFrames;
+gCrWebLegacy.remoteFrameRegistration.registerAllChildFrames = registerAllChildFrames;
diff --git a/components/autofill/ios/form_util/resources/create_fill_namespace.ts b/components/autofill/ios/form_util/resources/create_fill_namespace.ts
index 24ac6dc..5df8a59 100644
--- a/components/autofill/ios/form_util/resources/create_fill_namespace.ts
+++ b/components/autofill/ios/form_util/resources/create_fill_namespace.ts
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 
 // Add type extensions needed for other scripts defining the fill namespace.
 declare global {
@@ -22,16 +22,16 @@
   }
 }
 
-if (!gCrWeb.fill) {
+if (!gCrWebLegacy.fill) {
   /**
-   * Namespace for this file. It depends on |gCrWeb| having already been
-   * injected. String 'fill' is used in |gCrWeb['fill']| as it needs to be
+   * Namespace for this file. It depends on |gCrWebLegacy| having already been
+   * injected. String 'fill' is used in |gCrWebLegacy['fill']| as it needs to be
    * accessed in Objective-C code.
    */
-  gCrWeb.fill = {};
+  gCrWebLegacy.fill = {};
 
   // Store fill namespace object in a global __gCrWeb object referenced by a
   // string, so it does not get renamed by closure compiler during the
   // minification.
-  gCrWeb['fill'] = gCrWeb.fill;
+  gCrWebLegacy['fill'] = gCrWebLegacy.fill;
 }
diff --git a/components/autofill/ios/form_util/resources/fill.ts b/components/autofill/ios/form_util/resources/fill.ts
index f518790..a69f586e 100644
--- a/components/autofill/ios/form_util/resources/fill.ts
+++ b/components/autofill/ios/form_util/resources/fill.ts
@@ -8,7 +8,7 @@
 import {inferLabelFromNext} from '//components/autofill/ios/form_util/resources/fill_element_inference.js';
 import * as inferenceUtil from '//components/autofill/ios/form_util/resources/fill_element_inference_util.js';
 import type * as fillUtil from '//components/autofill/ios/form_util/resources/fill_util.js';
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 import {isTextField, removeQueryAndReferenceFromURL} from '//ios/web/public/js_messaging/resources/utils.js';
 
 // This file provides methods used to fill forms in JavaScript.
@@ -64,14 +64,14 @@
     elementArray[i] = null;
 
     const controlElement = controlElements[i];
-    if (!gCrWeb.fill.isAutofillableElement(controlElement)) {
+    if (!gCrWebLegacy.fill.isAutofillableElement(controlElement)) {
       continue;
     }
 
     // Create a new AutofillFormFieldData, fill it out and map it to the
     // field's name.
-    const formField = new gCrWeb['common'].JSONSafeObject();
-    gCrWeb.fill.webFormControlElementToFormField(controlElement, formField);
+    const formField = new gCrWebLegacy['common'].JSONSafeObject();
+    gCrWebLegacy.fill.webFormControlElementToFormField(controlElement, formField);
     formFields.push(formField);
     elementArray[i] = formField;
     fieldsExtracted[i] = true;
@@ -98,7 +98,7 @@
  * @param node The node to be processed.
  * @return Whether the node is visible or not.
  */
-gCrWeb.fill.isVisibleNode = function(node: Node): boolean {
+gCrWebLegacy.fill.isVisibleNode = function(node: Node): boolean {
   if (!node) {
     return false;
   }
@@ -111,7 +111,7 @@
   }
 
   // Verify all ancestors are focusable.
-  return !node.parentNode || gCrWeb.fill.isVisibleNode(node.parentNode);
+  return !node.parentNode || gCrWebLegacy.fill.isVisibleNode(node.parentNode);
 };
 
 /**
@@ -321,7 +321,7 @@
     const currentField = formFields[fieldIdx]!;
     if (!currentField.label) {
       currentField.label =
-          gCrWeb.fill.inferLabelForElement(controlElement)?.label || '';
+      gCrWebLegacy.fill.inferLabelForElement(controlElement)?.label || '';
     }
     if (currentField.label!.length > fillConstants.MAX_DATA_LENGTH) {
       currentField.label =
@@ -353,7 +353,7 @@
   // Protect against custom implementation of Array.toJSON in host pages.
   (form.fields as any).toJSON = null;
 
-  form.host_frame = gCrWeb.message.getFrameId();
+  form.host_frame = gCrWebLegacy.message.getFrameId();
 
   if (childFrames.length > 0) {
     form.child_frames = childFrames;
@@ -374,7 +374,7 @@
   }
   // Either register a new token when in the isolated world or read the last
   // registered token from the page content world.
-  return gCrWeb.remoteFrameRegistration?.registerChildFrame(frame) ??
+  return gCrWebLegacy.remoteFrameRegistration?.registerChildFrame(frame) ??
       frame.getAttribute(fillConstants.CHILD_FRAME_REMOTE_TOKEN_ATTRIBUTE);
 }
 
@@ -408,7 +408,7 @@
  * @return Whether there are fields and not too many fields in the
  *     form.
  */
-gCrWeb.fill.webFormElementToFormData = function(
+gCrWebLegacy.fill.webFormElementToFormData = function(
     frame: Window, formElement: HTMLFormElement,
     formControlElement: fillConstants.FormControlElement,
     form: fillUtil.AutofillFormData, field?: fillUtil.AutofillFormFieldData,
@@ -417,15 +417,15 @@
     return false;
   }
 
-  form.name = gCrWeb.form.getFormIdentifier(formElement);
+  form.name = gCrWebLegacy.form.getFormIdentifier(formElement);
   form.origin = removeQueryAndReferenceFromURL(frame.origin);
-  form.action = gCrWeb.fill.getCanonicalActionForForm(formElement);
+  form.action = gCrWebLegacy.fill.getCanonicalActionForForm(formElement);
 
   // The raw name and id attributes, which may be empty.
   form.name_attribute = formElement.getAttribute('name') || '';
   form.id_attribute = formElement.getAttribute('id') || '';
 
-  form.renderer_id = gCrWeb.fill.getUniqueID(formElement);
+  form.renderer_id = gCrWebLegacy.fill.getUniqueID(formElement);
 
   form.host_frame = frame.__gCrWeb.message.getFrameId();
 
@@ -436,17 +436,17 @@
   // computed by creating a <a> element, and we don't check if the action is
   // valid.
 
-  const controlElements = gCrWeb.form.getFormControlElements(formElement);
+  const controlElements = gCrWebLegacy.form.getFormControlElements(formElement);
 
   let iframeElements = extractChildFrames &&
-          gCrWeb.autofill_form_features.isAutofillAcrossIframesEnabled() ?
-      gCrWeb.form.getIframeElements(formElement) :
+      gCrWebLegacy.autofill_form_features.isAutofillAcrossIframesEnabled() ?
+      gCrWebLegacy.form.getIframeElements(formElement) :
       [];
 
   // To avoid performance bottlenecks, do not keep child frames if their
   // quantity exceeds the allowed threshold.
   if (iframeElements.length > fillConstants.MAX_EXTRACTABLE_FRAMES &&
-      gCrWeb.autofill_form_features
+      gCrWebLegacy.autofill_form_features
           .isAutofillAcrossIframesThrottlingEnabled()) {
     iframeElements = [];
   }
@@ -469,7 +469,7 @@
  * @param element The element to be processed.
  * @param field Field to fill in the element information.
  */
-gCrWeb.fill.webFormControlElementToFormField = function(
+gCrWebLegacy.fill.webFormControlElementToFormField = function(
     element: fillConstants.FormControlElement,
     field: fillUtil.AutofillFormFieldData) {
   if (!field || !element) {
@@ -478,14 +478,14 @@
   // The label is not officially part of a form control element; however, the
   // labels for all form control elements are scraped from the DOM and set in
   // form data.
-  field.identifier = gCrWeb.form.getFieldIdentifier(element);
-  field.name = gCrWeb.form.getFieldName(element);
+  field.identifier = gCrWebLegacy.form.getFieldIdentifier(element);
+  field.name = gCrWebLegacy.form.getFieldName(element);
 
   // The raw name and id attributes, which may be empty.
   field.name_attribute = element.getAttribute('name') || '';
   field.id_attribute = element.getAttribute('id') || '';
 
-  field.renderer_id = gCrWeb.fill.getUniqueID(element);
+  field.renderer_id = gCrWebLegacy.fill.getUniqueID(element);
 
   field.form_control_type = element.type;
   const autocompleteAttribute = element.getAttribute('autocomplete');
@@ -516,24 +516,24 @@
     field.placeholder_attribute = 'x-max-data-length-exceeded';
   }
 
-  field.aria_label = gCrWeb.fill.getAriaLabel(element);
-  field.aria_description = gCrWeb.fill.getAriaDescription(element);
+  field.aria_label = gCrWebLegacy.fill.getAriaLabel(element);
+  field.aria_description = gCrWebLegacy.fill.getAriaDescription(element);
 
-  if (!gCrWeb.fill.isAutofillableElement(element)) {
+  if (!gCrWebLegacy.fill.isAutofillableElement(element)) {
     return;
   }
 
-  if (gCrWeb.fill.isAutofillableInputElement(element) ||
+  if (gCrWebLegacy.fill.isAutofillableInputElement(element) ||
       inferenceUtil.isTextAreaElement(element) ||
-      gCrWeb.fill.isSelectElement(element)) {
+      gCrWebLegacy.fill.isSelectElement(element)) {
     field.is_autofilled = (element as any).isAutofilled;
-    field.is_user_edited = gCrWeb.form.fieldWasEditedByUser(element);
-    field.should_autocomplete = gCrWeb.fill.shouldAutocomplete(element);
+    field.is_user_edited = gCrWebLegacy.form.fieldWasEditedByUser(element);
+    field.should_autocomplete = gCrWebLegacy.fill.shouldAutocomplete(element);
     field.is_focusable = !element.disabled && !(element as any).readOnly &&
-        element.tabIndex >= 0 && gCrWeb.fill.isVisibleNode(element);
+        element.tabIndex >= 0 && gCrWebLegacy.fill.isVisibleNode(element);
   }
 
-  if (gCrWeb.fill.isAutofillableInputElement(element)) {
+  if (gCrWebLegacy.fill.isAutofillableInputElement(element)) {
     if (isTextField(element)) {
       field.max_length = (element as HTMLInputElement).maxLength;
       if (field.max_length === -1) {
@@ -541,14 +541,14 @@
         field.max_length = 524288;
       }
     }
-    field.is_checkable = gCrWeb.fill.isCheckableElement(element);
+    field.is_checkable = gCrWebLegacy.fill.isCheckableElement(element);
   } else if (inferenceUtil.isTextAreaElement(element)) {
     // Nothing more to do in this case.
   } else {
-    gCrWeb.fill.getOptionStringsFromElement(element, field);
+    gCrWebLegacy.fill.getOptionStringsFromElement(element, field);
   }
 
-  let value = gCrWeb.fill.value(element);
+  let value = gCrWebLegacy.fill.value(element);
 
   // There is a constraint on the maximum data length in method
   // WebFormControlElementToFormField() in form_autofill_util.h in order to
@@ -569,10 +569,10 @@
  * @param form The form to serialize.
  * @return a JSON encoded version of |form|
  */
-gCrWeb.fill.autofillSubmissionData =
+gCrWebLegacy.fill.autofillSubmissionData =
     function(form: HTMLFormElement): fillUtil.AutofillFormData {
-  const formData = new gCrWeb['common'].JSONSafeObject();
-  gCrWeb['fill'].webFormElementToFormData(window, form, null, formData, null);
+  const formData = new gCrWebLegacy['common'].JSONSafeObject();
+      gCrWebLegacy['fill'].webFormElementToFormData(window, form, null, formData, null);
   return formData;
 };
 
@@ -595,19 +595,19 @@
  * @param fieldsets out param for unowned fieldsets.
  * @return The elements that are not part of a form.
  */
-gCrWeb.fill.getUnownedAutofillableFormFieldElements = function(
+gCrWebLegacy.fill.getUnownedAutofillableFormFieldElements = function(
     elements: fillConstants.FormControlElement[],
     fieldsets: Element[]): fillConstants.FormControlElement[] {
   const unownedFieldsetChildren: fillConstants.FormControlElement[] = [];
   for (const element of elements) {
-    if (gCrWeb.form.isFormControlElement(element)) {
+    if (gCrWebLegacy.form.isFormControlElement(element)) {
       if (!element.form) {
         unownedFieldsetChildren.push(element);
       }
     }
 
-    if (gCrWeb.fill.hasTagName(element, 'fieldset') &&
-        !gCrWeb.fill.isElementInsideFormOrFieldSet(element)) {
+    if (gCrWebLegacy.fill.hasTagName(element, 'fieldset') &&
+        !gCrWebLegacy.fill.isElementInsideFormOrFieldSet(element)) {
       fieldsets.push(element);
     }
   }
@@ -653,7 +653,7 @@
  * @return Whether there are fields and not too many fields in the
  *     form.
  */
-gCrWeb.fill.unownedFormElementsAndFieldSetsToFormData = function(
+gCrWebLegacy.fill.unownedFormElementsAndFieldSetsToFormData = function(
     frame: Window, fieldsets: Element[],
     controlElements: fillConstants.FormControlElement[],
     iframeElements: HTMLIFrameElement[],
@@ -669,7 +669,7 @@
   // To avoid performance bottlenecks, do not keep child frames if their
   // quantity exceeds the allowed threshold.
   if (iframeElements.length > fillConstants.MAX_EXTRACTABLE_FRAMES &&
-      gCrWeb.autofill_form_features
+      gCrWebLegacy.autofill_form_features
           .isAutofillAcrossIframesThrottlingEnabled()) {
     iframeElements = [];
   }
@@ -738,7 +738,7 @@
   const autofillableElements
       : fillConstants.FormControlElement[] = [];
   for (const element of controlElements) {
-    if (!gCrWeb.fill.isAutofillableElement(element)) {
+    if (!gCrWebLegacy.fill.isAutofillableElement(element)) {
       continue;
     }
     autofillableElements.push(element);
diff --git a/components/autofill/ios/form_util/resources/fill_constants.ts b/components/autofill/ios/form_util/resources/fill_constants.ts
index fce9ca3..974ccf3 100644
--- a/components/autofill/ios/form_util/resources/fill_constants.ts
+++ b/components/autofill/ios/form_util/resources/fill_constants.ts
@@ -4,7 +4,7 @@
 
 import '//components/autofill/ios/form_util/resources/create_fill_namespace.js';
 
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 
 declare type FormControlElement =
     HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement;
@@ -83,4 +83,4 @@
   UNIQUE_ID_ATTRIBUTE,
 };
 
-gCrWeb.fill.ID_SYMBOL = ID_SYMBOL;
+gCrWebLegacy.fill.ID_SYMBOL = ID_SYMBOL;
diff --git a/components/autofill/ios/form_util/resources/fill_element_inference.ts b/components/autofill/ios/form_util/resources/fill_element_inference.ts
index 1fa206d..cdf9bbe 100644
--- a/components/autofill/ios/form_util/resources/fill_element_inference.ts
+++ b/components/autofill/ios/form_util/resources/fill_element_inference.ts
@@ -5,7 +5,7 @@
 import type {FormControlElement} from '//components/autofill/ios/form_util/resources/fill_constants.js';
 import type {InferredLabel} from '//components/autofill/ios/form_util/resources/fill_element_inference_util.js';
 import {ancestorTagNames, buildInferredLabelIfValid, findChildText, findChildTextWithIgnoreList, isTraversableContainerElement} from '//components/autofill/ios/form_util/resources/fill_element_inference_util.js';
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 
 /**
  * Shared function for InferLabelFromPrevious() and InferLabelFromNext().
@@ -53,18 +53,18 @@
     // Coalesce any text contained in multiple consecutive
     //  (a) plain text nodes or
     //  (b) inline HTML elements that are essentially equivalent to text nodes.
-    if (nodeType === Node.TEXT_NODE || gCrWeb.fill.hasTagName(sibling, 'b') ||
-        gCrWeb.fill.hasTagName(sibling, 'strong') ||
-        gCrWeb.fill.hasTagName(sibling, 'span') ||
-        gCrWeb.fill.hasTagName(sibling, 'font')) {
+    if (nodeType === Node.TEXT_NODE || gCrWebLegacy.fill.hasTagName(sibling, 'b') ||
+        gCrWebLegacy.fill.hasTagName(sibling, 'strong') ||
+        gCrWebLegacy.fill.hasTagName(sibling, 'span') ||
+        gCrWebLegacy.fill.hasTagName(sibling, 'font')) {
       const value = findChildText(sibling);
       // A text node's value will be empty if it is for a line break.
       const addSpace = nodeType === Node.TEXT_NODE && value.length === 0;
       if (forward) {
-        inferredLabel = gCrWeb.fill.combineAndCollapseWhitespace(
+        inferredLabel = gCrWebLegacy.fill.combineAndCollapseWhitespace(
             inferredLabel, value, addSpace);
       } else {
-        inferredLabel = gCrWeb.fill.combineAndCollapseWhitespace(
+        inferredLabel = gCrWebLegacy.fill.combineAndCollapseWhitespace(
             value, inferredLabel, addSpace);
       }
       continue;
@@ -79,14 +79,14 @@
 
     // <img> and <br> tags often appear between the input element and its
     // label text, so skip over them.
-    if (gCrWeb.fill.hasTagName(sibling, 'img') ||
-        gCrWeb.fill.hasTagName(sibling, 'br')) {
+    if (gCrWebLegacy.fill.hasTagName(sibling, 'img') ||
+        gCrWebLegacy.fill.hasTagName(sibling, 'br')) {
       continue;
     }
 
     // We only expect <p> and <label> tags to contain the full label text.
-    if (gCrWeb.fill.hasTagName(sibling, 'p') ||
-        gCrWeb.fill.hasTagName(sibling, 'label')) {
+    if (gCrWebLegacy.fill.hasTagName(sibling, 'p') ||
+        gCrWebLegacy.fill.hasTagName(sibling, 'label')) {
       return buildInferredLabelIfValid(findChildText(sibling));
     }
     break;
@@ -110,7 +110,7 @@
  * @param element An element to examine.
  * @return The label of element.
  */
-gCrWeb.fill.inferLabelFromPrevious = function(
+gCrWebLegacy.fill.inferLabelFromPrevious = function(
     element: FormControlElement): InferredLabel | null {
   return inferLabelFromSibling(element, false);
 };
@@ -168,7 +168,7 @@
     return null;
   }
 
-  return buildInferredLabelIfValid(gCrWeb.fill.getAriaLabel(element));
+  return buildInferredLabelIfValid(gCrWebLegacy.fill.getAriaLabel(element));
 }
 
 /**
@@ -203,7 +203,7 @@
  * @param element An element to examine.
  * @return The label of element.
  */
-gCrWeb.fill.inferLabelFromListItem = function(
+gCrWebLegacy.fill.inferLabelFromListItem = function(
     element: FormControlElement): InferredLabel | null {
   if (!element) {
     return null;
@@ -211,11 +211,11 @@
 
   let parentNode = element.parentNode;
   while (parentNode && parentNode.nodeType === Node.ELEMENT_NODE &&
-         !gCrWeb.fill.hasTagName(parentNode, 'li')) {
+         !gCrWebLegacy.fill.hasTagName(parentNode, 'li')) {
     parentNode = parentNode.parentNode;
   }
 
-  if (parentNode && gCrWeb.fill.hasTagName(parentNode, 'li')) {
+  if (parentNode && gCrWebLegacy.fill.hasTagName(parentNode, 'li')) {
     return buildInferredLabelIfValid(findChildText(parentNode));
   }
 
@@ -236,7 +236,7 @@
  * @param element An element to examine.
  * @return The label of element.
  */
-gCrWeb.fill.inferLabelFromTableColumn = function(
+gCrWebLegacy.fill.inferLabelFromTableColumn = function(
     element: FormControlElement): InferredLabel | null {
   if (!element) {
     return null;
@@ -244,7 +244,7 @@
 
   let parentNode = element.parentNode;
   while (parentNode && parentNode.nodeType === Node.ELEMENT_NODE &&
-         !gCrWeb.fill.hasTagName(parentNode, 'td')) {
+         !gCrWebLegacy.fill.hasTagName(parentNode, 'td')) {
     parentNode = parentNode.parentNode;
   }
 
@@ -257,8 +257,8 @@
   let r: InferredLabel | null = null;
   let previous = parentNode.previousSibling;
   while (!r && previous) {
-    if (gCrWeb.fill.hasTagName(previous, 'td') ||
-        gCrWeb.fill.hasTagName(previous, 'th')) {
+    if (gCrWebLegacy.fill.hasTagName(previous, 'td') ||
+        gCrWebLegacy.fill.hasTagName(previous, 'th')) {
       r = buildInferredLabelIfValid(findChildText(previous));
     }
     previous = previous.previousSibling;
@@ -283,7 +283,7 @@
  * @param element An element to examine.
  * @return The label of element.
  */
-gCrWeb.fill.inferLabelFromTableRow = function(
+gCrWebLegacy.fill.inferLabelFromTableRow = function(
     element: FormControlElement): InferredLabel | null {
   if (!element) {
     return null;
@@ -292,7 +292,7 @@
   let parentCell = element.parentNode;
   while (parentCell) {
     if (parentCell.nodeType === Node.ELEMENT_NODE &&
-        gCrWeb.fill.hasTagName(parentCell, 'td')) {
+        gCrWebLegacy.fill.hasTagName(parentCell, 'td')) {
       break;
     }
     parentCell = parentCell.parentNode;
@@ -313,7 +313,7 @@
   let cellIterator = cell.previousSibling;
   while (cellIterator) {
     if (cellIterator.nodeType === Node.ELEMENT_NODE &&
-        gCrWeb.fill.hasTagName(cellIterator, 'td')) {
+        gCrWebLegacy.fill.hasTagName(cellIterator, 'td')) {
       cellPosition += (cellIterator as HTMLTableCellElement).colSpan;
     }
     cellIterator = cellIterator.previousSibling;
@@ -323,7 +323,7 @@
   cellIterator = cell.nextSibling;
   while (cellIterator) {
     if (cellIterator.nodeType === Node.ELEMENT_NODE &&
-        gCrWeb.fill.hasTagName(cellIterator, 'td')) {
+        gCrWebLegacy.fill.hasTagName(cellIterator, 'td')) {
       cellCount += (cellIterator as HTMLTableCellElement).colSpan;
     }
     cellIterator = cellIterator.nextSibling;
@@ -336,7 +336,7 @@
   // Find the current row.
   let parentNode = element.parentNode;
   while (parentNode && parentNode.nodeType === Node.ELEMENT_NODE &&
-         !gCrWeb.fill.hasTagName(parentNode, 'tr')) {
+         !gCrWebLegacy.fill.hasTagName(parentNode, 'tr')) {
     parentNode = parentNode.parentNode;
   }
 
@@ -348,7 +348,7 @@
   let rowIt = parentNode.previousSibling;
   while (rowIt) {
     if (rowIt.nodeType === Node.ELEMENT_NODE &&
-        gCrWeb.fill.hasTagName(parentNode, 'tr')) {
+        gCrWebLegacy.fill.hasTagName(parentNode, 'tr')) {
       break;
     }
     rowIt = rowIt.previousSibling;
@@ -362,8 +362,8 @@
     let prevRowIt = rowIt.firstChild;
     while (prevRowIt) {
       if (prevRowIt.nodeType === Node.ELEMENT_NODE) {
-        if (gCrWeb.fill.hasTagName(prevRowIt, 'td') ||
-            gCrWeb.fill.hasTagName(prevRowIt, 'th')) {
+        if (gCrWebLegacy.fill.hasTagName(prevRowIt, 'td') ||
+            gCrWebLegacy.fill.hasTagName(prevRowIt, 'th')) {
           const span = (prevRowIt as HTMLTableCellElement).colSpan;
           const prevRowCountEnd = prevRowCount + span - 1;
           if (prevRowCount === cellPosition &&
@@ -389,7 +389,7 @@
   let r: InferredLabel | null = null;
   let previous = parentNode.previousSibling;
   while (!r && previous) {
-    if (gCrWeb.fill.hasTagName(previous, 'tr')) {
+    if (gCrWebLegacy.fill.hasTagName(previous, 'tr')) {
       r = buildInferredLabelIfValid(findChildText(previous));
     }
     previous = previous.previousSibling;
@@ -408,13 +408,13 @@
  * @param element An element to examine.
  * @return The label of element.
  */
-gCrWeb.fill.inferLabelFromEnclosingLabel = function(
+gCrWebLegacy.fill.inferLabelFromEnclosingLabel = function(
     element: FormControlElement): InferredLabel | null {
   if (!element) {
     return null;
   }
   let node = element.parentNode;
-  while (node && !gCrWeb.fill.hasTagName(node, 'label')) {
+  while (node && !gCrWebLegacy.fill.hasTagName(node, 'label')) {
     node = node.parentNode;
   }
   if (node) {
@@ -444,7 +444,7 @@
  * @param element An element to examine.
  * @return The label of element.
  */
-gCrWeb.fill.inferLabelFromDivTable = function(
+gCrWebLegacy.fill.inferLabelFromDivTable = function(
     element: FormControlElement): InferredLabel | null {
   if (!element) {
     return null;
@@ -457,7 +457,7 @@
   // Search the sibling and parent <div>s until we find a candidate label.
   let r: InferredLabel | null = null;
   while (!r && node) {
-    if (gCrWeb.fill.hasTagName(node, 'div')) {
+    if (gCrWebLegacy.fill.hasTagName(node, 'div')) {
       r = buildInferredLabelIfValid(
           lookingForParent
               ? findChildTextWithIgnoreList(node, divsToSkip)
@@ -485,7 +485,7 @@
     } else if (!lookingForParent) {
       // Infer a label from text nodes and unassigned <label> siblings.
       if (node.nodeType === Node.TEXT_NODE ||
-          (gCrWeb.fill.hasTagName(node, 'label') &&
+          (gCrWebLegacy.fill.hasTagName(node, 'label') &&
            !(node as HTMLLabelElement).control)) {
         r = buildInferredLabelIfValid(findChildText(node));
       }
@@ -521,7 +521,7 @@
  * @param element An element to examine.
  * @return The label of element.
  */
-gCrWeb.fill.inferLabelFromDefinitionList = function(
+gCrWebLegacy.fill.inferLabelFromDefinitionList = function(
     element: FormControlElement): InferredLabel | null {
   if (!element) {
     return null;
@@ -529,11 +529,11 @@
 
   let parentNode = element.parentNode;
   while (parentNode && parentNode.nodeType === Node.ELEMENT_NODE &&
-         !gCrWeb.fill.hasTagName(parentNode, 'dd')) {
+         !gCrWebLegacy.fill.hasTagName(parentNode, 'dd')) {
     parentNode = parentNode.parentNode;
   }
 
-  if (!parentNode || !gCrWeb.fill.hasTagName(parentNode, 'dd')) {
+  if (!parentNode || !gCrWebLegacy.fill.hasTagName(parentNode, 'dd')) {
     return null;
   }
 
@@ -543,7 +543,7 @@
     previous = previous.previousSibling;
   }
 
-  if (!previous || !gCrWeb.fill.hasTagName(previous, 'dt')) {
+  if (!previous || !gCrWebLegacy.fill.hasTagName(previous, 'dt')) {
     return null;
   }
 
@@ -560,17 +560,17 @@
  * @param element An element to examine.
  * @return The inferred label of element, or '' if none could be found.
  */
-gCrWeb.fill.inferLabelForElement = function(
+gCrWebLegacy.fill.inferLabelForElement = function(
     element: FormControlElement): InferredLabel | null {
   let r: InferredLabel | null = null;
-  if (gCrWeb.fill.isCheckableElement(element)) {
+  if (gCrWebLegacy.fill.isCheckableElement(element)) {
     r = inferLabelFromNext(element);
     if (r) {
       return r;
     }
   }
 
-  r = gCrWeb.fill.inferLabelFromPrevious(element);
+  r = gCrWebLegacy.fill.inferLabelFromPrevious(element);
   if (r) {
     return r;
   }
@@ -600,18 +600,18 @@
 
     seenTagNames[tagName] = true;
     if (tagName === 'LABEL') {
-      r = gCrWeb.fill.inferLabelFromEnclosingLabel(element);
+      r = gCrWebLegacy.fill.inferLabelFromEnclosingLabel(element);
     } else if (tagName === 'DIV') {
-      r = gCrWeb.fill.inferLabelFromDivTable(element);
+      r = gCrWebLegacy.fill.inferLabelFromDivTable(element);
     } else if (tagName === 'TD') {
-      r = gCrWeb.fill.inferLabelFromTableColumn(element);
+      r = gCrWebLegacy.fill.inferLabelFromTableColumn(element);
       if (!r) {
-        r = gCrWeb.fill.inferLabelFromTableRow(element);
+        r = gCrWebLegacy.fill.inferLabelFromTableRow(element);
       }
     } else if (tagName === 'DD') {
-      r = gCrWeb.fill.inferLabelFromDefinitionList(element);
+      r = gCrWebLegacy.fill.inferLabelFromDefinitionList(element);
     } else if (tagName === 'LI') {
-      r = gCrWeb.fill.inferLabelFromListItem(element);
+      r = gCrWebLegacy.fill.inferLabelFromListItem(element);
     } else if (tagName === 'FIELDSET') {
       break;
     }
diff --git a/components/autofill/ios/form_util/resources/fill_element_inference_util.ts b/components/autofill/ios/form_util/resources/fill_element_inference_util.ts
index aafc7bc..097d5f7 100644
--- a/components/autofill/ios/form_util/resources/fill_element_inference_util.ts
+++ b/components/autofill/ios/form_util/resources/fill_element_inference_util.ts
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 import {isTextField} from '//ios/web/public/js_messaging/resources/utils.js';
 
 /**
@@ -15,7 +15,7 @@
  * @param tag Tag name.
  * @return Whether the tag of node is tag.
  */
-gCrWeb.fill.hasTagName = function(node: Element, tag: string): boolean {
+gCrWebLegacy.fill.hasTagName = function(node: Element, tag: string): boolean {
   return node.nodeType === Node.ELEMENT_NODE &&
       (node).tagName === tag.toUpperCase();
 };
@@ -30,9 +30,9 @@
  * @return Whether element is one of the element types that can be
  *     autofilled.
  */
-gCrWeb.fill.isAutofillableElement = function(element: Element): boolean {
-  return gCrWeb.fill.isAutofillableInputElement(element) ||
-      gCrWeb.fill.isSelectElement(element) || isTextAreaElement(element);
+gCrWebLegacy.fill.isAutofillableElement = function(element: Element): boolean {
+  return gCrWebLegacy.fill.isAutofillableInputElement(element) ||
+      gCrWebLegacy.fill.isSelectElement(element) || isTextAreaElement(element);
 };
 
 /**
@@ -81,7 +81,7 @@
  *     be added as separator in the combination.
  * @return The combined string.
  */
-gCrWeb.fill.combineAndCollapseWhitespace = function(
+gCrWebLegacy.fill.combineAndCollapseWhitespace = function(
     prefix: string, suffix: string, forceWhitespace: boolean): string {
   const prefixTrimmed = trimWhitespaceTrailing(prefix);
   const prefixTrailingWhitespace = prefixTrimmed !== prefix;
@@ -127,9 +127,9 @@
     if (node.tagName === 'OPTION') {
       return '';
     }
-    if (gCrWeb.form.isFormControlElement(/** @type {Element} */ (node))) {
+    if (gCrWebLegacy.form.isFormControlElement(/** @type {Element} */ (node))) {
       const input = /** @type {FormControlElement} */ (node);
-      if (gCrWeb.fill.isAutofillableElement(input)) {
+      if (gCrWebLegacy.fill.isAutofillableElement(input)) {
         return '';
       }
     }
@@ -163,7 +163,7 @@
     // Emulate apparently incorrect Chromium behavior tracked in
     // https://crbug.com/239819.
     addSpace = false;
-    nodeText = gCrWeb.fill.combineAndCollapseWhitespace(
+    nodeText = gCrWebLegacy.fill.combineAndCollapseWhitespace(
         nodeText, childText, addSpace);
   }
 
@@ -175,7 +175,7 @@
   // Emulate apparently incorrect Chromium behavior tracked in
   // https://crbug.com/239819.
   addSpace = false;
-  nodeText = gCrWeb.fill.combineAndCollapseWhitespace(
+  nodeText = gCrWebLegacy.fill.combineAndCollapseWhitespace(
       nodeText, siblingText, addSpace);
 
   return nodeText;
@@ -271,7 +271,7 @@
  * @return Whether element is a 'select' element.
  */
 // TODO(crbug.com/40285548): Replace all `any` types with a specific type.
-gCrWeb.fill.isSelectElement = function(element: any): boolean {
+gCrWebLegacy.fill.isSelectElement = function(element: any): boolean {
   if (!element) {
     return false;
   }
@@ -305,7 +305,7 @@
  * @return Whether element is a checkbox or a radio button.
  */
 // TODO(crbug.com/40285548): Replace all `any` types with a specific type.
-gCrWeb.fill.isCheckableElement = function(element: any): boolean {
+gCrWebLegacy.fill.isCheckableElement = function(element: any): boolean {
   if (!element) {
     return false;
   }
@@ -323,8 +323,8 @@
  * @return Whether element is one of the input element types that
  *     can be autofilled.
  */
-gCrWeb.fill.isAutofillableInputElement = function(element: Element): boolean {
-  return isTextField(element) || gCrWeb.fill.isCheckableElement(element);
+gCrWebLegacy.fill.isAutofillableInputElement = function(element: Element): boolean {
+  return isTextField(element) || gCrWebLegacy.fill.isCheckableElement(element);
 };
 
 /**
diff --git a/components/autofill/ios/form_util/resources/fill_util.ts b/components/autofill/ios/form_util/resources/fill_util.ts
index f476a7d..30cb09d 100644
--- a/components/autofill/ios/form_util/resources/fill_util.ts
+++ b/components/autofill/ios/form_util/resources/fill_util.ts
@@ -6,7 +6,7 @@
 
 import * as fillConstants from '//components/autofill/ios/form_util/resources/fill_constants.js';
 import {findChildText} from '//components/autofill/ios/form_util/resources/fill_element_inference_util.js';
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 import {isTextField, removeQueryAndReferenceFromURL, trim} from '//ios/web/public/js_messaging/resources/utils.js';
 
 declare interface AutofillFormFieldData {
@@ -107,7 +107,7 @@
  * @param element An element to check if it can be autocompleted.
  * @return true if autocomplete dropdown should be suggested.
  */
-gCrWeb.fill.shouldAutocomplete = function(
+gCrWebLegacy.fill.shouldAutocomplete = function(
     element: fillConstants.FormControlElement|null): boolean {
   if (!autoComplete(element)) {
     return false;
@@ -181,7 +181,7 @@
  *     element's value is changed.
  * @return Whether the value has been set successfully.
  */
-gCrWeb.fill.setInputElementValue = function(
+gCrWebLegacy.fill.setInputElementValue = function(
     value: string, input: HTMLInputElement|null,
     callback: Function|undefined = undefined): boolean {
   if (!input) {
@@ -490,7 +490,7 @@
  * function GetCanonicalActionForForm.
  * @return Canonical action.
  */
-gCrWeb.fill.getCanonicalActionForForm = function(
+gCrWebLegacy.fill.getCanonicalActionForForm = function(
     formElement: HTMLFormElement): string {
   const rawAction = formElement.getAttribute('action') || '';
   const absoluteUrl = absoluteURL(formElement.ownerDocument, rawAction);
@@ -517,7 +517,7 @@
  * @param field A field that will contain the extracted option
  *     information.
  */
-gCrWeb.fill.getOptionStringsFromElement = function(
+gCrWebLegacy.fill.getOptionStringsFromElement = function(
     selectElement: HTMLSelectElement, field: OptionFieldStrings): void {
   field.option_values = [];
   // Protect against custom implementation of Array.toJSON in host pages.
@@ -549,10 +549,10 @@
  * @param element An element to examine.
  * @return The value for `element`.
  */
-gCrWeb.fill.value = function(
+gCrWebLegacy.fill.value = function(
     element: fillConstants.FormControlElement|HTMLOptionElement): string {
   let value = element.value;
-  if (gCrWeb.fill.isSelectElement(element)) {
+  if (gCrWebLegacy.fill.isSelectElement(element)) {
     const selectElement = element as HTMLSelectElement;
     if (selectElement.options.length > 0 && selectElement.selectedIndex === 0 &&
         selectElement.options[0]!.disabled &&
@@ -622,7 +622,7 @@
  * or the value of the aria-label attribute, with priority given to the
  * aria-labelledby text.
  */
-gCrWeb.fill.getAriaLabel = function(element: Element): string {
+gCrWebLegacy.fill.getAriaLabel = function(element: Element): string {
   let label = coalesceTextByIdList(element, 'aria-labelledby');
   if (!label) {
     label = element.getAttribute('aria-label') || '';
@@ -633,7 +633,7 @@
 /**
  * Returns the coalesced text referenced by the aria-describedby attribute.
  */
-gCrWeb.fill.getAriaDescription = function(element: Element): string {
+gCrWebLegacy.fill.getAriaDescription = function(element: Element): string {
   return coalesceTextByIdList(element, 'aria-describedby');
 };
 
@@ -648,13 +648,13 @@
  * @param element An element to examine.
  * @return Whether the element is inside a <form> or <fieldset>.
  */
-gCrWeb.fill.isElementInsideFormOrFieldSet = function(
+gCrWebLegacy.fill.isElementInsideFormOrFieldSet = function(
     element: fillConstants.FormControlElement): boolean {
   let parentNode = element.parentNode;
   while (parentNode) {
     if ((parentNode.nodeType === Node.ELEMENT_NODE) &&
-        (gCrWeb.fill.hasTagName(parentNode, 'form') ||
-         gCrWeb.fill.hasTagName(parentNode, 'fieldset'))) {
+        (gCrWebLegacy.fill.hasTagName(parentNode, 'form') ||
+         gCrWebLegacy.fill.hasTagName(parentNode, 'fieldset'))) {
       return true;
     }
     parentNode = parentNode.parentNode;
@@ -666,16 +666,16 @@
  * @param element Form or form input element.
  * @return Unique stable ID converted to string..
  */
-gCrWeb.fill.getUniqueID = function(element: any): string {
+gCrWebLegacy.fill.getUniqueID = function(element: any): string {
   // `setUniqueIDIfNeeded` is only available in the isolated content world.
   // Check before invoking it as this script is injected into the page content
   // world as well.
-  if (gCrWeb.fill.setUniqueIDIfNeeded) {
-    gCrWeb.fill.setUniqueIDIfNeeded(element);
+  if (gCrWebLegacy.fill.setUniqueIDIfNeeded) {
+    gCrWebLegacy.fill.setUniqueIDIfNeeded(element);
   }
 
   try {
-    const uniqueIDSymbol = gCrWeb.fill.ID_SYMBOL;
+    const uniqueIDSymbol = gCrWebLegacy.fill.ID_SYMBOL;
     if (typeof element[uniqueIDSymbol] !== 'undefined' &&
         !isNaN(element[uniqueIDSymbol]!)) {
       return element[uniqueIDSymbol].toString();
diff --git a/components/autofill/ios/form_util/resources/form.ts b/components/autofill/ios/form_util/resources/form.ts
index 0c2c6bc..732d28d9 100644
--- a/components/autofill/ios/form_util/resources/form.ts
+++ b/components/autofill/ios/form_util/resources/form.ts
@@ -8,7 +8,7 @@
 
 import {RENDERER_ID_NOT_SET} from '//components/autofill/ios/form_util/resources/fill_constants.js';
 import {getRemoteFrameToken} from '//components/autofill/ios/form_util/resources/fill_util.js';
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 import {sendWebKitMessage, trim} from '//ios/web/public/js_messaging/resources/utils.js';
 
 /**
@@ -283,7 +283,7 @@
     return null;
   }
   for (const form of document.forms) {
-    if (identifier.toString() === gCrWeb.fill.getUniqueID(form)) {
+    if (identifier.toString() === gCrWebLegacy.fill.getUniqueID(form)) {
       return form;
     }
   }
@@ -298,7 +298,7 @@
  * makes an edited field unedited.
  */
 function fieldWasEditedByUser(element: Element) {
-  return !gCrWeb.autofill_form_features
+  return !gCrWebLegacy.autofill_form_features
               .isAutofillCorrectUserEditedBitInParsedField() ||
       (wasEditedByUser.get(element) ?? false);
 }
@@ -327,10 +327,10 @@
 
   const message = {
     command: 'form.submit',
-    frameID: gCrWeb.message.getFrameId(),
-    formName: gCrWeb.form.getFormIdentifier(form),
+    frameID: gCrWebLegacy.message.getFrameId(),
+    formName: gCrWebLegacy.form.getFormIdentifier(form),
     href: getFullyQualifiedUrl(action),
-    formData: gCrWeb.fill.autofillSubmissionData(form),
+    formData: gCrWebLegacy.fill.autofillSubmissionData(form),
     remoteFrameToken: includeRemoteFrameToken ? getRemoteFrameToken() :
                                                 undefined,
     programmaticSubmission: programmaticSubmission,
@@ -339,7 +339,7 @@
   sendWebKitMessage(messageHandler, message);
 }
 
-gCrWeb.form = {
+gCrWebLegacy.form = {
   wasEditedByUser,
   isFormControlElement,
   getFormControlElements,
diff --git a/components/autofill/ios/form_util/resources/form_handlers.ts b/components/autofill/ios/form_util/resources/form_handlers.ts
index 77c83101..a4f7d43 100644
--- a/components/autofill/ios/form_util/resources/form_handlers.ts
+++ b/components/autofill/ios/form_util/resources/form_handlers.ts
@@ -11,7 +11,7 @@
 // Requires functions from fill.ts, form.ts, autofill_form_features.ts and
 // child_frame_registration_lib.ts.
 
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 import {sendWebKitMessage} from '//ios/web/public/js_messaging/resources/utils.js';
 
 /**
@@ -124,8 +124,8 @@
     lastFocusedElement = document.activeElement;
   }
   if (['change', 'input'].includes(evt.type) &&
-      gCrWeb.form.wasEditedByUser !== null) {
-    gCrWeb.form.wasEditedByUser.set(target, evt.isTrusted);
+      gCrWebLegacy.form.wasEditedByUser !== null) {
+    gCrWebLegacy.form.wasEditedByUser.set(target, evt.isTrusted);
   }
 
   if (evt.target !== lastFocusedElement) {
@@ -135,18 +135,18 @@
       target.tagName === 'FORM' ? target : (target as HTMLFormElement)['form'];
   const field = target.tagName === 'FORM' ? null : target;
 
-  const formRendererID = gCrWeb.fill.getUniqueID(form);
-  const fieldRendererID = gCrWeb.fill.getUniqueID(field);
+  const formRendererID = gCrWebLegacy.fill.getUniqueID(form);
+  const fieldRendererID = gCrWebLegacy.fill.getUniqueID(field);
 
   const fieldType = 'type' in target ? target.type : '';
   const fieldValue = 'value' in target ? target.value : '';
 
   const msg = {
     'command': 'form.activity',
-    'frameID': gCrWeb.message.getFrameId(),
-    'formName': gCrWeb.form.getFormIdentifier(form),
+    'frameID': gCrWebLegacy.message.getFrameId(),
+    'formName': gCrWebLegacy.form.getFormIdentifier(form),
     'formRendererID': formRendererID,
-    'fieldIdentifier': gCrWeb.form.getFieldIdentifier(field),
+    'fieldIdentifier': gCrWebLegacy.form.getFieldIdentifier(field),
     'fieldRendererID': fieldRendererID,
     'fieldType': fieldType,
     'type': evt.type,
@@ -166,7 +166,7 @@
     return;
   }
 
-  gCrWeb.form.formSubmitted(
+  gCrWebLegacy.form.formSubmitted(
       evt.target as HTMLFormElement,
       /* messageHandler= */ NATIVE_MESSAGE_HANDLER,
       /* programmaticSubmission= */ false);
@@ -221,8 +221,8 @@
  * the Child Frame Registration lib.
  */
 function processInboundMessage(event: MessageEvent<any>): void {
-  if (gCrWeb.autofill_form_features.isAutofillAcrossIframesEnabled()) {
-    gCrWeb.remoteFrameRegistration.processChildFrameMessage(event);
+  if (gCrWebLegacy.autofill_form_features.isAutofillAcrossIframesEnabled()) {
+    gCrWebLegacy.remoteFrameRegistration.processChildFrameMessage(event);
   }
 }
 
@@ -257,7 +257,7 @@
   if (formSubmitOriginalFunction === null) {
     formSubmitOriginalFunction = HTMLFormElement.prototype.submit;
     HTMLFormElement.prototype.submit = function() {
-      if (!gCrWeb.autofill_form_features
+      if (!gCrWebLegacy.autofill_form_features
                .isAutofillIsolatedContentWorldEnabled()) {
         // If an error happens in formSubmitted, this will cancel the form
         // submission which can lead to usability issue for the user.
@@ -265,7 +265,7 @@
         // is always called.
 
         try {
-          gCrWeb.form.formSubmitted(
+          gCrWebLegacy.form.formSubmitted(
               this,
               /* messageHandler= */ NATIVE_MESSAGE_HANDLER,
               /* programmaticSubmission= */ true);
@@ -313,9 +313,9 @@
 function findFormlessFieldsIds(elements: Element[]): string[] {
   return elements
       .filter(
-          e => gCrWeb.fill.isAutofillableElement(e) &&
+          e => gCrWebLegacy.fill.isAutofillableElement(e) &&
               !(e as HTMLInputElement).form)
-      .map(gCrWeb.fill.getUniqueID);
+      .map(gCrWebLegacy.fill.getUniqueID);
 }
 
 /**
@@ -352,7 +352,7 @@
       if (!addedFormMessage && formWasAdded) {
         addedFormMessage = {
           'command': 'form.activity',
-          'frameID': gCrWeb.message.getFrameId(),
+          'frameID': gCrWebLegacy.message.getFrameId(),
           'formName': '',
           'formRendererID': '',
           'fieldIdentifier': '',
@@ -391,12 +391,12 @@
         } else {
           // Send the removed forms identifiers to the browser.
           const filteredFormIDs =
-              forms.map(form => gCrWeb.fill.getUniqueID(form));
+              forms.map(form => gCrWebLegacy.fill.getUniqueID(form));
           removedFormMessage = {
             'command': 'form.removal',
-            'frameID': gCrWeb.message.getFrameId(),
-            'removedFormIDs': gCrWeb.stringify(filteredFormIDs),
-            'removedFieldIDs': gCrWeb.stringify(removedFormlessFieldsIds),
+            'frameID': gCrWebLegacy.message.getFrameId(),
+            'removedFormIDs': gCrWebLegacy.stringify(filteredFormIDs),
+            'removedFieldIDs': gCrWebLegacy.stringify(removedFormlessFieldsIds),
           };
           continue;
         }
@@ -406,8 +406,8 @@
         // Handle the removed formless field case.
         removedFormMessage = {
           'command': 'form.removal',
-          'frameID': gCrWeb.message.getFrameId(),
-          'removedFieldIDs': gCrWeb.stringify(removedFormlessFieldsIds),
+          'frameID': gCrWebLegacy.message.getFrameId(),
+          'removedFieldIDs': gCrWebLegacy.stringify(removedFormlessFieldsIds),
         };
         continue;
       } else if (formlessFieldsWereRemoved) {
@@ -420,7 +420,7 @@
         // mutation that is treated the same way as adding a new form.
         addedFormMessage = {
           'command': 'form.activity',
-          'frameID': gCrWeb.message.getFrameId(),
+          'frameID': gCrWebLegacy.message.getFrameId(),
           'formName': '',
           'formRendererID': '',
           'fieldIdentifier': '',
@@ -445,4 +445,4 @@
   formMutationObserver.observe(document, {childList: true, subtree: true});
 }
 
-gCrWeb.formHandlers = {trackFormMutations};
+gCrWebLegacy.formHandlers = {trackFormMutations};
diff --git a/components/autofill/ios/form_util/resources/programmatic_form_submission_handler.ts b/components/autofill/ios/form_util/resources/programmatic_form_submission_handler.ts
index 5d41e45..55aae6b0 100644
--- a/components/autofill/ios/form_util/resources/programmatic_form_submission_handler.ts
+++ b/components/autofill/ios/form_util/resources/programmatic_form_submission_handler.ts
@@ -10,7 +10,7 @@
 
 // Requires functions from fill.ts, form.ts, and autofill_form_features.ts.
 
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 //
 ///**
 // * The name of the message handler in the browser layer which will process
@@ -34,7 +34,7 @@
   // Put the formSubmitted in a try catch to ensure the original function
   // is always called.
   try {
-    gCrWeb.form.formSubmitted(
+    gCrWebLegacy.form.formSubmitted(
         this, /* messageHandler= */ NATIVE_MESSAGE_HANDLER,
         /* programmaticSubmission= */ true,
         /* includeRemoteFrameToken= */ true);
diff --git a/components/autofill/ios/form_util/resources/register_remote_frame_token.ts b/components/autofill/ios/form_util/resources/register_remote_frame_token.ts
index b8413a2..a3241dd 100644
--- a/components/autofill/ios/form_util/resources/register_remote_frame_token.ts
+++ b/components/autofill/ios/form_util/resources/register_remote_frame_token.ts
@@ -11,7 +11,7 @@
 // Requires functions from child_frame_registration_lib.ts.
 
 import {setRemoteFrameToken} from '//components/autofill/ios/form_util/resources/fill_util.js';
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 import {generateRandomId} from '//ios/web/public/js_messaging/resources/utils.js';
 
 function registerRemoteToken(): void {
@@ -21,7 +21,7 @@
   // browser layer uses remote tokens to map page content world frames to their
   // isolated world counter parts, which is where the rest of Autofill lives.
   setRemoteFrameToken(remoteFrameToken);
-  gCrWeb.remoteFrameRegistration.registerSelfWithRemoteToken(remoteFrameToken);
+  gCrWebLegacy.remoteFrameRegistration.registerSelfWithRemoteToken(remoteFrameToken);
 }
 
 
diff --git a/components/autofill/ios/form_util/resources/renderer_id.ts b/components/autofill/ios/form_util/resources/renderer_id.ts
index 3b4a14c4..17d3055 100644
--- a/components/autofill/ios/form_util/resources/renderer_id.ts
+++ b/components/autofill/ios/form_util/resources/renderer_id.ts
@@ -10,7 +10,7 @@
 import '//components/autofill/ios/form_util/resources/create_fill_namespace.js';
 
 import * as fillConstants from '//components/autofill/ios/form_util/resources/fill_constants.js';
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 
 // Extends the Element to add the ability to access its properties
 // via the [] notation.
@@ -27,19 +27,19 @@
  * Stores the next available ID for forms and fields. By convention, 0 means
  * null, so we start at 1 and increment from there.
  */
-document[gCrWeb.fill.ID_SYMBOL] = 1;
+document[gCrWebLegacy.fill.ID_SYMBOL] = 1;
 
 /**
  * @param element Form or form input element.
  */
-gCrWeb.fill.setUniqueIDIfNeeded = function(element: IndexableElement): void {
+gCrWebLegacy.fill.setUniqueIDIfNeeded = function(element: IndexableElement): void {
   try {
-    const uniqueIDSymbol = gCrWeb.fill.ID_SYMBOL;
+    const uniqueIDSymbol = gCrWebLegacy.fill.ID_SYMBOL;
     if (typeof element[uniqueIDSymbol] === 'undefined') {
       const elementID = document[uniqueIDSymbol]!++;
       element[uniqueIDSymbol] = elementID;
 
-      //  Store a copy of the ID in the DOM. gCrWeb.fill.getUniqueID will use
+      //  Store a copy of the ID in the DOM. gCrWebLegacy.fill.getUniqueID will use
       //  the DOM copy when running in the page content world.
       element.setAttribute(
           fillConstants.UNIQUE_ID_ATTRIBUTE, elementID.toString());
@@ -54,7 +54,7 @@
  * @param id Unique ID.
  * @return element Form or form input element.
  */
-gCrWeb.fill.getElementByUniqueID = function(id: number): Element|null {
+gCrWebLegacy.fill.getElementByUniqueID = function(id: number): Element|null {
   try {
     return elementMap.get(id).deref();
   } catch (e) {
diff --git a/components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/ModalDialogView.java b/components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/ModalDialogView.java
index b33b754..c69e071 100644
--- a/components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/ModalDialogView.java
+++ b/components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/ModalDialogView.java
@@ -10,7 +10,6 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.text.TextUtils;
-import android.text.method.LinkMovementMethod;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 import android.view.KeyEvent;
@@ -145,8 +144,6 @@
         mFooterContainer = findViewById(R.id.footer);
         mFooterMessageView = findViewById(R.id.footer_message);
         mButtonGroup = findViewById(R.id.button_group);
-        mMessageParagraph1.setMovementMethod(LinkMovementMethod.getInstance());
-        mFooterMessageView.setMovementMethod(LinkMovementMethod.getInstance());
         mFooterContainer.setBackgroundColor(
                 SemanticColorUtils.getColorSurfaceContainerLow(getContext()));
         updateContentVisibility();
@@ -422,9 +419,12 @@
         updateContentVisibility();
     }
 
-    /** @param message The message in the dialog content. */
+    /**
+     * @param message The message in the dialog content.
+     */
     void setMessageParagraph1(CharSequence message) {
         mMessageParagraph1.setText(message);
+        UiUtils.maybeSetLinkMovementMethod(mMessageParagraph1);
         updateContentVisibility();
     }
 
@@ -547,9 +547,12 @@
         getButton(buttonType).setEnabled(enabled);
     }
 
-    /** @param message The message in the dialog footer. */
+    /**
+     * @param message The message in the dialog footer.
+     */
     void setFooterMessage(CharSequence message) {
         mFooterMessageView.setText(message);
+        UiUtils.maybeSetLinkMovementMethod(mFooterMessageView);
         updateContentVisibility();
     }
 
diff --git a/components/browser_ui/settings/android/widget/java/src/org/chromium/components/browser_ui/settings/TextMessagePreference.java b/components/browser_ui/settings/android/widget/java/src/org/chromium/components/browser_ui/settings/TextMessagePreference.java
index 424815a..840e092 100644
--- a/components/browser_ui/settings/android/widget/java/src/org/chromium/components/browser_ui/settings/TextMessagePreference.java
+++ b/components/browser_ui/settings/android/widget/java/src/org/chromium/components/browser_ui/settings/TextMessagePreference.java
@@ -5,8 +5,6 @@
 package org.chromium.components.browser_ui.settings;
 
 import android.content.Context;
-import android.text.method.LinkMovementMethod;
-import android.text.method.MovementMethod;
 import android.util.AttributeSet;
 import android.widget.TextView;
 
@@ -14,13 +12,13 @@
 
 import org.chromium.build.annotations.NullMarked;
 import org.chromium.build.annotations.Nullable;
+import org.chromium.ui.UiUtils;
 
 /** A preference that displays informational text, and a summary which can contain a link. */
 @NullMarked
 public class TextMessagePreference extends ChromeBasePreference {
     private @Nullable TextView mTitleView;
     private @Nullable TextView mSummaryView;
-    private MovementMethod mMovementMethod = LinkMovementMethod.getInstance();
     private @Nullable Integer mLiveRegionMode;
     private @Nullable CharSequence mTitleContentDescription;
     private @Nullable CharSequence mSummaryContentDescription;
@@ -38,7 +36,9 @@
 
         mTitleView = (TextView) holder.findViewById(android.R.id.title);
         mSummaryView = (TextView) holder.findViewById(android.R.id.summary);
-        setSummaryMovementMethod(mMovementMethod);
+        if (mSummaryView != null && getSummary() != null) {
+            UiUtils.maybeSetLinkMovementMethod(mSummaryView);
+        }
         if (mLiveRegionMode != null) {
             setAccessibilityLiveRegion(mLiveRegionMode);
         }
@@ -69,16 +69,6 @@
     }
 
     /**
-     * @param movementMethod Set the movement method of the summary TextView.
-     */
-    public void setSummaryMovementMethod(MovementMethod movementMethod) {
-        mMovementMethod = movementMethod;
-        if (mSummaryView != null) {
-            mSummaryView.setMovementMethod(movementMethod);
-        }
-    }
-
-    /**
      * Sets the accessibility live region property on the views related to this preference.
      *
      * @param liveRegionMode One of View.ACCESSIBILITY_LIVE_REGION_NONE, POLITE, or ASSERTIVE.
diff --git a/components/content_settings/core/browser/cookie_settings.cc b/components/content_settings/core/browser/cookie_settings.cc
index 5818205..7a91123 100644
--- a/components/content_settings/core/browser/cookie_settings.cc
+++ b/components/content_settings/core/browser/cookie_settings.cc
@@ -401,9 +401,8 @@
     case CookieControlsMode::kIncognitoOnly:
       return is_incognito_;
     case CookieControlsMode::kOff:
-      return base::FeatureList::IsEnabled(
-                 privacy_sandbox::kAlwaysBlock3pcsIncognito) &&
-             is_incognito_;
+      return is_incognito_ && base::FeatureList::IsEnabled(
+                                  privacy_sandbox::kAlwaysBlock3pcsIncognito);
   }
 #endif
 }
diff --git a/components/crash/android/java/src/org/chromium/components/crash/NativeAndJavaSmartExceptionReporter.java b/components/crash/android/java/src/org/chromium/components/crash/NativeAndJavaSmartExceptionReporter.java
index 6f6225b1..a159e1c 100644
--- a/components/crash/android/java/src/org/chromium/components/crash/NativeAndJavaSmartExceptionReporter.java
+++ b/components/crash/android/java/src/org/chromium/components/crash/NativeAndJavaSmartExceptionReporter.java
@@ -22,18 +22,14 @@
 @NullMarked
 public class NativeAndJavaSmartExceptionReporter {
     private static void uploadReport(Throwable exception, Callback<Throwable> pureJavaReport) {
-        PostTask.postTask(
-                TaskTraits.UI_BEST_EFFORT,
-                () -> {
-                    if (PureJavaExceptionHandler.isEnabled()) {
-                        // The Java exception reporter should be called on the UI thread to prevent
-                        // race conditions.
-                        pureJavaReport.onResult(exception);
-                    } else {
-                        // The native exception reporter requires to be called on the UI thread.
-                        JavaExceptionReporter.reportException(exception);
-                    }
-                });
+        if (PureJavaExceptionHandler.isEnabled()) {
+            pureJavaReport.onResult(exception);
+        } else {
+            // The native exception reporter requires to be called on the UI thread.
+            PostTask.postTask(
+                    TaskTraits.UI_BEST_EFFORT,
+                    () -> JavaExceptionReporter.reportException(exception));
+        }
     }
 
     public static void postUploadReport(Throwable exception, Callback<Throwable> pureJavaReport) {
diff --git a/components/cronet/PRESUBMIT.py b/components/cronet/PRESUBMIT.py
index 1674079..661419d 100644
--- a/components/cronet/PRESUBMIT.py
+++ b/components/cronet/PRESUBMIT.py
@@ -9,40 +9,15 @@
 
 import os
 
+PRESUBMIT_VERSION = '2.0.0'
 
-def _PyLintChecks(input_api, output_api):
-    pylint_checks = input_api.canned_checks.GetPylint(
-        input_api,
-        output_api,
-        extra_paths_list=_GetPathsToPrepend(input_api),
-        pylintrc='pylintrc',
-        version='2.7')
+
+def CheckPyLint(input_api, output_api):
+    pylint_checks = input_api.canned_checks.GetPylint(input_api, output_api)
     return input_api.RunTests(pylint_checks)
 
 
-def _GetPathsToPrepend(input_api):
-    current_dir = input_api.PresubmitLocalPath()
-    chromium_src_dir = input_api.os_path.join(current_dir, '..', '..')
-    return [
-        input_api.os_path.join(chromium_src_dir, 'components'),
-        input_api.os_path.join(chromium_src_dir, 'tools', 'perf'),
-        input_api.os_path.join(chromium_src_dir, 'build', 'android'),
-        input_api.os_path.join(chromium_src_dir, 'build', 'android', 'gyp'),
-        input_api.os_path.join(chromium_src_dir, 'mojo', 'public', 'tools',
-                               'bindings', 'pylib'),
-        input_api.os_path.join(chromium_src_dir, 'net', 'tools', 'net_docs'),
-        input_api.os_path.join(chromium_src_dir, 'tools'),
-        input_api.os_path.join(chromium_src_dir, 'third_party'),
-        input_api.os_path.join(chromium_src_dir, 'third_party', 'catapult',
-                               'telemetry'),
-        input_api.os_path.join(chromium_src_dir, 'third_party', 'catapult',
-                               'devil'),
-        input_api.os_path.join(chromium_src_dir, 'third_party', 'catapult',
-                               'common', 'py_utils'),
-    ]
-
-
-def _PackageChecks(input_api, output_api):
+def CheckPackage(input_api, output_api):
     """Verify API classes are in org.chromium.net package, and implementation
   classes are not in org.chromium.net package."""
     api_packages = ['org.chromium.net', 'org.chromium.net.apihelpers']
@@ -78,24 +53,22 @@
     if problems:
         return [
             output_api.PresubmitError(
-                'API classes must be in org.chromium.net package, and implementation\n'
+                'API classes must be in org.chromium.net package, '
+                'and implementation\n'
                 'classes must not be in org.chromium.net package.', problems)
         ]
     return []
 
 
-def _RunToolsUnittests(input_api, output_api):
-    return input_api.canned_checks.RunUnitTestsInDirectory(
-        input_api, output_api, '.', [r'^tools_unittest\.py$'])
-
-
-def _ChangeAffectsCronetTools(change):
-    """ Returns |true| if the change may affect Cronet tools. """
-
-    for path in change.LocalPaths():
-        if path.startswith(os.path.join('components', 'cronet', 'tools')):
-            return True
-    return False
+def CheckUnittests(input_api, output_api):
+    return input_api.RunTests(
+        input_api.canned_checks.GetUnitTestsRecursively(
+            input_api,
+            output_api,
+            os.path.join(input_api.change.RepositoryRoot(), 'components',
+                         'cronet'),
+            files_to_check=['.*test\\.py$'],
+            files_to_skip=[]))
 
 
 GOOD_CHANGE_ID_TXT = 'good_change_id'
@@ -155,21 +128,24 @@
         unknown_keys.append(key)
 
     if unknown_keys:
-        return '\t - entry contains unknown key(s): %s. Expected either %s, %s, ' \
-          '%s or %s.\n' % \
-          (unknown_keys, BAD_CHANGE_ID_TXT, GOOD_CHANGE_ID_TXT, BUG_TXT,
-           COMMENT_TXT)
+        return (f'\t - entry contains unknown key(s): {unknown_keys}. '
+                f'Expected either {GOOD_CHANGE_ID_TXT}, {BUG_TXT} or '
+                f'{COMMENT_TXT}\n')
     return ''
 
 
-def _BreakageFileChecks(input_api, output_api, file):
+def CheckBreakagesFile(input_api, output_api):
     """Verify that the change_ids listed in the breakages file are valid."""
-    breakages = input_api.json.loads(input_api.ReadFile(file))["breakages"]
+    breakages_file = _GetBreakagesFilePathIfChanged(input_api.change)
+    if not breakages_file:
+        return []
+    breakages = input_api.json.loads(
+        input_api.ReadFile(breakages_file))["breakages"]
     problems = []
     for i, breakage in enumerate(breakages):
         problem = ""
-        # ensures that the entries, where existing are valid and that there are no
-        # unknown keys.
+        # ensures that the entries, where existing are valid and that there are
+        # no unknown keys.
         problem += _GetInvalidChangeIdText(input_api, breakage,
                                            BAD_CHANGE_ID_TXT)
         problem += _GetInvalidChangeIdText(input_api, breakage,
@@ -188,20 +164,3 @@
                 'Please cross-check the entries.', problems)
         ]
     return []
-
-
-def CheckChangeOnUpload(input_api, output_api):
-    results = []
-    results.extend(_PyLintChecks(input_api, output_api))
-    results.extend(_PackageChecks(input_api, output_api))
-    if _ChangeAffectsCronetTools(input_api.change):
-        results.extend(_RunToolsUnittests(input_api, output_api))
-    breakages_file = _GetBreakagesFilePathIfChanged(input_api.change)
-    if breakages_file:
-        results.extend(
-            _BreakageFileChecks(input_api, output_api, breakages_file))
-    return results
-
-
-def CheckChangeOnCommit(input_api, output_api):
-    return _RunToolsUnittests(input_api, output_api)
diff --git a/components/cronet/gn2bp/PRESUBMIT.py b/components/cronet/gn2bp/PRESUBMIT.py
deleted file mode 100644
index bb917cf..0000000
--- a/components/cronet/gn2bp/PRESUBMIT.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright 2024 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-"""Presubmit script for android buildbot.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for
-details on the presubmit API built into depot_tools.
-"""
-
-# See third_party/depot_tools/presubmit_support.py
-PRESUBMIT_VERSION = '2.0.0'
-
-
-def CheckGenerateBuildScriptsOutput(input_api, output_api):
-  presubmit_script_path = input_api.PresubmitLocalPath()
-  return input_api.RunTests(
-      input_api.canned_checks.GetUnitTests(
-          input_api,
-          output_api,
-          unit_tests=[
-              input_api.os_path.join(presubmit_script_path, 'tests',
-                                     'gen_android_bp_test.py')
-          ],
-      ))
diff --git a/components/cronet/tools/api_static_checks_unittest.py b/components/cronet/tools/api_static_checks_unittest.py
index 25e6479..5e9445d 100755
--- a/components/cronet/tools/api_static_checks_unittest.py
+++ b/components/cronet/tools/api_static_checks_unittest.py
@@ -15,10 +15,14 @@
 
 REPOSITORY_ROOT = os.path.abspath(
     os.path.join(os.path.dirname(__file__), '..', '..', '..'))
+sys.path.insert(0, REPOSITORY_ROOT)
 
-sys.path.append(os.path.join(REPOSITORY_ROOT, 'components'))
-from cronet.tools import api_static_checks  # pylint: disable=wrong-import-position
-from cronet.tools import update_api  # pylint: disable=wrong-import-position
+from build.android.gyp.util import build_utils  # pylint: disable=wrong-import-position
+from components.cronet.tools import api_static_checks  # pylint: disable=wrong-import-position
+from components.cronet.tools import update_api  # pylint: disable=wrong-import-position
+
+JAR_PATH = os.path.join(build_utils.JAVA_HOME, 'bin', 'jar')
+JAVAC_PATH = os.path.join(build_utils.JAVA_HOME, 'bin', 'javac')
 
 # pylint: disable=useless-object-inheritance
 
@@ -89,8 +93,9 @@
       java_file.write('public class %s {' % class_name)
       java_file.write(java)
       java_file.write('}')
-    os.system('javac %s' % java_filename)
-    os.system('jar cf %s %s' % (jar_filename, class_filenames))
+    os.system(f'{os.path.abspath(JAVAC_PATH)} {java_filename}')
+    os.system(
+        f'{os.path.abspath(JAR_PATH)} cf {jar_filename} {class_filenames}')
     return jar_filename
 
   def run_check_api_calls(self, api_java, impl_java):
diff --git a/components/cross_device/logging/logging.cc b/components/cross_device/logging/logging.cc
index 51b3eb0..5cad8f2 100644
--- a/components/cross_device/logging/logging.cc
+++ b/components/cross_device/logging/logging.cc
@@ -16,17 +16,17 @@
   const std::string string_from_stream = stream_.str();
   CrossDeviceLogBuffer::GetInstance()->AddLogMessage(
       CrossDeviceLogBuffer::LogMessage(string_from_stream, feature_,
-                                       base::Time::Now(), std::string(file_),
-                                       line_, severity_));
+                                       base::Time::Now(), file_.data(), line_,
+                                       severity_));
 
   // Don't emit VERBOSE-level logging to the standard logging system.
   if (severity_ <= logging::LOGGING_VERBOSE &&
-      logging::GetVlogLevelHelper(file_) <= 0) {
+      logging::GetVlogLevelHelper(file_.data(), file_.size()) <= 0) {
     return;
   }
 
   // The destructor of |log_message| also creates a log for the standard logging
   // system.
-  logging::LogMessage log_message(file_, line_, severity_);
+  logging::LogMessage log_message(file_.data(), line_, severity_);
   log_message.stream() << string_from_stream;
 }
diff --git a/components/cross_device/logging/logging.h b/components/cross_device/logging/logging.h
index 62e3304..76dec7d8 100644
--- a/components/cross_device/logging/logging.h
+++ b/components/cross_device/logging/logging.h
@@ -15,9 +15,9 @@
 // Use the CD_LOG() macro for all logging related to Cross Device Features so
 // the debug page can reflect all logs related to this feature in the internal
 // debug WebUI (chrome://nearby-internals).
-#define CD_LOG(severity, feature)                                   \
-  CrossDeviceScopedLogMessage(std::string_view(__FILE__), __LINE__, \
-                              logging::LOGGING_##severity, feature) \
+#define CD_LOG(severity, feature)                                              \
+  CrossDeviceScopedLogMessage(std::string_view(__FILE__, std::size(__FILE__)), \
+                              __LINE__, logging::LOGGING_##severity, feature)  \
       .stream()
 
 // An intermediate object used by the CD_LOG macro, wrapping a
diff --git a/components/cross_device/logging/logging_unittest.cc b/components/cross_device/logging/logging_unittest.cc
index 3e9cf56..7588a475 100644
--- a/components/cross_device/logging/logging_unittest.cc
+++ b/components/cross_device/logging/logging_unittest.cc
@@ -2,18 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/cross_device/logging/logging.h"
-
 #include <stddef.h>
 
-#include <string_view>
-
 #include "base/no_destructor.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/strings/string_number_conversions.h"
-#include "components/cross_device/logging/log_buffer.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+#include "components/cross_device/logging/log_buffer.h"
+#include "components/cross_device/logging/logging.h"
+
 namespace {
 
 const char kLog1[] = "Mahogony destined to make a sturdy table";
@@ -29,7 +27,7 @@
 }
 
 bool HandleStandardLogMessage(int severity,
-                              std::string_view file,
+                              const char* file,
                               int line,
                               size_t message_start,
                               const std::string& str) {
diff --git a/components/enterprise/connectors/core/enterprise_interstitial_base.cc b/components/enterprise/connectors/core/enterprise_interstitial_base.cc
index dcce645..2fd80720 100644
--- a/components/enterprise/connectors/core/enterprise_interstitial_base.cc
+++ b/components/enterprise/connectors/core/enterprise_interstitial_base.cc
@@ -15,8 +15,6 @@
     base::Value::Dict& load_time_data) const {
   load_time_data.Set("overridable", false);
   load_time_data.Set("hide_primary_button", false);
-  load_time_data.Set("show_recurrent_error_paragraph", false);
-  load_time_data.Set("recurrentErrorParagraph", "");
   load_time_data.Set("openDetails", "");
   load_time_data.Set("explanationParagraph", "");
   load_time_data.Set("finalParagraph", "");
diff --git a/components/input/web_input_event_builders_ios.mm b/components/input/web_input_event_builders_ios.mm
index 0eb0853c..7f13d8a 100644
--- a/components/input/web_input_event_builders_ios.mm
+++ b/components/input/web_input_event_builders_ios.mm
@@ -9,10 +9,10 @@
 
 #include "components/input/web_input_event_builders_ios.h"
 
-#import <BrowserEngineKit/BrowserEngineKit.h>
 #import <UIKit/UIKit.h>
 
 #include "base/apple/foundation_util.h"
+#include "base/notimplemented.h"
 #include "base/notreached.h"
 #include "third_party/blink/public/common/input/web_pointer_event.h"
 #include "third_party/blink/public/common/input/web_touch_point.h"
@@ -22,6 +22,10 @@
 #include "ui/events/keycodes/keyboard_code_conversion.h"
 #include "ui/events/keycodes/keyboard_code_conversion_ios.h"
 
+#if !BUILDFLAG(IS_IOS_TVOS)
+#import <BrowserEngineKit/BrowserEngineKit.h>
+#endif
+
 namespace input {
 
 namespace {
@@ -184,6 +188,8 @@
   return touch;
 }
 
+#if !BUILDFLAG(IS_IOS_TVOS)
+
 NSString* FilterSpecialCharacter(NSString* str) {
   if ([str length] != 1) {
     return str;
@@ -225,9 +231,12 @@
   return event.GetModifiers() & blink::WebInputEvent::kMetaKey;
 }
 
+#endif  // !BUILDFLAG(IS_IOS_TVOS)
+
 }  // namespace
 
 blink::WebKeyboardEvent WebKeyboardEventBuilder::Build(gfx::NativeEvent event) {
+#if !BUILDFLAG(IS_IOS_TVOS)
   BEKeyEntry* entry = std::get<base::apple::OwnedBEKeyEntry>(event).Get();
   CHECK(entry);
 
@@ -279,6 +288,10 @@
   result.is_system_key = IsSystemKeyEvent(result);
 
   return result;
+#else
+  TVOS_NOT_YET_IMPLEMENTED();
+  return blink::WebKeyboardEvent();
+#endif  // !BUILDFLAG(IS_IOS_TVOS)
 }
 
 blink::WebGestureEvent WebGestureEventBuilder::Build(UIEvent*, UIView*) {
diff --git a/components/language/ios/browser/resources/language_detection.ts b/components/language/ios/browser/resources/language_detection.ts
index abed48fc..efbc4a3 100644
--- a/components/language/ios/browser/resources/language_detection.ts
+++ b/components/language/ios/browser/resources/language_detection.ts
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 import {sendWebKitMessage} from '//ios/web/public/js_messaging/resources/utils.js';
 
 // Mark: Private properties
@@ -128,7 +128,7 @@
     'hasNoTranslate': false,
     'htmlLang': document.documentElement.lang,
     'httpContentLanguage': httpContentLanguage,
-    'frameId': gCrWeb.message.getFrameId(),
+    'frameId': gCrWebLegacy.message.getFrameId(),
   };
 
   if (hasNoTranslate()) {
@@ -153,7 +153,7 @@
 
 // Mark: Public API
 
-gCrWeb.languageDetection = {
+gCrWebLegacy.languageDetection = {
   detectLanguage,
   retrieveBufferedTextContent,
 };
diff --git a/components/lookalikes/core/lookalike_url_ui_util.cc b/components/lookalikes/core/lookalike_url_ui_util.cc
index 2566d49..e2a772b 100644
--- a/components/lookalikes/core/lookalike_url_ui_util.cc
+++ b/components/lookalikes/core/lookalike_url_ui_util.cc
@@ -106,13 +106,9 @@
   load_time_data.Set("lookalike_url", true);
   load_time_data.Set("overridable", false);
   load_time_data.Set("hide_primary_button", false);
-  load_time_data.Set("show_recurrent_error_paragraph", false);
-
-  load_time_data.Set("recurrentErrorParagraph", "");
   load_time_data.Set("openDetails", "");
   load_time_data.Set("explanationParagraph", "");
   load_time_data.Set("finalParagraph", "");
-
   load_time_data.Set("type", "LOOKALIKE");
 }
 
diff --git a/components/ntp_tiles/most_visited_sites.cc b/components/ntp_tiles/most_visited_sites.cc
index 5b9dec2..b74bb29e 100644
--- a/components/ntp_tiles/most_visited_sites.cc
+++ b/components/ntp_tiles/most_visited_sites.cc
@@ -159,7 +159,7 @@
     supervised_user::SupervisedUserService* supervised_user_service,
     scoped_refptr<history::TopSites> top_sites,
     std::unique_ptr<PopularSites> popular_sites,
-    std::unique_ptr<CustomLinksManager> custom_links,
+    std::unique_ptr<CustomLinksManager> custom_links_manager,
     std::unique_ptr<IconCacher> icon_cacher,
     bool is_default_chrome_app_migrated,
     bool is_custom_links_mixable)
@@ -168,7 +168,7 @@
       supervised_user_service_(supervised_user_service),
       top_sites_(top_sites),
       popular_sites_(std::move(popular_sites)),
-      custom_links_(std::move(custom_links)),
+      custom_links_manager_(std::move(custom_links_manager)),
       icon_cacher_(std::move(icon_cacher)),
       is_default_chrome_app_migrated_(is_default_chrome_app_migrated),
       is_custom_links_mixable_(is_custom_links_mixable),
@@ -212,7 +212,7 @@
     case TileSource::ALLOWLIST:
       return supervised_user_service_ != nullptr;
     case TileSource::CUSTOM_LINKS:
-      return custom_links_ != nullptr;
+      return custom_links_manager_ != nullptr;
   }
   NOTREACHED();
 }
@@ -249,10 +249,11 @@
       top_sites_observation_.Observe(top_sites_.get());
     }
 
-    if (custom_links_) {
+    if (custom_links_manager_) {
       custom_links_subscription_ =
-          custom_links_->RegisterCallbackForOnChanged(base::BindRepeating(
-              &MostVisitedSites::OnCustomLinksChanged, base::Unretained(this)));
+          custom_links_manager_->RegisterCallbackForOnChanged(
+              base::BindRepeating(&MostVisitedSites::OnCustomLinksChanged,
+                                  base::Unretained(this)));
     }
   }
 
@@ -280,31 +281,31 @@
 }
 
 void MostVisitedSites::InitializeCustomLinks() {
-  if (!custom_links_ || !current_tiles_.has_value() ||
+  if (!custom_links_manager_ || !current_tiles_.has_value() ||
       !IsCustomLinksEnabled()) {
     return;
   }
 
-  // TODO(crbug.com/397422358): Convert |current_tiles_| to |custom_links_|
-  // only if |is_custom_links_mixable_| is false.
-  if (custom_links_->Initialize(current_tiles_.value())) {
+  // TODO(crbug.com/397422358): Convert |current_tiles_| to links in
+  // |custom_links_manager_| only if |is_custom_links_mixable_| is false.
+  if (custom_links_manager_->Initialize(current_tiles_.value())) {
     custom_links_action_count_ = 0;
   }
 }
 
 void MostVisitedSites::UninitializeCustomLinks() {
-  if (!custom_links_ || !IsCustomLinksEnabled()) {
+  if (!custom_links_manager_ || !IsCustomLinksEnabled()) {
     return;
   }
 
   custom_links_action_count_ = -1;
-  custom_links_->Uninitialize();
+  custom_links_manager_->Uninitialize();
   BuildCurrentTiles();
 }
 
 bool MostVisitedSites::IsCustomLinksInitialized() {
-  return custom_links_ && IsCustomLinksEnabled() &&
-         custom_links_->IsInitialized();
+  return custom_links_manager_ && IsCustomLinksEnabled() &&
+         custom_links_manager_->IsInitialized();
 }
 
 bool MostVisitedSites::IsExclusivelyCustomLinks() {
@@ -335,33 +336,33 @@
 
 bool MostVisitedSites::AddCustomLink(const GURL& url,
                                      const std::u16string& title) {
-  return ApplyCustomLinksAction(
-      base::BindOnce(&CustomLinksManager::AddLink,
-                     base::Unretained(custom_links_.get()), url, title));
+  return ApplyCustomLinksAction(base::BindOnce(
+      &CustomLinksManager::AddLink,
+      base::Unretained(custom_links_manager_.get()), url, title));
 }
 
 bool MostVisitedSites::UpdateCustomLink(const GURL& url,
                                         const GURL& new_url,
                                         const std::u16string& new_title) {
   return ApplyCustomLinksAction(base::BindOnce(
-      &CustomLinksManager::UpdateLink, base::Unretained(custom_links_.get()),
-      url, new_url, new_title));
+      &CustomLinksManager::UpdateLink,
+      base::Unretained(custom_links_manager_.get()), url, new_url, new_title));
 }
 
 bool MostVisitedSites::ReorderCustomLink(const GURL& url, size_t new_pos) {
-  return ApplyCustomLinksAction(
-      base::BindOnce(&CustomLinksManager::ReorderLink,
-                     base::Unretained(custom_links_.get()), url, new_pos));
+  return ApplyCustomLinksAction(base::BindOnce(
+      &CustomLinksManager::ReorderLink,
+      base::Unretained(custom_links_manager_.get()), url, new_pos));
 }
 
 bool MostVisitedSites::DeleteCustomLink(const GURL& url) {
   return ApplyCustomLinksAction(
       base::BindOnce(&CustomLinksManager::DeleteLink,
-                     base::Unretained(custom_links_.get()), url));
+                     base::Unretained(custom_links_manager_.get()), url));
 }
 
 void MostVisitedSites::UndoCustomLinkAction() {
-  if (!custom_links_ || !IsCustomLinksEnabled()) {
+  if (!custom_links_manager_ || !IsCustomLinksEnabled()) {
     return;
   }
 
@@ -369,13 +370,13 @@
   // custom links.
   if (custom_links_action_count_-- == 1) {
     UninitializeCustomLinks();
-  } else if (custom_links_->UndoAction()) {
+  } else if (custom_links_manager_->UndoAction()) {
     BuildCurrentTiles();
   }
 }
 
 size_t MostVisitedSites::GetCustomLinkNum() {
-  return custom_links_->GetLinks().size();
+  return custom_links_manager_->GetLinks().size();
 }
 
 void MostVisitedSites::AddOrRemoveBlockedUrl(const GURL& url, bool add_url) {
@@ -419,7 +420,8 @@
 }
 
 size_t MostVisitedSites::GetMaxNumSites() const {
-  return max_num_sites_ + (custom_links_ && IsCustomLinksEnabled() ? 1 : 0);
+  return max_num_sites_ +
+         (custom_links_manager_ && IsCustomLinksEnabled() ? 1 : 0);
 }
 
 void MostVisitedSites::InitiateTopSitesQuery() {
@@ -456,8 +458,8 @@
 #endif
 
     NTPTile tile;
-    tile.title =
-        custom_links_ ? GenerateShortTitle(visited.title) : visited.title;
+    tile.title = custom_links_manager_ ? GenerateShortTitle(visited.title)
+                                       : visited.title;
     tile.url = visited.url;
     tile.source = TileSource::TOP_SITES;
     // MostVisitedURL.title is either the title or the URL which is treated
@@ -476,7 +478,7 @@
 
 void MostVisitedSites::BuildCurrentTiles() {
   if (IsExclusivelyCustomLinks()) {
-    BuildCustomLinks(custom_links_->GetLinks());
+    BuildCustomLinks(custom_links_manager_->GetLinks());
     return;
   }
 
@@ -615,16 +617,16 @@
   return new_tiles;
 }
 
-// Ensures |custom_links_| is initialized (exits on failure), then runs
+// Ensures |custom_links_manager_| is initialized (exits on failure), then runs
 // |custom_links_action|. On success, builds the tileset. On failure, if this is
 // the first custom link action then uninitialize custom links.
 bool MostVisitedSites::ApplyCustomLinksAction(
     base::OnceCallback<bool()> custom_links_action) {
-  if (!custom_links_ || !IsCustomLinksEnabled()) {
+  if (!custom_links_manager_ || !IsCustomLinksEnabled()) {
     return false;
   }
 
-  bool is_first_action = !custom_links_->IsInitialized();
+  bool is_first_action = !custom_links_manager_->IsInitialized();
   // Initialize custom links if they have not been initialized yet.
   InitializeCustomLinks();
 
@@ -643,13 +645,13 @@
 }
 
 void MostVisitedSites::OnCustomLinksChanged() {
-  DCHECK(custom_links_);
+  DCHECK(custom_links_manager_);
   if (!IsCustomLinksEnabled()) {
     return;
   }
 
-  if (custom_links_->IsInitialized()) {
-    BuildCustomLinks(custom_links_->GetLinks());
+  if (custom_links_manager_->IsInitialized()) {
+    BuildCustomLinks(custom_links_manager_->GetLinks());
   } else {
     // Since custom links have been uninitialized (e.g. through Chrome sync), we
     // should show the regular Most Visited tiles.
@@ -659,7 +661,7 @@
 
 void MostVisitedSites::BuildCustomLinks(
     const std::vector<CustomLinksManager::Link>& links) {
-  DCHECK(custom_links_);
+  DCHECK(custom_links_manager_);
 
   NTPTilesVector tiles;
   // The maximum number of custom links that can be shown is independent of the
diff --git a/components/ntp_tiles/most_visited_sites.h b/components/ntp_tiles/most_visited_sites.h
index f4cadfe..349e941 100644
--- a/components/ntp_tiles/most_visited_sites.h
+++ b/components/ntp_tiles/most_visited_sites.h
@@ -279,8 +279,9 @@
       const std::set<std::string>& hosts_to_skip,
       size_t num_max_tiles);
 
-  // Ensures |custom_links_| is initialized, then runs |custom_links_action|.
-  // Performs on-failure cleanup. Returns whether the action was successful.
+  // Ensures |custom_links_manager_| is initialized, then runs
+  // |custom_links_action|. Performs on-failure cleanup. Returns whether the
+  // action was successful.
   bool ApplyCustomLinksAction(base::OnceCallback<bool()> custom_links_action);
 
   // Callback for when an update is reported by CustomLinksManager.
@@ -344,7 +345,7 @@
 
   scoped_refptr<history::TopSites> top_sites_;
   std::unique_ptr<PopularSites> const popular_sites_;
-  std::unique_ptr<CustomLinksManager> const custom_links_;
+  std::unique_ptr<CustomLinksManager> const custom_links_manager_;
   std::unique_ptr<IconCacher> const icon_cacher_;
   std::unique_ptr<HomepageClient> homepage_client_;
   bool is_default_chrome_app_migrated_;
diff --git a/components/ntp_tiles/most_visited_sites_unittest.cc b/components/ntp_tiles/most_visited_sites_unittest.cc
index 95ebec9..2c0ac88e 100644
--- a/components/ntp_tiles/most_visited_sites_unittest.cc
+++ b/components/ntp_tiles/most_visited_sites_unittest.cc
@@ -412,11 +412,12 @@
     // Custom links needs to be nullptr when MostVisitedSites is created, unless
     // the custom links feature is enabled. Custom links is disabled for
     // Android, iOS, and third-party NTPs.
-    std::unique_ptr<StrictMock<MockCustomLinksManager>> mock_custom_links;
+    std::unique_ptr<StrictMock<MockCustomLinksManager>>
+        mock_custom_links_manager;
     if (is_custom_links_enabled_) {
-      mock_custom_links =
+      mock_custom_links_manager =
           std::make_unique<StrictMock<MockCustomLinksManager>>();
-      mock_custom_links_ = mock_custom_links.get();
+      mock_custom_links_manager_ = mock_custom_links_manager.get();
     }
 
     if (IsPopularSitesFeatureEnabled()) {
@@ -449,7 +450,7 @@
     most_visited_sites_ = std::make_unique<MostVisitedSites>(
         &pref_service_, /*identity_manager=*/nullptr,
         /*supervised_user_service=*/nullptr, mock_top_sites_,
-        popular_sites_factory_.New(), std::move(mock_custom_links),
+        popular_sites_factory_.New(), std::move(mock_custom_links_manager),
         std::move(icon_cacher),
         /*is_default_chrome_app_migrated=*/true, is_custom_links_mixable_);
   }
@@ -493,7 +494,7 @@
   StrictMock<MockMostVisitedSitesObserver> mock_other_observer_;
   std::unique_ptr<MostVisitedSites> most_visited_sites_;
   base::test::ScopedFeatureList feature_list_;
-  raw_ptr<MockCustomLinksManager> mock_custom_links_;
+  raw_ptr<MockCustomLinksManager> mock_custom_links_manager_;
   raw_ptr<MockIconCacher> icon_cacher_;
 };
 
@@ -1058,7 +1059,7 @@
         .WillRepeatedly(
             base::test::RunOnceCallbackRepeatedly<0>(expected_list));
     EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
-    EXPECT_CALL(*mock_custom_links_, IsInitialized())
+    EXPECT_CALL(*mock_custom_links_manager_, IsInitialized())
         .WillRepeatedly(Return(false));
     EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
         .WillOnce(SaveArg<0>(sections));
@@ -1067,9 +1068,9 @@
   void ExpectBuildWithCustomLinks(
       const std::vector<CustomLinksManager::Link>& expected_links,
       std::map<SectionType, NTPTilesVector>* sections) {
-    EXPECT_CALL(*mock_custom_links_, IsInitialized())
+    EXPECT_CALL(*mock_custom_links_manager_, IsInitialized())
         .WillRepeatedly(Return(true));
-    EXPECT_CALL(*mock_custom_links_, GetLinks())
+    EXPECT_CALL(*mock_custom_links_manager_, GetLinks())
         .WillOnce(ReturnRef(expected_links));
     EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
         .WillOnce(SaveArg<0>(sections));
@@ -1083,7 +1084,7 @@
 
   // Build tiles when custom links is not initialized. Tiles should be Top
   // Sites.
-  EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
+  EXPECT_CALL(*mock_custom_links_manager_, RegisterCallbackForOnChanged(_));
   ExpectBuildWithTopSites(
       MostVisitedURLList{MakeMostVisitedURL(kTestTitle, kTestUrl)}, &sections);
   most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
@@ -1129,7 +1130,7 @@
 
   // Build tiles when custom links is not initialized. Tiles should be Top
   // Sites.
-  EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
+  EXPECT_CALL(*mock_custom_links_manager_, RegisterCallbackForOnChanged(_));
   ExpectBuildWithTopSites(
       MostVisitedURLList{MakeMostVisitedURL(kTestTitle, kTestUrl)}, &sections);
   most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
@@ -1141,7 +1142,8 @@
               MatchesTile(kTestTitle, kTestUrl, TileSource::TOP_SITES));
 
   // Initialize custom links and rebuild tiles. Tiles should be custom links.
-  EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(true));
+  EXPECT_CALL(*mock_custom_links_manager_, Initialize(_))
+      .WillOnce(Return(true));
   ExpectBuildWithCustomLinks(expected_links, &sections);
   most_visited_sites_->InitializeCustomLinks();
   most_visited_sites_->RefreshTiles();
@@ -1151,11 +1153,11 @@
       ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::CUSTOM_LINKS)));
 
   // Uninitialize custom links and rebuild tiles. Tiles should be Top Sites.
-  EXPECT_CALL(*mock_custom_links_, Uninitialize());
+  EXPECT_CALL(*mock_custom_links_manager_, Uninitialize());
   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs(_))
       .WillRepeatedly(base::test::RunOnceCallbackRepeatedly<0>(
           MostVisitedURLList{MakeMostVisitedURL(kTestTitle, kTestUrl)}));
-  EXPECT_CALL(*mock_custom_links_, IsInitialized())
+  EXPECT_CALL(*mock_custom_links_manager_, IsInitialized())
       .WillRepeatedly(Return(false));
   EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
       .WillOnce(SaveArg<0>(&sections));
@@ -1177,7 +1179,7 @@
 
   // Build tiles when custom links is not initialized. Tiles should be Top
   // Sites.
-  EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
+  EXPECT_CALL(*mock_custom_links_manager_, RegisterCallbackForOnChanged(_));
   ExpectBuildWithTopSites(
       MostVisitedURLList{MakeMostVisitedURL(kTestTitle, kTestUrl)}, &sections);
   most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
@@ -1189,7 +1191,8 @@
               MatchesTile(kTestTitle, kTestUrl, TileSource::TOP_SITES));
 
   // Initialize custom links and rebuild tiles. Tiles should be custom links.
-  EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(true));
+  EXPECT_CALL(*mock_custom_links_manager_, Initialize(_))
+      .WillOnce(Return(true));
   ExpectBuildWithCustomLinks(expected_links, &sections);
   most_visited_sites_->InitializeCustomLinks();
   most_visited_sites_->RefreshTiles();
@@ -1216,7 +1219,7 @@
 
   // Build tiles when custom links is not initialized. Tiles should be from
   // Top Sites.
-  EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
+  EXPECT_CALL(*mock_custom_links_manager_, RegisterCallbackForOnChanged(_));
   ExpectBuildWithTopSites(
       MostVisitedURLList{MakeMostVisitedURL(kTestTitle16, kTestUrl)},
       &sections);
@@ -1238,7 +1241,7 @@
 
   // Try to disable custom links again. This should not rebuild the tiles.
   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs(_)).Times(0);
-  EXPECT_CALL(*mock_custom_links_, GetLinks()).Times(0);
+  EXPECT_CALL(*mock_custom_links_manager_, GetLinks()).Times(0);
   most_visited_sites_->EnableCustomLinks(false);
   base::RunLoop().RunUntilIdle();
 }
@@ -1252,7 +1255,7 @@
 
   // Build tiles when custom links is initialized and not disabled. Tiles should
   // be custom links.
-  EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
+  EXPECT_CALL(*mock_custom_links_manager_, RegisterCallbackForOnChanged(_));
   EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
   ExpectBuildWithCustomLinks(expected_links, &sections);
   most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
@@ -1266,7 +1269,7 @@
   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs(_))
       .WillRepeatedly(base::test::RunOnceCallbackRepeatedly<0>(
           MostVisitedURLList{MakeMostVisitedURL(kTestTitle16, kTestUrl)}));
-  EXPECT_CALL(*mock_custom_links_, IsInitialized())
+  EXPECT_CALL(*mock_custom_links_manager_, IsInitialized())
       .WillRepeatedly(Return(false));
   EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
       .WillOnce(SaveArg<0>(&sections));
@@ -1300,7 +1303,7 @@
   std::map<SectionType, NTPTilesVector> sections;
 
   // Build tiles from Top Sites. The tiles should have short titles.
-  EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
+  EXPECT_CALL(*mock_custom_links_manager_, RegisterCallbackForOnChanged(_));
   ExpectBuildWithTopSites(
       MostVisitedURLList{MakeMostVisitedURL(kTestTitle1, kTestUrl1),
                          MakeMostVisitedURL(kTestTitle2, kTestUrl2),
@@ -1350,7 +1353,7 @@
   std::map<SectionType, NTPTilesVector> sections;
 
   // Build tiles from Top Sites. The tiles should have short titles.
-  EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
+  EXPECT_CALL(*mock_custom_links_manager_, RegisterCallbackForOnChanged(_));
   ExpectBuildWithTopSites(
       MostVisitedURLList{MakeMostVisitedURL(kTestTitle1, kTestUrl1),
                          MakeMostVisitedURL(kTestTitle2, kTestUrl2),
@@ -1414,7 +1417,7 @@
   std::map<SectionType, NTPTilesVector> sections;
 
   // Build tiles from Top Sites. The tiles should have short titles.
-  EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
+  EXPECT_CALL(*mock_custom_links_manager_, RegisterCallbackForOnChanged(_));
   ExpectBuildWithTopSites(
       MostVisitedURLList{MakeMostVisitedURL(kTestTitle1, kTestUrl1),
                          MakeMostVisitedURL(kTestTitle2, kTestUrl2),
@@ -1455,7 +1458,7 @@
   std::map<SectionType, NTPTilesVector> sections;
 
   // Build tiles from Top Sites. The tiles should have short titles.
-  EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
+  EXPECT_CALL(*mock_custom_links_manager_, RegisterCallbackForOnChanged(_));
   ExpectBuildWithTopSites(
       MostVisitedURLList{MakeMostVisitedURL(kTestTitle1, kTestUrl1),
                          MakeMostVisitedURL(kTestTitle2, kTestUrl2)},
@@ -1480,7 +1483,7 @@
   std::map<SectionType, NTPTilesVector> sections;
 
   // Build initial tiles with Top Sites.
-  EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
+  EXPECT_CALL(*mock_custom_links_manager_, RegisterCallbackForOnChanged(_));
   ExpectBuildWithTopSites(
       MostVisitedURLList{MakeMostVisitedURL(kTestTitle, kTestUrl)}, &sections);
   most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
@@ -1492,11 +1495,13 @@
               MatchesTile(kTestTitle, kTestUrl, TileSource::TOP_SITES));
 
   // Initialize custom links and complete a custom link action.
-  EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(true));
-  EXPECT_CALL(*mock_custom_links_, AddLink(_, _)).WillOnce(Return(true));
-  EXPECT_CALL(*mock_custom_links_, IsInitialized())
+  EXPECT_CALL(*mock_custom_links_manager_, Initialize(_))
+      .WillOnce(Return(true));
+  EXPECT_CALL(*mock_custom_links_manager_, AddLink(_, _))
+      .WillOnce(Return(true));
+  EXPECT_CALL(*mock_custom_links_manager_, IsInitialized())
       .WillRepeatedly(Return(true));
-  EXPECT_CALL(*mock_custom_links_, GetLinks())
+  EXPECT_CALL(*mock_custom_links_manager_, GetLinks())
       .WillRepeatedly(ReturnRef(expected_links));
   EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
       .WillOnce(SaveArg<0>(&sections));
@@ -1507,12 +1512,12 @@
       ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::CUSTOM_LINKS)));
 
   // Undo the action. This should uninitialize custom links.
-  EXPECT_CALL(*mock_custom_links_, UndoAction()).Times(0);
-  EXPECT_CALL(*mock_custom_links_, Uninitialize());
+  EXPECT_CALL(*mock_custom_links_manager_, UndoAction()).Times(0);
+  EXPECT_CALL(*mock_custom_links_manager_, Uninitialize());
   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs(_))
       .WillRepeatedly(base::test::RunOnceCallbackRepeatedly<0>(
           MostVisitedURLList{MakeMostVisitedURL(kTestTitle, kTestUrl)}));
-  EXPECT_CALL(*mock_custom_links_, IsInitialized())
+  EXPECT_CALL(*mock_custom_links_manager_, IsInitialized())
       .WillRepeatedly(Return(false));
   EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
       .WillOnce(SaveArg<0>(&sections));
@@ -1533,7 +1538,7 @@
   std::map<SectionType, NTPTilesVector> sections;
 
   // Build initial tiles with Top Sites.
-  EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
+  EXPECT_CALL(*mock_custom_links_manager_, RegisterCallbackForOnChanged(_));
   ExpectBuildWithTopSites(
       MostVisitedURLList{MakeMostVisitedURL(kTestTitle, kTestUrl)}, &sections);
   most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
@@ -1545,11 +1550,13 @@
               MatchesTile(kTestTitle, kTestUrl, TileSource::TOP_SITES));
 
   // Initialize custom links and complete a custom link action.
-  EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(true));
-  EXPECT_CALL(*mock_custom_links_, UpdateLink(_, _, _)).WillOnce(Return(true));
-  EXPECT_CALL(*mock_custom_links_, IsInitialized())
+  EXPECT_CALL(*mock_custom_links_manager_, Initialize(_))
+      .WillOnce(Return(true));
+  EXPECT_CALL(*mock_custom_links_manager_, UpdateLink(_, _, _))
+      .WillOnce(Return(true));
+  EXPECT_CALL(*mock_custom_links_manager_, IsInitialized())
       .WillRepeatedly(Return(true));
-  EXPECT_CALL(*mock_custom_links_, GetLinks())
+  EXPECT_CALL(*mock_custom_links_manager_, GetLinks())
       .WillRepeatedly(ReturnRef(expected_links));
   EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
       .WillRepeatedly(SaveArg<0>(&sections));
@@ -1561,20 +1568,23 @@
       ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::CUSTOM_LINKS)));
 
   // Complete a second custom link action.
-  EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(false));
-  EXPECT_CALL(*mock_custom_links_, DeleteLink(_)).WillOnce(Return(true));
-  EXPECT_CALL(*mock_custom_links_, IsInitialized())
+  EXPECT_CALL(*mock_custom_links_manager_, Initialize(_))
+      .WillOnce(Return(false));
+  EXPECT_CALL(*mock_custom_links_manager_, DeleteLink(_))
+      .WillOnce(Return(true));
+  EXPECT_CALL(*mock_custom_links_manager_, IsInitialized())
       .WillRepeatedly(Return(true));
-  EXPECT_CALL(*mock_custom_links_, GetLinks())
+  EXPECT_CALL(*mock_custom_links_manager_, GetLinks())
       .WillOnce(ReturnRef(expected_links));
   most_visited_sites_->DeleteCustomLink(GURL("test.com"));
   base::RunLoop().RunUntilIdle();
 
   // Undo the second action. This should not uninitialize custom links.
-  EXPECT_CALL(*mock_custom_links_, UndoAction()).WillOnce(Return(true));
-  EXPECT_CALL(*mock_custom_links_, Uninitialize()).Times(0);
-  EXPECT_CALL(*mock_custom_links_, IsInitialized()).WillOnce(Return(true));
-  EXPECT_CALL(*mock_custom_links_, GetLinks())
+  EXPECT_CALL(*mock_custom_links_manager_, UndoAction()).WillOnce(Return(true));
+  EXPECT_CALL(*mock_custom_links_manager_, Uninitialize()).Times(0);
+  EXPECT_CALL(*mock_custom_links_manager_, IsInitialized())
+      .WillOnce(Return(true));
+  EXPECT_CALL(*mock_custom_links_manager_, GetLinks())
       .WillOnce(ReturnRef(expected_links));
   most_visited_sites_->UndoCustomLinkAction();
   base::RunLoop().RunUntilIdle();
@@ -1589,7 +1599,7 @@
   std::map<SectionType, NTPTilesVector> sections;
 
   // Build initial tiles with Top Sites.
-  EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
+  EXPECT_CALL(*mock_custom_links_manager_, RegisterCallbackForOnChanged(_));
   ExpectBuildWithTopSites(
       MostVisitedURLList{MakeMostVisitedURL(kTestTitle, kTestUrl)}, &sections);
   most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
@@ -1602,22 +1612,26 @@
 
   // Fail to add a custom link. This should not initialize custom links but
   // notify.
-  EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(true));
-  EXPECT_CALL(*mock_custom_links_, AddLink(_, _)).WillOnce(Return(false));
-  EXPECT_CALL(*mock_custom_links_, IsInitialized())
+  EXPECT_CALL(*mock_custom_links_manager_, Initialize(_))
+      .WillOnce(Return(true));
+  EXPECT_CALL(*mock_custom_links_manager_, AddLink(_, _))
+      .WillOnce(Return(false));
+  EXPECT_CALL(*mock_custom_links_manager_, IsInitialized())
       .WillRepeatedly(Return(false));
-  EXPECT_CALL(*mock_custom_links_, Uninitialize());
+  EXPECT_CALL(*mock_custom_links_manager_, Uninitialize());
   EXPECT_CALL(mock_observer_, OnURLsAvailable(_)).Times(1);
   most_visited_sites_->AddCustomLink(GURL(kTestUrl), u"test");
   base::RunLoop().RunUntilIdle();
 
   // Fail to edit a custom link. This should not initialize custom links but
   // notify.
-  EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(true));
-  EXPECT_CALL(*mock_custom_links_, UpdateLink(_, _, _)).WillOnce(Return(false));
-  EXPECT_CALL(*mock_custom_links_, IsInitialized())
+  EXPECT_CALL(*mock_custom_links_manager_, Initialize(_))
+      .WillOnce(Return(true));
+  EXPECT_CALL(*mock_custom_links_manager_, UpdateLink(_, _, _))
+      .WillOnce(Return(false));
+  EXPECT_CALL(*mock_custom_links_manager_, IsInitialized())
       .WillRepeatedly(Return(false));
-  EXPECT_CALL(*mock_custom_links_, Uninitialize());
+  EXPECT_CALL(*mock_custom_links_manager_, Uninitialize());
   EXPECT_CALL(mock_observer_, OnURLsAvailable(_)).Times(1);
   most_visited_sites_->UpdateCustomLink(GURL("test.com"), GURL("test2.com"),
                                         u"test");
@@ -1625,22 +1639,26 @@
 
   // Fail to reorder a custom link. This should not initialize custom links but
   // notify.
-  EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(true));
-  EXPECT_CALL(*mock_custom_links_, ReorderLink(_, _)).WillOnce(Return(false));
-  EXPECT_CALL(*mock_custom_links_, IsInitialized())
+  EXPECT_CALL(*mock_custom_links_manager_, Initialize(_))
+      .WillOnce(Return(true));
+  EXPECT_CALL(*mock_custom_links_manager_, ReorderLink(_, _))
+      .WillOnce(Return(false));
+  EXPECT_CALL(*mock_custom_links_manager_, IsInitialized())
       .WillRepeatedly(Return(false));
-  EXPECT_CALL(*mock_custom_links_, Uninitialize());
+  EXPECT_CALL(*mock_custom_links_manager_, Uninitialize());
   EXPECT_CALL(mock_observer_, OnURLsAvailable(_)).Times(1);
   most_visited_sites_->ReorderCustomLink(GURL("test.com"), 1);
   base::RunLoop().RunUntilIdle();
 
   // Fail to delete a custom link. This should not initialize custom links but
   // notify.
-  EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(true));
-  EXPECT_CALL(*mock_custom_links_, DeleteLink(_)).WillOnce(Return(false));
-  EXPECT_CALL(*mock_custom_links_, IsInitialized())
+  EXPECT_CALL(*mock_custom_links_manager_, Initialize(_))
+      .WillOnce(Return(true));
+  EXPECT_CALL(*mock_custom_links_manager_, DeleteLink(_))
+      .WillOnce(Return(false));
+  EXPECT_CALL(*mock_custom_links_manager_, IsInitialized())
       .WillRepeatedly(Return(false));
-  EXPECT_CALL(*mock_custom_links_, Uninitialize());
+  EXPECT_CALL(*mock_custom_links_manager_, Uninitialize());
   EXPECT_CALL(mock_observer_, OnURLsAvailable(_)).Times(1);
   most_visited_sites_->DeleteCustomLink(GURL("test.com"));
   base::RunLoop().RunUntilIdle();
@@ -1657,7 +1675,7 @@
 
   // Build initial tiles with Top Sites.
   base::RepeatingClosure custom_links_callback;
-  EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_))
+  EXPECT_CALL(*mock_custom_links_manager_, RegisterCallbackForOnChanged(_))
       .WillOnce(DoAll(SaveArg<0>(&custom_links_callback),
                       Return(ByMove(base::CallbackListSubscription()))));
   ExpectBuildWithTopSites(
@@ -1673,9 +1691,9 @@
 
   // Notify that there is a new set of custom links. This should replace the
   // current tiles with custom links.
-  EXPECT_CALL(*mock_custom_links_, IsInitialized())
+  EXPECT_CALL(*mock_custom_links_manager_, IsInitialized())
       .WillRepeatedly(Return(true));
-  EXPECT_CALL(*mock_custom_links_, GetLinks())
+  EXPECT_CALL(*mock_custom_links_manager_, GetLinks())
       .WillRepeatedly(ReturnRef(expected_links));
   EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
       .WillOnce(SaveArg<0>(&sections));
@@ -1687,12 +1705,12 @@
 
   // Notify that custom links have been uninitialized. This should rebuild the
   // tiles with Top Sites.
-  EXPECT_CALL(*mock_custom_links_, IsInitialized())
+  EXPECT_CALL(*mock_custom_links_manager_, IsInitialized())
       .WillRepeatedly(Return(false));
   EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs(_))
       .WillRepeatedly(base::test::RunOnceCallbackRepeatedly<0>(
           MostVisitedURLList{MakeMostVisitedURL(kTestTitle1, kTestUrl1)}));
-  EXPECT_CALL(*mock_custom_links_, IsInitialized())
+  EXPECT_CALL(*mock_custom_links_manager_, IsInitialized())
       .WillRepeatedly(Return(false));
   EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
       .WillOnce(SaveArg<0>(&sections));
diff --git a/components/omnibox/OWNERS b/components/omnibox/OWNERS
index 8e4c7e9..4867676 100644
--- a/components/omnibox/OWNERS
+++ b/components/omnibox/OWNERS
@@ -6,6 +6,7 @@
 khalidpeer@chromium.org
 mahmadi@chromium.org
 manukh@chromium.org
+niharm@google.com
 mfacey@chromium.org
 mpearson@chromium.org
 orinj@chromium.org
diff --git a/components/omnibox/browser/autocomplete_provider.cc b/components/omnibox/browser/autocomplete_provider.cc
index dff1c44..fa8fd330 100644
--- a/components/omnibox/browser/autocomplete_provider.cc
+++ b/components/omnibox/browser/autocomplete_provider.cc
@@ -181,7 +181,7 @@
     case TYPE_MOST_VISITED_SITES:
       return metrics::OmniboxEventProto::MOST_VISITED_SITES;
     case TYPE_VERBATIM_MATCH:
-      return metrics::OmniboxEventProto::ZERO_SUGGEST;
+      return metrics::OmniboxEventProto::VERBATIM_MATCH;
     case TYPE_VOICE_SUGGEST:
       return metrics::OmniboxEventProto::SEARCH;
     case TYPE_HISTORY_FUZZY:
diff --git a/components/omnibox/browser/omnibox_client.h b/components/omnibox/browser/omnibox_client.h
index dfdf4792..d754c68 100644
--- a/components/omnibox/browser/omnibox_client.h
+++ b/components/omnibox/browser/omnibox_client.h
@@ -184,6 +184,10 @@
   virtual void OnFocusChanged(OmniboxFocusState state,
                               OmniboxFocusChangeReason reason) {}
 
+  // Called to notify clients when keyword mode is entered or exited.
+  virtual void OnKeywordModeChanged(bool entered,
+                                    const std::u16string& keyword) {}
+
   // Called to show HaTS survey if the proper criteria is met.
   virtual void MaybeShowOnFocusHatsSurvey(AutocompleteProviderClient* client,
                                           std::u16string text) {}
diff --git a/components/omnibox/browser/omnibox_edit_model.cc b/components/omnibox/browser/omnibox_edit_model.cc
index 25ae8802..8fd17ec 100644
--- a/components/omnibox/browser/omnibox_edit_model.cc
+++ b/components/omnibox/browser/omnibox_edit_model.cc
@@ -879,6 +879,12 @@
   DCHECK(template_url);
   controller_->StopAutocomplete(/*clear_result=*/false);
 
+  if (keyword_ != template_url->keyword()) {
+    // Note, this is not the only place that keyword mode can be entered, but
+    // it would be better to make it so than to add extra notification calls
+    // elsewhere. At present, the method is only meaningfully used for exit.
+    controller_->client()->OnKeywordModeChanged(true, template_url->keyword());
+  }
   SetKeyword(template_url->keyword());
   SetKeywordPlaceholder(placeholder_text);
   is_keyword_hint_ = false;
@@ -1054,6 +1060,7 @@
   bool entry_by_tab = keyword_mode_entry_method_ == OmniboxEventProto::TAB;
 
   controller_->ClearPopupKeywordMode();
+  controller_->client()->OnKeywordModeChanged(false, keyword_);
 
   // There are several possible states we could have been in before the user hit
   // backspace or shift-tab to enter this function:
diff --git a/components/omnibox/browser/omnibox_metrics_provider.cc b/components/omnibox/browser/omnibox_metrics_provider.cc
index 116f5ba..dba63d4e 100644
--- a/components/omnibox/browser/omnibox_metrics_provider.cc
+++ b/components/omnibox/browser/omnibox_metrics_provider.cc
@@ -436,23 +436,26 @@
     return;
   }
   ukm::builders::Omnibox_SuggestionUsed event(log.ukm_source_id);
-  event.SetResultTypeGroup(static_cast<int64_t>(client_summarized_result_type));
-  event.SetResultType(static_cast<int64_t>(omnibox_event_result_type));
   event.SetPageClassification(
       static_cast<int64_t>(log.current_page_classification));
   event.SetProviderType(static_cast<int64_t>(provider_type));
+  event.SetResultType(static_cast<int64_t>(omnibox_event_result_type));
+  event.SetResultTypeGroup(static_cast<int64_t>(client_summarized_result_type));
   event.SetSelectedIndex(log.selection.line);
+  // Set the time since the user last focused the omnibox only if set/valid.
+  if (log.elapsed_time_since_user_focused_omnibox != kDefaultTimeDelta) {
+    event.SetTimeSinceLastFocusMs(ukm::GetExponentialBucketMinForUserTiming(
+        log.elapsed_time_since_user_focused_omnibox.InMilliseconds()));
+  }
   event.SetTypedLength(log.text.length());
   // Set the typing duration only if set/valid.
   if (log.elapsed_time_since_user_first_modified_omnibox != kDefaultTimeDelta) {
     event.SetTypingDurationMs(ukm::GetExponentialBucketMinForUserTiming(
         log.elapsed_time_since_user_first_modified_omnibox.InMilliseconds()));
   }
-  // Set the time since the user last focused the omnibox only if set/valid.
-  if (log.elapsed_time_since_user_focused_omnibox != kDefaultTimeDelta) {
-    event.SetTimeSinceLastFocusMs(ukm::GetExponentialBucketMinForUserTiming(
-        log.elapsed_time_since_user_focused_omnibox.InMilliseconds()));
-  }
+  event.SetZeroPrefixSearchShown(
+      log.zero_prefix_search_suggestions_shown_in_session);
+  event.SetZeroPrefixUrlShown(log.zero_prefix_url_suggestions_shown_in_session);
   event.Record(ukm::UkmRecorder::Get());
 }
 
diff --git a/components/omnibox/browser/omnibox_metrics_provider_unittest.cc b/components/omnibox/browser/omnibox_metrics_provider_unittest.cc
index 034f934..744019a 100644
--- a/components/omnibox/browser/omnibox_metrics_provider_unittest.cc
+++ b/components/omnibox/browser/omnibox_metrics_provider_unittest.cc
@@ -343,9 +343,6 @@
     EXPECT_EQ(ukm_recorder.GetEntriesByName(entry_name).size(), 1ul);
     auto* entry = ukm_recorder.GetEntriesByName(entry_name)[0].get();
     ukm_recorder.ExpectEntryMetric(
-        entry, ukm::builders::Omnibox_SuggestionUsed::kResultTypeGroupName,
-        static_cast<uint64_t>(ClientSummarizedResultType::kSearch));
-    ukm_recorder.ExpectEntryMetric(
         entry, ukm::builders::Omnibox_SuggestionUsed::kPageClassificationName,
         static_cast<uint64_t>(
             metrics::OmniboxEventProto_PageClassification_NTP_REALBOX));
@@ -357,18 +354,28 @@
         static_cast<uint64_t>(
             metrics::OmniboxEventProto_Suggestion::SEARCH_SUGGEST));
     ukm_recorder.ExpectEntryMetric(
+        entry, ukm::builders::Omnibox_SuggestionUsed::kResultTypeGroupName,
+        static_cast<uint64_t>(ClientSummarizedResultType::kSearch));
+    ukm_recorder.ExpectEntryMetric(
         entry, ukm::builders::Omnibox_SuggestionUsed::kSelectedIndexName, 1ul);
-    ukm_recorder.ExpectEntryMetric(
-        entry, ukm::builders::Omnibox_SuggestionUsed::kTypedLengthName, 7ul);
-    ukm_recorder.ExpectEntryMetric(
-        entry, ukm::builders::Omnibox_SuggestionUsed::kTypingDurationMsName,
-        0ul);
     // With exponential bucketing scheme with a standard spacing of 2.0, 10
     // falls into the 8-16 bucket as the boundaries of the buckets increase
     // exponentially, e.g., 1, 2, 4, 8, 16, etc.
     ukm_recorder.ExpectEntryMetric(
         entry, ukm::builders::Omnibox_SuggestionUsed::kTimeSinceLastFocusMsName,
         8ul);
+    ukm_recorder.ExpectEntryMetric(
+        entry, ukm::builders::Omnibox_SuggestionUsed::kTypedLengthName, 7ul);
+    ukm_recorder.ExpectEntryMetric(
+        entry, ukm::builders::Omnibox_SuggestionUsed::kTypingDurationMsName,
+        0ul);
+    ukm_recorder.ExpectEntryMetric(
+        entry,
+        ukm::builders::Omnibox_SuggestionUsed::kZeroPrefixSearchShownName,
+        false);
+    ukm_recorder.ExpectEntryMetric(
+        entry, ukm::builders::Omnibox_SuggestionUsed::kZeroPrefixUrlShownName,
+        false);
   }
   {
     base::HistogramTester histogram_tester;
@@ -415,9 +422,6 @@
     EXPECT_EQ(ukm_recorder.GetEntriesByName(entry_name).size(), 1ul);
     auto* entry = ukm_recorder.GetEntriesByName(entry_name)[0].get();
     ukm_recorder.ExpectEntryMetric(
-        entry, ukm::builders::Omnibox_SuggestionUsed::kResultTypeGroupName,
-        static_cast<uint64_t>(ClientSummarizedResultType::kSearch));
-    ukm_recorder.ExpectEntryMetric(
         entry, ukm::builders::Omnibox_SuggestionUsed::kPageClassificationName,
         static_cast<uint64_t>(
             metrics::OmniboxEventProto_PageClassification_NTP_REALBOX));
@@ -429,18 +433,28 @@
         static_cast<uint64_t>(
             metrics::OmniboxEventProto_Suggestion::SEARCH_SUGGEST));
     ukm_recorder.ExpectEntryMetric(
+        entry, ukm::builders::Omnibox_SuggestionUsed::kResultTypeGroupName,
+        static_cast<uint64_t>(ClientSummarizedResultType::kSearch));
+    ukm_recorder.ExpectEntryMetric(
         entry, ukm::builders::Omnibox_SuggestionUsed::kSelectedIndexName, 1ul);
-    ukm_recorder.ExpectEntryMetric(
-        entry, ukm::builders::Omnibox_SuggestionUsed::kTypedLengthName, 0ul);
-    ukm_recorder.ExpectEntryMetric(
-        entry, ukm::builders::Omnibox_SuggestionUsed::kTypingDurationMsName,
-        0ul);
     // With exponential bucketing scheme with a standard spacing of 2.0, 10
     // falls into the 8-16 bucket as the boundaries of the buckets increase
     // exponentially, e.g., 1, 2, 4, 8, 16, etc.
     ukm_recorder.ExpectEntryMetric(
         entry, ukm::builders::Omnibox_SuggestionUsed::kTimeSinceLastFocusMsName,
         8ul);
+    ukm_recorder.ExpectEntryMetric(
+        entry, ukm::builders::Omnibox_SuggestionUsed::kTypedLengthName, 0ul);
+    ukm_recorder.ExpectEntryMetric(
+        entry, ukm::builders::Omnibox_SuggestionUsed::kTypingDurationMsName,
+        0ul);
+    ukm_recorder.ExpectEntryMetric(
+        entry,
+        ukm::builders::Omnibox_SuggestionUsed::kZeroPrefixSearchShownName,
+        true);
+    ukm_recorder.ExpectEntryMetric(
+        entry, ukm::builders::Omnibox_SuggestionUsed::kZeroPrefixUrlShownName,
+        true);
   }
 }
 
diff --git a/components/openscreen_platform/logging.cc b/components/openscreen_platform/logging.cc
index d89111b..6df9c5a9 100644
--- a/components/openscreen_platform/logging.cc
+++ b/components/openscreen_platform/logging.cc
@@ -35,7 +35,7 @@
 
 bool IsLoggingOn(LogLevel level, std::string_view file) {
   if (level == LogLevel::kVerbose) {
-    return ::logging::GetVlogLevelHelper(file) > 0;
+    return ::logging::GetVlogLevelHelper(file.data(), file.size()) > 0;
   }
   return ::logging::ShouldCreateLogMessage(MapLogLevel(level));
 }
diff --git a/components/optimization_guide/internal b/components/optimization_guide/internal
index f9d7428..d0d7e49 160000
--- a/components/optimization_guide/internal
+++ b/components/optimization_guide/internal
@@ -1 +1 @@
-Subproject commit f9d7428c4e3f83168b67a9974764646f5b5741fb
+Subproject commit d0d7e49feef85c1ef7e783521a20babc50ab3342
diff --git a/components/page_load_metrics/browser/observers/performance_manager_metrics_observer.cc b/components/page_load_metrics/browser/observers/performance_manager_metrics_observer.cc
index 0a58e2b9..4e3e738 100644
--- a/components/page_load_metrics/browser/observers/performance_manager_metrics_observer.cc
+++ b/components/page_load_metrics/browser/observers/performance_manager_metrics_observer.cc
@@ -47,6 +47,10 @@
     "PageLoad.Clients.PerformanceManager.LCPWithoutLoadedIdle";
 constexpr char kLoadedIdleWithoutLCPHistogram[] =
     "PageLoad.Clients.PerformanceManager.LoadedIdleWithoutLCP";
+constexpr char kNavigationToLoadedIdleHistogram[] =
+    "PageLoad.Clients.PerformanceManager.NavigationToLoadedIdle";
+constexpr char kNavigationWithoutLoadedIdleHistogram[] =
+    "PageLoad.Clients.PerformanceManager.NavigationWithoutLoadedIdle";
 
 class LoadedIdleObserver final
     : public PageNodeObserver,
@@ -174,7 +178,7 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   CHECK(loaded_idle_time_.is_null());
   loaded_idle_time_ = loaded_idle_time;
-  LogMetricsIfLoaded(/*is_final=*/false);
+  LogMetricsIfAvailable();
 }
 
 ObservePolicy PerformanceManagerMetricsObserver::OnStart(
@@ -228,101 +232,164 @@
 ObservePolicy
 PerformanceManagerMetricsObserver::FlushMetricsOnAppEnterBackground(
     const page_load_metrics::mojom::PageLoadTiming&) {
-  return LogMetricsIfLoaded(/*is_final=*/false);
+  return LogMetricsIfAvailable();
 }
 
 void PerformanceManagerMetricsObserver::OnComplete(
     const page_load_metrics::mojom::PageLoadTiming&) {
-  LogMetricsIfLoaded(/*is_final=*/true);
+  LogFinalMetrics();
 }
 
 void PerformanceManagerMetricsObserver::OnFailedProvisionalLoad(
     const page_load_metrics::FailedProvisionalLoadInfo&) {
-  LogMetricsIfLoaded(/*is_final=*/true);
+  LogFinalMetrics();
 }
 
-ObservePolicy PerformanceManagerMetricsObserver::LogMetricsIfLoaded(
-    bool is_final) {
+std::optional<base::TimeDelta>
+PerformanceManagerMetricsObserver::DeltaFromNavigationStartTime(
+    base::TimeTicks time) const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  CHECK_NE(visibility_, Visibility::kUnknown);
-  if (logged_metrics_) {
-    return STOP_OBSERVING;
-  }
-
   const base::TimeTicks navigation_start_time =
       GetDelegate().GetNavigationStart();
   CHECK(!navigation_start_time.is_null());
+  // `navigation_start_time` is reported from renderers so can't be guaranteed
+  // monotonically increasing compared to TimeTicks::Now() taken in this
+  // process. Return nullopt if it's not valid.
+  if (time < navigation_start_time) {
+    return std::nullopt;
+  }
+  return time - navigation_start_time;
+}
 
-  std::optional<base::TimeDelta> loaded_idle_delta;
-  if (!loaded_idle_time_.is_null()) {
-    loaded_idle_delta = loaded_idle_time_ - navigation_start_time;
-    if (loaded_idle_delta->is_negative()) {
-      // `navigation_start_time` is reported from renderers so can't be
-      // guaranteed monotonically increasing compared to TimeTicks::Now() taken
-      // in this process. Bail out if it's not valid.
-      return STOP_OBSERVING;
-    }
+ObservePolicy PerformanceManagerMetricsObserver::LogMetricsIfAvailable() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (loaded_idle_time_.is_null()) {
+    // Keep waiting for loaded idle time to come in.
+    return CONTINUE_OBSERVING;
   }
 
-  const page_load_metrics::ContentfulPaintTimingInfo& lcp_info =
-      GetDelegate()
-          .GetLargestContentfulPaintHandler()
-          .MergeMainFrameAndSubframes();
+  const std::optional<base::TimeDelta> loaded_idle_delta =
+      DeltaFromNavigationStartTime(loaded_idle_time_);
+  if (!loaded_idle_delta.has_value()) {
+    // Bail out if the delta from navigation start isn't valid.
+    return STOP_OBSERVING;
+  }
 
-  if (lcp_info.ContainsValidTime() && loaded_idle_delta.has_value()) {
-    // Log time between LCP and LoadedIdle. If LoadedIdle came before LCP
-    // (unexpected) the negative TimeDelta will be logged in the 0 bucket.
+  // Log metrics about LoadedIdle time.
+  if (!logged_load_metrics_) {
+    // Broken down by visibility.
+    base::UmaHistogramMediumTimes(
+        base::StrCat({kNavigationToLoadedIdleHistogram,
+                      GetVisibilitySuffix(visibility_)}),
+        loaded_idle_delta.value());
+    // All page loads.
+    base::UmaHistogramMediumTimes(kNavigationToLoadedIdleHistogram,
+                                  loaded_idle_delta.value());
+    logged_load_metrics_ = true;
+  }
+
+  // Log time between LCP and LoadedIdle.
+  if (!logged_lcp_metrics_) {
+    const page_load_metrics::ContentfulPaintTimingInfo& lcp_info =
+        GetDelegate()
+            .GetLargestContentfulPaintHandler()
+            .MergeMainFrameAndSubframes();
+    if (!lcp_info.ContainsValidTime()) {
+      // Keep waiting for LCP to come in.
+      return CONTINUE_OBSERVING;
+    }
+
+    // If LoadedIdle came before LCP (unexpected) the negative TimeDelta will
+    // be logged in the 0 bucket.
     CHECK(!lcp_info.Time()->is_negative());
     CHECK(!loaded_idle_delta->is_negative());
     base::TimeDelta loaded_idle_delta_from_lcp =
         loaded_idle_delta.value() - lcp_info.Time().value();
 
     // Broken down by visibility.
-    UmaHistogramMediumTimes(base::StrCat({kLCPToLoadedIdleHistogram,
-                                          GetVisibilitySuffix(visibility_)}),
-                            loaded_idle_delta_from_lcp);
+    base::UmaHistogramMediumTimes(
+        base::StrCat(
+            {kLCPToLoadedIdleHistogram, GetVisibilitySuffix(visibility_)}),
+        loaded_idle_delta_from_lcp);
     // All page loads.
-    UmaHistogramMediumTimes(kLCPToLoadedIdleHistogram,
-                            loaded_idle_delta_from_lcp);
+    base::UmaHistogramMediumTimes(kLCPToLoadedIdleHistogram,
+                                  loaded_idle_delta_from_lcp);
 
-    logged_metrics_ = true;
-    return STOP_OBSERVING;
+    logged_lcp_metrics_ = true;
   }
 
-  if (is_final && lcp_info.ContainsValidTime()) {
+  if (logged_load_metrics_ && logged_lcp_metrics_) {
+    // Nothing more to log.
+    return STOP_OBSERVING;
+  }
+  // Keep waiting.
+  return CONTINUE_OBSERVING;
+}
+
+void PerformanceManagerMetricsObserver::LogFinalMetrics() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  LogMetricsIfAvailable();
+
+  if (!logged_load_metrics_) {
+    // Log that navigation stopped without receiving LoadIdleTime.
+    CHECK(loaded_idle_time_.is_null());
+
+    const std::optional<base::TimeDelta> navigation_delta =
+        DeltaFromNavigationStartTime(base::TimeTicks::Now());
+    if (navigation_delta.has_value()) {
+      // Broken down by visibility.
+      base::UmaHistogramMediumTimes(
+          base::StrCat({kNavigationWithoutLoadedIdleHistogram,
+                        GetVisibilitySuffix(visibility_)}),
+          navigation_delta.value());
+      // All page loads.
+      base::UmaHistogramMediumTimes(kNavigationWithoutLoadedIdleHistogram,
+                                    navigation_delta.value());
+      logged_load_metrics_ = true;
+    }
+  }
+
+  if (logged_lcp_metrics_) {
+    // Nothing more to log.
+    return;
+  }
+
+  const page_load_metrics::ContentfulPaintTimingInfo& lcp_info =
+      GetDelegate()
+          .GetLargestContentfulPaintHandler()
+          .MergeMainFrameAndSubframes();
+  if (lcp_info.ContainsValidTime()) {
     // Page never reached LoadedIdle.
+    CHECK(loaded_idle_time_.is_null());
     CHECK(!lcp_info.Time()->is_negative());
 
     // Broken down by visibility.
-    UmaHistogramMediumTimes(base::StrCat({kLCPWithoutLoadedIdleHistogram,
-                                          GetVisibilitySuffix(visibility_)}),
-                            lcp_info.Time().value());
+    base::UmaHistogramMediumTimes(
+        base::StrCat(
+            {kLCPWithoutLoadedIdleHistogram, GetVisibilitySuffix(visibility_)}),
+        lcp_info.Time().value());
     // All page loads.
-    UmaHistogramMediumTimes(kLCPWithoutLoadedIdleHistogram,
-                            lcp_info.Time().value());
+    base::UmaHistogramMediumTimes(kLCPWithoutLoadedIdleHistogram,
+                                  lcp_info.Time().value());
 
-    logged_metrics_ = true;
-    return STOP_OBSERVING;
-  }
-
-  if (is_final && loaded_idle_delta.has_value()) {
+    logged_lcp_metrics_ = true;
+  } else if (!loaded_idle_time_.is_null()) {
     // Page reached LoadedIdle without recording LCP.
-    CHECK(!loaded_idle_delta->is_negative());
+    const std::optional<base::TimeDelta> loaded_idle_delta =
+        DeltaFromNavigationStartTime(loaded_idle_time_);
+    if (loaded_idle_delta.has_value()) {
+      // Broken down by visibility.
+      base::UmaHistogramMediumTimes(
+          base::StrCat({kLoadedIdleWithoutLCPHistogram,
+                        GetVisibilitySuffix(visibility_)}),
+          loaded_idle_delta.value());
+      // All page loads.
+      base::UmaHistogramMediumTimes(kLoadedIdleWithoutLCPHistogram,
+                                    loaded_idle_delta.value());
 
-    // Broken down by visibility.
-    UmaHistogramMediumTimes(base::StrCat({kLoadedIdleWithoutLCPHistogram,
-                                          GetVisibilitySuffix(visibility_)}),
-                            loaded_idle_delta.value());
-    // All page loads.
-    UmaHistogramMediumTimes(kLoadedIdleWithoutLCPHistogram,
-                            loaded_idle_delta.value());
-
-    logged_metrics_ = true;
-    return STOP_OBSERVING;
+      logged_lcp_metrics_ = true;
+    }
   }
-
-  // Keep waiting.
-  return CONTINUE_OBSERVING;
 }
 
 void PerformanceManagerMetricsObserver::WatchForLoadedIdle(
diff --git a/components/page_load_metrics/browser/observers/performance_manager_metrics_observer.h b/components/page_load_metrics/browser/observers/performance_manager_metrics_observer.h
index 733f96e..92796acf 100644
--- a/components/page_load_metrics/browser/observers/performance_manager_metrics_observer.h
+++ b/components/page_load_metrics/browser/observers/performance_manager_metrics_observer.h
@@ -5,6 +5,8 @@
 #ifndef COMPONENTS_PAGE_LOAD_METRICS_BROWSER_OBSERVERS_PERFORMANCE_MANAGER_METRICS_OBSERVER_H_
 #define COMPONENTS_PAGE_LOAD_METRICS_BROWSER_OBSERVERS_PERFORMANCE_MANAGER_METRICS_OBSERVER_H_
 
+#include <optional>
+
 #include "base/memory/weak_ptr.h"
 #include "base/sequence_checker.h"
 #include "base/time/time.h"
@@ -71,12 +73,25 @@
       const page_load_metrics::FailedProvisionalLoadInfo&) override;
 
  private:
-  // Logs UMA metrics if the load times are available. If `is_final` is true,
-  // this will not be called again so it logs all metrics. Otherwise it only
-  // logs metrics if both FirstContentfulPaint and LoadedIdle were observed.
-  // Returns STOP_OBSERVING if it logs metrics since there's no need to
-  // continue observing.
-  ObservePolicy LogMetricsIfLoaded(bool is_final);
+  // Returns the delta between the navigation start (which is reported from
+  // renderers) and `time`, which should be a timestamp taken in this process
+  // after starting navigation. Since timestamps from different processes can't
+  // be guaranteed to be monotonically increasing, returns nullopt if the delta
+  // would be negative.
+  std::optional<base::TimeDelta> DeltaFromNavigationStartTime(
+      base::TimeTicks time) const;
+
+  // Logs NavigationToLoadedIdle and LCPToLoadedIdle UMA metrics if the load
+  // times are available. Returns STOP_OBSERVING if all metrics are logged,
+  // since there's no need to continue observing, or CONTINUE_OBSERVING to keep
+  // waiting for load times.
+  ObservePolicy LogMetricsIfAvailable();
+
+  // Logs UMA metrics when a load is finished or abandoned. This logs the same
+  // metrics as LogMetricsIfLoaded(), plus some of NavigationWithoutLoadedIdle,
+  // LCPWithoutLoadedIdle, and LoadedIdleWithoutLCP for any load times that
+  // aren't available.
+  void LogFinalMetrics();
 
   // Starts watching for `page_node`, the PerformanceManager node for this page
   // load, to reach LoadedIdle.
@@ -89,9 +104,9 @@
   Visibility visibility_ GUARDED_BY_CONTEXT(sequence_checker_) =
       Visibility::kUnknown;
 
-  // True if metrics were already logged, in which case further calls to
-  // LogMetricsIfLoaded() will do nothing.
-  bool logged_metrics_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
+  // True if various metrics were already logged, to prevent logging them twice.
+  bool logged_load_metrics_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
+  bool logged_lcp_metrics_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
 
   // The time that the page load reached LoadedIdle, or 0 if this wasn't
   // observed yet.
diff --git a/components/password_manager/core/browser/password_manager_unittest.cc b/components/password_manager/core/browser/password_manager_unittest.cc
index bb21323..bec607c1c 100644
--- a/components/password_manager/core/browser/password_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_manager_unittest.cc
@@ -28,8 +28,10 @@
 #include "build/build_config.h"
 #include "components/affiliations/core/browser/fake_affiliation_service.h"
 #include "components/autofill/core/browser/autofill_type.h"
+#include "components/autofill/core/browser/crowdsourcing/randomized_encoder.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/test_utils/autofill_test_utils.h"
+#include "components/autofill/core/common/autofill_prefs.h"
 #include "components/autofill/core/common/field_data_manager.h"
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/form_data_test_api.h"
@@ -459,6 +461,11 @@
 #endif
 
     prefs_ = std::make_unique<TestingPrefServiceSimple>();
+    prefs_->registry()->RegisterStringPref(
+        autofill::prefs::kAutofillUploadEncodingSeed, "default_secret");
+    prefs_->registry()->RegisterBooleanPref(
+        autofill::RandomizedEncoder::kUrlKeyedAnonymizedDataCollectionEnabled,
+        false);
     prefs_->registry()->RegisterBooleanPref(
         prefs::kPasswordLeakDetectionEnabled, true);
     prefs_->registry()->RegisterBooleanPref(::prefs::kSafeBrowsingEnabled,
diff --git a/components/password_manager/core/browser/votes_uploader.cc b/components/password_manager/core/browser/votes_uploader.cc
index 4be1e5c..b5387be7 100644
--- a/components/password_manager/core/browser/votes_uploader.cc
+++ b/components/password_manager/core/browser/votes_uploader.cc
@@ -456,7 +456,11 @@
   FormStructure form_structure(form_to_upload.form_data);
   form_structure.set_submission_event(submitted_form.submission_event);
 
-  FieldTypeSet available_field_types;
+  autofill::EncodeUploadRequestOptions options;
+  options.encoder = RandomizedEncoder::Create(client_->GetPrefs());
+  options.login_form_signature = login_form_signature;
+  options.observed_submission = true;
+
   // A map from field names to field types.
   FieldTypeMap field_types;
   // Used to detect whether the vote is corrupted because of duplicate field
@@ -531,7 +535,7 @@
   LabelFields(
       field_types, field_name_collision,
       {{form_to_upload.username_element_renderer_id, username_vote_type}},
-      &form_structure, &available_field_types);
+      &form_structure, &options.available_field_types);
 
   if (password_manager_util::IsLoggingActive(client_)) {
     BrowserSavePasswordProgressLogger logger(client_->GetCurrentLogManager());
@@ -539,8 +543,7 @@
                             password_attributes);
   }
 
-  return SendUploadRequest(form_structure, available_field_types,
-                           login_form_signature, password_attributes,
+  return SendUploadRequest(form_structure, options, password_attributes,
                            should_set_passwords_were_revealed);
 }
 
@@ -563,6 +566,10 @@
   FormStructure form_structure(form_to_upload.form_data);
   form_structure.set_submission_event(form_to_upload.submission_event);
 
+  autofill::EncodeUploadRequestOptions options;
+  options.encoder = RandomizedEncoder::Create(client_->GetPrefs());
+  options.observed_submission = true;
+
   FieldTypeMap field_types;
   bool field_name_collision = false;
   SetFieldType(form_to_upload.username_element_renderer_id, autofill::USERNAME,
@@ -576,9 +583,8 @@
         AutofillUploadContents::Field::FIRST_USE;
   }
 
-  FieldTypeSet available_field_types;
   LabelFields(field_types, field_name_collision, vote_types, &form_structure,
-              &available_field_types);
+              &options.available_field_types);
   SetKnownValueFlag(pending_credentials, best_matches, &form_structure);
 
   // Annotate the form with the source language of the page.
@@ -593,8 +599,7 @@
                             std::nullopt);
   }
 
-  SendUploadRequest(form_structure, available_field_types,
-                    /*login_form_signature=*/std::nullopt,
+  SendUploadRequest(form_structure, options,
                     /*password_attributes=*/std::nullopt,
                     /*should_set_passwords_were_revealed=*/false);
 }
@@ -889,19 +894,12 @@
 std::vector<autofill::AutofillUploadContents>
 VotesUploader::EncodeUploadRequest(
     autofill::FormStructure& form,
-    const autofill::FieldTypeSet& available_field_types,
-    std::optional<FormSignature> login_form_signature,
+    const autofill::EncodeUploadRequestOptions& options,
     std::optional<PasswordAttributesMetadata> password_attributes,
     bool should_set_passwords_were_revealed) {
   // Annotate the form with the source language of the page.
   form.set_current_page_language(client_->GetPageLanguage());
 
-  autofill::EncodeUploadRequestOptions options;
-  options.encoder = RandomizedEncoder::Create(client_->GetPrefs());
-  options.available_field_types = available_field_types;
-  options.login_form_signature = login_form_signature;
-  options.observed_submission = true;
-
   std::vector<AutofillUploadContents> upload_contents =
       autofill::EncodeUploadRequest(form, options);
   CHECK(!upload_contents.empty());
@@ -918,8 +916,7 @@
 
 bool VotesUploader::SendUploadRequest(
     autofill::FormStructure& form_to_upload,
-    const FieldTypeSet& available_field_types,
-    std::optional<FormSignature> login_form_signature,
+    const autofill::EncodeUploadRequestOptions& options,
     std::optional<PasswordAttributesMetadata> password_attributes,
     bool should_set_passwords_were_revealed) {
   AutofillCrowdsourcingManager* crowdsourcing_manager =
@@ -929,8 +926,7 @@
   }
 
   return crowdsourcing_manager->StartUploadRequest(
-      EncodeUploadRequest(form_to_upload, available_field_types,
-                          login_form_signature, password_attributes,
+      EncodeUploadRequest(form_to_upload, options, password_attributes,
                           should_set_passwords_were_revealed),
       form_to_upload.submission_source(),
       /*is_password_manager_upload=*/true);
@@ -1072,8 +1068,11 @@
       FormStructure::CreateForPasswordManagerUpload(predictions.form_signature,
                                                     field_signatures);
 
+  autofill::EncodeUploadRequestOptions options;
+  options.encoder = RandomizedEncoder::Create(client_->GetPrefs());
+  options.observed_submission = true;
+
   // Label the username field with a SINGLE_USERNAME or NOT_USERNAME vote.
-  FieldTypeSet available_field_types;
   for (size_t i = 0; i < form_to_upload->field_count(); ++i) {
     AutofillField* field = form_to_upload->field(i);
     FieldRendererId field_renderer_id = predictions.fields[i].renderer_id;
@@ -1083,7 +1082,7 @@
       continue;
     }
     if (!SetSingleUsernameVoteOnUsernameForm(
-            field, single_username, &available_field_types,
+            field, single_username, &options.available_field_types,
             predictions.form_signature,
             is_most_recent_single_username_candidate,
             is_forgot_password_vote)) {
@@ -1093,15 +1092,14 @@
   }
 
   // Upload a vote on the username form if available.
-  if (!available_field_types.empty()) {
+  if (!options.available_field_types.empty()) {
     if (password_manager_util::IsLoggingActive(client_)) {
       BrowserSavePasswordProgressLogger logger(client_->GetCurrentLogManager());
       logger.LogFormStructure(Logger::STRING_USERNAME_FIRST_FLOW_VOTE,
                               *form_to_upload, std::nullopt);
     }
 
-    if (SendUploadRequest(*form_to_upload, available_field_types,
-                          /*login_form_signature=*/std::nullopt,
+    if (SendUploadRequest(*form_to_upload, options,
                           /*password_attributes=*/std::nullopt,
                           /*should_set_passwords_were_revealed=*/false)) {
       return true;
diff --git a/components/password_manager/core/browser/votes_uploader.h b/components/password_manager/core/browser/votes_uploader.h
index 634417e..1ef0aa7 100644
--- a/components/password_manager/core/browser/votes_uploader.h
+++ b/components/password_manager/core/browser/votes_uploader.h
@@ -23,6 +23,7 @@
 
 namespace autofill {
 class AutofillField;
+struct EncodeUploadRequestOptions;
 class FormData;
 class FormStructure;
 }  // namespace autofill
@@ -307,8 +308,7 @@
   // information that needs to be sent to the Autofill server.
   std::vector<autofill::AutofillUploadContents> EncodeUploadRequest(
       autofill::FormStructure& form,
-      const autofill::FieldTypeSet& available_field_types,
-      std::optional<autofill::FormSignature> login_form_signature,
+      const autofill::EncodeUploadRequestOptions& options,
       std::optional<PasswordAttributesMetadata> password_attributes,
       bool should_set_passwords_were_revealed);
 
@@ -316,8 +316,7 @@
   // `true` if the vote is sent, `false` otherwise.
   bool SendUploadRequest(
       autofill::FormStructure& form_to_upload,
-      const autofill::FieldTypeSet& available_field_types,
-      std::optional<autofill::FormSignature> login_form_signature,
+      const autofill::EncodeUploadRequestOptions& options,
       std::optional<PasswordAttributesMetadata> password_attributes,
       bool should_set_passwords_were_revealed);
 
diff --git a/components/password_manager/ios/resources/password_controller.ts b/components/password_manager/ios/resources/password_controller.ts
index 8010e6e5..cb768a6 100644
--- a/components/password_manager/ios/resources/password_controller.ts
+++ b/components/password_manager/ios/resources/password_controller.ts
@@ -4,11 +4,11 @@
 
 import * as fillConstants from '//components/autofill/ios/form_util/resources/fill_constants.js';
 import type {AutofillFormData} from '//components/autofill/ios/form_util/resources/fill_util.js';
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 import {isTextField, sendWebKitMessage} from '//ios/web/public/js_messaging/resources/utils.js';
 
 /**
- * @fileoverview Installs Passwords management functions on the gCrWeb object.
+ * @fileoverview Installs Passwords management functions on the gCrWebLegacy object.
  *
  * It scans the DOM, extracting and storing password forms and returns a JSON
  * string representing an array of objects, each of which represents an Password
@@ -50,7 +50,7 @@
 function findPasswordForms(): string {
   const formDataList: AutofillFormData[] = [];
   getPasswordFormDataList(formDataList);
-  return gCrWeb.stringify(formDataList);
+  return gCrWebLegacy.stringify(formDataList);
 }
 
 /**
@@ -84,7 +84,7 @@
  */
 function onSubmitButtonTouchEnd(evt: Event) {
   const form = (evt.currentTarget as HTMLFormElement)['form'];
-  const formData = gCrWeb.passwords.getPasswordFormData(form);
+  const formData = gCrWebLegacy.passwords.getPasswordFormData(form);
   if (!formData) {
     return;
   }
@@ -101,7 +101,7 @@
     return null;
   }
   for (const input of inputs) {
-    if (identifier.toString() === gCrWeb.fill.getUniqueID(input)) {
+    if (identifier.toString() === gCrWebLegacy.fill.getUniqueID(input)) {
       return input;
     }
   }
@@ -114,7 +114,7 @@
  *   are returned.
  */
 function getFormInputElements(form: HTMLFormElement): HTMLInputElement[] {
-  return gCrWeb.form.getFormControlElements(form).filter((element: Element) => {
+  return gCrWebLegacy.form.getFormControlElements(form).filter((element: Element) => {
     return element.tagName === 'INPUT';
   });
 }
@@ -128,17 +128,17 @@
   const hasFormTag =
       identifier.toString() !== fillConstants.RENDERER_ID_NOT_SET;
   const form =
-      hasFormTag ? gCrWeb.form.getFormElementFromRendererId(identifier) : null;
+      hasFormTag ? gCrWebLegacy.form.getFormElementFromRendererId(identifier) : null;
   if (!form && hasFormTag) {
     return '{}';
   }
   const formData = hasFormTag ?
-      gCrWeb.passwords.getPasswordFormData(form) :
-      gCrWeb.passwords.getPasswordFormDataFromUnownedElements();
+    gCrWebLegacy.passwords.getPasswordFormData(form) :
+    gCrWebLegacy.passwords.getPasswordFormDataFromUnownedElements();
   if (!formData) {
     return '{}';
   }
-  return gCrWeb.stringify(formData);
+  return gCrWebLegacy.stringify(formData);
 }
 
 /**
@@ -156,7 +156,7 @@
 function fillPasswordForm(
     formData: AutofillFormData, username: string,
     password: string): FillResult {
-  const form = gCrWeb.form.getFormElementFromRendererId(formData.renderer_id);
+  const form = gCrWebLegacy.form.getFormElementFromRendererId(formData.renderer_id);
   if (form) {
     const inputs = getFormInputElements(form);
     return fillUsernameAndPassword(inputs, formData, username, password);
@@ -164,7 +164,7 @@
 
   // Check fields that are not inside any <form> tag.
   const unownedInputs =
-      gCrWeb.fill.getUnownedAutofillableFormFieldElements(document.all, []);
+      gCrWebLegacy.fill.getUnownedAutofillableFormFieldElements(document.all, []);
   if (unownedInputs.length > 0) {
     return fillUsernameAndPassword(unownedInputs, formData, username, password);
   }
@@ -212,13 +212,13 @@
     formIdentifier: number, newPasswordIdentifier: number,
     confirmPasswordIdentifier: number, password: string,
     hasFormTag: boolean): boolean {
-  const form = gCrWeb.form.getFormElementFromRendererId(formIdentifier);
+  const form = gCrWebLegacy.form.getFormElementFromRendererId(formIdentifier);
   if (!form && hasFormTag) {
     return false;
   }
   const inputs = hasFormTag ?
       getFormInputElements(form) :
-      gCrWeb.fill.getUnownedAutofillableFormFieldElements(document.all, []);
+      gCrWebLegacy.fill.getUnownedAutofillableFormFieldElements(document.all, []);
   const newPasswordField =
       findInputByFieldRendererID(inputs, newPasswordIdentifier);
   if (!newPasswordField) {
@@ -226,12 +226,12 @@
   }
   // Avoid resetting if same value, as it moves cursor to the end.
   if (newPasswordField.value !== password) {
-    gCrWeb.fill.setInputElementValue(password, newPasswordField);
+    gCrWebLegacy.fill.setInputElementValue(password, newPasswordField);
   }
   const confirmPasswordField =
       findInputByFieldRendererID(inputs, confirmPasswordIdentifier);
   if (confirmPasswordField && confirmPasswordField.value !== password) {
-    gCrWeb.fill.setInputElementValue(password, confirmPasswordField);
+    gCrWebLegacy.fill.setInputElementValue(password, confirmPasswordField);
   }
   return true;
 }
@@ -322,13 +322,13 @@
   // pre-filled by the website.
   const didFillUsername: boolean =
       (isUsernameEditable &&
-       gCrWeb.fill.setInputElementValue(username, usernameInput)) as boolean;
+       gCrWebLegacy.fill.setInputElementValue(username, usernameInput)) as boolean;
 
   // Fill the password if needed.
   const didFillPassword: boolean =
       Boolean(
           !!passwordInput &&
-          gCrWeb.fill.setInputElementValue(password, passwordInput)) as boolean;
+              gCrWebLegacy.fill.setInputElementValue(password, passwordInput)) as boolean;
 
   return {
     didFillUsername,
@@ -366,7 +366,7 @@
     }
   }
   const unownedFormData =
-      gCrWeb.passwords.getPasswordFormDataFromUnownedElements();
+  gCrWebLegacy.passwords.getPasswordFormDataFromUnownedElements();
   if (unownedFormData && isRecognizedCredentialForm(unownedFormData)) {
     formDataList.push(unownedFormData);
   }
@@ -380,13 +380,13 @@
 function getPasswordFormDataFromUnownedElements(): object|null {
   const fieldsets: fillConstants.FormControlElement[] = [];
   const unownedControlElements =
-      gCrWeb.fill.getUnownedAutofillableFormFieldElements(
+  gCrWebLegacy.fill.getUnownedAutofillableFormFieldElements(
           document.all, fieldsets);
   if (unownedControlElements.length === 0) {
     return null;
   }
-  const unownedForm = new gCrWeb['common'].JSONSafeObject();
-  const hasUnownedForm = gCrWeb.fill.unownedFormElementsAndFieldSetsToFormData(
+  const unownedForm = new gCrWebLegacy['common'].JSONSafeObject();
+  const hasUnownedForm = gCrWebLegacy.fill.unownedFormElementsAndFieldSetsToFormData(
       window, fieldsets, unownedControlElements, /* iframeElements= */[], false,
       unownedForm);
   return hasUnownedForm ? unownedForm : null;
@@ -400,13 +400,13 @@
 function getPasswordFormData(
     formElement: HTMLFormElement): AutofillFormData|null {
   const formData = {} as AutofillFormData;
-  const ok = gCrWeb.fill.webFormElementToFormData(
+  const ok = gCrWebLegacy.fill.webFormElementToFormData(
       window, formElement, /*formControlElement=*/ null, formData,
       /*field=*/ null);
   return ok ? formData : null;
 }
 
-gCrWeb.passwords = {
+gCrWebLegacy.passwords = {
   findPasswordForms,
   getPasswordFormDataAsString,
   fillPasswordForm,
diff --git a/components/peripherals/logging/logging_unittest.cc b/components/peripherals/logging/logging_unittest.cc
index 79a64a4..9eeb810 100644
--- a/components/peripherals/logging/logging_unittest.cc
+++ b/components/peripherals/logging/logging_unittest.cc
@@ -6,8 +6,6 @@
 
 #include <stddef.h>
 
-#include <string_view>
-
 #include "ash/constants/ash_features.h"
 #include "base/no_destructor.h"
 #include "base/strings/string_number_conversions.h"
@@ -33,7 +31,7 @@
 }
 
 bool HandleStandardLogMessage(int severity,
-                              std::string_view file,
+                              const char* file,
                               int line,
                               size_t message_start,
                               const std::string& str) {
diff --git a/components/policy/core/common/policy_logger.cc b/components/policy/core/common/policy_logger.cc
index a77b5b5..f6c8a6a4 100644
--- a/components/policy/core/common/policy_logger.cc
+++ b/components/policy/core/common/policy_logger.cc
@@ -145,16 +145,19 @@
 
   // Check for verbose logging.
   if (log_verbosity_ != policy::PolicyLogger::LogHelper::kNoVerboseLog) {
-    LAZY_STREAM(::logging::LogMessage(file_, line_, -(log_verbosity_)).stream(),
-                log_verbosity_ <= ::logging::GetVlogLevelHelper(file_))
+    LAZY_STREAM(
+        ::logging::LogMessage(file_.data(), line_, -(log_verbosity_)).stream(),
+        log_verbosity_ <=
+            ::logging::GetVlogLevelHelper(file_.data(), file_.size()))
         << message_buffer_.str();
     return;
   }
 
   int log_severity_int = GetLogSeverityInt(log_severity_);
 
-  LAZY_STREAM(::logging::LogMessage(file_, line_, log_severity_int).stream(),
-              ::logging::ShouldCreateLogMessage(log_severity_int))
+  LAZY_STREAM(
+      ::logging::LogMessage(file_.data(), line_, log_severity_int).stream(),
+      ::logging::ShouldCreateLogMessage(log_severity_int))
       << message_buffer_.str();
 }
 
diff --git a/components/policy/core/common/policy_pref_names.cc b/components/policy/core/common/policy_pref_names.cc
index faa0331f..cafb385c 100644
--- a/components/policy/core/common/policy_pref_names.cc
+++ b/components/policy/core/common/policy_pref_names.cc
@@ -148,11 +148,6 @@
 const char kLocalTestPoliciesForNextStartup[] =
     "local_test_policies_for_next_startup";
 
-// A boolean pref indicating whether to fire deprecated/removed mutation events.
-// If false, mutation events might not be fired.
-const char kMutationEventsEnabled[] =
-    "policy.deprecated_mutation_events_enabled";
-
 // Enables the deprecated :--foo syntax of CSS custom state. The :--foo syntax
 // was deprecated and replaced by :state(foo).
 const char kCSSCustomStateDeprecatedSyntaxEnabled[] =
diff --git a/components/policy/core/common/policy_pref_names.h b/components/policy/core/common/policy_pref_names.h
index ae02ad90..bbe01ab 100644
--- a/components/policy/core/common/policy_pref_names.h
+++ b/components/policy/core/common/policy_pref_names.h
@@ -80,7 +80,6 @@
 extern const char kHasDismissedPolicyPagePromotionBanner[];
 extern const char kAllowBackForwardCacheForCacheControlNoStorePageEnabled[];
 extern const char kLocalTestPoliciesForNextStartup[];
-extern const char kMutationEventsEnabled[];
 extern const char kCSSCustomStateDeprecatedSyntaxEnabled[];
 extern const char kSelectParserRelaxationEnabled[];
 extern const char kForcePermissionPolicyUnloadDefaultEnabled[];
diff --git a/components/policy/resources/templates/policy_definitions/Miscellaneous/MutationEventsEnabled.yaml b/components/policy/resources/templates/policy_definitions/Miscellaneous/MutationEventsEnabled.yaml
index c04e860..8acb1d72 100644
--- a/components/policy/resources/templates/policy_definitions/Miscellaneous/MutationEventsEnabled.yaml
+++ b/components/policy/resources/templates/policy_definitions/Miscellaneous/MutationEventsEnabled.yaml
@@ -4,7 +4,7 @@
 desc: |-
   This policy provides a temporary opt-back-in to a deprecated and removed set of platform events called Mutation Events.
   When this policy is Enabled, mutation events will continue to be fired, even if they've been disabled by default for normal web users. When this policy is Disabled or unset, these events may not be fired.
-  This policy is a temporary workaround, and will be removed in M135.
+  This policy is a temporary workaround, and will no longer work in M137.
 example_value: true
 features:
   dynamic_refresh: true
@@ -21,9 +21,9 @@
 schema:
   type: boolean
 supported_on:
-- chrome.*:124-
-- chrome_os:124-
-- android:124-
-- webview_android:124-
+- chrome.*:124-136
+- chrome_os:124-136
+- android:124-136
+- webview_android:124-136
 tags: []
 type: main
diff --git a/components/policy/resources/templates/policy_definitions/PowerManagement/DevicePowerAdaptiveChargingEnabled.yaml b/components/policy/resources/templates/policy_definitions/PowerManagement/DevicePowerAdaptiveChargingEnabled.yaml
index 870c8fc..30db2a8 100644
--- a/components/policy/resources/templates/policy_definitions/PowerManagement/DevicePowerAdaptiveChargingEnabled.yaml
+++ b/components/policy/resources/templates/policy_definitions/PowerManagement/DevicePowerAdaptiveChargingEnabled.yaml
@@ -1,5 +1,6 @@
 caption: Enable adaptive charging model to hold charging process to extend battery
   life
+deprecated: true
 default: true
 default_for_enterprise_users: false
 desc: |-
@@ -26,9 +27,10 @@
     ChromeOS</ex></ph>
   value: false
 owners:
-- thanhdng@chromium.org
+- chromeos-power-team@google.com
+- jingmuli@google.com
 - napper@chromium.org
-- dbasehore@chromium.org
+- thanhdng@chromium.org
 schema:
   type: boolean
 supported_on:
diff --git a/components/policy/resources/templates/policy_definitions/PowerManagement/DevicePowerBatteryChargingOptimization.yaml b/components/policy/resources/templates/policy_definitions/PowerManagement/DevicePowerBatteryChargingOptimization.yaml
index 6cd039f..a67827f 100644
--- a/components/policy/resources/templates/policy_definitions/PowerManagement/DevicePowerBatteryChargingOptimization.yaml
+++ b/components/policy/resources/templates/policy_definitions/PowerManagement/DevicePowerBatteryChargingOptimization.yaml
@@ -2,19 +2,22 @@
 desc: |-
   Battery health can be affected by factors like frequent full charges and extended charging durations. This policy provides three options to optimize charging behavior and mitigate these factors, ultimately prolonging battery lifespan.
 
+  Leaving the policy unset - Users can use Adaptive Charging toggle button to enable/disable Adaptive Charging.
+
   Setting the policy to 1 - Standard or leaving it unset, the battery charges normally to 100%. This disables adaptive and limited charging.
 
   Setting the policy to 2 - Adaptive, the device learns your charging habits and delays charging to 100% until necessary. This helps prolong battery health.
 
   Setting the policy to 3 - Limited, the battery charges only to around 80% to maximize its lifespan.
 
-  This policy overrides <ph name="DEVICE_POWER_ADAPTIVE_CHARGING_ENABLED_POLICY_NAME">DevicePowerAdaptiveChargingEnabled</ph>.
+  If the <ph name="DEVICE_POWER_BATTERY_CHARGING_OPTIMIZATION_POLICY_NAME">DevicePowerBatteryChargingOptimization</ph> policy is set, it takes precedence over the <ph name="DEVICE_POWER_ADAPTIVE_CHARGING_ENABLED_POLICY_NAME">DevicePowerAdaptiveChargingEnabled</ph> policy.
 
-  The <ph name="DEVICE_POWER_BATTERY_CHARGING_OPTIMIZATION_POLICY_NAME">DevicePowerBatteryChargingOptimization</ph> and <ph name="DEVICE_POWER_ADAPTIVE_CHARGING_ENABLED_POLICY_NAME">DevicePowerAdaptiveChargingEnabled</ph> polices always take precedence over user settings.
+  If the <ph name="DEVICE_POWER_BATTERY_CHARGING_OPTIMIZATION_POLICY_NAME">DevicePowerBatteryChargingOptimization</ph> policy is not set, then the <ph name="DEVICE_POWER_ADAPTIVE_CHARGING_ENABLED_POLICY_NAME">DevicePowerAdaptiveChargingEnabled</ph> policy controls whether the adaptive charging feature is enabled or disabled.
 
+  <ph name="DEVICE_POWER_ADAPTIVE_CHARGING_ENABLED_POLICY_NAME">DevicePowerAdaptiveChargingEnabled</ph> will be deprecated.
 device_only: true
 example_value: 1
-default: 1
+default: null
 features:
   dynamic_refresh: true
   per_profile: false
diff --git a/components/policy/resources/templates/policy_definitions/SkyVault/LocalUserFilesMigrationDestination.yaml b/components/policy/resources/templates/policy_definitions/SkyVault/LocalUserFilesMigrationDestination.yaml
index 98cc0731..31ba7f8 100644
--- a/components/policy/resources/templates/policy_definitions/SkyVault/LocalUserFilesMigrationDestination.yaml
+++ b/components/policy/resources/templates/policy_definitions/SkyVault/LocalUserFilesMigrationDestination.yaml
@@ -23,7 +23,7 @@
 - caption: Keep local files in read-only mode
   name: "read_only"
   value: "read_only"
-- caption: Delete existing local files  (supported since version 136)
+- caption: Delete existing local files  (supported since version 137)
   name: "delete"
   value: "delete"
 owners:
diff --git a/components/policy/test/data/pref_mapping/DevicePowerBatteryChargingOptimization.json b/components/policy/test/data/pref_mapping/DevicePowerBatteryChargingOptimization.json
index c66edeb..08b2f36 100644
--- a/components/policy/test/data/pref_mapping/DevicePowerBatteryChargingOptimization.json
+++ b/components/policy/test/data/pref_mapping/DevicePowerBatteryChargingOptimization.json
@@ -44,7 +44,7 @@
         }
       },
       {
-        "note":"Check when DevicePowerBatteryChargingOptimization is unset, DevicePowerAdaptiveChargingEnabled can still set adaptive charging",
+        "note":"Check that DevicePowerBatteryChargingOptimization sets the preference correctly (Standard).",
         "policies": {
           "DevicePowerBatteryChargingOptimization": 1
         },
diff --git a/components/policy/test/data/pref_mapping/MutationEventsEnabled.json b/components/policy/test/data/pref_mapping/MutationEventsEnabled.json
index b196b7e..667ff76 100644
--- a/components/policy/test/data/pref_mapping/MutationEventsEnabled.json
+++ b/components/policy/test/data/pref_mapping/MutationEventsEnabled.json
@@ -1,42 +1,5 @@
 [
   {
-    "os": [
-      "win",
-      "linux",
-      "mac",
-      "chromeos",
-      "android",
-      "fuchsia"
-    ],
-    "policy_pref_mapping_tests": [
-      {
-        "policies": {
-          "MutationEventsEnabled": true
-        },
-        "prefs": {
-          "policy.deprecated_mutation_events_enabled": {
-            "value": true
-          }
-        }
-      },
-      {
-        "policies": {
-          "MutationEventsEnabled": false
-        },
-        "prefs": {
-          "policy.deprecated_mutation_events_enabled": {
-            "value": false
-          }
-        }
-      },
-      {
-        "policies": {},
-        "prefs": {
-          "policy.deprecated_mutation_events_enabled": {
-            "default_value": false
-          }
-        }
-      }
-    ]
+    "reason_for_missing_test": "Deprecated"
   }
 ]
diff --git a/components/saved_tab_groups/public/features.cc b/components/saved_tab_groups/public/features.cc
index 4eb9f92..c5a60408 100644
--- a/components/saved_tab_groups/public/features.cc
+++ b/components/saved_tab_groups/public/features.cc
@@ -26,11 +26,6 @@
              "TabGroupSyncAndroid",
              base::FEATURE_ENABLED_BY_DEFAULT);
 
-// Feature flag used to enable tab group revisit surface.
-BASE_FEATURE(kTabGroupPaneAndroid,
-             "TabGroupPaneAndroid",
-             base::FEATURE_ENABLED_BY_DEFAULT);
-
 // Feature flag used to determine whether the network layer is disabled for
 // tab group sync.
 BASE_FEATURE(kTabGroupSyncDisableNetworkLayer,
diff --git a/components/saved_tab_groups/public/features.h b/components/saved_tab_groups/public/features.h
index 93d7307..a16d239 100644
--- a/components/saved_tab_groups/public/features.h
+++ b/components/saved_tab_groups/public/features.h
@@ -12,8 +12,6 @@
 
 BASE_DECLARE_FEATURE(kTabGroupSyncAndroid);
 
-BASE_DECLARE_FEATURE(kTabGroupPaneAndroid);
-
 BASE_DECLARE_FEATURE(kTabGroupSyncDisableNetworkLayer);
 
 BASE_DECLARE_FEATURE(kTabGroupsSaveV2);
diff --git a/components/security_interstitials/content/captive_portal_blocking_page.cc b/components/security_interstitials/content/captive_portal_blocking_page.cc
index ec06ed05..061da0f4 100644
--- a/components/security_interstitials/content/captive_portal_blocking_page.cc
+++ b/components/security_interstitials/content/captive_portal_blocking_page.cc
@@ -181,8 +181,6 @@
   load_time_data.Set("closeDetails", "");
   load_time_data.Set("explanationParagraph", "");
   load_time_data.Set("finalParagraph", "");
-  load_time_data.Set("recurrentErrorParagraph", "");
-  load_time_data.Set("show_recurrent_error_paragraph", false);
   load_time_data.Set(security_interstitials::kDisplayCheckBox, false);
 
   PopulateEnhancedProtectionMessage(load_time_data);
diff --git a/components/security_interstitials/content/insecure_form_blocking_page.cc b/components/security_interstitials/content/insecure_form_blocking_page.cc
index e03243e..2de4068 100644
--- a/components/security_interstitials/content/insecure_form_blocking_page.cc
+++ b/components/security_interstitials/content/insecure_form_blocking_page.cc
@@ -105,8 +105,6 @@
   load_time_data.Set("type", "INSECURE_FORM");
   load_time_data.Set("overridable", false);
   load_time_data.Set("hide_primary_button", false);
-  load_time_data.Set("show_recurrent_error_paragraph", false);
-  load_time_data.Set("recurrentErrorParagraph", "");
   load_time_data.Set("openDetails", "");
   load_time_data.Set("explanationParagraph", "");
   load_time_data.Set("finalParagraph", "");
diff --git a/components/security_interstitials/core/browser/resources/interstitial_large.html b/components/security_interstitials/core/browser/resources/interstitial_large.html
index 86f5a3d3..c46649fe 100644
--- a/components/security_interstitials/core/browser/resources/interstitial_large.html
+++ b/components/security_interstitials/core/browser/resources/interstitial_large.html
@@ -42,9 +42,6 @@
           <div id="error-debugging-info" class="hidden"></div>
         </div>
       </div>
-      <div id="recurrent-error-message">
-        $i18nRaw{recurrentErrorParagraph}
-      </div>
       <div id="blocked-site-message" class="hidden">
         <p id="blocked-site-message-header"></p>
         <p id="blocked-site-message-reason"></p>
diff --git a/components/security_interstitials/core/browser/resources/interstitial_large_without_promo.html b/components/security_interstitials/core/browser/resources/interstitial_large_without_promo.html
index 37cb263..d959254b 100644
--- a/components/security_interstitials/core/browser/resources/interstitial_large_without_promo.html
+++ b/components/security_interstitials/core/browser/resources/interstitial_large_without_promo.html
@@ -40,9 +40,6 @@
           <div id="error-debugging-info" class="hidden"></div>
         </div>
       </div>
-      <div id="recurrent-error-message">
-        $i18nRaw{recurrentErrorParagraph}
-      </div>
       <div id="extended-reporting-opt-in" class="hidden">
         <label>
           <div class="checkboxes">
diff --git a/components/security_interstitials/core/common/resources/interstitial_common.css b/components/security_interstitials/core/common/resources/interstitial_common.css
index 035a097..5a92670 100644
--- a/components/security_interstitials/core/common/resources/interstitial_common.css
+++ b/components/security_interstitials/core/common/resources/interstitial_common.css
@@ -237,22 +237,6 @@
   opacity: 1;
 }
 
-#recurrent-error-message {
-  background: #ededed;
-  border-radius: 4px;
-  margin-bottom: 16px;
-  margin-top: 12px;
-  padding: 12px 16px;
-}
-
-.showing-recurrent-error-message #extended-reporting-opt-in {
-  margin-top: 16px;
-}
-
-.showing-recurrent-error-message #enhanced-protection-message {
-  margin-top: 16px;
-}
-
 @media (max-width: 700px) {
   .interstitial-wrapper {
     padding: 0 10%;
diff --git a/components/security_interstitials/core/common_string_util.cc b/components/security_interstitials/core/common_string_util.cc
index fd24041..abd20d7b 100644
--- a/components/security_interstitials/core/common_string_util.cc
+++ b/components/security_interstitials/core/common_string_util.cc
@@ -31,10 +31,6 @@
                      l10n_util::GetStringUTF16(IDS_SSL_OPEN_DETAILS_BUTTON));
   load_time_data.Set("closeDetails",
                      l10n_util::GetStringUTF16(IDS_SSL_CLOSE_DETAILS_BUTTON));
-  // Not used by most interstitials; can be overridden by individual
-  // interstitials as needed.
-  load_time_data.Set("recurrentErrorParagraph", "");
-  load_time_data.Set("show_recurrent_error_paragraph", false);
   load_time_data.Set("optInLink", l10n_util::GetStringUTF16(
                                       IDS_SAFE_BROWSING_SCOUT_REPORTING_AGREE));
   load_time_data.Set(
diff --git a/components/security_interstitials/core/https_only_mode_ui_util.cc b/components/security_interstitials/core/https_only_mode_ui_util.cc
index b9af9853..68b7b007 100644
--- a/components/security_interstitials/core/https_only_mode_ui_util.cc
+++ b/components/security_interstitials/core/https_only_mode_ui_util.cc
@@ -79,8 +79,6 @@
   load_time_data.Set("type", "HTTPS_ONLY");
   load_time_data.Set("overridable", false);
   load_time_data.Set("hide_primary_button", false);
-  load_time_data.Set("show_recurrent_error_paragraph", false);
-  load_time_data.Set("recurrentErrorParagraph", "");
   load_time_data.Set("openDetails", "");
   load_time_data.Set("explanationParagraph", "");
   load_time_data.Set("finalParagraph", "");
diff --git a/components/security_interstitials/core/safe_browsing_loud_error_ui.cc b/components/security_interstitials/core/safe_browsing_loud_error_ui.cc
index df1eeb67..0107766c 100644
--- a/components/security_interstitials/core/safe_browsing_loud_error_ui.cc
+++ b/components/security_interstitials/core/safe_browsing_loud_error_ui.cc
@@ -120,10 +120,6 @@
       break;
   }
 
-  // Not used by this interstitial.
-  load_time_data.Set("recurrentErrorParagraph", "");
-  load_time_data.Set("show_recurrent_error_paragraph", false);
-
   PopulateExtendedReportingOption(load_time_data);
   PopulateEnhancedProtectionMessage(load_time_data);
 }
diff --git a/components/security_interstitials/core/safe_browsing_quiet_error_ui.cc b/components/security_interstitials/core/safe_browsing_quiet_error_ui.cc
index 82a7a3d..bdc86b5 100644
--- a/components/security_interstitials/core/safe_browsing_quiet_error_ui.cc
+++ b/components/security_interstitials/core/safe_browsing_quiet_error_ui.cc
@@ -71,10 +71,6 @@
       PopulateBillingLoadTimeData(load_time_data);
       break;
   }
-
-  // Not used by this interstitial.
-  load_time_data.Set("recurrentErrorParagraph", "");
-  load_time_data.Set("show_recurrent_error_paragraph", false);
 }
 
 void SafeBrowsingQuietErrorUI::SetGiantWebViewForTesting(
diff --git a/components/signin/core/browser/signin_metrics_service.cc b/components/signin/core/browser/signin_metrics_service.cc
index 2dd5349..b07e48a 100644
--- a/components/signin/core/browser/signin_metrics_service.cc
+++ b/components/signin/core/browser/signin_metrics_service.cc
@@ -183,6 +183,7 @@
     case signin_metrics::AccessPoint::kGlicLaunchButton:
     case signin_metrics::AccessPoint::kHistoryPage:
     case signin_metrics::AccessPoint::kCollaborationJoinTabGroup:
+    case signin_metrics::AccessPoint::kHistorySyncOptinExpansionPill:
       return;
   }
 
diff --git a/components/signin/public/base/signin_metrics.cc b/components/signin/public/base/signin_metrics.cc
index d9159c2..ef6e1ac0 100644
--- a/components/signin/public/base/signin_metrics.cc
+++ b/components/signin/public/base/signin_metrics.cc
@@ -463,6 +463,7 @@
     case AccessPoint::kCctAccountMismatchNotification:
     case AccessPoint::kDriveFilePickerIos:
     case AccessPoint::kHistoryPage:
+    case AccessPoint::kHistorySyncOptinExpansionPill:
       NOTREACHED() << "Access point " << static_cast<int>(access_point)
                    << " is not supposed to log signin user actions.";
     case AccessPoint::kCollaborationShareTabGroup:
@@ -746,6 +747,7 @@
     case AccessPoint::kGlicLaunchButton:
     case AccessPoint::kHistoryPage:
     case AccessPoint::kCollaborationJoinTabGroup:
+    case AccessPoint::kHistorySyncOptinExpansionPill:
       NOTREACHED() << "Signin_Impression_From* user actions are not recorded "
                       "for access point "
                    << static_cast<int>(access_point);
diff --git a/components/signin/public/base/signin_metrics.h b/components/signin/public/base/signin_metrics.h
index b5c524c..f43b0cd 100644
--- a/components/signin/public/base/signin_metrics.h
+++ b/components/signin/public/base/signin_metrics.h
@@ -261,10 +261,13 @@
   // Access point triggered when a user attempts to join a tab group without
   // being signed in or synced.
   kCollaborationJoinTabGroup = 76,
+  // Access point triggered when a user attempts to opt-in to history sync from
+  // the history sync opt-in expanded pill.
+  kHistorySyncOptinExpansionPill = 77,
   // Add values above this line with a corresponding label to the
   // "SigninAccessPoint" enum in
   // tools/metrics/histograms/metadata/signin/enums.xml.
-  kMaxValue = kCollaborationJoinTabGroup,  // This must be last.
+  kMaxValue = kHistorySyncOptinExpansionPill,  // This must be last.
 };
 // LINT.ThenChange(/tools/metrics/histograms/metadata/signin/enums.xml)
 
diff --git a/components/signin/public/base/signin_metrics_unittest.cc b/components/signin/public/base/signin_metrics_unittest.cc
index 60b856d1..4f07e9ca 100644
--- a/components/signin/public/base/signin_metrics_unittest.cc
+++ b/components/signin/public/base/signin_metrics_unittest.cc
@@ -223,6 +223,8 @@
         return "HistoryPage";
       case AccessPoint::kCollaborationJoinTabGroup:
         return "CollaborationJoinTabGroup";
+      case AccessPoint::kHistorySyncOptinExpansionPill:
+        return "HistorySyncOptinExpansionPill";
     }
   }
 };
diff --git a/components/signin/public/base/signin_switches.cc b/components/signin/public/base/signin_switches.cc
index 1046e01..8fd055b1 100644
--- a/components/signin/public/base/signin_switches.cc
+++ b/components/signin/public/base/signin_switches.cc
@@ -15,7 +15,7 @@
 #if BUILDFLAG(IS_ANDROID)
 BASE_FEATURE(kCctSignInPrompt,
              "CctSignInPrompt",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+             base::FEATURE_ENABLED_BY_DEFAULT);
 
 // Migrate usages of USM flag to force child account sign-in to use the account
 // capability `IsSubjectToParentalControls`.
diff --git a/components/sync/protocol/autofill_valuable_specifics.proto b/components/sync/protocol/autofill_valuable_specifics.proto
index 0628dc2..4a7e591 100644
--- a/components/sync/protocol/autofill_valuable_specifics.proto
+++ b/components/sync/protocol/autofill_valuable_specifics.proto
@@ -31,6 +31,9 @@
 
     // The loyalty card text code.
     optional string loyalty_card_number = 4;
+
+    // Merchant domains associated to the loyalty card.
+    repeated string merchant_domains = 5;
   }
 
   oneof valuable_data {
diff --git a/components/test/data/update_client/zucchini_patch_test/README.md b/components/test/data/update_client/zucchini_patch_test/README.md
new file mode 100644
index 0000000..05b1a20
--- /dev/null
+++ b/components/test/data/update_client/zucchini_patch_test/README.md
@@ -0,0 +1,19 @@
+This directory contains test files for zucchini patching.
+
+The zip files can be regenerated using the following commands:
+
+```
+rm app1.zip; rm app2.zip; mkdir tmp; cd tmp;
+cp ../../puffin_patch_test/puffin_app_v1.crx3 tmp.crx3; unzip tmp.crx3;
+rm tmp.crx3; zip -r -0 app1 *; mv app1.zip ..; ls; rm -rf *;
+cp ../../puffin_patch_test/puffin_app_v2.crx3 tmp.crx3; unzip tmp.crx3;
+rm tmp.crx3; zip -r -0 app2 *; mv app2.zip ..; cd ..; rm -rf tmp;
+```
+
+The zucchini files can then be regenerated by building `zucchini` and running:
+```
+out/Default/zucchini -gen \
+  components/test/data/update_client/zucchini_patch_test/app1.zip \
+  components/test/data/update_client/zucchini_patch_test/app2.zip \
+  components/test/data/update_client/zucchini_patch_test/app1_to_app2.zucchini
+```
diff --git a/components/test/data/update_client/zucchini_patch_test/app1.zip b/components/test/data/update_client/zucchini_patch_test/app1.zip
new file mode 100644
index 0000000..49758574
--- /dev/null
+++ b/components/test/data/update_client/zucchini_patch_test/app1.zip
Binary files differ
diff --git a/components/test/data/update_client/zucchini_patch_test/app1_to_app2.zucchini b/components/test/data/update_client/zucchini_patch_test/app1_to_app2.zucchini
new file mode 100644
index 0000000..86aceefb
--- /dev/null
+++ b/components/test/data/update_client/zucchini_patch_test/app1_to_app2.zucchini
Binary files differ
diff --git a/components/test/data/update_client/zucchini_patch_test/app2.zip b/components/test/data/update_client/zucchini_patch_test/app2.zip
new file mode 100644
index 0000000..69740f3
--- /dev/null
+++ b/components/test/data/update_client/zucchini_patch_test/app2.zip
Binary files differ
diff --git a/components/test/data/viz/backdrop_filter_quality_0_33skia_gl.png b/components/test/data/viz/backdrop_filter_quality_0_33skia_gl.png
new file mode 100644
index 0000000..79df3bcc
--- /dev/null
+++ b/components/test/data/viz/backdrop_filter_quality_0_33skia_gl.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
new file mode 100644
index 0000000..ff2914e
--- /dev/null
+++ 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_0_33skia_vk.png b/components/test/data/viz/backdrop_filter_quality_0_33skia_vk.png
new file mode 100644
index 0000000..48460a0
--- /dev/null
+++ b/components/test/data/viz/backdrop_filter_quality_0_33skia_vk.png
Binary files differ
diff --git a/components/test/data/viz/backdrop_filter_quality_0_33sw.png b/components/test/data/viz/backdrop_filter_quality_0_33sw.png
new file mode 100644
index 0000000..55f4408
--- /dev/null
+++ b/components/test/data/viz/backdrop_filter_quality_0_33sw.png
Binary files differ
diff --git a/components/test/data/viz/backdrop_filter_quality_1_0skia_gl.png b/components/test/data/viz/backdrop_filter_quality_1_0skia_gl.png
new file mode 100644
index 0000000..c921d8e6
--- /dev/null
+++ b/components/test/data/viz/backdrop_filter_quality_1_0skia_gl.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
new file mode 100644
index 0000000..c875ed7
--- /dev/null
+++ b/components/test/data/viz/backdrop_filter_quality_1_0skia_graphite.png
Binary files differ
diff --git a/components/test/data/viz/backdrop_filter_quality_1_0skia_vk.png b/components/test/data/viz/backdrop_filter_quality_1_0skia_vk.png
new file mode 100644
index 0000000..3c0fb48
--- /dev/null
+++ b/components/test/data/viz/backdrop_filter_quality_1_0skia_vk.png
Binary files differ
diff --git a/components/test/data/viz/backdrop_filter_quality_1_0sw.png b/components/test/data/viz/backdrop_filter_quality_1_0sw.png
new file mode 100644
index 0000000..55f4408
--- /dev/null
+++ b/components/test/data/viz/backdrop_filter_quality_1_0sw.png
Binary files differ
diff --git a/components/test/data/viz/unit_tests_bundle_data.filelist b/components/test/data/viz/unit_tests_bundle_data.filelist
index a448dcb..fd7d1e8 100644
--- a/components/test/data/viz/unit_tests_bundle_data.filelist
+++ b/components/test/data/viz/unit_tests_bundle_data.filelist
@@ -36,6 +36,14 @@
 //components/test/data/viz/backdrop_filter_on_scaled_layer_skia_graphite.png
 //components/test/data/viz/backdrop_filter_on_scaled_layer_skia_vk.png
 //components/test/data/viz/backdrop_filter_on_scaled_layer_sw.png
+//components/test/data/viz/backdrop_filter_quality_0_33skia_gl.png
+//components/test/data/viz/backdrop_filter_quality_0_33skia_graphite.png
+//components/test/data/viz/backdrop_filter_quality_0_33skia_vk.png
+//components/test/data/viz/backdrop_filter_quality_0_33sw.png
+//components/test/data/viz/backdrop_filter_quality_1_0skia_gl.png
+//components/test/data/viz/backdrop_filter_quality_1_0skia_graphite.png
+//components/test/data/viz/backdrop_filter_quality_1_0skia_vk.png
+//components/test/data/viz/backdrop_filter_quality_1_0sw.png
 //components/test/data/viz/backdrop_filter_rotated_skia_gl.png
 //components/test/data/viz/backdrop_filter_rotated_skia_graphite.png
 //components/test/data/viz/backdrop_filter_rotated_skia_vk.png
diff --git a/components/translate/ios/browser/resources/translate_ios.ts b/components/translate/ios/browser/resources/translate_ios.ts
index 6146457e..c4ea37b 100644
--- a/components/translate/ios/browser/resources/translate_ios.ts
+++ b/components/translate/ios/browser/resources/translate_ios.ts
@@ -8,7 +8,7 @@
  *
  */
 
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 import {sendWebKitMessage} from '//ios/web/public/js_messaging/resources/utils.js';
 
 // The implementation of the cr module is located in
@@ -60,7 +60,7 @@
 }
 
 // Mark: Public API
-gCrWeb.translate = {
+gCrWebLegacy.translate = {
   installCallbacks,
   startTranslation,
   revertTranslation,
diff --git a/components/update_client/BUILD.gn b/components/update_client/BUILD.gn
index 8cd2e61..b9a84942 100644
--- a/components/update_client/BUILD.gn
+++ b/components/update_client/BUILD.gn
@@ -42,6 +42,8 @@
   deps = [
     ":update_client",
     "//base",
+    "//components/zucchini:zucchini_io",
+    "//components/zucchini:zucchini_lib",
     "//third_party/puffin:libpuffpatch",
   ]
   include_dirs = [ "//third_party/puffin/src/include" ]
@@ -67,6 +69,7 @@
     ":update_client",
     "//components/services/patch/public/cpp",
     "//components/services/patch/public/mojom",
+    "//components/zucchini:zucchini_lib",
     "//mojo/public/cpp/bindings",
   ]
 }
@@ -107,6 +110,8 @@
     "op_install.h",
     "op_puffin.cc",
     "op_puffin.h",
+    "op_zucchini.cc",
+    "op_zucchini.h",
     "patcher.h",
     "persisted_data.cc",
     "persisted_data.h",
@@ -167,6 +172,7 @@
     "//components/crx_file",
     "//components/prefs",
     "//components/version_info",
+    "//components/zucchini:zucchini_lib",
     "//crypto",
     "//third_party/zlib/google:compression_utils",
     "//url",
@@ -270,6 +276,9 @@
     "//components/test/data/update_client/updatecheck_reply_noupdate.json",
     "//components/test/data/update_client/updatecheck_reply_parse_error.json",
     "//components/test/data/update_client/updatecheck_reply_unknownapp.json",
+    "//components/test/data/update_client/zucchini_patch_test/app1.zip",
+    "//components/test/data/update_client/zucchini_patch_test/app1_to_app2.zucchini",
+    "//components/test/data/update_client/zucchini_patch_test/app2.zip",
   ]
   outputs = [ "{{bundle_resources_dir}}/" +
               "{{source_root_relative_dir}}/{{source_file_part}}" ]
@@ -291,6 +300,7 @@
     "crx_cache_unittest.cc",
     "op_download_unittest.cc",
     "op_puffin_unittest.cc",
+    "op_zucchini_unittest.cc",
     "persisted_data_unittest.cc",
     "ping_manager_unittest.cc",
     "protocol_parser_json_unittest.cc",
diff --git a/components/update_client/DEPS b/components/update_client/DEPS
index 76807cc..e1d8f84 100644
--- a/components/update_client/DEPS
+++ b/components/update_client/DEPS
@@ -5,6 +5,7 @@
   "+components/prefs",
   "+components/services/unzip",
   "+components/version_info",
+  "+components/zucchini",
   "+crypto",
   "+mojo/public",
   "+third_party/puffin",
diff --git a/components/update_client/op_zucchini.cc b/components/update_client/op_zucchini.cc
new file mode 100644
index 0000000..38c615fe
--- /dev/null
+++ b/components/update_client/op_zucchini.cc
@@ -0,0 +1,167 @@
+// 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/update_client/op_zucchini.h"
+
+#include <string>
+#include <utility>
+
+#include "base/files/file.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/functional/bind.h"
+#include "base/functional/callback.h"
+#include "base/functional/callback_helpers.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/task/bind_post_task.h"
+#include "base/task/sequenced_task_runner.h"
+#include "base/task/thread_pool.h"
+#include "base/types/expected.h"
+#include "base/values.h"
+#include "components/update_client/configurator.h"
+#include "components/update_client/crx_cache.h"
+#include "components/update_client/patcher.h"
+#include "components/update_client/protocol_definition.h"
+#include "components/update_client/task_traits.h"
+#include "components/update_client/update_client_errors.h"
+#include "components/zucchini/zucchini.h"
+
+namespace update_client {
+
+namespace {
+
+// The sequence of calls is:
+//
+// [Original Sequence]    [Blocking Pool]
+//
+// ZucchiniOperation
+// CacheLookupDone
+//                        Patch
+//                        Cleanup
+// PatchDone
+// [original callback]
+//
+// All errors shortcut to PatchDone.
+
+base::Value::Dict MakeEvent(
+    base::expected<base::FilePath, CategorizedError> result) {
+  base::Value::Dict event;
+  event.Set("eventtype", protocol_request::kEventZucchini);
+  event.Set("eventresult",
+            static_cast<int>(result.has_value()
+                                 ? protocol_request::kEventResultSuccess
+                                 : protocol_request::kEventResultError));
+
+  if (!result.has_value()) {
+    CategorizedError error = result.error();
+    if (error.category_ != ErrorCategory::kNone) {
+      event.Set("errorcat", static_cast<int>(error.category_));
+    }
+    if (error.code_ != 0) {
+      event.Set("errorcode", error.code_);
+    }
+    if (error.extra_ != 0) {
+      event.Set("extracode1", error.extra_);
+    }
+  }
+  return event;
+}
+
+// Runs on the original sequence. Adds events and calls the original callback.
+void PatchDone(
+    base::OnceCallback<void(base::expected<base::FilePath, CategorizedError>)>
+        callback,
+    base::RepeatingCallback<void(base::Value::Dict)> event_adder,
+    base::expected<base::FilePath, CategorizedError> result) {
+  event_adder.Run(MakeEvent(result));
+  base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
+      FROM_HERE, base::BindOnce(std::move(callback), result));
+}
+
+// Runs in the blocking pool. Deletes any files that are no longer needed.
+void CleanUp(
+    base::OnceCallback<void(base::expected<base::FilePath, CategorizedError>)>
+        callback,
+    const base::FilePath& patch_file,
+    const base::FilePath& new_file,
+    int result) {
+  base::DeleteFile(patch_file);
+  if (result) {
+    base::DeleteFile(new_file);
+    std::move(callback).Run(base::unexpected<CategorizedError>(
+        {.category_ = ErrorCategory::kUnpack,
+         .code_ = static_cast<int>(UnpackerError::kDeltaOperationFailure),
+         .extra_ = result}));
+    return;
+  }
+  std::move(callback).Run(new_file);
+}
+
+// Runs in the blocking pool. Opens file handles and applies the patch.
+void Patch(
+    scoped_refptr<Patcher> patcher,
+    const base::FilePath& old_file,
+    const base::FilePath& patch_file,
+    const base::FilePath& temp_dir,
+    base::OnceCallback<void(base::expected<base::FilePath, CategorizedError>)>
+        callback) {
+  base::FilePath new_file = temp_dir.Append(FILE_PATH_LITERAL("puffpatch_out"));
+  patcher->PatchZucchini(
+      base::File(old_file, base::File::FLAG_OPEN | base::File::FLAG_READ),
+      base::File(patch_file, base::File::FLAG_OPEN | base::File::FLAG_READ),
+      base::File(new_file, base::File::FLAG_CREATE | base::File::FLAG_READ |
+                               base::File::FLAG_WRITE |
+                               base::File::FLAG_WIN_EXCLUSIVE_WRITE |
+                               base::File::FLAG_WIN_SHARE_DELETE |
+                               base::File::FLAG_CAN_DELETE_ON_CLOSE),
+      base::BindOnce(&CleanUp, std::move(callback), patch_file, new_file));
+}
+
+// Runs on the original sequence.
+void CacheLookupDone(
+    scoped_refptr<Patcher> patcher,
+    const base::FilePath& patch_file,
+    const base::FilePath& temp_dir,
+    base::OnceCallback<void(base::expected<base::FilePath, CategorizedError>)>
+        callback,
+    base::expected<base::FilePath, UnpackerError> cache_result) {
+  if (!cache_result.has_value()) {
+    base::ThreadPool::PostTaskAndReply(
+        FROM_HERE, kTaskTraits,
+        base::BindOnce(IgnoreResult(&base::DeleteFile), patch_file),
+        base::BindOnce(std::move(callback),
+                       base::unexpected<CategorizedError>(
+                           {.category_ = ErrorCategory::kUnpack,
+                            .code_ = static_cast<int>(cache_result.error())})));
+    return;
+  }
+  base::ThreadPool::CreateSequencedTaskRunner(kTaskTraits)
+      ->PostTask(FROM_HERE,
+                 base::BindOnce(&Patch, patcher, cache_result.value(),
+                                patch_file, temp_dir, std::move(callback)));
+}
+
+}  // namespace
+
+base::OnceClosure ZucchiniOperation(
+    scoped_refptr<CrxCache> crx_cache,
+    scoped_refptr<Patcher> patcher,
+    base::RepeatingCallback<void(base::Value::Dict)> event_adder,
+    const std::string& id,
+    const std::string& prev_hash,
+    const base::FilePath& patch_file,
+    base::OnceCallback<void(base::expected<base::FilePath, CategorizedError>)>
+        callback) {
+  crx_cache->GetByHash(
+      prev_hash,
+      base::BindOnce(&CacheLookupDone, patcher, patch_file,
+                     patch_file.DirName(),
+                     base::BindPostTaskToCurrentDefault(base::BindOnce(
+                         &PatchDone, std::move(callback), event_adder))));
+  return base::DoNothing();
+}
+
+}  // namespace update_client
diff --git a/components/update_client/op_zucchini.h b/components/update_client/op_zucchini.h
new file mode 100644
index 0000000..0104089d
--- /dev/null
+++ b/components/update_client/op_zucchini.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 COMPONENTS_UPDATE_CLIENT_OP_ZUCCHINI_H_
+#define COMPONENTS_UPDATE_CLIENT_OP_ZUCCHINI_H_
+
+#include <string>
+
+#include "base/functional/callback_forward.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/types/expected.h"
+#include "base/values.h"
+#include "components/update_client/crx_cache.h"
+#include "components/update_client/patcher.h"
+
+namespace base {
+class FilePath;
+}
+
+namespace update_client {
+
+struct CategorizedError;
+
+// Apply a zucchini patch. `callback` is posted to the sequence
+// ZucchiniOperation was called on, with a file path containing the result of
+// the patch, if successful. If unsuccessful, `callback` is posted with an
+// error. In either case, `patch_file` is deleted. Returns a cancellation
+// callback.
+base::OnceClosure ZucchiniOperation(
+    scoped_refptr<CrxCache> crx_cache,
+    scoped_refptr<Patcher> patcher,
+    base::RepeatingCallback<void(base::Value::Dict)> event_adder,
+    const std::string& id,
+    const std::string& prev_hash,
+    const base::FilePath& patch_file,
+    base::OnceCallback<void(base::expected<base::FilePath, CategorizedError>)>
+        callback);
+
+}  // namespace update_client
+
+#endif  // COMPONENTS_UPDATE_CLIENT_OP_ZUCCHINI_H_
diff --git a/components/update_client/op_zucchini_unittest.cc b/components/update_client/op_zucchini_unittest.cc
new file mode 100644
index 0000000..e23b779
--- /dev/null
+++ b/components/update_client/op_zucchini_unittest.cc
@@ -0,0 +1,206 @@
+// 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/update_client/op_zucchini.h"
+
+#include <optional>
+#include <string>
+#include <vector>
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/functional/bind.h"
+#include "base/functional/callback_helpers.h"
+#include "base/memory/ref_counted.h"
+#include "base/run_loop.h"
+#include "base/sequence_checker.h"
+#include "base/test/bind.h"
+#include "base/test/task_environment.h"
+#include "base/types/expected.h"
+#include "base/values.h"
+#include "components/services/patch/in_process_file_patcher.h"
+#include "components/update_client/crx_cache.h"
+#include "components/update_client/patch/patch_impl.h"
+#include "components/update_client/test_utils.h"
+#include "components/update_client/update_client_errors.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace update_client {
+
+class ZucchiniOperationTest : public testing::Test {
+ private:
+  // env_ must be constructed before sequence_checker_.
+  base::test::TaskEnvironment env_;
+
+ protected:
+  void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); }
+
+  base::FilePath TempPath(const std::string& basename) {
+    return temp_dir_.GetPath().AppendUTF8(basename);
+  }
+
+  base::FilePath CopyToTemp(const std::string& src) {
+    base::FilePath dest =
+        TempPath(base::FilePath().AppendUTF8(src).BaseName().AsUTF8Unsafe());
+    EXPECT_TRUE(base::CopyFile(GetTestFilePath(src.c_str()), dest));
+    return dest;
+  }
+
+  base::RepeatingCallback<void(base::Value::Dict)> MakePingCallback() {
+    return base::BindLambdaForTesting(
+        [&](base::Value::Dict ping) { pings_.push_back(std::move(ping)); });
+  }
+
+  SEQUENCE_CHECKER(sequence_checker_);
+  base::RunLoop loop_;
+  std::vector<base::Value::Dict> pings_;
+
+ private:
+  base::ScopedTempDir temp_dir_;
+};
+
+TEST_F(ZucchiniOperationTest, Success) {
+  auto cache = base::MakeRefCounted<CrxCache>(TempPath("cache"));
+
+  // `ZucchiniOperation` deletes the patch file, so copy it to the temp dir.
+  base::FilePath patch_file =
+      CopyToTemp("zucchini_patch_test/app1_to_app2.zucchini");
+
+  // `CrxCache::Put` will move the v1 file, so copy it into the temp dir.
+  base::FilePath old_file = CopyToTemp("zucchini_patch_test/app1.zip");
+
+  cache->Put(
+      old_file, "appid", "hash1", "prev_hash",
+      base::BindLambdaForTesting([&](base::expected<base::FilePath,
+                                                    UnpackerError> r) {
+        ASSERT_TRUE(r.has_value());
+        ZucchiniOperation(
+            cache,
+            base::MakeRefCounted<PatchChromiumFactory>(
+                base::BindRepeating(&patch::LaunchInProcessFilePatcher))
+                ->Create(),
+            MakePingCallback(), "appid", "hash1", patch_file,
+            base::BindLambdaForTesting(
+                [&](base::expected<base::FilePath, CategorizedError> result) {
+                  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+                  loop_.Quit();
+                  ASSERT_TRUE(result.has_value());
+                  EXPECT_TRUE(base::ContentsEqual(
+                      GetTestFilePath("zucchini_patch_test/app2.zip"),
+                      result.value()));
+                }));
+      }));
+  loop_.Run();
+  EXPECT_FALSE(base::PathExists(patch_file));
+  ASSERT_EQ(pings_.size(), 1u);
+  EXPECT_EQ(pings_[0].FindInt("eventtype"), 61);
+  EXPECT_EQ(pings_[0].FindInt("eventresult"), 1);
+  EXPECT_EQ(pings_[0].Find("errorcat"), nullptr);
+  EXPECT_EQ(pings_[0].Find("errorcode"), nullptr);
+  EXPECT_EQ(pings_[0].Find("extracode1"), nullptr);
+}
+
+TEST_F(ZucchiniOperationTest, BadPatch) {
+  auto cache = base::MakeRefCounted<CrxCache>(TempPath("cache"));
+
+  // ZucchiniOperation deletes the patch file, so copy it to the temp dir. For
+  // this test, use an malformed patch file - a copy of app2.zip is good
+  // enough.
+  base::FilePath patch_file = CopyToTemp("zucchini_patch_test/app2.zip");
+
+  // CrxCache::Put will move the v1 file, so copy it into the temp dir.
+  base::FilePath old_file = CopyToTemp("zucchini_patch_test/app1.zip");
+
+  cache->Put(
+      old_file, "appid", "hash1", "prev_hash",
+      base::BindLambdaForTesting([&](base::expected<base::FilePath,
+                                                    UnpackerError> r) {
+        ASSERT_TRUE(r.has_value());
+        ZucchiniOperation(
+            cache,
+            base::MakeRefCounted<PatchChromiumFactory>(
+                base::BindRepeating(&patch::LaunchInProcessFilePatcher))
+                ->Create(),
+            MakePingCallback(), "appid", "hash1", patch_file,
+            base::BindLambdaForTesting(
+                [&](base::expected<base::FilePath, CategorizedError> result) {
+                  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+                  loop_.Quit();
+                  ASSERT_FALSE(result.has_value());
+                  EXPECT_EQ(
+                      result.error().code_,
+                      static_cast<int>(UnpackerError::kDeltaOperationFailure));
+                }));
+      }));
+  loop_.Run();
+  EXPECT_FALSE(base::PathExists(patch_file));
+  ASSERT_EQ(pings_.size(), 1u);
+  EXPECT_EQ(pings_[0].FindInt("eventtype"), 61);
+  EXPECT_EQ(pings_[0].FindInt("eventresult"), 0);
+  EXPECT_EQ(pings_[0].FindInt("errorcat"), 2);
+  EXPECT_EQ(pings_[0].FindInt("errorcode"), 14);
+  EXPECT_EQ(pings_[0].FindInt("extracode1"), 4);
+}
+
+TEST_F(ZucchiniOperationTest, NotInCache) {
+  auto cache = base::MakeRefCounted<CrxCache>(TempPath("cache"));
+
+  // ZucchiniOperation deletes the patch file, so copy it to the temp dir.
+  base::FilePath patch_file =
+      CopyToTemp("zucchini_patch_test/app1_to_app2.zucchini");
+
+  ZucchiniOperation(
+      cache,
+      base::MakeRefCounted<PatchChromiumFactory>(
+          base::BindRepeating(&patch::LaunchInProcessFilePatcher))
+          ->Create(),
+      MakePingCallback(), "appid", "prev_hash", patch_file,
+      base::BindLambdaForTesting(
+          [&](base::expected<base::FilePath, CategorizedError> result) {
+            DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+            loop_.Quit();
+            ASSERT_FALSE(result.has_value());
+            EXPECT_EQ(result.error().code_,
+                      static_cast<int>(UnpackerError::kCrxCacheFileNotCached));
+          }));
+  loop_.Run();
+  EXPECT_FALSE(base::PathExists(patch_file));
+  ASSERT_EQ(pings_.size(), 1u);
+  EXPECT_EQ(pings_[0].FindInt("eventtype"), 61);
+  EXPECT_EQ(pings_[0].FindInt("eventresult"), 0);
+  EXPECT_EQ(pings_[0].FindInt("errorcat"), 2);
+  EXPECT_EQ(pings_[0].FindInt("errorcode"), 23);
+  EXPECT_EQ(pings_[0].Find("extracode1"), nullptr);
+}
+
+TEST_F(ZucchiniOperationTest, NoCache) {
+  // ZucchiniOperation deletes the patch file, so copy it to the temp dir.
+  base::FilePath patch_file =
+      CopyToTemp("zucchini_patch_test/app1_to_app2.zucchini");
+
+  ZucchiniOperation(
+      base::MakeRefCounted<CrxCache>(std::nullopt),
+      base::MakeRefCounted<PatchChromiumFactory>(
+          base::BindRepeating(&patch::LaunchInProcessFilePatcher))
+          ->Create(),
+      MakePingCallback(), "appid", "prev_hash", patch_file,
+      base::BindLambdaForTesting(
+          [&](base::expected<base::FilePath, CategorizedError> result) {
+            DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+            loop_.Quit();
+            ASSERT_FALSE(result.has_value());
+            EXPECT_EQ(result.error().code_,
+                      static_cast<int>(UnpackerError::kCrxCacheNotProvided));
+          }));
+  loop_.Run();
+  EXPECT_FALSE(base::PathExists(patch_file));
+  ASSERT_EQ(pings_.size(), 1u);
+  EXPECT_EQ(pings_[0].FindInt("eventtype"), 61);
+  EXPECT_EQ(pings_[0].FindInt("eventresult"), 0);
+  EXPECT_EQ(pings_[0].FindInt("errorcat"), 2);
+  EXPECT_EQ(pings_[0].FindInt("errorcode"), 21);
+}
+
+}  // namespace update_client
diff --git a/components/update_client/patch/in_process_patcher.cc b/components/update_client/patch/in_process_patcher.cc
index a0d89788..4c90c6b9 100644
--- a/components/update_client/patch/in_process_patcher.cc
+++ b/components/update_client/patch/in_process_patcher.cc
@@ -9,6 +9,8 @@
 #include "base/files/file.h"
 #include "base/functional/callback.h"
 #include "base/memory/scoped_refptr.h"
+#include "components/zucchini/zucchini.h"
+#include "components/zucchini/zucchini_integration.h"
 #include "third_party/puffin/src/include/puffin/puffpatch.h"
 
 namespace update_client {
@@ -27,6 +29,15 @@
         std::move(input_file), std::move(patch_file), std::move(output_file)));
   }
 
+  void PatchZucchini(base::File old_file,
+                     base::File patch_file,
+                     base::File destination_file,
+                     PatchCompleteCallback callback) const override {
+    std::move(callback).Run(static_cast<int>(
+        zucchini::Apply(std::move(old_file), std::move(patch_file),
+                        std::move(destination_file))));
+  }
+
  protected:
   ~InProcessPatcher() override = default;
 };
diff --git a/components/update_client/patch/patch_impl.cc b/components/update_client/patch/patch_impl.cc
index 6ef083a5..9335880 100644
--- a/components/update_client/patch/patch_impl.cc
+++ b/components/update_client/patch/patch_impl.cc
@@ -5,9 +5,12 @@
 #include "components/update_client/patch/patch_impl.h"
 
 #include "base/files/file_path.h"
+#include "base/functional/bind.h"
 #include "base/functional/callback.h"
-#include "base/notreached.h"
+#include "base/task/sequenced_task_runner.h"
 #include "components/services/patch/public/cpp/patch.h"
+#include "components/update_client/update_client_errors.h"
+#include "components/zucchini/zucchini.h"
 
 namespace update_client {
 
@@ -27,6 +30,39 @@
                      std::move(callback));
   }
 
+  void PatchZucchini(base::File old_file,
+                     base::File patch_file,
+                     base::File destination_file,
+                     PatchCompleteCallback callback) const override {
+    if (!old_file.IsValid()) {
+      base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
+          FROM_HERE, base::BindOnce(std::move(callback),
+                                    static_cast<int>(
+                                        UnpackerError::kPatchInvalidOldFile)));
+      return;
+    }
+    if (!patch_file.IsValid()) {
+      base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
+          FROM_HERE,
+          base::BindOnce(
+              std::move(callback),
+              static_cast<int>(UnpackerError::kPatchInvalidPatchFile)));
+      return;
+    }
+    if (!destination_file.IsValid()) {
+      base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
+          FROM_HERE, base::BindOnce(std::move(callback),
+                                    static_cast<int>(
+                                        UnpackerError::kPatchInvalidNewFile)));
+      return;
+    }
+    patch::ZucchiniPatch(callback_.Run(), std::move(old_file),
+                         std::move(patch_file), std::move(destination_file),
+                         base::BindOnce([](zucchini::status::Code result) {
+                           return static_cast<int>(result);
+                         }).Then(std::move(callback)));
+  }
+
  protected:
   ~PatcherImpl() override = default;
 
diff --git a/components/update_client/patcher.h b/components/update_client/patcher.h
index 1053168d..fe006567 100644
--- a/components/update_client/patcher.h
+++ b/components/update_client/patcher.h
@@ -26,6 +26,11 @@
                               base::File output_file_path,
                               PatchCompleteCallback callback) const = 0;
 
+  virtual void PatchZucchini(base::File input_file_path,
+                             base::File patch_file_path,
+                             base::File output_file_path,
+                             PatchCompleteCallback callback) const = 0;
+
  protected:
   friend class base::RefCountedThreadSafe<Patcher>;
   Patcher() = default;
diff --git a/components/update_client/ping_manager_unittest.cc b/components/update_client/ping_manager_unittest.cc
index 9b1975b..40ba62446 100644
--- a/components/update_client/ping_manager_unittest.cc
+++ b/components/update_client/ping_manager_unittest.cc
@@ -154,7 +154,7 @@
 
     EXPECT_TRUE(request.contains("@os"));
     EXPECT_EQ("fake_prodid", CHECK_DEREF(request.FindString("@updater")));
-    EXPECT_EQ("crx3,download,puff,run",
+    EXPECT_EQ("crx3,download,puff,run,zucchini",
               CHECK_DEREF(request.FindString("acceptformat")));
     EXPECT_TRUE(request.contains("arch"));
     EXPECT_EQ("cr", CHECK_DEREF(request.FindString("dedup")));
diff --git a/components/update_client/pipeline.cc b/components/update_client/pipeline.cc
index 50a0206..62756959 100644
--- a/components/update_client/pipeline.cc
+++ b/components/update_client/pipeline.cc
@@ -29,6 +29,7 @@
 #include "components/update_client/op_download.h"
 #include "components/update_client/op_install.h"
 #include "components/update_client/op_puffin.h"
+#include "components/update_client/op_zucchini.h"
 #include "components/update_client/protocol_parser.h"
 #include "components/update_client/unzipper.h"
 #include "components/update_client/update_client_errors.h"
@@ -255,6 +256,11 @@
           cache_check, base::BindOnce(&PuffOperation, crx_cache,
                                       config->GetPatcherFactory()->Create(),
                                       event_adder, id, operation.sha256_from)));
+    } else if (operation.type == "zucchini") {
+      ops.push(SkipIfCached(
+          cache_check, base::BindOnce(&ZucchiniOperation, crx_cache,
+                                      config->GetPatcherFactory()->Create(),
+                                      event_adder, id, operation.sha256_from)));
     } else if (operation.type == "crx3") {
       ops.push(base::BindOnce(
           &InstallOperation, crx_cache, config->GetUnzipperFactory()->Create(),
diff --git a/components/update_client/protocol_definition.h b/components/update_client/protocol_definition.h
index 83777e4..cd94b18 100644
--- a/components/update_client/protocol_definition.h
+++ b/components/update_client/protocol_definition.h
@@ -32,6 +32,7 @@
 inline constexpr int kEventUpdate = 3;
 inline constexpr int kEventUninstall = 4;
 inline constexpr int kEventDownload = 14;
+inline constexpr int kEventZucchini = 61;
 inline constexpr int kEventPuff = 62;
 inline constexpr int kEventCrx3 = 63;
 
diff --git a/components/update_client/protocol_serializer_json.cc b/components/update_client/protocol_serializer_json.cc
index 983f0db..ba5e75d 100644
--- a/components/update_client/protocol_serializer_json.cc
+++ b/components/update_client/protocol_serializer_json.cc
@@ -24,7 +24,7 @@
   request_node.Set("protocol", request.protocol_version);
   request_node.Set("ismachine", request.is_machine);
   request_node.Set("dedup", "cr");
-  request_node.Set("acceptformat", "crx3,download,puff,run");
+  request_node.Set("acceptformat", "crx3,download,puff,run,zucchini");
   if (!request.additional_attributes.empty()) {
     for (const auto& [name, value] : request.additional_attributes) {
       request_node.Set(name, value);
diff --git a/components/update_client/protocol_serializer_json_unittest.cc b/components/update_client/protocol_serializer_json_unittest.cc
index d5dc781..874493a 100644
--- a/components/update_client/protocol_serializer_json_unittest.cc
+++ b/components/update_client/protocol_serializer_json_unittest.cc
@@ -62,7 +62,7 @@
                             std::move(apps)));
     constexpr char regex[] =
         R"({"request":{"@os":"\w+","@updater":"prod_id",)"
-        R"("acceptformat":"crx3,download,puff,run",)"
+        R"("acceptformat":"crx3,download,puff,run,zucchini",)"
         R"("apps":\[{"ap":"ap1","appid":"id1","attr1":"1","attr2":"2",)"
         R"("brand":"BRND","cohort":"c1","cohorthint":"ch1","cohortname":"cn1",)"
         R"("data":\[{"index":"foobar_install_data_index","name":"install"}],)"
@@ -147,7 +147,8 @@
       {}));
   constexpr char regex[] =
       R"({"request":{"@os":"\w+","@updater":"prod_id",)"
-      R"("acceptformat":"crx3,download,puff,run","arch":"\w+","dedup":"cr",)"
+      R"("acceptformat":"crx3,download,puff,run,zucchini",)"
+      R"("arch":"\w+","dedup":"cr",)"
       R"("dlpref":"cacheable","domainjoined":true,"extra":"params",)"
       R"("hw":{"avx":(true|false),)"
       R"("physmemory":\d+,"sse":(true|false),"sse2":(true|false),)"
diff --git a/components/update_client/update_checker_unittest.cc b/components/update_client/update_checker_unittest.cc
index aaf8784a..0b66fb9 100644
--- a/components/update_client/update_checker_unittest.cc
+++ b/components/update_client/update_checker_unittest.cc
@@ -284,7 +284,8 @@
   ASSERT_TRUE(request->FindString("@updater"));
   EXPECT_EQ("fake_prodid", *request->FindString("@updater"));
   ASSERT_TRUE(request->FindString("acceptformat"));
-  EXPECT_EQ("crx3,download,puff,run", *request->FindString("acceptformat"));
+  EXPECT_EQ("crx3,download,puff,run,zucchini",
+            *request->FindString("acceptformat"));
   EXPECT_TRUE(request->contains("arch"));
   ASSERT_TRUE(request->FindString("dedup"));
   EXPECT_EQ("cr", *request->FindString("dedup"));
diff --git a/components/update_client/update_client_errors.h b/components/update_client/update_client_errors.h
index 4afa3bf9..0a8adb4 100644
--- a/components/update_client/update_client_errors.h
+++ b/components/update_client/update_client_errors.h
@@ -87,6 +87,9 @@
   kCrxCacheNotProvided = 21,
   kCrxCacheMetadataCorrupted = 22,
   kCrxCacheFileNotCached = 23,
+  kPatchInvalidOldFile = 24,
+  kPatchInvalidPatchFile = 25,
+  kPatchInvalidNewFile = 26,
 };
 
 // These errors are returned with the |kInstall| error category and
diff --git a/components/viz/service/display/display_resource_provider_skia.cc b/components/viz/service/display/display_resource_provider_skia.cc
index f9e0fb3b..dc22f38 100644
--- a/components/viz/service/display/display_resource_provider_skia.cc
+++ b/components/viz/service/display/display_resource_provider_skia.cc
@@ -152,21 +152,9 @@
     resources_.emplace_back(id, &resource);
 
     if (!resource.image_context) {
-      // SkColorSpace covers only RGB portion of the gfx::ColorSpace, YUV
-      // portion is handled via SkYuvColorSpace at places where we create YUV
-      // images.
-      sk_sp<SkColorSpace> image_color_space =
-          resource.transferable.color_space.GetAsFullRangeRGB()
-              .ToSkColorSpace();
-
       resource.image_context =
           resource_provider_->external_use_client_->CreateImageContext(
-              resource.transferable.mailbox(),
-              resource.transferable.sync_token(),
-              resource.transferable.texture_target(),
-              resource.transferable.size, resource.transferable.format,
-              maybe_concurrent_reads, resource.transferable.ycbcr_info,
-              std::move(image_color_space), resource.transferable.origin,
+              resource.transferable, maybe_concurrent_reads,
               raw_draw_is_possible);
     }
     resource.locked_for_external_use = true;
diff --git a/components/viz/service/display/display_resource_provider_skia_unittest.cc b/components/viz/service/display/display_resource_provider_skia_unittest.cc
index c1436fc3..2d85c9ab 100644
--- a/components/viz/service/display/display_resource_provider_skia_unittest.cc
+++ b/components/viz/service/display/display_resource_provider_skia_unittest.cc
@@ -68,17 +68,10 @@
   MOCK_METHOD1(ReleaseImageContexts,
                gpu::SyncToken(
                    std::vector<std::unique_ptr<ImageContext>> image_contexts));
-  MOCK_METHOD10(
+  MOCK_METHOD3(
       CreateImageContext,
-      std::unique_ptr<ImageContext>(const gpu::Mailbox& mailbox,
-                                    const gpu::SyncToken& sync_token,
-                                    uint32_t texture_target,
-                                    const gfx::Size&,
-                                    SharedImageFormat,
+      std::unique_ptr<ImageContext>(const TransferableResource& resource,
                                     bool,
-                                    const std::optional<gpu::VulkanYCbCrInfo>&,
-                                    sk_sp<SkColorSpace>,
-                                    GrSurfaceOrigin,
                                     bool));
 };
 
@@ -172,22 +165,20 @@
   auto format = SinglePlaneFormat::kRGBA_8888;
   auto owned_image_context = std::make_unique<ExternalUseClient::ImageContext>(
       mailbox, sync_token1, GL_TEXTURE_2D, size, format,
-      /*ycbcr_info=*/std::nullopt, /*color_space=*/nullptr,
-      kTopLeft_GrSurfaceOrigin);
+      /*color_space=*/nullptr, kTopLeft_GrSurfaceOrigin);
   auto* image_context = owned_image_context.get();
 
-  gpu::Mailbox mailbox_out;
-  gpu::SyncToken sync_token_out;
-  EXPECT_CALL(client_, CreateImageContext(_, _, _, _, _, _, _, _, _, _))
-      .WillOnce(DoAll(SaveArg<0>(&mailbox_out), SaveArg<1>(&sync_token_out),
+  TransferableResource resource_out;
+  EXPECT_CALL(client_, CreateImageContext(_, _, _))
+      .WillOnce(DoAll(SaveArg<0>(&resource_out),
                       Return(ByMove(std::move(owned_image_context)))));
 
   ExternalUseClient::ImageContext* locked_image_context =
       lock_set_->LockResource(parent_id, /*maybe_concurrent_reads=*/true,
                               /*is_video_plane=*/false);
   EXPECT_EQ(image_context, locked_image_context);
-  ASSERT_EQ(mailbox_out, mailbox);
-  ASSERT_TRUE(sync_token_out.HasData());
+  ASSERT_EQ(resource_out.mailbox(), mailbox);
+  ASSERT_TRUE(resource_out.sync_token().HasData());
 
   // Don't release while locked.
   EXPECT_CALL(client_, ReleaseImageContexts(_)).Times(0);
@@ -255,22 +246,20 @@
   auto format = SinglePlaneFormat::kRGBA_8888;
   auto owned_image_context = std::make_unique<ExternalUseClient::ImageContext>(
       mailbox, sync_token1, GL_TEXTURE_2D, size, format,
-      /*ycbcr_info=*/std::nullopt, /*color_space=*/nullptr,
-      kTopLeft_GrSurfaceOrigin);
+      /*color_space=*/nullptr, kTopLeft_GrSurfaceOrigin);
   auto* image_context = owned_image_context.get();
 
-  gpu::Mailbox mailbox_out;
-  gpu::SyncToken sync_token_out;
-  EXPECT_CALL(client_, CreateImageContext(_, _, _, _, _, _, _, _, _, _))
-      .WillOnce(DoAll(SaveArg<0>(&mailbox_out), SaveArg<1>(&sync_token_out),
+  TransferableResource resource_out;
+  EXPECT_CALL(client_, CreateImageContext(_, _, _))
+      .WillOnce(DoAll(SaveArg<0>(&resource_out),
                       Return(ByMove(std::move(owned_image_context)))));
 
   ExternalUseClient::ImageContext* locked_image_context =
       lock_set_->LockResource(parent_id, /*maybe_concurrent_reads=*/true,
                               /*is_video_plane=*/false);
   EXPECT_EQ(image_context, locked_image_context);
-  ASSERT_EQ(mailbox_out, mailbox);
-  ASSERT_TRUE(sync_token_out.HasData());
+  ASSERT_EQ(resource_out.mailbox(), mailbox);
+  ASSERT_TRUE(resource_out.sync_token().HasData());
 
   // Don't release while locked.
   EXPECT_CALL(client_, ReleaseImageContexts(_)).Times(0);
diff --git a/components/viz/service/display/external_use_client.cc b/components/viz/service/display/external_use_client.cc
index e766b9d6..ba62af86 100644
--- a/components/viz/service/display/external_use_client.cc
+++ b/components/viz/service/display/external_use_client.cc
@@ -9,23 +9,35 @@
 
 namespace viz {
 
-ExternalUseClient::ImageContext::ImageContext(
-    const gpu::Mailbox& mailbox,
-    const gpu::SyncToken& sync_token,
-    uint32_t texture_target,
-    const gfx::Size& size,
-    SharedImageFormat format,
-    const std::optional<gpu::VulkanYCbCrInfo>& ycbcr_info,
-    sk_sp<SkColorSpace> color_space,
-    GrSurfaceOrigin origin)
+ExternalUseClient::ImageContext::ImageContext(const gpu::Mailbox& mailbox,
+                                              const gpu::SyncToken& sync_token,
+                                              uint32_t texture_target,
+                                              const gfx::Size& size,
+                                              SharedImageFormat format,
+                                              sk_sp<SkColorSpace> color_space,
+                                              GrSurfaceOrigin origin)
     : mailbox_(mailbox),
       sync_token_(sync_token),
       texture_target_(texture_target),
       size_(size),
       format_(format),
       color_space_(std::move(color_space)),
-      origin_(origin),
-      ycbcr_info_(ycbcr_info) {}
+      origin_(origin) {}
+
+ExternalUseClient::ImageContext::ImageContext(
+    const TransferableResource& resource)
+    : mailbox_(resource.mailbox()),
+      sync_token_(resource.sync_token()),
+      texture_target_(resource.texture_target()),
+      size_(resource.size),
+      format_(resource.format),
+      // SkColorSpace covers only RGB portion of the gfx::ColorSpace, YUV
+      // portion is handled via SkYuvColorSpace at places where we create YUV
+      // images.
+      color_space_(resource.color_space.GetAsFullRangeRGB().ToSkColorSpace()),
+      origin_(resource.origin),
+      resource_source_(resource.resource_source),
+      ycbcr_info_(resource.ycbcr_info) {}
 
 ExternalUseClient::ImageContext::~ImageContext() = default;
 
diff --git a/components/viz/service/display/external_use_client.h b/components/viz/service/display/external_use_client.h
index 1e71128..82d17c04 100644
--- a/components/viz/service/display/external_use_client.h
+++ b/components/viz/service/display/external_use_client.h
@@ -13,6 +13,7 @@
 #include "base/check.h"
 #include "base/memory/raw_ptr.h"
 #include "components/viz/common/resources/shared_image_format.h"
+#include "components/viz/common/resources/transferable_resource.h"
 #include "components/viz/service/viz_service_export.h"
 #include "gpu/command_buffer/common/mailbox.h"
 #include "gpu/command_buffer/common/sync_token.h"
@@ -45,10 +46,11 @@
                  uint32_t texture_target,
                  const gfx::Size& size,
                  SharedImageFormat format,
-                 const std::optional<gpu::VulkanYCbCrInfo>& ycbcr_info,
                  sk_sp<SkColorSpace> color_space,
                  GrSurfaceOrigin origin);
 
+    explicit ImageContext(const TransferableResource& resource);
+
     ImageContext(const ImageContext&) = delete;
     ImageContext& operator=(const ImageContext&) = delete;
 
@@ -76,6 +78,9 @@
     }
 
     GrSurfaceOrigin origin() const { return origin_; }
+    TransferableResource::ResourceSource resource_source() const {
+      return resource_source_;
+    }
 
     std::optional<gpu::VulkanYCbCrInfo> ycbcr_info() { return ycbcr_info_; }
 
@@ -113,6 +118,8 @@
     const SharedImageFormat format_;
     const sk_sp<SkColorSpace> color_space_;
     const GrSurfaceOrigin origin_;
+    const TransferableResource::ResourceSource resource_source_ =
+        TransferableResource::ResourceSource::kUnknown;
 
     SkAlphaType alpha_type_ = kPremul_SkAlphaType;
 
@@ -131,15 +138,8 @@
   // If |maybe_concurrent_reads| is true then there can be concurrent reads to
   // the texture that modify GL texture parameters.
   virtual std::unique_ptr<ImageContext> CreateImageContext(
-      const gpu::Mailbox& mailbox,
-      const gpu::SyncToken& sync_token,
-      uint32_t texture_target,
-      const gfx::Size& size,
-      SharedImageFormat format,
+      const TransferableResource& resource,
       bool maybe_concurrent_reads,
-      const std::optional<gpu::VulkanYCbCrInfo>& ycbcr_info,
-      sk_sp<SkColorSpace> color_space,
-      GrSurfaceOrigin origin,
       bool raw_draw_if_possible) = 0;
 
   virtual gpu::SyncToken ReleaseImageContexts(
diff --git a/components/viz/service/display_embedder/image_context_impl.cc b/components/viz/service/display_embedder/image_context_impl.cc
index 68e7cdb..5a9b40c 100644
--- a/components/viz/service/display_embedder/image_context_impl.cc
+++ b/components/viz/service/display_embedder/image_context_impl.cc
@@ -119,29 +119,25 @@
 
 namespace viz {
 
-ImageContextImpl::ImageContextImpl(
-    const gpu::Mailbox& mailbox,
-    const gpu::SyncToken& sync_token,
-    uint32_t texture_target,
-    const gfx::Size& size,
-    SharedImageFormat format,
-    bool maybe_concurrent_reads,
-    const std::optional<gpu::VulkanYCbCrInfo>& ycbcr_info,
-    sk_sp<SkColorSpace> color_space,
-    GrSurfaceOrigin origin,
-    bool is_for_render_pass,
-    bool raw_draw_if_possible)
+ImageContextImpl::ImageContextImpl(const TransferableResource& resource,
+                                   bool maybe_concurrent_reads,
+                                   bool raw_draw_if_possible)
+    : ImageContext(resource),
+      maybe_concurrent_reads_(maybe_concurrent_reads),
+      raw_draw_if_possible_(raw_draw_if_possible) {}
+
+ImageContextImpl::ImageContextImpl(const gpu::Mailbox& mailbox,
+                                   const gfx::Size& size,
+                                   SharedImageFormat format,
+                                   sk_sp<SkColorSpace> color_space)
     : ImageContext(mailbox,
-                   sync_token,
-                   texture_target,
+                   gpu::SyncToken(),
+                   /*texture_target=*/GL_TEXTURE_2D,
                    size,
                    format,
-                   ycbcr_info,
                    color_space,
-                   origin),
-      maybe_concurrent_reads_(maybe_concurrent_reads),
-      is_for_render_pass_(is_for_render_pass),
-      raw_draw_if_possible_(raw_draw_if_possible) {}
+                   /*origin=*/kTopLeft_GrSurfaceOrigin),
+      is_for_render_pass_(true) {}
 
 ImageContextImpl::~ImageContextImpl() {
   DeleteFallbackTextures();
diff --git a/components/viz/service/display_embedder/image_context_impl.h b/components/viz/service/display_embedder/image_context_impl.h
index 815101f..77037b1 100644
--- a/components/viz/service/display_embedder/image_context_impl.h
+++ b/components/viz/service/display_embedder/image_context_impl.h
@@ -46,17 +46,15 @@
 // SkiaOutputSurfaceImplOnGpu. {Begin,End}Access is called from the GPU thread.
 class ImageContextImpl final : public ExternalUseClient::ImageContext {
  public:
+  ImageContextImpl(const TransferableResource& resource,
+                   bool maybe_concurrent_reads,
+                   bool raw_draw_if_possible);
+
+  // Used only for creating promise image from RenderPass.
   ImageContextImpl(const gpu::Mailbox& mailbox,
-                   const gpu::SyncToken& sync_token,
-                   uint32_t texture_target,
                    const gfx::Size& size,
                    SharedImageFormat format,
-                   bool maybe_concurrent_reads,
-                   const std::optional<gpu::VulkanYCbCrInfo>& ycbcr_info,
-                   sk_sp<SkColorSpace> color_space,
-                   GrSurfaceOrigin origin,
-                   bool is_for_render_pass,
-                   bool raw_draw_if_possible = false);
+                   sk_sp<SkColorSpace> color_space);
 
   ImageContextImpl(const ImageContextImpl&) = delete;
   ImageContextImpl& operator=(const ImageContextImpl&) = delete;
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.cc b/components/viz/service/display_embedder/skia_output_surface_impl.cc
index 260d02d..d922eb33 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl.cc
@@ -33,6 +33,7 @@
 #include "components/viz/common/frame_sinks/copy_output_request.h"
 #include "components/viz/common/frame_sinks/copy_output_util.h"
 #include "components/viz/common/resources/shared_image_format_utils.h"
+#include "components/viz/common/resources/transferable_resource.h"
 #include "components/viz/service/debugger/viz_debugger.h"
 #include "components/viz/service/display/external_use_client.h"
 #include "components/viz/service/display/output_surface_client.h"
@@ -764,21 +765,11 @@
 }
 
 std::unique_ptr<ExternalUseClient::ImageContext>
-SkiaOutputSurfaceImpl::CreateImageContext(
-    const gpu::Mailbox& mailbox,
-    const gpu::SyncToken& sync_token,
-    uint32_t texture_target,
-    const gfx::Size& size,
-    SharedImageFormat format,
-    bool maybe_concurrent_reads,
-    const std::optional<gpu::VulkanYCbCrInfo>& ycbcr_info,
-    sk_sp<SkColorSpace> color_space,
-    GrSurfaceOrigin origin,
-    bool raw_draw_if_possible) {
-  return std::make_unique<ImageContextImpl>(
-      mailbox, sync_token, texture_target, size, format, maybe_concurrent_reads,
-      ycbcr_info, std::move(color_space), origin,
-      /*is_for_render_pass=*/false, raw_draw_if_possible);
+SkiaOutputSurfaceImpl::CreateImageContext(const TransferableResource& resource,
+                                          bool maybe_concurrent_reads,
+                                          bool raw_draw_if_possible) {
+  return std::make_unique<ImageContextImpl>(resource, maybe_concurrent_reads,
+                                            raw_draw_if_possible);
 }
 
 DBG_FLAG_FBOOL("skia_gpu.swap_buffers.force_disable_makecurrent",
@@ -985,12 +976,8 @@
 
   auto& image_context = render_pass_image_cache_[id];
   if (!image_context) {
-    image_context = std::make_unique<ImageContextImpl>(
-        mailbox, gpu::SyncToken(), GL_TEXTURE_2D, size, format,
-        /*maybe_concurrent_reads=*/false,
-        /*ycbcr_info=*/std::nullopt, std::move(color_space),
-        kTopLeft_GrSurfaceOrigin,
-        /*is_for_render_pass=*/true);
+    image_context = std::make_unique<ImageContextImpl>(mailbox, size, format,
+                                                       std::move(color_space));
   }
   if (!image_context->has_image()) {
     // NOTE: The ColorSpace parameter is relevant only for external sampling,
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.h b/components/viz/service/display_embedder/skia_output_surface_impl.h
index 90b9f19b..b39d747 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl.h
+++ b/components/viz/service/display_embedder/skia_output_surface_impl.h
@@ -179,15 +179,8 @@
   gpu::SyncToken ReleaseImageContexts(
       std::vector<std::unique_ptr<ImageContext>> image_contexts) override;
   std::unique_ptr<ExternalUseClient::ImageContext> CreateImageContext(
-      const gpu::Mailbox& mailbox,
-      const gpu::SyncToken& sync_token,
-      uint32_t texture_target,
-      const gfx::Size& size,
-      SharedImageFormat format,
+      const TransferableResource& resource,
       bool maybe_concurrent_reads,
-      const std::optional<gpu::VulkanYCbCrInfo>& ycbcr_info,
-      sk_sp<SkColorSpace> color_space,
-      GrSurfaceOrigin origin,
       bool raw_draw_if_possible) override;
 
   void InitDelegatedInkPointRendererReceiver(
diff --git a/components/viz/service/gl/gpu_service_impl.cc b/components/viz/service/gl/gpu_service_impl.cc
index 24cf446..7b3153e 100644
--- a/components/viz/service/gl/gpu_service_impl.cc
+++ b/components/viz/service/gl/gpu_service_impl.cc
@@ -172,12 +172,12 @@
 
 // Forward declare log handlers so they can be used within LogMessageManager.
 bool PreInitializeLogHandler(int severity,
-                             std::string_view file,
+                             const char* file,
                              int line,
                              size_t message_start,
                              const std::string& message);
 bool PostInitializeLogHandler(int severity,
-                              std::string_view file,
+                              const char* file,
                               int line,
                               size_t message_start,
                               const std::string& message);
@@ -269,7 +269,7 @@
 }
 
 bool PreInitializeLogHandler(int severity,
-                             std::string_view file,
+                             const char* file,
                              int line,
                              size_t message_start,
                              const std::string& message) {
@@ -280,7 +280,7 @@
 }
 
 bool PostInitializeLogHandler(int severity,
-                              std::string_view file,
+                              const char* file,
                               int line,
                               size_t message_start,
                               const std::string& message) {
diff --git a/components/viz/service/layers/layer_context_impl.cc b/components/viz/service/layers/layer_context_impl.cc
index 3f7bbbf6..82ad833 100644
--- a/components/viz/service/layers/layer_context_impl.cc
+++ b/components/viz/service/layers/layer_context_impl.cc
@@ -590,6 +590,36 @@
   return base::ok();
 }
 
+void DeserializeViewTransitionRequests(
+    cc::LayerTreeImpl& layers,
+    std::vector<mojom::ViewTransitionRequestPtr>& wire_data) {
+  for (auto& wire : wire_data) {
+    std::unique_ptr<cc::ViewTransitionRequest> request;
+    switch (wire->type) {
+      case mojom::CompositorFrameTransitionDirectiveType::kSave:
+        // Callback is not used at all in
+        // ViewTransitionRequest::ConstructDirective, therefore it's not
+        // wired in mojom::ViewTransitionRequest to viz, and here we just use
+        // a placeholder.
+        request = cc::ViewTransitionRequest::CreateCapture(
+            wire->transition_token, wire->maybe_cross_frame_sink,
+            wire->capture_resource_ids,
+            cc::ViewTransitionRequest::ViewTransitionCaptureCallback());
+        break;
+      case mojom::CompositorFrameTransitionDirectiveType::kAnimateRenderer:
+        request = cc::ViewTransitionRequest::CreateAnimateRenderer(
+            wire->transition_token, wire->maybe_cross_frame_sink);
+        break;
+      case mojom::CompositorFrameTransitionDirectiveType::kRelease:
+        request = cc::ViewTransitionRequest::CreateRelease(
+            wire->transition_token, wire->maybe_cross_frame_sink);
+        break;
+    }
+    request->set_sequence_id(wire->sequence_id);
+    layers.AddViewTransitionRequest(std::move(request));
+  }
+}
+
 gfx::StepsTimingFunction::StepPosition DeserializeTimingStepPosition(
     mojom::TimingStepPosition step_position) {
   switch (step_position) {
@@ -1185,6 +1215,11 @@
     layers.SetSurfaceRanges(surface_ranges);
   }
 
+  if (update->view_transition_requests) {
+    DeserializeViewTransitionRequests(layers,
+                                      *(update->view_transition_requests));
+  }
+
   RETURN_IF_ERROR(
       CreateOrUpdateLayers(*this, update->layers, update->layer_order, layers));
 
@@ -1232,6 +1267,7 @@
     return base::unexpected("Invalid painted device scale factor");
   }
   layers.set_painted_device_scale_factor(update->painted_device_scale_factor);
+  layers.SetDisplayColorSpaces(update->display_color_spaces);
   if (update->local_surface_id_from_parent) {
     layers.SetLocalSurfaceIdFromParent(*update->local_surface_id_from_parent);
   }
diff --git a/components/viz/test/fake_skia_output_surface.cc b/components/viz/test/fake_skia_output_surface.cc
index 228976a..b34b526 100644
--- a/components/viz/test/fake_skia_output_surface.cc
+++ b/components/viz/test/fake_skia_output_surface.cc
@@ -18,6 +18,7 @@
 #include "components/viz/common/frame_sinks/copy_output_request.h"
 #include "components/viz/common/frame_sinks/copy_output_util.h"
 #include "components/viz/common/resources/shared_image_format_utils.h"
+#include "components/viz/common/resources/transferable_resource.h"
 #include "components/viz/service/display/output_surface_client.h"
 #include "components/viz/service/display/output_surface_frame.h"
 #include "gpu/GLES2/gl2extchromium.h"
@@ -145,20 +146,10 @@
 }
 
 std::unique_ptr<ExternalUseClient::ImageContext>
-FakeSkiaOutputSurface::CreateImageContext(
-    const gpu::Mailbox& mailbox,
-    const gpu::SyncToken& sync_token,
-    uint32_t texture_target,
-    const gfx::Size& size,
-    SharedImageFormat format,
-    bool concurrent_reads,
-    const std::optional<gpu::VulkanYCbCrInfo>& ycbcr_info,
-    sk_sp<SkColorSpace> color_space,
-    GrSurfaceOrigin origin,
-    bool raw_draw_if_possible) {
-  return std::make_unique<ExternalUseClient::ImageContext>(
-      mailbox, sync_token, texture_target, size, format, ycbcr_info,
-      std::move(color_space), origin);
+FakeSkiaOutputSurface::CreateImageContext(const TransferableResource& resource,
+                                          bool concurrent_reads,
+                                          bool raw_draw_if_possible) {
+  return std::make_unique<ExternalUseClient::ImageContext>(resource);
 }
 
 SkCanvas* FakeSkiaOutputSurface::BeginPaintRenderPass(
diff --git a/components/viz/test/fake_skia_output_surface.h b/components/viz/test/fake_skia_output_surface.h
index a1adf94..eb0cad1 100644
--- a/components/viz/test/fake_skia_output_surface.h
+++ b/components/viz/test/fake_skia_output_surface.h
@@ -119,15 +119,8 @@
   gpu::SyncToken ReleaseImageContexts(
       const std::vector<std::unique_ptr<ImageContext>> image_contexts) override;
   std::unique_ptr<ImageContext> CreateImageContext(
-      const gpu::Mailbox& mailbox,
-      const gpu::SyncToken& sync_token,
-      uint32_t texture_target,
-      const gfx::Size& size,
-      SharedImageFormat format,
+      const TransferableResource& resource,
       bool concurrent_reads,
-      const std::optional<gpu::VulkanYCbCrInfo>& ycbcr_info,
-      sk_sp<SkColorSpace> color_space,
-      GrSurfaceOrigin origin,
       bool raw_draw_if_possible) override;
 
   gpu::SharedImageInterface* GetSharedImageInterface();
diff --git a/content/app/ios/appex/child_process_bridge.mm b/content/app/ios/appex/child_process_bridge.mm
index 01959369..c2bd02e4 100644
--- a/content/app/ios/appex/child_process_bridge.mm
+++ b/content/app/ios/appex/child_process_bridge.mm
@@ -13,7 +13,7 @@
 #include <xpc/xpc.h>
 
 #include "base/apple/bundle_locations.h"
-#include "base/apple/mach_port_rendezvous.h"
+#include "base/apple/mach_port_rendezvous_ios.h"
 #include "base/check_op.h"
 #include "base/command_line.h"
 #include "base/system/sys_info.h"
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 399896c..c87f1992 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -3396,10 +3396,10 @@
     deps += [
       ":fontations_name_table_ffi",
       ":reflection_jni_headers",
-      ":transfer_input_to_viz_result_enum",
       "//cc/slim",
       "//components/tracing:graphics_provider",
       "//content/public/android:browser_jni",
+      "//content/public/browser:transfer_input_to_viz_result_enum",
       "//device/gamepad/public/mojom",
       "//gpu/command_buffer/service:gles2",
       "//media",
@@ -3721,9 +3721,6 @@
   java_cpp_enum("client_data_json_generated_enum") {
     sources = [ "webauth/client_data_json.h" ]
   }
-  java_cpp_enum("transfer_input_to_viz_result_enum") {
-    sources = [ "renderer_host/input/transfer_input_to_viz_result.h" ]
-  }
 }
 
 if (is_mac) {
diff --git a/content/browser/child_process_launcher_helper.cc b/content/browser/child_process_launcher_helper.cc
index 4574d896..753aaec8 100644
--- a/content/browser/child_process_launcher_helper.cc
+++ b/content/browser/child_process_launcher_helper.cc
@@ -39,7 +39,7 @@
 #endif
 
 #if BUILDFLAG(IS_IOS)
-#include "base/apple/mach_port_rendezvous.h"
+#include "base/apple/mach_port_rendezvous_ios.h"
 #endif
 
 namespace content {
diff --git a/content/browser/child_process_launcher_helper_ios.mm b/content/browser/child_process_launcher_helper_ios.mm
index 25789ff0..0d7ea77 100644
--- a/content/browser/child_process_launcher_helper_ios.mm
+++ b/content/browser/child_process_launcher_helper_ios.mm
@@ -13,7 +13,7 @@
 
 #include <list>
 
-#include "base/apple/mach_port_rendezvous.h"
+#include "base/apple/mach_port_rendezvous_ios.h"
 #include "base/no_destructor.h"
 #include "base/threading/platform_thread.h"
 #include "content/browser/child_process_launcher.h"
diff --git a/content/browser/interest_group/interest_group_pmt_report_util.cc b/content/browser/interest_group/interest_group_pmt_report_util.cc
index f9f58b1..62e74704 100644
--- a/content/browser/interest_group/interest_group_pmt_report_util.cc
+++ b/content/browser/interest_group/interest_group_pmt_report_util.cc
@@ -111,8 +111,8 @@
 // PrivateModelTrainingRequest
 PrivateModelTrainingRequest::PrivateModelTrainingRequest(
     auction_worklet::mojom::PrivateModelTrainingRequestDataPtr pmt_request_data,
-    const url::Origin reporting_origin,
-    const BiddingAndAuctionServerKey public_key)
+    url::Origin reporting_origin,
+    BiddingAndAuctionServerKey public_key)
     : PrivateModelTrainingRequest(std::move(pmt_request_data),
                                   std::move(reporting_origin),
                                   std::move(public_key),
@@ -121,13 +121,13 @@
 
 PrivateModelTrainingRequest::PrivateModelTrainingRequest(
     auction_worklet::mojom::PrivateModelTrainingRequestDataPtr pmt_request_data,
-    const url::Origin reporting_origin,
-    const BiddingAndAuctionServerKey public_key,
-    const base::Uuid report_id,
-    const base::Time scheduled_report_time)
+    url::Origin reporting_origin,
+    BiddingAndAuctionServerKey public_key,
+    base::Uuid report_id,
+    base::Time scheduled_report_time)
     : shared_info_(std::move(report_id),
                    std::move(reporting_origin),
-                   std::move(scheduled_report_time)),
+                   scheduled_report_time),
       pmt_request_data_(std::move(pmt_request_data)),
       public_key_(std::move(public_key)) {}
 
@@ -241,12 +241,12 @@
 
 // Shared Info
 PrivateModelTrainingRequest::SharedInfo::SharedInfo(
-    const base::Uuid report_id,
-    const url::Origin reporting_origin,
-    const base::Time scheduled_report_time)
+    base::Uuid report_id,
+    url::Origin reporting_origin,
+    base::Time scheduled_report_time)
     : report_id(std::move(report_id)),
       reporting_origin(std::move(reporting_origin)),
-      scheduled_report_time(std::move(scheduled_report_time)) {}
+      scheduled_report_time(scheduled_report_time) {}
 PrivateModelTrainingRequest::SharedInfo::~SharedInfo() = default;
 PrivateModelTrainingRequest::SharedInfo::SharedInfo(const SharedInfo&) =
     default;
diff --git a/content/browser/interest_group/interest_group_pmt_report_util.h b/content/browser/interest_group/interest_group_pmt_report_util.h
index be7afe6..0e1adf5a5 100644
--- a/content/browser/interest_group/interest_group_pmt_report_util.h
+++ b/content/browser/interest_group/interest_group_pmt_report_util.h
@@ -62,15 +62,15 @@
   PrivateModelTrainingRequest(
       auction_worklet::mojom::PrivateModelTrainingRequestDataPtr
           pmt_request_data,
-      const url::Origin reporting_origin,
-      const BiddingAndAuctionServerKey public_key,
-      const base::Uuid report_id,
-      const base::Time scheduled_report_time);
+      url::Origin reporting_origin,
+      BiddingAndAuctionServerKey public_key,
+      base::Uuid report_id,
+      base::Time scheduled_report_time);
 
   struct SharedInfo {
-    SharedInfo(const base::Uuid report_id,
-               const url::Origin reporting_origin,
-               const base::Time scheduled_report_time);
+    SharedInfo(base::Uuid report_id,
+               url::Origin reporting_origin,
+               base::Time scheduled_report_time);
     ~SharedInfo();
     SharedInfo(const SharedInfo&);
     SharedInfo(SharedInfo&&);
diff --git a/content/browser/interest_group/interest_group_storage.cc b/content/browser/interest_group/interest_group_storage.cc
index 07c97996..786108a2 100644
--- a/content/browser/interest_group/interest_group_storage.cc
+++ b/content/browser/interest_group/interest_group_storage.cc
@@ -89,6 +89,10 @@
   ListOfTimestampAndCounts compacted_click_events;
 };
 
+// Reason why a database lookup couldn't produce a result. It could be an
+// error, or just because there is nothing there.
+enum class MissingReason { kNotInDb, kDbError, kDecodeError };
+
 const base::FilePath::CharType kDatabasePath[] =
     FILE_PATH_LITERAL("InterestGroups");
 
@@ -4642,14 +4646,11 @@
 }
 
 // Loads the view and click data for `provider_origin`, `eligible_origin`.
-// Returns std::nullopt on failure, and an empty
-// `ViewClickCountsForProviderAndEligible` if no counts are stored for the given
-// (`provider_origin`, `eligible_origin`) tuple.
-std::optional<ViewClickCountsForProviderAndEligible>
+// Returns data if available, or reason if there isn't otherwise.
+base::expected<ViewClickCountsForProviderAndEligible, MissingReason>
 DoGetViewClickCountsForProviderAndEligible(sql::Database& db,
                                            const url::Origin& provider_origin,
                                            const url::Origin& eligible_origin) {
-  ViewClickCountsForProviderAndEligible result;
   sql::Statement get_counts(
       db.GetCachedStatement(SQL_FROM_HERE,
                             "SELECT uncompacted_view_events,"
@@ -4659,21 +4660,19 @@
                             "FROM view_and_click_events "
                             "WHERE provider_origin=? AND eligible_origin=?"));
   if (!get_counts.is_valid()) {
-    DLOG(ERROR) << "GetViewClickCountsForProviderAndEligible SQL statement did "
-                   "not compile: "
-                << db.GetErrorMessage();
-    return std::nullopt;
+    return base::unexpected(MissingReason::kDbError);
   }
   get_counts.Reset(true);
   get_counts.BindString(0, provider_origin.Serialize());
   get_counts.BindString(1, eligible_origin.Serialize());
   if (!get_counts.Step()) {
-    // No counts stored, return empty counts lists.
-    return result;
+    // No counts stored.
+    return base::unexpected(MissingReason::kNotInDb);
   }
   if (!get_counts.Succeeded()) {
-    return std::nullopt;
+    return base::unexpected(MissingReason::kDbError);
   }
+  ViewClickCountsForProviderAndEligible result;
   if (!result.uncompacted_view_events.ParseFromString(
           get_counts.ColumnStringView(0)) ||
       !result.compacted_view_events.ParseFromString(
@@ -4685,7 +4684,7 @@
     base::UmaHistogramEnumeration(
         "Storage.InterestGroup.ProtoDeserializationResult.ListOfTimestamps",
         InterestGroupStorageProtoSerializationResult::kFailed);
-    return std::nullopt;
+    return base::unexpected(MissingReason::kDecodeError);
   } else {
     base::UmaHistogramEnumeration(
         "Storage.InterestGroup.ProtoDeserializationResult.ListOfTimestamps",
@@ -4718,7 +4717,6 @@
     view_or_click_counts->past_90_days += count;
   }
   // Older expired events may exist -- maintenance will eventually remove them.
-  // TODO(crbug.com/394108643): Implement click / view removal logic.
 }
 
 // Mutates `group`'s browser signals, filling in loaded view and click counts.
@@ -4741,13 +4739,19 @@
 
   for (const url::Origin& provider_origin :
        *group.interest_group.view_and_click_counts_providers) {
-    std::optional<ViewClickCountsForProviderAndEligible> partial_counts =
-        DoGetViewClickCountsForProviderAndEligible(
+    base::expected<ViewClickCountsForProviderAndEligible, MissingReason>
+        partial_counts = DoGetViewClickCountsForProviderAndEligible(
             /*db=*/db,
             /*provider_origin=*/provider_origin,
             /*eligible_origin=*/group.interest_group.owner);
-    if (!partial_counts) {
-      return false;
+    if (!partial_counts.has_value()) {
+      switch (partial_counts.error()) {
+        case MissingReason::kDbError:
+        case MissingReason::kDecodeError:
+          return false;
+        case MissingReason::kNotInDb:
+          continue;
+      }
     }
 
     for (int64_t timestamp :
@@ -6102,9 +6106,7 @@
     map[timestamp] += count;
   } else if (event_age <= base::Days(1)) {
     map[TruncateToHour(timestamp)] += count;
-  } else {
-    // TODO(crbug.com/394108643): Drop entries older than 90 days, and
-    // remove resultant DB rows with no events.
+  } else if (event_age <= base::Days(90)) {
     map[TruncateToDay(timestamp)] += count;
   }
 }
@@ -6272,6 +6274,14 @@
     return false;
   }
 
+  sql::Statement delete_row(
+      db.GetCachedStatement(SQL_FROM_HERE,
+                            "DELETE FROM view_and_click_events "
+                            "WHERE provider_origin=? AND eligible_origin=?"));
+  if (!delete_row.is_valid()) {
+    return false;
+  }
+
   // For each (provider_origin, eligible_origin) in view_and_click_events,
   // compact that (provider_origin, eligible_origin), and write the updated
   // results:
@@ -6310,17 +6320,29 @@
       return false;
     }
 
-    // Done compacting this (provider_origin, eligible_origin) row -- write the
-    // results back to the database.
-    update_row.BindString(0, raw_views->uncompacted_events);
-    update_row.BindString(1, raw_views->compacted_events);
-    update_row.BindString(2, raw_clicks->uncompacted_events);
-    update_row.BindString(3, raw_clicks->compacted_events);
-    update_row.BindString(4, provider_origin);
-    update_row.BindString(5, eligible_origin);
+    // Done compacting this (provider_origin, eligible_origin) row.
+    // If something is left, write the results back to the database,
+    // otherwise delete it.
+    if (raw_views->uncompacted_events.empty() &&
+        raw_views->compacted_events.empty() &&
+        raw_clicks->uncompacted_events.empty() &&
+        raw_clicks->compacted_events.empty()) {
+      delete_row.BindString(0, provider_origin);
+      delete_row.BindString(1, eligible_origin);
+      if (!delete_row.Run()) {
+        return false;
+      }
+    } else {
+      update_row.BindString(0, raw_views->uncompacted_events);
+      update_row.BindString(1, raw_views->compacted_events);
+      update_row.BindString(2, raw_clicks->uncompacted_events);
+      update_row.BindString(3, raw_clicks->compacted_events);
+      update_row.BindString(4, provider_origin);
+      update_row.BindString(5, eligible_origin);
 
-    if (!update_row.Run()) {
-      return false;
+      if (!update_row.Run()) {
+        return false;
+      }
     }
   }
   if (!get_all_rows_sql.Succeeded()) {
@@ -7438,6 +7460,20 @@
   return ComputeCompactClickiness(now, raw);
 }
 
+bool InterestGroupStorage::
+    CheckViewClickCountsForProviderAndEligibleNotInDbForTesting(
+        const url::Origin& provider_origin,
+        const url::Origin& eligible_origin) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (!EnsureDBInitialized()) {
+    return false;
+  }
+
+  auto status = DoGetViewClickCountsForProviderAndEligible(
+      *db_, provider_origin, eligible_origin);
+  return !status.has_value() && status.error() == MissingReason::kNotInDb;
+}
+
 void InterestGroupStorage::DatabaseErrorCallback(int extended_error,
                                                  sql::Statement* stmt) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/content/browser/interest_group/interest_group_storage.h b/content/browser/interest_group/interest_group_storage.h
index a8c4ad6..517fe10c 100644
--- a/content/browser/interest_group/interest_group_storage.h
+++ b/content/browser/interest_group/interest_group_storage.h
@@ -304,6 +304,15 @@
       base::Time now,
       const InterestGroupStorage::ClickinessCompactionRawEvents& raw);
 
+  // Returns true if there is no entry for given
+  // (provider_origin, eligible_origin) in database view/click table.
+  //
+  // Returns false if the entry exists, or if there is some sort of an error
+  // with the database.
+  bool CheckViewClickCountsForProviderAndEligibleNotInDbForTesting(
+      const url::Origin& provider_origin,
+      const url::Origin& eligible_origin);
+
  private:
   // Private constructor that allows changing the idle period, used by
   // CreateWithIdlePeriodForTesting().
diff --git a/content/browser/interest_group/interest_group_storage_unittest.cc b/content/browser/interest_group/interest_group_storage_unittest.cc
index 8518bb0..1072a0816 100644
--- a/content/browser/interest_group/interest_group_storage_unittest.cc
+++ b/content/browser/interest_group/interest_group_storage_unittest.cc
@@ -3868,6 +3868,68 @@
   base::test::ScopedFeatureList scoped_feature_list_;
 };
 
+TEST_F(InterestGroupStorageWithNoIdleFastForwardTest, ViewClickExpire) {
+  std::unique_ptr<InterestGroupStorage> storage = CreateStorage();
+
+  AdAuctionEventRecord record_view;
+  record_view.type = AdAuctionEventRecord::Type::kView;
+  record_view.providing_origin = kViewClickProviderOrigin1;
+  record_view.eligible_origins = {kViewClickEligibleOrigin1};
+  ASSERT_TRUE(record_view.IsValid());
+
+  AdAuctionEventRecord record_click;
+  record_click.type = AdAuctionEventRecord::Type::kClick;
+  record_click.providing_origin = kViewClickProviderOrigin1;
+  record_click.eligible_origins = {kViewClickEligibleOrigin1};
+  ASSERT_TRUE(record_click.IsValid());
+
+  base::Time start_time = base::Time::Now();
+
+  storage->RecordViewClick(record_view);
+  storage->RecordViewClick(record_view);
+  storage->RecordViewClick(record_click);
+  EXPECT_FALSE(
+      storage->CheckViewClickCountsForProviderAndEligibleNotInDbForTesting(
+          kViewClickProviderOrigin1, kViewClickEligibleOrigin1));
+
+  // Quickly fast fordward by 91 days (not 90 to account for rounding),
+  // then a bit more to get maintenance to happen with that much time elapsed.
+  FastForwardWithoutIdlingBy(task_environment(), *storage, base::Days(91));
+  task_environment().FastForwardBy(kIdlePeriod);
+
+  // Check that maintenance (and therefore compaction) has occurred.
+  EXPECT_LE(start_time + base::Days(91),
+            storage->GetLastMaintenanceTimeForTesting());
+
+  EXPECT_TRUE(
+      storage->CheckViewClickCountsForProviderAndEligibleNotInDbForTesting(
+          kViewClickProviderOrigin1, kViewClickEligibleOrigin1));
+
+  // Doing a fancy high-level read via an IG just gives 0 for all counters.
+  InterestGroup g = NewInterestGroup(kViewClickEligibleOrigin1, "cars");
+  g.view_and_click_counts_providers = {{kViewClickProviderOrigin1}};
+  g.expiry = base::Time::Now() + base::Days(90);
+  storage->JoinInterestGroup(g, GURL("https://joining-site.test"));
+
+  std::vector<StorageInterestGroup> groups =
+      storage->GetInterestGroupsForOwner(kViewClickEligibleOrigin1);
+  ASSERT_EQ(1u, groups.size());
+
+  blink::mojom::ViewAndClickCountsPtr& view_and_click_counts =
+      groups[0].bidding_browser_signals->view_and_click_counts;
+
+  EXPECT_EQ(0, view_and_click_counts->view_counts->past_hour);
+  EXPECT_EQ(0, view_and_click_counts->view_counts->past_day);
+  EXPECT_EQ(0, view_and_click_counts->view_counts->past_week);
+  EXPECT_EQ(0, view_and_click_counts->view_counts->past_30_days);
+  EXPECT_EQ(0, view_and_click_counts->view_counts->past_90_days);
+  EXPECT_EQ(0, view_and_click_counts->click_counts->past_hour);
+  EXPECT_EQ(0, view_and_click_counts->click_counts->past_day);
+  EXPECT_EQ(0, view_and_click_counts->click_counts->past_week);
+  EXPECT_EQ(0, view_and_click_counts->click_counts->past_30_days);
+  EXPECT_EQ(0, view_and_click_counts->click_counts->past_90_days);
+}
+
 // Like InterestGroupStorage.ExpirationDeletesMetadata, but it also checks edge
 // cases near the expiration point.
 //
diff --git a/content/browser/network_service_instance_impl.cc b/content/browser/network_service_instance_impl.cc
index 7f20925..006435b 100644
--- a/content/browser/network_service_instance_impl.cc
+++ b/content/browser/network_service_instance_impl.cc
@@ -396,16 +396,15 @@
   // in another process.
   if (IsOutOfProcessNetworkService()) {
     std::unique_ptr<base::Environment> env(base::Environment::Create());
-    std::string value;
-    if (env->HasVar(kKrb5CCEnvName)) {
-      env->GetVar(kKrb5CCEnvName, &value);
+    std::optional<std::string> value = env->GetVar(kKrb5CCEnvName);
+    if (value.has_value()) {
       network_service_params->environment.push_back(
-          network::mojom::EnvironmentVariable::New(kKrb5CCEnvName, value));
+          network::mojom::EnvironmentVariable::New(kKrb5CCEnvName, *value));
     }
-    if (env->HasVar(kKrb5ConfEnvName)) {
-      env->GetVar(kKrb5ConfEnvName, &value);
+    value = env->GetVar(kKrb5ConfEnvName);
+    if (value.has_value()) {
       network_service_params->environment.push_back(
-          network::mojom::EnvironmentVariable::New(kKrb5ConfEnvName, value));
+          network::mojom::EnvironmentVariable::New(kKrb5ConfEnvName, *value));
     }
   }
 #endif  // BUILDFLAG(IS_POSIX)
@@ -655,16 +654,16 @@
             << "ssl-key-log-file argument missing";
       } else {
         std::unique_ptr<base::Environment> env(base::Environment::Create());
-        std::string env_str;
-        if (env->GetVar("SSLKEYLOGFILE", &env_str)) {
+        std::optional<std::string> env_str = env->GetVar("SSLKEYLOGFILE");
+        if (env_str.has_value()) {
           UMA_HISTOGRAM_ENUMERATION(kSSLKeyLogFileHistogram,
                                     SSLKeyLogFileAction::kEnvVarFound);
 #if BUILDFLAG(IS_WIN)
           // base::Environment returns environment variables in UTF-8 on
           // Windows.
-          ssl_key_log_path = base::FilePath(base::UTF8ToWide(env_str));
+          ssl_key_log_path = base::FilePath(base::UTF8ToWide(*env_str));
 #else
-          ssl_key_log_path = base::FilePath(env_str);
+          ssl_key_log_path = base::FilePath(*env_str);
 #endif
         }
       }
diff --git a/content/browser/renderer_host/clipboard_host_impl.cc b/content/browser/renderer_host/clipboard_host_impl.cc
index 68c7cdb..9a969b2 100644
--- a/content/browser/renderer_host/clipboard_host_impl.cc
+++ b/content/browser/renderer_host/clipboard_host_impl.cc
@@ -185,7 +185,7 @@
 #endif  // BUILDFLAG(IS_CHROMEOS)
 
   if (file_type_only) {
-    types = {base::UTF8ToUTF16(ui::kMimeTypeUriList)};
+    types = {ui::kMimeTypeUriList16};
   } else {
     clipboard->ReadAvailableTypes(clipboard_buffer, data_endpoint.get(),
                                   &types);
diff --git a/content/browser/renderer_host/input/input_transfer_handler_android.h b/content/browser/renderer_host/input/input_transfer_handler_android.h
index 9831ca9..cc7c12b 100644
--- a/content/browser/renderer_host/input/input_transfer_handler_android.h
+++ b/content/browser/renderer_host/input/input_transfer_handler_android.h
@@ -9,8 +9,8 @@
 
 #include "base/android/scoped_java_ref.h"
 #include "base/memory/raw_ptr.h"
-#include "content/browser/renderer_host/input/transfer_input_to_viz_result.h"
 #include "content/common/content_export.h"
+#include "content/public/browser/android/transfer_input_to_viz_result.h"
 #include "content/public/browser/render_widget_host.h"
 #include "gpu/ipc/common/surface_handle.h"
 #include "ui/events/android/motion_event_android.h"
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index 2cadb96..e30b10cf 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -232,17 +232,17 @@
   std::vector<DropData::Metadata> metadata;
   if (drop_data.text) {
     metadata.push_back(DropData::Metadata::CreateForMimeType(
-        DropData::Kind::STRING, base::ASCIIToUTF16(ui::kMimeTypePlainText)));
+        DropData::Kind::STRING, ui::kMimeTypePlainText16));
   }
 
   if (drop_data.url.is_valid()) {
     metadata.push_back(DropData::Metadata::CreateForMimeType(
-        DropData::Kind::STRING, base::ASCIIToUTF16(ui::kMimeTypeUriList)));
+        DropData::Kind::STRING, ui::kMimeTypeUriList16));
   }
 
   if (drop_data.html) {
     metadata.push_back(DropData::Metadata::CreateForMimeType(
-        DropData::Kind::STRING, base::ASCIIToUTF16(ui::kMimeTypeHtml)));
+        DropData::Kind::STRING, ui::kMimeTypeHtml16));
   }
 
   // On Aura, filenames are available before drop.
diff --git a/content/browser/service_host/utility_process_host_browsertest.cc b/content/browser/service_host/utility_process_host_browsertest.cc
index 26de0c8..00176ea 100644
--- a/content/browser/service_host/utility_process_host_browsertest.cc
+++ b/content/browser/service_host/utility_process_host_browsertest.cc
@@ -60,7 +60,7 @@
 #endif
 
 #if BUILDFLAG(IS_MAC)
-#include "base/apple/mach_port_rendezvous.h"
+#include "base/apple/mach_port_rendezvous_mac.h"
 #endif
 
 namespace content {
diff --git a/content/browser/web_contents/web_contents_view_android.cc b/content/browser/web_contents/web_contents_view_android.cc
index 2cf9776..722f25a 100644
--- a/content/browser/web_contents/web_contents_view_android.cc
+++ b/content/browser/web_contents/web_contents_view_android.cc
@@ -469,9 +469,9 @@
     case JNI_DragEvent::ACTION_DRAG_ENTERED: {
       drag_metadata_.clear();
       for (const std::u16string& mime_type : event.mime_types()) {
-        if (mime_type == base::ASCIIToUTF16(ui::kMimeTypePlainText) ||
-            mime_type == base::ASCIIToUTF16(ui::kMimeTypeHtml) ||
-            mime_type == base::ASCIIToUTF16(ui::kMimeTypeMozillaUrl)) {
+        if (mime_type == ui::kMimeTypePlainText16 ||
+            mime_type == ui::kMimeTypeHtml16 ||
+            mime_type == ui::kMimeTypeMozillaUrl16) {
           drag_metadata_.push_back(DropData::Metadata::CreateForMimeType(
               DropData::Kind::STRING, mime_type));
         } else {
diff --git a/content/browser/web_package/signed_exchange_devtools_proxy.cc b/content/browser/web_package/signed_exchange_devtools_proxy.cc
index 7a4851f..b7dab3d 100644
--- a/content/browser/web_package/signed_exchange_devtools_proxy.cc
+++ b/content/browser/web_package/signed_exchange_devtools_proxy.cc
@@ -41,12 +41,19 @@
     std::optional<SignedExchangeError::FieldIndexPair> error_field) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   errors_.push_back(SignedExchangeError(message, std::move(error_field)));
-  WebContents* web_contents =
-      WebContents::FromFrameTreeNodeId(frame_tree_node_id_);
-  if (!web_contents)
+
+  FrameTreeNode* frame_tree_node =
+      FrameTreeNode::GloballyFindByID(frame_tree_node_id_);
+  if (!frame_tree_node) {
     return;
-  web_contents->GetPrimaryMainFrame()->AddMessageToConsole(
-      blink::mojom::ConsoleMessageLevel::kError, message);
+  }
+
+  RenderFrameHost* rfh = frame_tree_node->current_frame_host();
+  if (!rfh) {
+    return;
+  }
+
+  rfh->AddMessageToConsole(blink::mojom::ConsoleMessageLevel::kError, message);
 }
 
 void SignedExchangeDevToolsProxy::CertificateRequestSent(
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index 680f1037..720c3e6 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -460,8 +460,6 @@
       {wrf::EnableScriptedSpeechSynthesis, switches::kDisableSpeechSynthesisAPI,
        false},
       {wrf::EnableSharedWorker, switches::kDisableSharedWorkers, false},
-      {wrf::EnableMutationEvents, blink::switches::kMutationEventsEnabled,
-       true},
       {wrf::EnableKeyboardFocusableScrollers,
        blink::switches::kKeyboardFocusableScrollersEnabled, true},
       {wrf::EnableKeyboardFocusableScrollers,
diff --git a/content/common/features.gni b/content/common/features.gni
index 4eba17ec..f4d0526 100644
--- a/content/common/features.gni
+++ b/content/common/features.gni
@@ -19,7 +19,6 @@
   # depending on the build argument.
   mbi_mode = is_linux || is_chromeos || is_mac || is_win || is_android
 
-  # We allow legacy IPC to be enabled for Android (GIN Java bridge), and
-  # Pepper usage.
-  content_enable_legacy_ipc = is_android || enable_ppapi
+  # We allow legacy IPC to be enabled for Pepper usage.
+  content_enable_legacy_ipc = enable_ppapi
 }
diff --git a/content/common/profiling_utils.cc b/content/common/profiling_utils.cc
index 417a848..7a713471 100644
--- a/content/common/profiling_utils.cc
+++ b/content/common/profiling_utils.cc
@@ -41,13 +41,14 @@
   base::PathService::Get(base::DIR_TEMP, &path);
   path = path.Append("pgo_profiles/");
 #else
-  std::string prof_template;
+
   std::unique_ptr<base::Environment> env(base::Environment::Create());
-  if (env->GetVar("LLVM_PROFILE_FILE", &prof_template)) {
+  std::optional<std::string> prof_template = env->GetVar("LLVM_PROFILE_FILE");
+  if (prof_template.has_value()) {
 #if BUILDFLAG(IS_WIN)
-    path = base::FilePath(base::UTF8ToWide(prof_template)).DirName();
+    path = base::FilePath(base::UTF8ToWide(*prof_template)).DirName();
 #else
-    path = base::FilePath(prof_template).DirName();
+    path = base::FilePath(*prof_template).DirName();
 #endif
   }
 #endif
diff --git a/content/gpu/in_process_gpu_thread.cc b/content/gpu/in_process_gpu_thread.cc
index 9be776b..a29e19e 100644
--- a/content/gpu/in_process_gpu_thread.cc
+++ b/content/gpu/in_process_gpu_thread.cc
@@ -25,7 +25,7 @@
 #include "base/android/jni_android.h"
 #endif
 
-#if BUILDFLAG(IS_IOS)
+#if BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_IOS_TVOS)
 #include "gpu/ipc/common/ios/be_layer_hierarchy_transport.h"
 #endif
 
@@ -38,7 +38,7 @@
 
 }  // namespace
 
-#if BUILDFLAG(IS_IOS)
+#if BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_IOS_TVOS)
 class InProcessGpuThread::BELayerHierarchyTransportImpl
     : public gpu::BELayerHierarchyTransport {
  public:
@@ -88,7 +88,7 @@
   io_thread_type = base::ThreadType::kDisplayCritical;
 #endif
 
-#if BUILDFLAG(IS_IOS)
+#if BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_IOS_TVOS)
   be_layer_transport_ =
       std::make_unique<InProcessGpuThread::BELayerHierarchyTransportImpl>();
 #endif
diff --git a/content/gpu/in_process_gpu_thread.h b/content/gpu/in_process_gpu_thread.h
index 838b022..a97445de 100644
--- a/content/gpu/in_process_gpu_thread.h
+++ b/content/gpu/in_process_gpu_thread.h
@@ -33,7 +33,7 @@
   void CleanUp() override;
 
  private:
-#if BUILDFLAG(IS_IOS)
+#if BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_IOS_TVOS)
   class BELayerHierarchyTransportImpl;
 #endif
 
@@ -42,7 +42,7 @@
   // Deleted in CleanUp() on the gpu thread, so don't use smart pointers.
   std::unique_ptr<ChildProcess> gpu_process_;
   gpu::GpuPreferences gpu_preferences_;
-#if BUILDFLAG(IS_IOS)
+#if BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_IOS_TVOS)
   std::unique_ptr<BELayerHierarchyTransportImpl> be_layer_transport_;
 #endif
 };
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn
index 8a8e2fd..835f6b87 100644
--- a/content/public/android/BUILD.gn
+++ b/content/public/android/BUILD.gn
@@ -232,11 +232,11 @@
     ":content_jni_headers",
     ":is_ready_to_pay_service_aidl",
     "//content/browser:client_data_json_generated_enum",
-    "//content/browser:transfer_input_to_viz_result_enum",
     "//content/browser/accessibility:content_browser_accessibility_java_enums_srcjar",
     "//content/browser/sms:sms_provider_gms_backend_enum",
     "//content/public/browser:bluetooth_chooser_event_javagen",
     "//content/public/browser:digital_identity_enum",
+    "//content/public/browser:transfer_input_to_viz_result_enum",
     "//ui/touch_selection:ui_touch_handle_orientation_srcjar",
     "//ui/touch_selection:ui_touch_selection_enums_srcjar",
   ]
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn
index 2f6e47c..03fbaa8b 100644
--- a/content/public/browser/BUILD.gn
+++ b/content/public/browser/BUILD.gn
@@ -769,6 +769,9 @@
       "digital_identity_provider.h",
     ]
   }
+  java_cpp_enum("transfer_input_to_viz_result_enum") {
+    sources = [ "android/transfer_input_to_viz_result.h" ]
+  }
 }
 
 proto_library("proto") {
diff --git a/content/browser/renderer_host/input/transfer_input_to_viz_result.h b/content/public/browser/android/transfer_input_to_viz_result.h
similarity index 80%
rename from content/browser/renderer_host/input/transfer_input_to_viz_result.h
rename to content/public/browser/android/transfer_input_to_viz_result.h
index 6941dba..796fab21 100644
--- a/content/browser/renderer_host/input/transfer_input_to_viz_result.h
+++ b/content/public/browser/android/transfer_input_to_viz_result.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_TRANSFER_INPUT_TO_VIZ_RESULT_H_
-#define CONTENT_BROWSER_RENDERER_HOST_INPUT_TRANSFER_INPUT_TO_VIZ_RESULT_H_
+#ifndef CONTENT_PUBLIC_BROWSER_ANDROID_TRANSFER_INPUT_TO_VIZ_RESULT_H_
+#define CONTENT_PUBLIC_BROWSER_ANDROID_TRANSFER_INPUT_TO_VIZ_RESULT_H_
 
 namespace content {
 
@@ -30,4 +30,4 @@
 
 }  // namespace content
 
-#endif  // CONTENT_BROWSER_RENDERER_HOST_INPUT_TRANSFER_INPUT_TO_VIZ_RESULT_H_
+#endif  // CONTENT_PUBLIC_BROWSER_ANDROID_TRANSFER_INPUT_TO_VIZ_RESULT_H_
diff --git a/content/public/common/content_switch_dependent_feature_overrides.cc b/content/public/common/content_switch_dependent_feature_overrides.cc
index 1ed6ca09..35db8043 100644
--- a/content/public/common/content_switch_dependent_feature_overrides.cc
+++ b/content/public/common/content_switch_dependent_feature_overrides.cc
@@ -46,6 +46,10 @@
        std::cref(features::kOriginIsolationHeader),
        base::FeatureList::OVERRIDE_ENABLE_FEATURE},
       {switches::kEnableExperimentalWebPlatformFeatures,
+       std::cref(
+           blink::features::kDocumentPolicyIncludeJSCallStacksInCrashReports),
+       base::FeatureList::OVERRIDE_ENABLE_FEATURE},
+      {switches::kEnableExperimentalWebPlatformFeatures,
        std::cref(features::kEnableCanvas2DLayers),
        base::FeatureList::OVERRIDE_ENABLE_FEATURE},
       {switches::kEnableExperimentalWebPlatformFeatures,
diff --git a/content/public/test/browser_test_base.cc b/content/public/test/browser_test_base.cc
index 0555a07..cf0cbd1 100644
--- a/content/public/test/browser_test_base.cc
+++ b/content/public/test/browser_test_base.cc
@@ -530,8 +530,8 @@
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kEnableTracing)) {
     DCHECK(!logging::GetLogMessageHandler());
-    logging::SetLogMessageHandler([](int severity, std::string_view file,
-                                     int line, size_t message_start,
+    logging::SetLogMessageHandler([](int severity, const char* file, int line,
+                                     size_t message_start,
                                      const std::string& str) {
       // TODO(crbug.com/40161080): Print the message to the console before
       // calling this to ensure that the message is still printed if something
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc
index a222102..02d8a20 100644
--- a/content/public/test/browser_test_utils.cc
+++ b/content/public/test/browser_test_utils.cc
@@ -1008,6 +1008,14 @@
   rwhi->InsertVisualStateCallback(std::move(first_frame_done));
 }
 
+void SimulateEndOfPaintHoldingOnPrimaryMainFrame(WebContents* web_contents) {
+  WebContentsImpl* web_contents_impl =
+      static_cast<WebContentsImpl*>(web_contents);
+  RenderWidgetHostImpl* main_frame_rwh =
+      web_contents_impl->GetPrimaryMainFrame()->GetRenderWidgetHost();
+  main_frame_rwh->ForceFirstFrameAfterNavigationTimeout();
+}
+
 void SimulateMouseClick(WebContents* web_contents,
                         int modifiers,
                         blink::WebMouseEvent::Button button) {
diff --git a/content/public/test/browser_test_utils.h b/content/public/test/browser_test_utils.h
index dca0d2a8..91afbb9 100644
--- a/content/public/test/browser_test_utils.h
+++ b/content/public/test/browser_test_utils.h
@@ -349,8 +349,12 @@
 // RenderWidgetHostInputEventRouter and thus can target OOPIFs. If an OOPIF is
 // the intended target, ensure that its hit test data is available for routing,
 // using `WaitForHitTestData`, first.
-// Note: For simulating clicks inside a fenced frame tree, this function does
-// not work. Use `SimulateClickInFencedFrameTree` in
+//
+// Notes:
+// - Input events to a page may not work right after a page load, see
+// `SimulateEndOfPaintHoldingOnPrimaryMainFrame` for a workaround.
+// - For simulating clicks inside a fenced frame tree, this function does not
+// work. Use `SimulateClickInFencedFrameTree` in
 // `content/public/test/fenced_frame_test_util.cc`
 void SimulateMouseClick(WebContents* web_contents,
                         int modifiers,
@@ -361,8 +365,12 @@
 // through RenderWidgetHostInputEventRouter and thus can target OOPIFs. If an
 // OOPIF is the intended target, ensure that its hit test data is available for
 // routing, using `WaitForHitTestData`, first.
-// Note: For simulating clicks inside a fenced frame tree, this function does
-// not work. Use `SimulateClickInFencedFrameTree` in
+//
+// Notes:
+// - Input events to a page may not work right after a page load, see
+// `SimulateEndOfPaintHoldingOnPrimaryMainFrame` for a workaround.
+// - For simulating clicks inside a fenced frame tree, this function does not
+// work. Use `SimulateClickInFencedFrameTree` in
 // `content/public/test/fenced_frame_test_util.cc`
 void SimulateMouseClickAt(WebContents* web_contents,
                           int modifiers,
@@ -383,11 +391,17 @@
 
 // Retrieves the center coordinates of the element with id |id| and simulates a
 // mouse click there using SimulateMouseClickAt().
+//
+// Note: Input events to a page may not work right after a page load, see
+// `SimulateEndOfPaintHoldingOnPrimaryMainFrame` for a workaround.
 void SimulateMouseClickOrTapElementWithId(content::WebContents* web_contents,
                                           std::string_view id);
 
 // Simulates asynchronously a mouse enter/move/leave event. The mouse event is
 // routed through RenderWidgetHostInputEventRouter and thus can target OOPIFs.
+//
+// Note: Input events to a page may not work right after a page load, see
+// `SimulateEndOfPaintHoldingOnPrimaryMainFrame` for a workaround.
 void SimulateMouseEvent(WebContents* web_contents,
                         blink::WebInputEvent::Type type,
                         const gfx::Point& point);
@@ -397,6 +411,9 @@
                         const gfx::Point& point);
 
 // Simulate a mouse wheel event.
+//
+// Note: Input events to a page may not work right after a page load, see
+// `SimulateEndOfPaintHoldingOnPrimaryMainFrame` for a workaround.
 void SimulateMouseWheelEvent(WebContents* web_contents,
                              const gfx::Point& point,
                              const gfx::Vector2d& delta,
@@ -417,34 +434,42 @@
 #endif  // !BUILDFLAG(IS_MAC)
 
 // Sends a GesturePinch Begin/Update/End sequence.
+//
+// Note: Input events to a page may not work right after a page load, see
+// `SimulateEndOfPaintHoldingOnPrimaryMainFrame` for a workaround.
 void SimulateGesturePinchSequence(RenderWidgetHost* render_widget_host,
                                   const gfx::Point& point,
                                   float scale,
                                   blink::WebGestureDevice source_device);
-
 void SimulateGesturePinchSequence(WebContents* web_contents,
                                   const gfx::Point& point,
                                   float scale,
                                   blink::WebGestureDevice source_device);
 
 // Sends a simple, three-event (Begin/Update/End) gesture scroll.
+//
+// Note: Input event to a page may not work right after a page load, see
+// `SimulateEndOfPaintHoldingOnPrimaryMainFrame` for a workaround.
 void SimulateGestureScrollSequence(RenderWidgetHost* render_widget_host,
                                    const gfx::Point& point,
                                    const gfx::Vector2dF& delta);
-
 void SimulateGestureScrollSequence(WebContents* web_contents,
                                    const gfx::Point& point,
                                    const gfx::Vector2dF& delta);
 
+// Note: Input event to a page may not work right after a page load, see
+// `SimulateEndOfPaintHoldingOnPrimaryMainFrame` for a workaround.
 void SimulateGestureEvent(RenderWidgetHost* render_widget_host,
                           const blink::WebGestureEvent& gesture_event,
                           const ui::LatencyInfo& latency);
-
 void SimulateGestureEvent(WebContents* web_contents,
                           const blink::WebGestureEvent& gesture_event,
                           const ui::LatencyInfo& latency);
 
 // Taps the screen at |point|, using gesture Tap or TapDown.
+//
+// Note: Input event to a page may not work right after a page load, see
+// `SimulateEndOfPaintHoldingOnPrimaryMainFrame` for a workaround.
 void SimulateTapAt(WebContents* web_contents, const gfx::Point& point);
 void SimulateTapDownAt(WebContents* web_contents, const gfx::Point& point);
 
@@ -455,10 +480,15 @@
 
 #if defined(USE_AURA)
 // Generates a TouchEvent of |event_type| at |point|.
+//
+// Note: Input event to a page may not work right after a page load, see
+// `SimulateEndOfPaintHoldingOnPrimaryMainFrame` for a workaround.
 void SimulateTouchEventAt(WebContents* web_contents,
                           ui::EventType event_type,
                           const gfx::Point& point);
 
+// Note: Input event to a page may not work right after a page load, see
+// `SimulateEndOfPaintHoldingOnPrimaryMainFrame` for a workaround.
 void SimulateLongTapAt(WebContents* web_contents, const gfx::Point& point);
 
 // Can be used to wait for the caret bounds associated with `web_contents` to
@@ -508,6 +538,9 @@
 #endif
 
 // Taps the screen with modifires at |point|.
+//
+// Note: Input event to a page may not work right after a page load, see
+// `SimulateEndOfPaintHoldingOnPrimaryMainFrame` for a workaround.
 void SimulateTapWithModifiersAt(WebContents* web_contents,
                                 unsigned Modifiers,
                                 const gfx::Point& point);
@@ -520,6 +553,9 @@
 // or the keyboard layout.
 // If set to true, the modifiers |control|, |shift|, |alt|, and |command| are
 // pressed down first before the key event, and released after.
+//
+// Note: Input event to a page may not work right after a page load, see
+// `SimulateEndOfPaintHoldingOnPrimaryMainFrame` for a workaround.
 void SimulateKeyPress(WebContents* web_contents,
                       ui::DomKey key,
                       ui::DomCode code,
@@ -532,6 +568,9 @@
 // Like SimulateKeyPress(), but does not send the char (AKA keypress) event.
 // This is useful for arrow keys and other key presses that do not generate
 // characters.
+//
+// Note: Input event to a page may not work right after a page load, see
+// `SimulateEndOfPaintHoldingOnPrimaryMainFrame` for a workaround.
 void SimulateKeyPressWithoutChar(WebContents* web_contents,
                                  ui::DomKey key,
                                  ui::DomCode code,
@@ -572,6 +611,17 @@
 // RenderFrameHost
 void SimulateActiveStateForWidget(RenderFrameHost* frame, bool active);
 
+// Simulates the end of paint-holding on the primary main frame of
+// `web_contents`. Paint-holding is the browser feature to continue to show a
+// snapshot of the pre-navigation page (instead of a blank page) until the
+// renderer for the post-navigation page has pushed content to the GPU.  The
+// input events received during paint-holding should not be processed by the
+// post-navigation renderer because the users haven't yet seen the new page.
+//
+// Tests that are paint-holding agnostic need to call this method to be able to
+// send input events to a page right after the page is loaded.
+void SimulateEndOfPaintHoldingOnPrimaryMainFrame(WebContents* web_contents);
+
 // Return the value set for VisitedLinkSalt in the navigation's commit_params.
 std::optional<uint64_t> GetVisitedLinkSaltForNavigation(
     NavigationHandle* navigation_handle);
diff --git a/content/public/test/network_service_test_helper.cc b/content/public/test/network_service_test_helper.cc
index bcdffbd..f0b9906 100644
--- a/content/public/test/network_service_test_helper.cc
+++ b/content/public/test/network_service_test_helper.cc
@@ -635,9 +635,8 @@
   void GetEnvironmentVariableValue(
       const std::string& name,
       GetEnvironmentVariableValueCallback callback) override {
-    std::string value;
-    base::Environment::Create()->GetVar(name, &value);
-    std::move(callback).Run(value);
+    std::move(callback).Run(
+        base::Environment::Create()->GetVar(name).value_or(std::string()));
   }
 
   void Log(const std::string& message, LogCallback callback) override {
diff --git a/content/services/auction_worklet/bidder_worklet.cc b/content/services/auction_worklet/bidder_worklet.cc
index c7a2c582..34745083 100644
--- a/content/services/auction_worklet/bidder_worklet.cc
+++ b/content/services/auction_worklet/bidder_worklet.cc
@@ -979,7 +979,7 @@
     ContextRecycler& context_recycler,
     const std::optional<std::string>& auction_signals_json,
     const std::optional<std::string>& per_buyer_signals_json,
-    const std::string seller_signals_json,
+    const std::string& seller_signals_json,
     bool is_for_additional_bid,
     const std::optional<std::string>& interest_group_name_reporting_id,
     const std::optional<std::string>& buyer_reporting_id,
diff --git a/content/services/auction_worklet/bidder_worklet.h b/content/services/auction_worklet/bidder_worklet.h
index 07fcdd5..f7bcf4fb 100644
--- a/content/services/auction_worklet/bidder_worklet.h
+++ b/content/services/auction_worklet/bidder_worklet.h
@@ -533,7 +533,7 @@
         ContextRecycler& context_recycler,
         const std::optional<std::string>& auction_signals_json,
         const std::optional<std::string>& per_buyer_signals_json,
-        const std::string seller_signals_json,
+        const std::string& seller_signals_json,
         bool is_for_additional_bid,
         const std::optional<std::string>& interest_group_name_reporting_id,
         const std::optional<std::string>& buyer_reporting_id,
diff --git a/content/test/mock_clipboard_host.cc b/content/test/mock_clipboard_host.cc
index 1febe00..6da6a92 100644
--- a/content/test/mock_clipboard_host.cc
+++ b/content/test/mock_clipboard_host.cc
@@ -51,14 +51,18 @@
 
 std::vector<std::u16string> MockClipboardHost::ReadStandardFormatNames() {
   std::vector<std::u16string> types;
-  if (!plain_text_.empty())
-    types.push_back(base::ASCIIToUTF16(ui::kMimeTypePlainText));
-  if (!html_text_.empty())
-    types.push_back(base::ASCIIToUTF16(ui::kMimeTypeHtml));
-  if (!svg_text_.empty())
-    types.push_back(base::ASCIIToUTF16(ui::kMimeTypeSvg));
-  if (!png_.empty())
-    types.push_back(base::ASCIIToUTF16(ui::kMimeTypePng));
+  if (!plain_text_.empty()) {
+    types.push_back(ui::kMimeTypePlainText16);
+  }
+  if (!html_text_.empty()) {
+    types.push_back(ui::kMimeTypeHtml16);
+  }
+  if (!svg_text_.empty()) {
+    types.push_back(ui::kMimeTypeSvg16);
+  }
+  if (!png_.empty()) {
+    types.push_back(ui::kMimeTypePng16);
+  }
   for (auto& it : custom_data_) {
     CHECK(!base::Contains(types, it.first));
     types.push_back(it.first);
@@ -212,7 +216,7 @@
   // Append the "web " prefix since it is removed by the clipboard writer during
   // write.
   std::u16string web_format =
-      base::StrCat({base::ASCIIToUTF16(ui::kWebClipboardFormatPrefix), format});
+      base::StrCat({ui::kWebClipboardFormatPrefix16, format});
   unsanitized_custom_data_map_[web_format] = std::move(data_copy);
 }
 
diff --git a/extensions/browser/extension_registrar.cc b/extensions/browser/extension_registrar.cc
index b2583a6..fbf5725 100644
--- a/extensions/browser/extension_registrar.cc
+++ b/extensions/browser/extension_registrar.cc
@@ -207,6 +207,23 @@
   }
 }
 
+void ExtensionRegistrar::AddNewOrUpdatedExtension(
+    const Extension* extension,
+    const base::flat_set<int>& disable_reasons,
+    int install_flags,
+    const syncer::StringOrdinal& page_ordinal,
+    const std::string& install_parameter,
+    base::Value::Dict ruleset_install_prefs) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  extension_prefs_->OnExtensionInstalled(
+      extension, disable_reasons, page_ordinal, install_flags,
+      install_parameter, std::move(ruleset_install_prefs));
+
+  delegate_->OnAddNewOrUpdatedExtension(extension);
+
+  FinishInstallation(extension);
+}
+
 void ExtensionRegistrar::RemoveExtension(const ExtensionId& extension_id,
                                          UnloadedExtensionReason reason) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
diff --git a/extensions/browser/extension_registrar.h b/extensions/browser/extension_registrar.h
index 2faa6ab3..1026acbf 100644
--- a/extensions/browser/extension_registrar.h
+++ b/extensions/browser/extension_registrar.h
@@ -14,6 +14,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/scoped_observation.h"
 #include "components/keyed_service/core/keyed_service.h"
+#include "components/sync/model/string_ordinal.h"
 #include "extensions/browser/blocklist_state.h"
 #include "extensions/browser/disable_reason.h"
 #include "extensions/browser/extension_prefs.h"
@@ -66,6 +67,9 @@
     virtual void PreAddExtension(const Extension* extension,
                                  const Extension* old_extension) = 0;
 
+    // Handles extension install tasks before AddExtension.
+    virtual void OnAddNewOrUpdatedExtension(const Extension* extension) = 0;
+
     // Handles updating the browser context when an extension is activated
     // (becomes enabled).
     virtual void PostActivateExtension(
@@ -153,6 +157,18 @@
   // added as enabled, it will be activated.
   void AddExtension(scoped_refptr<const Extension> extension);
 
+  // Updates preferences for a new or updated extension; notifies observers that
+  // the extension is installed, e.g., to update event handlers on background
+  // pages; and performs other extension install tasks before calling
+  // AddExtension.
+  // |install_flags| is a bitmask of InstallFlags.
+  void AddNewOrUpdatedExtension(const Extension* extension,
+                                const base::flat_set<int>& disable_reasons,
+                                int install_flags,
+                                const syncer::StringOrdinal& page_ordinal,
+                                const std::string& install_parameter,
+                                base::Value::Dict ruleset_install_prefs);
+
   // Removes |extension| from the extension system by deactivating it if it is
   // enabled and removing references to it from the ExtensionRegistry's
   // enabled, disabled or terminated sets.
diff --git a/extensions/browser/extension_registrar_unittest.cc b/extensions/browser/extension_registrar_unittest.cc
index f0739ac..dfd35396 100644
--- a/extensions/browser/extension_registrar_unittest.cc
+++ b/extensions/browser/extension_registrar_unittest.cc
@@ -69,6 +69,7 @@
   MOCK_METHOD2(PreAddExtension,
                void(const Extension* extension,
                     const Extension* old_extension));
+  MOCK_METHOD1(OnAddNewOrUpdatedExtension, void(const Extension* extension));
   MOCK_METHOD1(PostActivateExtension,
                void(scoped_refptr<const Extension> extension));
   MOCK_METHOD1(PostDeactivateExtension,
diff --git a/extensions/shell/browser/shell_extension_loader.cc b/extensions/shell/browser/shell_extension_loader.cc
index 01377daea..c7f4d24a 100644
--- a/extensions/shell/browser/shell_extension_loader.cc
+++ b/extensions/shell/browser/shell_extension_loader.cc
@@ -142,6 +142,9 @@
                                        disable_reason::DISABLE_RELOAD);
 }
 
+void ShellExtensionLoader::OnAddNewOrUpdatedExtension(
+    const Extension* extension) {}
+
 void ShellExtensionLoader::PostActivateExtension(
     scoped_refptr<const Extension> extension) {}
 
diff --git a/extensions/shell/browser/shell_extension_loader.h b/extensions/shell/browser/shell_extension_loader.h
index 8fad87d..2e2df1b8 100644
--- a/extensions/shell/browser/shell_extension_loader.h
+++ b/extensions/shell/browser/shell_extension_loader.h
@@ -55,6 +55,7 @@
   bool CanAddExtension(const Extension* extension) override;
   void PreAddExtension(const Extension* extension,
                        const Extension* old_extension) override;
+  void OnAddNewOrUpdatedExtension(const Extension* extension) override;
   void PostActivateExtension(scoped_refptr<const Extension> extension) override;
   void PostDeactivateExtension(
       scoped_refptr<const Extension> extension) override;
diff --git a/headless/lib/browser/protocol/target_handler.cc b/headless/lib/browser/protocol/target_handler.cc
index 720a515e0..4fcfeb7 100644
--- a/headless/lib/browser/protocol/target_handler.cc
+++ b/headless/lib/browser/protocol/target_handler.cc
@@ -34,11 +34,6 @@
     auto agent_host = content::DevToolsAgentHost::GetForId(target_id);
     if (agent_host) {
       // The target is still alive, so destroy it.
-      DCHECK(agent_host->GetWebContents());
-
-      HeadlessWebContentsImpl* web_contents =
-          HeadlessWebContentsImpl::From(agent_host->GetWebContents());
-      web_contents->Close();
       agent_host->Close();
     }
     hidden_web_contents_.erase(hidden_web_contents_.begin());
diff --git a/headless/test/data/protocol/sanity/hidden-target-create-expected.txt b/headless/test/data/protocol/sanity/hidden-target-create-expected.txt
index af8e178b..8610f493 100644
--- a/headless/test/data/protocol/sanity/hidden-target-create-expected.txt
+++ b/headless/test/data/protocol/sanity/hidden-target-create-expected.txt
@@ -35,6 +35,12 @@
         targetId : <string 0>
     }
 }
+TargetDestroyed{
+    method : Target.targetDestroyed
+    params : {
+        targetId : <string 0>
+    }
+}
 Expected error response: {
     code : -32001
     message : Session with given id not found.
diff --git a/headless/test/data/protocol/sanity/hidden-target-create.js b/headless/test/data/protocol/sanity/hidden-target-create.js
index 11c5c84..6691f7020 100644
--- a/headless/test/data/protocol/sanity/hidden-target-create.js
+++ b/headless/test/data/protocol/sanity/hidden-target-create.js
@@ -21,6 +21,9 @@
   testRunner.browserP().Target.onDetachedFromTarget((event) => {
     testRunnerLog(event, 'DetachedFromTarget');
   });
+  testRunner.browserP().Target.onTargetDestroyed((event) => {
+    testRunnerLog(event, 'TargetDestroyed');
+  });
   /**
    * Filter out the targets that are already present in the existing targets set
    * keeping only the new targets. If the result is an error, return the error.
@@ -68,7 +71,9 @@
       `Filtered targets via browser session: `);
 
   testRunnerLog('Disconnect the parent session');
-  await newBrowserSession.disconnect();
+  newBrowserSession.disconnect();
+
+  await testRunner.browserP().Target.onceTargetDestroyed();
 
   // Verify the hidden target's session is closed.
   testRunnerLog(
diff --git a/infra/config/dev/subprojects/chromium/ci.star b/infra/config/dev/subprojects/chromium/ci.star
index d1736e63..181e03ba 100644
--- a/infra/config/dev/subprojects/chromium/ci.star
+++ b/infra/config/dev/subprojects/chromium/ci.star
@@ -116,14 +116,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "main_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.ARM,
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder_mb",
+            config = "base_config",
         ),
     ),
     gn_args = gn_args.config(
diff --git a/infra/config/generated/builders-dev/ci/android-pie-arm64-rel-dev/properties.json b/infra/config/generated/builders-dev/ci/android-pie-arm64-rel-dev/properties.json
index 96c8ac3..4861ab1 100644
--- a/infra/config/generated/builders-dev/ci/android-pie-arm64-rel-dev/properties.json
+++ b/infra/config/generated/builders-dev/ci/android-pie-arm64-rel-dev/properties.json
@@ -19,11 +19,14 @@
               "builder_group": "chromium.dev",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/build/android-build-perf-developer/properties.json b/infra/config/generated/builders/build/android-build-perf-developer/properties.json
index 98e27c4..054b1e4c 100644
--- a/infra/config/generated/builders/build/android-build-perf-developer/properties.json
+++ b/infra/config/generated/builders/build/android-build-perf-developer/properties.json
@@ -16,7 +16,7 @@
               "builder_group": "chromium.build",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/build/android-build-perf-ninja/properties.json b/infra/config/generated/builders/build/android-build-perf-ninja/properties.json
index bc349f2..900dc82b 100644
--- a/infra/config/generated/builders/build/android-build-perf-ninja/properties.json
+++ b/infra/config/generated/builders/build/android-build-perf-ninja/properties.json
@@ -16,7 +16,7 @@
               "builder_group": "chromium.build",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/build/android-build-perf-siso/properties.json b/infra/config/generated/builders/build/android-build-perf-siso/properties.json
index f79a4430..56f4b2e 100644
--- a/infra/config/generated/builders/build/android-build-perf-siso/properties.json
+++ b/infra/config/generated/builders/build/android-build-perf-siso/properties.json
@@ -16,7 +16,7 @@
               "builder_group": "chromium.build",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git "a/infra/config/generated/builders/ci/Android FYI Experimental Release \050Pixel 6\051/properties.json" "b/infra/config/generated/builders/ci/Android FYI Experimental Release \050Pixel 6\051/properties.json"
index 41d2717..5bdb384 100644
--- "a/infra/config/generated/builders/ci/Android FYI Experimental Release \050Pixel 6\051/properties.json"
+++ "b/infra/config/generated/builders/ci/Android FYI Experimental Release \050Pixel 6\051/properties.json"
@@ -13,14 +13,15 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -49,14 +50,15 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git "a/infra/config/generated/builders/ci/Android FYI Release \050NVIDIA Shield TV\051/properties.json" "b/infra/config/generated/builders/ci/Android FYI Release \050NVIDIA Shield TV\051/properties.json"
index f86c386..d6b9920 100644
--- "a/infra/config/generated/builders/ci/Android FYI Release \050NVIDIA Shield TV\051/properties.json"
+++ "b/infra/config/generated/builders/ci/Android FYI Release \050NVIDIA Shield TV\051/properties.json"
@@ -13,7 +13,7 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
@@ -46,7 +46,7 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
diff --git "a/infra/config/generated/builders/ci/Android FYI Release \050Nexus 5X\051/properties.json" "b/infra/config/generated/builders/ci/Android FYI Release \050Nexus 5X\051/properties.json"
index 3e4f10f..32bd6b31 100644
--- "a/infra/config/generated/builders/ci/Android FYI Release \050Nexus 5X\051/properties.json"
+++ "b/infra/config/generated/builders/ci/Android FYI Release \050Nexus 5X\051/properties.json"
@@ -13,14 +13,15 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -48,14 +49,15 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git "a/infra/config/generated/builders/ci/Android FYI Release \050Pixel 2\051/properties.json" "b/infra/config/generated/builders/ci/Android FYI Release \050Pixel 2\051/properties.json"
index 307d6221..8672f9b0 100644
--- "a/infra/config/generated/builders/ci/Android FYI Release \050Pixel 2\051/properties.json"
+++ "b/infra/config/generated/builders/ci/Android FYI Release \050Pixel 2\051/properties.json"
@@ -13,7 +13,7 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
@@ -45,7 +45,7 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
diff --git "a/infra/config/generated/builders/ci/Android FYI Release \050Pixel 4\051/properties.json" "b/infra/config/generated/builders/ci/Android FYI Release \050Pixel 4\051/properties.json"
index 8791acb..0f16f2ed 100644
--- "a/infra/config/generated/builders/ci/Android FYI Release \050Pixel 4\051/properties.json"
+++ "b/infra/config/generated/builders/ci/Android FYI Release \050Pixel 4\051/properties.json"
@@ -13,7 +13,7 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
@@ -45,7 +45,7 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
diff --git "a/infra/config/generated/builders/ci/Android FYI Release \050Pixel 6\051/properties.json" "b/infra/config/generated/builders/ci/Android FYI Release \050Pixel 6\051/properties.json"
index 2df09f6..ba56d2d 100644
--- "a/infra/config/generated/builders/ci/Android FYI Release \050Pixel 6\051/properties.json"
+++ "b/infra/config/generated/builders/ci/Android FYI Release \050Pixel 6\051/properties.json"
@@ -13,14 +13,15 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -49,14 +50,15 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git "a/infra/config/generated/builders/ci/Android FYI Release \050Samsung A13\051/properties.json" "b/infra/config/generated/builders/ci/Android FYI Release \050Samsung A13\051/properties.json"
index e241470..81b14cb 100644
--- "a/infra/config/generated/builders/ci/Android FYI Release \050Samsung A13\051/properties.json"
+++ "b/infra/config/generated/builders/ci/Android FYI Release \050Samsung A13\051/properties.json"
@@ -13,7 +13,7 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
@@ -46,7 +46,7 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
diff --git "a/infra/config/generated/builders/ci/Android FYI Release \050Samsung A23\051/properties.json" "b/infra/config/generated/builders/ci/Android FYI Release \050Samsung A23\051/properties.json"
index 573b631..78b4c44 100644
--- "a/infra/config/generated/builders/ci/Android FYI Release \050Samsung A23\051/properties.json"
+++ "b/infra/config/generated/builders/ci/Android FYI Release \050Samsung A23\051/properties.json"
@@ -13,7 +13,7 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
@@ -46,7 +46,7 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
diff --git "a/infra/config/generated/builders/ci/Android FYI Release \050Samsung S23\051/properties.json" "b/infra/config/generated/builders/ci/Android FYI Release \050Samsung S23\051/properties.json"
index e291597..cf545ed 100644
--- "a/infra/config/generated/builders/ci/Android FYI Release \050Samsung S23\051/properties.json"
+++ "b/infra/config/generated/builders/ci/Android FYI Release \050Samsung S23\051/properties.json"
@@ -13,11 +13,14 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -46,14 +49,15 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git "a/infra/config/generated/builders/ci/Android Release \050Nexus 5X\051/properties.json" "b/infra/config/generated/builders/ci/Android Release \050Nexus 5X\051/properties.json"
index e459389..ef94923f 100644
--- "a/infra/config/generated/builders/ci/Android Release \050Nexus 5X\051/properties.json"
+++ "b/infra/config/generated/builders/ci/Android Release \050Nexus 5X\051/properties.json"
@@ -17,7 +17,7 @@
               "builder_group": "chromium.gpu",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git "a/infra/config/generated/builders/ci/Android Release \050Pixel 2\051/properties.json" "b/infra/config/generated/builders/ci/Android Release \050Pixel 2\051/properties.json"
index 95fc8a6..dd06105 100644
--- "a/infra/config/generated/builders/ci/Android Release \050Pixel 2\051/properties.json"
+++ "b/infra/config/generated/builders/ci/Android Release \050Pixel 2\051/properties.json"
@@ -17,7 +17,7 @@
               "builder_group": "chromium.gpu",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git "a/infra/config/generated/builders/ci/Android WebView O \050dbg\051/properties.json" "b/infra/config/generated/builders/ci/Android WebView O \050dbg\051/properties.json"
index 51dfbb1..173f1db 100644
--- "a/infra/config/generated/builders/ci/Android WebView O \050dbg\051/properties.json"
+++ "b/infra/config/generated/builders/ci/Android WebView O \050dbg\051/properties.json"
@@ -17,14 +17,15 @@
                 "apply_configs": [
                   "remove_all_system_webviews"
                 ],
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -53,14 +54,15 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git "a/infra/config/generated/builders/ci/Android WebView P \050dbg\051/properties.json" "b/infra/config/generated/builders/ci/Android WebView P \050dbg\051/properties.json"
index 6213804..6cfa5d43 100644
--- "a/infra/config/generated/builders/ci/Android WebView P \050dbg\051/properties.json"
+++ "b/infra/config/generated/builders/ci/Android WebView P \050dbg\051/properties.json"
@@ -17,14 +17,15 @@
                 "apply_configs": [
                   "remove_all_system_webviews"
                 ],
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -53,14 +54,15 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git "a/infra/config/generated/builders/ci/Android arm Builder \050dbg\051/properties.json" "b/infra/config/generated/builders/ci/Android arm Builder \050dbg\051/properties.json"
index 703e1c7..7f5e2ec 100644
--- "a/infra/config/generated/builders/ci/Android arm Builder \050dbg\051/properties.json"
+++ "b/infra/config/generated/builders/ci/Android arm Builder \050dbg\051/properties.json"
@@ -17,14 +17,15 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git "a/infra/config/generated/builders/ci/Android arm64 Builder \050dbg\051/properties.json" "b/infra/config/generated/builders/ci/Android arm64 Builder \050dbg\051/properties.json"
index 2d93648..27982868e 100644
--- "a/infra/config/generated/builders/ci/Android arm64 Builder \050dbg\051/properties.json"
+++ "b/infra/config/generated/builders/ci/Android arm64 Builder \050dbg\051/properties.json"
@@ -20,14 +20,15 @@
                 "apply_configs": [
                   "remove_all_system_webviews"
                 ],
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -59,14 +60,15 @@
                 "apply_configs": [
                   "remove_all_system_webviews"
                 ],
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -95,14 +97,15 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -126,14 +129,15 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -162,14 +166,15 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git "a/infra/config/generated/builders/ci/Android arm64 Builder All Targets \050dbg\051/properties.json" "b/infra/config/generated/builders/ci/Android arm64 Builder All Targets \050dbg\051/properties.json"
index 6b7bf8f6..c5e341a 100644
--- "a/infra/config/generated/builders/ci/Android arm64 Builder All Targets \050dbg\051/properties.json"
+++ "b/infra/config/generated/builders/ci/Android arm64 Builder All Targets \050dbg\051/properties.json"
@@ -17,14 +17,15 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git "a/infra/config/generated/builders/ci/Android x64 Builder \050dbg\051/properties.json" "b/infra/config/generated/builders/ci/Android x64 Builder \050dbg\051/properties.json"
index bd37149..b122d0a 100644
--- "a/infra/config/generated/builders/ci/Android x64 Builder \050dbg\051/properties.json"
+++ "b/infra/config/generated/builders/ci/Android x64 Builder \050dbg\051/properties.json"
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -45,11 +48,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -78,14 +84,15 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -114,14 +121,15 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -150,11 +158,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -183,11 +194,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -216,11 +230,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -249,11 +266,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git "a/infra/config/generated/builders/ci/Android x64 Builder All Targets \050dbg\051/properties.json" "b/infra/config/generated/builders/ci/Android x64 Builder All Targets \050dbg\051/properties.json"
index 8d06354..d1b6c0a 100644
--- "a/infra/config/generated/builders/ci/Android x64 Builder All Targets \050dbg\051/properties.json"
+++ "b/infra/config/generated/builders/ci/Android x64 Builder All Targets \050dbg\051/properties.json"
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git "a/infra/config/generated/builders/ci/Android x86 Builder \050dbg\051/properties.json" "b/infra/config/generated/builders/ci/Android x86 Builder \050dbg\051/properties.json"
index 4c6e33d..372e2581 100644
--- "a/infra/config/generated/builders/ci/Android x86 Builder \050dbg\051/properties.json"
+++ "b/infra/config/generated/builders/ci/Android x86 Builder \050dbg\051/properties.json"
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x86_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/Dawn Android arm Builder/properties.json b/infra/config/generated/builders/ci/Dawn Android arm Builder/properties.json
index 3f34f5b2..cc86be1 100644
--- a/infra/config/generated/builders/ci/Dawn Android arm Builder/properties.json
+++ b/infra/config/generated/builders/ci/Dawn Android arm Builder/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
@@ -47,7 +47,7 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
@@ -82,7 +82,7 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
diff --git a/infra/config/generated/builders/ci/Dawn Android arm DEPS Builder/properties.json b/infra/config/generated/builders/ci/Dawn Android arm DEPS Builder/properties.json
index a4299cc..71fd307 100644
--- a/infra/config/generated/builders/ci/Dawn Android arm DEPS Builder/properties.json
+++ b/infra/config/generated/builders/ci/Dawn Android arm DEPS Builder/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
@@ -46,7 +46,7 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
@@ -80,7 +80,7 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
diff --git "a/infra/config/generated/builders/ci/Dawn Android arm DEPS Release \050Nexus 5X\051/properties.json" "b/infra/config/generated/builders/ci/Dawn Android arm DEPS Release \050Nexus 5X\051/properties.json"
index be7d7a9..cd3855f 100644
--- "a/infra/config/generated/builders/ci/Dawn Android arm DEPS Release \050Nexus 5X\051/properties.json"
+++ "b/infra/config/generated/builders/ci/Dawn Android arm DEPS Release \050Nexus 5X\051/properties.json"
@@ -14,7 +14,7 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
@@ -43,7 +43,7 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
diff --git "a/infra/config/generated/builders/ci/Dawn Android arm DEPS Release \050Pixel 4\051/properties.json" "b/infra/config/generated/builders/ci/Dawn Android arm DEPS Release \050Pixel 4\051/properties.json"
index 3779995..7965dc0 100644
--- "a/infra/config/generated/builders/ci/Dawn Android arm DEPS Release \050Pixel 4\051/properties.json"
+++ "b/infra/config/generated/builders/ci/Dawn Android arm DEPS Release \050Pixel 4\051/properties.json"
@@ -14,7 +14,7 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
@@ -43,7 +43,7 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
diff --git "a/infra/config/generated/builders/ci/Dawn Android arm Release \050Nexus 5X\051/properties.json" "b/infra/config/generated/builders/ci/Dawn Android arm Release \050Nexus 5X\051/properties.json"
index c30b5daf..2a91f86 100644
--- "a/infra/config/generated/builders/ci/Dawn Android arm Release \050Nexus 5X\051/properties.json"
+++ "b/infra/config/generated/builders/ci/Dawn Android arm Release \050Nexus 5X\051/properties.json"
@@ -14,7 +14,7 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
@@ -44,7 +44,7 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
diff --git "a/infra/config/generated/builders/ci/Dawn Android arm Release \050Pixel 4\051/properties.json" "b/infra/config/generated/builders/ci/Dawn Android arm Release \050Pixel 4\051/properties.json"
index 497eb439..1de7d57c 100644
--- "a/infra/config/generated/builders/ci/Dawn Android arm Release \050Pixel 4\051/properties.json"
+++ "b/infra/config/generated/builders/ci/Dawn Android arm Release \050Pixel 4\051/properties.json"
@@ -14,7 +14,7 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
@@ -44,7 +44,7 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
diff --git a/infra/config/generated/builders/ci/Dawn Android arm64 Builder/properties.json b/infra/config/generated/builders/ci/Dawn Android arm64 Builder/properties.json
index dd0b596..9d7fb8b5 100644
--- a/infra/config/generated/builders/ci/Dawn Android arm64 Builder/properties.json
+++ b/infra/config/generated/builders/ci/Dawn Android arm64 Builder/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -46,11 +49,14 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -81,11 +87,14 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -116,11 +125,14 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/Dawn Android arm64 DEPS Builder/properties.json b/infra/config/generated/builders/ci/Dawn Android arm64 DEPS Builder/properties.json
index 99aa14d..07829341 100644
--- a/infra/config/generated/builders/ci/Dawn Android arm64 DEPS Builder/properties.json
+++ b/infra/config/generated/builders/ci/Dawn Android arm64 DEPS Builder/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -45,11 +48,14 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git "a/infra/config/generated/builders/ci/Dawn Android arm64 DEPS Release \050Pixel 6\051/properties.json" "b/infra/config/generated/builders/ci/Dawn Android arm64 DEPS Release \050Pixel 6\051/properties.json"
index cbbfa0d..db8d61b 100644
--- "a/infra/config/generated/builders/ci/Dawn Android arm64 DEPS Release \050Pixel 6\051/properties.json"
+++ "b/infra/config/generated/builders/ci/Dawn Android arm64 DEPS Release \050Pixel 6\051/properties.json"
@@ -14,11 +14,14 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -42,11 +45,14 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git "a/infra/config/generated/builders/ci/Dawn Android arm64 Experimental Release \050Pixel 6\051/properties.json" "b/infra/config/generated/builders/ci/Dawn Android arm64 Experimental Release \050Pixel 6\051/properties.json"
index b1ab1d5..0e9f54e 100644
--- "a/infra/config/generated/builders/ci/Dawn Android arm64 Experimental Release \050Pixel 6\051/properties.json"
+++ "b/infra/config/generated/builders/ci/Dawn Android arm64 Experimental Release \050Pixel 6\051/properties.json"
@@ -14,11 +14,14 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -43,11 +46,14 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git "a/infra/config/generated/builders/ci/Dawn Android arm64 Release \050Pixel 6\051/properties.json" "b/infra/config/generated/builders/ci/Dawn Android arm64 Release \050Pixel 6\051/properties.json"
index 7b12895..a6815ab 100644
--- "a/infra/config/generated/builders/ci/Dawn Android arm64 Release \050Pixel 6\051/properties.json"
+++ "b/infra/config/generated/builders/ci/Dawn Android arm64 Release \050Pixel 6\051/properties.json"
@@ -14,11 +14,14 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -43,11 +46,14 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git "a/infra/config/generated/builders/ci/Dawn Android arm64 Release \050Samsung S24\051/properties.json" "b/infra/config/generated/builders/ci/Dawn Android arm64 Release \050Samsung S24\051/properties.json"
index 8847c05c..915f2ae 100644
--- "a/infra/config/generated/builders/ci/Dawn Android arm64 Release \050Samsung S24\051/properties.json"
+++ "b/infra/config/generated/builders/ci/Dawn Android arm64 Release \050Samsung S24\051/properties.json"
@@ -14,11 +14,14 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -43,11 +46,14 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/GPU FYI Android arm Builder/properties.json b/infra/config/generated/builders/ci/GPU FYI Android arm Builder/properties.json
index 5f403278..e161160a 100644
--- a/infra/config/generated/builders/ci/GPU FYI Android arm Builder/properties.json
+++ b/infra/config/generated/builders/ci/GPU FYI Android arm Builder/properties.json
@@ -16,7 +16,7 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
@@ -49,7 +49,7 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
@@ -81,7 +81,7 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
@@ -113,7 +113,7 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
@@ -146,7 +146,7 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
@@ -179,7 +179,7 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
diff --git a/infra/config/generated/builders/ci/GPU FYI Android arm64 Builder/properties.json b/infra/config/generated/builders/ci/GPU FYI Android arm64 Builder/properties.json
index db8dbb0..c17eeeee 100644
--- a/infra/config/generated/builders/ci/GPU FYI Android arm64 Builder/properties.json
+++ b/infra/config/generated/builders/ci/GPU FYI Android arm64 Builder/properties.json
@@ -16,14 +16,15 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -52,14 +53,15 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -87,14 +89,15 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -123,11 +126,14 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -156,14 +162,15 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/Linux Builder/targets/chromium.linux.json b/infra/config/generated/builders/ci/Linux Builder/targets/chromium.linux.json
index c09f385..c6d04f53 100644
--- a/infra/config/generated/builders/ci/Linux Builder/targets/chromium.linux.json
+++ b/infra/config/generated/builders/ci/Linux Builder/targets/chromium.linux.json
@@ -2121,6 +2121,35 @@
         "test_id_prefix": "ninja://:blink_web_tests/"
       },
       {
+        "args": [
+          "--test-type=wdspec"
+        ],
+        "ci_only": true,
+        "experiment_percentage": 100,
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [
+            "--verbose"
+          ],
+          "script": "//third_party/blink/tools/merge_web_test_results.py"
+        },
+        "name": "webdriver_wpt_tests",
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "results_handler": "layout tests",
+        "swarming": {
+          "dimensions": {
+            "os": "Ubuntu-22.04"
+          },
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 2
+        },
+        "test": "chrome_wpt_tests",
+        "test_id_prefix": "ninja://:chrome_wpt_tests/"
+      },
+      {
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
diff --git a/infra/config/generated/builders/ci/Linux Tests/targets/chromium.linux.json b/infra/config/generated/builders/ci/Linux Tests/targets/chromium.linux.json
index 9810070f..a32621d4 100644
--- a/infra/config/generated/builders/ci/Linux Tests/targets/chromium.linux.json
+++ b/infra/config/generated/builders/ci/Linux Tests/targets/chromium.linux.json
@@ -2090,6 +2090,35 @@
         "test_id_prefix": "ninja://:blink_web_tests/"
       },
       {
+        "args": [
+          "--test-type=wdspec"
+        ],
+        "ci_only": true,
+        "experiment_percentage": 100,
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [
+            "--verbose"
+          ],
+          "script": "//third_party/blink/tools/merge_web_test_results.py"
+        },
+        "name": "webdriver_wpt_tests",
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "results_handler": "layout tests",
+        "swarming": {
+          "dimensions": {
+            "os": "Ubuntu-22.04"
+          },
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 2
+        },
+        "test": "chrome_wpt_tests",
+        "test_id_prefix": "ninja://:chrome_wpt_tests/"
+      },
+      {
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
diff --git a/infra/config/generated/builders/ci/Oreo Phone Tester/properties.json b/infra/config/generated/builders/ci/Oreo Phone Tester/properties.json
index 0a227ca..3f82c91 100644
--- a/infra/config/generated/builders/ci/Oreo Phone Tester/properties.json
+++ b/infra/config/generated/builders/ci/Oreo Phone Tester/properties.json
@@ -14,14 +14,15 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -45,14 +46,15 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/Site Isolation Android/properties.json b/infra/config/generated/builders/ci/Site Isolation Android/properties.json
index 3b1c5982..d6c2840 100644
--- a/infra/config/generated/builders/ci/Site Isolation Android/properties.json
+++ b/infra/config/generated/builders/ci/Site Isolation Android/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "arm64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git "a/infra/config/generated/builders/ci/ToTAndroid \050dbg\051/properties.json" "b/infra/config/generated/builders/ci/ToTAndroid \050dbg\051/properties.json"
index 92a7a54..98ab67a 100644
--- "a/infra/config/generated/builders/ci/ToTAndroid \050dbg\051/properties.json"
+++ "b/infra/config/generated/builders/ci/ToTAndroid \050dbg\051/properties.json"
@@ -17,7 +17,7 @@
               "builder_group": "chromium.clang",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "clang_builder_mb_x64"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/ToTAndroid x64/properties.json b/infra/config/generated/builders/ci/ToTAndroid x64/properties.json
index 671df7e..03309d4 100644
--- a/infra/config/generated/builders/ci/ToTAndroid x64/properties.json
+++ b/infra/config/generated/builders/ci/ToTAndroid x64/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.clang",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "clang_builder_mb_x64"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/ToTAndroid x86/properties.json b/infra/config/generated/builders/ci/ToTAndroid x86/properties.json
index 2fcdd0c..f36a710 100644
--- a/infra/config/generated/builders/ci/ToTAndroid x86/properties.json
+++ b/infra/config/generated/builders/ci/ToTAndroid x86/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.clang",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "clang_builder_mb_x64"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/ToTAndroid/properties.json b/infra/config/generated/builders/ci/ToTAndroid/properties.json
index 2f232a1..de0320b 100644
--- a/infra/config/generated/builders/ci/ToTAndroid/properties.json
+++ b/infra/config/generated/builders/ci/ToTAndroid/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.clang",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "clang_builder_mb_x64"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/ToTAndroid64/properties.json b/infra/config/generated/builders/ci/ToTAndroid64/properties.json
index c0117500..0709a93 100644
--- a/infra/config/generated/builders/ci/ToTAndroid64/properties.json
+++ b/infra/config/generated/builders/ci/ToTAndroid64/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.clang",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "clang_builder_mb_x64"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/ToTAndroidCoverage x86/properties.json b/infra/config/generated/builders/ci/ToTAndroidCoverage x86/properties.json
index 78023b1..99106fb 100644
--- a/infra/config/generated/builders/ci/ToTAndroidCoverage x86/properties.json
+++ b/infra/config/generated/builders/ci/ToTAndroidCoverage x86/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.clang",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "clang_builder_mb_x64"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/ToTAndroidOfficial/properties.json b/infra/config/generated/builders/ci/ToTAndroidOfficial/properties.json
index 28e359c..c269d3b 100644
--- a/infra/config/generated/builders/ci/ToTAndroidOfficial/properties.json
+++ b/infra/config/generated/builders/ci/ToTAndroidOfficial/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.clang",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "clang_builder_mb_x64"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/android-10-arm64-rel/properties.json b/infra/config/generated/builders/ci/android-10-arm64-rel/properties.json
index 56ce87c4..bdecc076 100644
--- a/infra/config/generated/builders/ci/android-10-arm64-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-10-arm64-rel/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/android-10-x86-fyi-rel/properties.json b/infra/config/generated/builders/ci/android-10-x86-fyi-rel/properties.json
index 226474b5..11187f3 100644
--- a/infra/config/generated/builders/ci/android-10-x86-fyi-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-10-x86-fyi-rel/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "x86_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-10-x86-rel/properties.json b/infra/config/generated/builders/ci/android-10-x86-rel/properties.json
index 385b9603..8327987 100644
--- a/infra/config/generated/builders/ci/android-10-x86-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-10-x86-rel/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "x86_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-11-x86-fyi-rel/properties.json b/infra/config/generated/builders/ci/android-11-x86-fyi-rel/properties.json
index 68ad34d..9cd1588 100644
--- a/infra/config/generated/builders/ci/android-11-x86-fyi-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-11-x86-fyi-rel/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "x86_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-11-x86-rel/properties.json b/infra/config/generated/builders/ci/android-11-x86-rel/properties.json
index bc5dda6..09c57c5 100644
--- a/infra/config/generated/builders/ci/android-11-x86-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-11-x86-rel/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-12-x64-dbg-tests/properties.json b/infra/config/generated/builders/ci/android-12-x64-dbg-tests/properties.json
index 083ae65..893eaa7 100644
--- a/infra/config/generated/builders/ci/android-12-x64-dbg-tests/properties.json
+++ b/infra/config/generated/builders/ci/android-12-x64-dbg-tests/properties.json
@@ -14,11 +14,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -42,11 +45,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-12-x64-fyi-rel/properties.json b/infra/config/generated/builders/ci/android-12-x64-fyi-rel/properties.json
index a99c3958..98a5e04 100644
--- a/infra/config/generated/builders/ci/android-12-x64-fyi-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-12-x64-fyi-rel/properties.json
@@ -14,14 +14,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -50,14 +50,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-12-x64-rel/properties.json b/infra/config/generated/builders/ci/android-12-x64-rel/properties.json
index 2b7d2bb..4da73bde 100644
--- a/infra/config/generated/builders/ci/android-12-x64-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-12-x64-rel/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -53,14 +53,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-12l-landscape-x64-dbg-tests/properties.json b/infra/config/generated/builders/ci/android-12l-landscape-x64-dbg-tests/properties.json
index dfac979..b9c82094 100644
--- a/infra/config/generated/builders/ci/android-12l-landscape-x64-dbg-tests/properties.json
+++ b/infra/config/generated/builders/ci/android-12l-landscape-x64-dbg-tests/properties.json
@@ -14,11 +14,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -42,14 +45,15 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-12l-x64-dbg-tests/properties.json b/infra/config/generated/builders/ci/android-12l-x64-dbg-tests/properties.json
index e2439901..0e6d7a8 100644
--- a/infra/config/generated/builders/ci/android-12l-x64-dbg-tests/properties.json
+++ b/infra/config/generated/builders/ci/android-12l-x64-dbg-tests/properties.json
@@ -14,11 +14,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -42,14 +45,15 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-12l-x64-fyi-dbg/properties.json b/infra/config/generated/builders/ci/android-12l-x64-fyi-dbg/properties.json
index 120a69f3a..e389f96 100644
--- a/infra/config/generated/builders/ci/android-12l-x64-fyi-dbg/properties.json
+++ b/infra/config/generated/builders/ci/android-12l-x64-fyi-dbg/properties.json
@@ -17,14 +17,15 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-12l-x64-rel-cq/properties.json b/infra/config/generated/builders/ci/android-12l-x64-rel-cq/properties.json
index ba9b9d2..60c2563 100644
--- a/infra/config/generated/builders/ci/android-12l-x64-rel-cq/properties.json
+++ b/infra/config/generated/builders/ci/android-12l-x64-rel-cq/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-13-x64-fyi-rel/properties.json b/infra/config/generated/builders/ci/android-13-x64-fyi-rel/properties.json
index 25e3932..240314bd 100644
--- a/infra/config/generated/builders/ci/android-13-x64-fyi-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-13-x64-fyi-rel/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-13-x64-rel/properties.json b/infra/config/generated/builders/ci/android-13-x64-rel/properties.json
index 08cb89fd..fbab828 100644
--- a/infra/config/generated/builders/ci/android-13-x64-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-13-x64-rel/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-14-arm64-fyi-rel/properties.json b/infra/config/generated/builders/ci/android-14-arm64-fyi-rel/properties.json
index 64ee3def..f292f29 100644
--- a/infra/config/generated/builders/ci/android-14-arm64-fyi-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-14-arm64-fyi-rel/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-14-arm64-rel/properties.json b/infra/config/generated/builders/ci/android-14-arm64-rel/properties.json
index 7dc0a6b9..122bcf2 100644
--- a/infra/config/generated/builders/ci/android-14-arm64-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-14-arm64-rel/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/android-14-tablet-landscape-arm64-rel/properties.json b/infra/config/generated/builders/ci/android-14-tablet-landscape-arm64-rel/properties.json
index d73b702..8143f1f8 100644
--- a/infra/config/generated/builders/ci/android-14-tablet-landscape-arm64-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-14-tablet-landscape-arm64-rel/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-14-x64-fyi-rel/properties.json b/infra/config/generated/builders/ci/android-14-x64-fyi-rel/properties.json
index 2a01c93f..a5dc10e 100644
--- a/infra/config/generated/builders/ci/android-14-x64-fyi-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-14-x64-fyi-rel/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-14-x64-rel/properties.json b/infra/config/generated/builders/ci/android-14-x64-rel/properties.json
index c6a8fb19..ae6b76c6 100644
--- a/infra/config/generated/builders/ci/android-14-x64-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-14-x64-rel/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-15-tablet-landscape-x64-dbg-tests/properties.json b/infra/config/generated/builders/ci/android-15-tablet-landscape-x64-dbg-tests/properties.json
index 91157c7..624bf071 100644
--- a/infra/config/generated/builders/ci/android-15-tablet-landscape-x64-dbg-tests/properties.json
+++ b/infra/config/generated/builders/ci/android-15-tablet-landscape-x64-dbg-tests/properties.json
@@ -14,11 +14,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -42,11 +45,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-15-tablet-landscape-x64-rel/properties.json b/infra/config/generated/builders/ci/android-15-tablet-landscape-x64-rel/properties.json
index 44b94bb1..d1b67a0 100644
--- a/infra/config/generated/builders/ci/android-15-tablet-landscape-x64-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-15-tablet-landscape-x64-rel/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-15-tablet-x64-dbg-tests/properties.json b/infra/config/generated/builders/ci/android-15-tablet-x64-dbg-tests/properties.json
index 13b068e..fd09e68b 100644
--- a/infra/config/generated/builders/ci/android-15-tablet-x64-dbg-tests/properties.json
+++ b/infra/config/generated/builders/ci/android-15-tablet-x64-dbg-tests/properties.json
@@ -14,11 +14,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -42,11 +45,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-15-tablet-x64-rel/properties.json b/infra/config/generated/builders/ci/android-15-tablet-x64-rel/properties.json
index 67ad3bb..e5878311 100644
--- a/infra/config/generated/builders/ci/android-15-tablet-x64-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-15-tablet-x64-rel/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-15-x64-fyi-rel/properties.json b/infra/config/generated/builders/ci/android-15-x64-fyi-rel/properties.json
index 5eaad7a..d337cd8 100644
--- a/infra/config/generated/builders/ci/android-15-x64-fyi-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-15-x64-fyi-rel/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-15-x64-rel/properties.json b/infra/config/generated/builders/ci/android-15-x64-rel/properties.json
index c4f6074..852716ad4 100644
--- a/infra/config/generated/builders/ci/android-15-x64-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-15-x64-rel/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-16-x64-fyi-rel/properties.json b/infra/config/generated/builders/ci/android-16-x64-fyi-rel/properties.json
index 8e2b456..4ebd58e4 100644
--- a/infra/config/generated/builders/ci/android-16-x64-fyi-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-16-x64-fyi-rel/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-annotator-rel/properties.json b/infra/config/generated/builders/ci/android-annotator-rel/properties.json
index 1942a37..a6bca23 100644
--- a/infra/config/generated/builders/ci/android-annotator-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-annotator-rel/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/android-archive-rel/properties.json b/infra/config/generated/builders/ci/android-archive-rel/properties.json
index ecbda11..30c18690 100644
--- a/infra/config/generated/builders/ci/android-archive-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-archive-rel/properties.json
@@ -24,7 +24,7 @@
               "builder_group": "chromium",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/android-arm64-archive-rel/properties.json b/infra/config/generated/builders/ci/android-arm64-archive-rel/properties.json
index 43bacc6..2144f63 100644
--- a/infra/config/generated/builders/ci/android-arm64-archive-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-arm64-archive-rel/properties.json
@@ -24,7 +24,7 @@
               "builder_group": "chromium",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/android-arm64-proguard-rel/properties.json b/infra/config/generated/builders/ci/android-arm64-proguard-rel/properties.json
index ecf1482..46b0d8a5 100644
--- a/infra/config/generated/builders/ci/android-arm64-proguard-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-arm64-proguard-rel/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/android-bfcache-rel/properties.json b/infra/config/generated/builders/ci/android-bfcache-rel/properties.json
index 9a7c82c..40ba4c01 100644
--- a/infra/config/generated/builders/ci/android-bfcache-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-bfcache-rel/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "x86_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-cast-arm-dbg/properties.json b/infra/config/generated/builders/ci/android-cast-arm-dbg/properties.json
index cab4dd78..b2f38466a 100644
--- a/infra/config/generated/builders/ci/android-cast-arm-dbg/properties.json
+++ b/infra/config/generated/builders/ci/android-cast-arm-dbg/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "cast_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "cast_builder",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-cast-arm-rel/properties.json b/infra/config/generated/builders/ci/android-cast-arm-rel/properties.json
index 5f0f45f..175d79d 100644
--- a/infra/config/generated/builders/ci/android-cast-arm-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-cast-arm-rel/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "cast_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "cast_builder",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-cast-arm64-dbg/properties.json b/infra/config/generated/builders/ci/android-cast-arm64-dbg/properties.json
index 319d3eec..0a6c92f 100644
--- a/infra/config/generated/builders/ci/android-cast-arm64-dbg/properties.json
+++ b/infra/config/generated/builders/ci/android-cast-arm64-dbg/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "cast_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "cast_builder",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-cast-arm64-rel/properties.json b/infra/config/generated/builders/ci/android-cast-arm64-rel/properties.json
index a12e7e8..d873d5a 100644
--- a/infra/config/generated/builders/ci/android-cast-arm64-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-cast-arm64-rel/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "cast_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "cast_builder",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-chrome-13-x64-wpt-android-specific/properties.json b/infra/config/generated/builders/ci/android-chrome-13-x64-wpt-android-specific/properties.json
index 4fd65fe..cfca3727 100644
--- a/infra/config/generated/builders/ci/android-chrome-13-x64-wpt-android-specific/properties.json
+++ b/infra/config/generated/builders/ci/android-chrome-13-x64-wpt-android-specific/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-chrome-pie-x86-wpt-fyi-rel/properties.json b/infra/config/generated/builders/ci/android-chrome-pie-x86-wpt-fyi-rel/properties.json
index a843cc3..0ece03c2 100644
--- a/infra/config/generated/builders/ci/android-chrome-pie-x86-wpt-fyi-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-chrome-pie-x86-wpt-fyi-rel/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-code-coverage-native/properties.json b/infra/config/generated/builders/ci/android-code-coverage-native/properties.json
index 2d02e8b..bbf0d24 100644
--- a/infra/config/generated/builders/ci/android-code-coverage-native/properties.json
+++ b/infra/config/generated/builders/ci/android-code-coverage-native/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.coverage",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/android-code-coverage/properties.json b/infra/config/generated/builders/ci/android-code-coverage/properties.json
index 385c2e8c..79ec7dd8 100644
--- a/infra/config/generated/builders/ci/android-code-coverage/properties.json
+++ b/infra/config/generated/builders/ci/android-code-coverage/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.coverage",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/android-cronet-arm-dbg/properties.json b/infra/config/generated/builders/ci/android-cronet-arm-dbg/properties.json
index 9f9a026..cdfbe65 100644
--- a/infra/config/generated/builders/ci/android-cronet-arm-dbg/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-arm-dbg/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/android-cronet-arm-rel/properties.json b/infra/config/generated/builders/ci/android-cronet-arm-rel/properties.json
index 36e0121a..7e65eaf 100644
--- a/infra/config/generated/builders/ci/android-cronet-arm-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-arm-rel/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/android-cronet-arm64-dbg/properties.json b/infra/config/generated/builders/ci/android-cronet-arm64-dbg/properties.json
index 4c97e8f..7657fa9 100644
--- a/infra/config/generated/builders/ci/android-cronet-arm64-dbg/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-arm64-dbg/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/android-cronet-arm64-gn2bp-dbg/properties.json b/infra/config/generated/builders/ci/android-cronet-arm64-gn2bp-dbg/properties.json
index 8aed6d1a7..841aa1a 100644
--- a/infra/config/generated/builders/ci/android-cronet-arm64-gn2bp-dbg/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-arm64-gn2bp-dbg/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/android-cronet-arm64-rel/properties.json b/infra/config/generated/builders/ci/android-cronet-arm64-rel/properties.json
index ed8cf3d..b543e6ec 100644
--- a/infra/config/generated/builders/ci/android-cronet-arm64-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-arm64-rel/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/android-cronet-asan-arm-rel/properties.json b/infra/config/generated/builders/ci/android-cronet-asan-arm-rel/properties.json
index 77d51133..4464d38 100644
--- a/infra/config/generated/builders/ci/android-cronet-asan-arm-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-asan-arm-rel/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/android-cronet-asan-x86-rel/properties.json b/infra/config/generated/builders/ci/android-cronet-asan-x86-rel/properties.json
index 1fa22b0..2871af0 100644
--- a/infra/config/generated/builders/ci/android-cronet-asan-x86-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-asan-x86-rel/properties.json
@@ -16,7 +16,7 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -24,7 +24,7 @@
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-cronet-code-coverage-java/properties.json b/infra/config/generated/builders/ci/android-cronet-code-coverage-java/properties.json
index b3e907e..42c4dd5 100644
--- a/infra/config/generated/builders/ci/android-cronet-code-coverage-java/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-code-coverage-java/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.coverage",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -25,7 +25,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-cronet-code-coverage-native/properties.json b/infra/config/generated/builders/ci/android-cronet-code-coverage-native/properties.json
index dbc46cf..e24c171f 100644
--- a/infra/config/generated/builders/ci/android-cronet-code-coverage-native/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-code-coverage-native/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.coverage",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -25,7 +25,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-cronet-mainline-clang-arm64-dbg/properties.json b/infra/config/generated/builders/ci/android-cronet-mainline-clang-arm64-dbg/properties.json
index 3b3e4d8..de97358 100644
--- a/infra/config/generated/builders/ci/android-cronet-mainline-clang-arm64-dbg/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-mainline-clang-arm64-dbg/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/android-cronet-mainline-clang-arm64-rel/properties.json b/infra/config/generated/builders/ci/android-cronet-mainline-clang-arm64-rel/properties.json
index 243f068f..e400dd5 100644
--- a/infra/config/generated/builders/ci/android-cronet-mainline-clang-arm64-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-mainline-clang-arm64-rel/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/android-cronet-mainline-clang-riscv64-dbg/properties.json b/infra/config/generated/builders/ci/android-cronet-mainline-clang-riscv64-dbg/properties.json
index f446282..09b6608 100644
--- a/infra/config/generated/builders/ci/android-cronet-mainline-clang-riscv64-dbg/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-mainline-clang-riscv64-dbg/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/android-cronet-mainline-clang-riscv64-rel/properties.json b/infra/config/generated/builders/ci/android-cronet-mainline-clang-riscv64-rel/properties.json
index 3909cb7..6fe33c1 100644
--- a/infra/config/generated/builders/ci/android-cronet-mainline-clang-riscv64-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-mainline-clang-riscv64-rel/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/android-cronet-mainline-clang-x86-dbg/properties.json b/infra/config/generated/builders/ci/android-cronet-mainline-clang-x86-dbg/properties.json
index 488fe842..80346913 100644
--- a/infra/config/generated/builders/ci/android-cronet-mainline-clang-x86-dbg/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-mainline-clang-x86-dbg/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -25,7 +25,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-cronet-mainline-clang-x86-rel/properties.json b/infra/config/generated/builders/ci/android-cronet-mainline-clang-x86-rel/properties.json
index f9885eb..564bc47 100644
--- a/infra/config/generated/builders/ci/android-cronet-mainline-clang-x86-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-mainline-clang-x86-rel/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -25,7 +25,7 @@
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-cronet-riscv64-dbg/properties.json b/infra/config/generated/builders/ci/android-cronet-riscv64-dbg/properties.json
index 2199ba0..cd90039 100644
--- a/infra/config/generated/builders/ci/android-cronet-riscv64-dbg/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-riscv64-dbg/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/android-cronet-riscv64-rel/properties.json b/infra/config/generated/builders/ci/android-cronet-riscv64-rel/properties.json
index 35c9378..3a3ec7f3 100644
--- a/infra/config/generated/builders/ci/android-cronet-riscv64-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-riscv64-rel/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/android-cronet-x64-dbg-12-tests/properties.json b/infra/config/generated/builders/ci/android-cronet-x64-dbg-12-tests/properties.json
index 7425e1e1..5c8190424 100644
--- a/infra/config/generated/builders/ci/android-cronet-x64-dbg-12-tests/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-x64-dbg-12-tests/properties.json
@@ -14,7 +14,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -22,7 +22,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -46,7 +46,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -54,7 +54,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-cronet-x64-dbg-13-tests/properties.json b/infra/config/generated/builders/ci/android-cronet-x64-dbg-13-tests/properties.json
index 68ef2fb4..bf2c9f3 100644
--- a/infra/config/generated/builders/ci/android-cronet-x64-dbg-13-tests/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-x64-dbg-13-tests/properties.json
@@ -14,7 +14,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -22,7 +22,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -46,7 +46,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -54,7 +54,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-cronet-x64-dbg-14-tests/properties.json b/infra/config/generated/builders/ci/android-cronet-x64-dbg-14-tests/properties.json
index 827bea1..e662e66 100644
--- a/infra/config/generated/builders/ci/android-cronet-x64-dbg-14-tests/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-x64-dbg-14-tests/properties.json
@@ -14,7 +14,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -22,7 +22,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -46,7 +46,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -54,7 +54,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-cronet-x64-dbg-15-tests/properties.json b/infra/config/generated/builders/ci/android-cronet-x64-dbg-15-tests/properties.json
index 3e75348..ca793135 100644
--- a/infra/config/generated/builders/ci/android-cronet-x64-dbg-15-tests/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-x64-dbg-15-tests/properties.json
@@ -14,7 +14,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -22,7 +22,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -46,7 +46,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -54,7 +54,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-cronet-x64-dbg-16-tests/properties.json b/infra/config/generated/builders/ci/android-cronet-x64-dbg-16-tests/properties.json
index 79a4014..019d1450 100644
--- a/infra/config/generated/builders/ci/android-cronet-x64-dbg-16-tests/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-x64-dbg-16-tests/properties.json
@@ -14,7 +14,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -22,7 +22,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -46,7 +46,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -54,7 +54,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_bits": 64,
                 "target_platform": "android"
               },
diff --git a/infra/config/generated/builders/ci/android-cronet-x64-dbg/properties.json b/infra/config/generated/builders/ci/android-cronet-x64-dbg/properties.json
index 4ab7a36..3af28fc 100644
--- a/infra/config/generated/builders/ci/android-cronet-x64-dbg/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-x64-dbg/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -25,7 +25,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -49,7 +49,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -57,7 +57,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -86,7 +86,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -94,7 +94,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -123,7 +123,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -131,7 +131,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -160,7 +160,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -168,7 +168,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -197,7 +197,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -205,7 +205,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_bits": 64,
                 "target_platform": "android"
               },
diff --git a/infra/config/generated/builders/ci/android-cronet-x64-rel/properties.json b/infra/config/generated/builders/ci/android-cronet-x64-rel/properties.json
index 4c4057db..ed2440d 100644
--- a/infra/config/generated/builders/ci/android-cronet-x64-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-x64-rel/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -25,7 +25,7 @@
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-cronet-x86-dbg-10-tests/properties.json b/infra/config/generated/builders/ci/android-cronet-x86-dbg-10-tests/properties.json
index e23b818..c2dfd67e 100644
--- a/infra/config/generated/builders/ci/android-cronet-x86-dbg-10-tests/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-x86-dbg-10-tests/properties.json
@@ -14,7 +14,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -22,7 +22,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
@@ -46,7 +46,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -54,7 +54,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-cronet-x86-dbg-11-tests/properties.json b/infra/config/generated/builders/ci/android-cronet-x86-dbg-11-tests/properties.json
index f5e1881..d7d8e53 100644
--- a/infra/config/generated/builders/ci/android-cronet-x86-dbg-11-tests/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-x86-dbg-11-tests/properties.json
@@ -14,7 +14,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -22,7 +22,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
@@ -46,7 +46,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -54,7 +54,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-cronet-x86-dbg-marshmallow-tests/properties.json b/infra/config/generated/builders/ci/android-cronet-x86-dbg-marshmallow-tests/properties.json
index c5ea2a05..a9835fc 100644
--- a/infra/config/generated/builders/ci/android-cronet-x86-dbg-marshmallow-tests/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-x86-dbg-marshmallow-tests/properties.json
@@ -14,7 +14,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -22,7 +22,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
@@ -46,7 +46,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -54,7 +54,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-cronet-x86-dbg-nougat-tests/properties.json b/infra/config/generated/builders/ci/android-cronet-x86-dbg-nougat-tests/properties.json
index ccd2b44..cbc76df 100644
--- a/infra/config/generated/builders/ci/android-cronet-x86-dbg-nougat-tests/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-x86-dbg-nougat-tests/properties.json
@@ -14,7 +14,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -22,7 +22,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
@@ -46,7 +46,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -54,7 +54,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-cronet-x86-dbg-oreo-tests/properties.json b/infra/config/generated/builders/ci/android-cronet-x86-dbg-oreo-tests/properties.json
index 3924c8fc..16a42c0 100644
--- a/infra/config/generated/builders/ci/android-cronet-x86-dbg-oreo-tests/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-x86-dbg-oreo-tests/properties.json
@@ -14,7 +14,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -22,7 +22,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
@@ -46,7 +46,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -54,7 +54,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-cronet-x86-dbg-pie-tests/properties.json b/infra/config/generated/builders/ci/android-cronet-x86-dbg-pie-tests/properties.json
index 4577114..f3fc7dfa 100644
--- a/infra/config/generated/builders/ci/android-cronet-x86-dbg-pie-tests/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-x86-dbg-pie-tests/properties.json
@@ -14,7 +14,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -22,7 +22,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
@@ -46,7 +46,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -54,7 +54,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-cronet-x86-dbg/properties.json b/infra/config/generated/builders/ci/android-cronet-x86-dbg/properties.json
index 9f31bd7..47e76cbc 100644
--- a/infra/config/generated/builders/ci/android-cronet-x86-dbg/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-x86-dbg/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -25,7 +25,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
@@ -49,7 +49,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -57,7 +57,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
@@ -86,7 +86,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -94,7 +94,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
@@ -123,7 +123,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -131,7 +131,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
@@ -160,7 +160,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -168,7 +168,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
@@ -197,7 +197,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -205,7 +205,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
@@ -234,7 +234,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -242,7 +242,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-cronet-x86-rel/properties.json b/infra/config/generated/builders/ci/android-cronet-x86-rel/properties.json
index 58e0305..f37a7b0 100644
--- a/infra/config/generated/builders/ci/android-cronet-x86-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-cronet-x86-rel/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -25,7 +25,7 @@
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-desktop-15-x64-fyi-rel/properties.json b/infra/config/generated/builders/ci/android-desktop-15-x64-fyi-rel/properties.json
index 5c0cbb9..44d5d04 100644
--- a/infra/config/generated/builders/ci/android-desktop-15-x64-fyi-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-desktop-15-x64-fyi-rel/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android.desktop.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-desktop-arm64-archive-rel/properties.json b/infra/config/generated/builders/ci/android-desktop-arm64-archive-rel/properties.json
index 7fdf6bb..68267e26 100644
--- a/infra/config/generated/builders/ci/android-desktop-arm64-archive-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-desktop-arm64-archive-rel/properties.json
@@ -24,7 +24,7 @@
               "builder_group": "chromium",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/android-desktop-arm64-compile-dbg/properties.json b/infra/config/generated/builders/ci/android-desktop-arm64-compile-dbg/properties.json
index 417efe0..8bc11f5 100644
--- a/infra/config/generated/builders/ci/android-desktop-arm64-compile-dbg/properties.json
+++ b/infra/config/generated/builders/ci/android-desktop-arm64-compile-dbg/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android.desktop",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-desktop-arm64-compile-rel/properties.json b/infra/config/generated/builders/ci/android-desktop-arm64-compile-rel/properties.json
index 81637bb..aa22b83 100644
--- a/infra/config/generated/builders/ci/android-desktop-arm64-compile-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-desktop-arm64-compile-rel/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android.desktop",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-desktop-x64-archive-rel/properties.json b/infra/config/generated/builders/ci/android-desktop-x64-archive-rel/properties.json
index e8fc142..f0c618b1 100644
--- a/infra/config/generated/builders/ci/android-desktop-x64-archive-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-desktop-x64-archive-rel/properties.json
@@ -24,7 +24,7 @@
               "builder_group": "chromium",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -32,7 +32,7 @@
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-desktop-x64-compile-dbg/properties.json b/infra/config/generated/builders/ci/android-desktop-x64-compile-dbg/properties.json
index 7682c6c..6b676d7 100644
--- a/infra/config/generated/builders/ci/android-desktop-x64-compile-dbg/properties.json
+++ b/infra/config/generated/builders/ci/android-desktop-x64-compile-dbg/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android.desktop",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-desktop-x64-compile-rel/properties.json b/infra/config/generated/builders/ci/android-desktop-x64-compile-rel/properties.json
index f4eb552..4cdf2e2d 100644
--- a/infra/config/generated/builders/ci/android-desktop-x64-compile-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-desktop-x64-compile-rel/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android.desktop",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -45,11 +48,14 @@
               "builder_group": "chromium.android.desktop",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-desktop-x64-rel-15-tests/properties.json b/infra/config/generated/builders/ci/android-desktop-x64-rel-15-tests/properties.json
index c930f15..c6241d11 100644
--- a/infra/config/generated/builders/ci/android-desktop-x64-rel-15-tests/properties.json
+++ b/infra/config/generated/builders/ci/android-desktop-x64-rel-15-tests/properties.json
@@ -14,11 +14,14 @@
               "builder_group": "chromium.android.desktop",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -42,11 +45,14 @@
               "builder_group": "chromium.android.desktop",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-fieldtrial-rel/properties.json b/infra/config/generated/builders/ci/android-fieldtrial-rel/properties.json
index 2c2b286..04f0ee9a 100644
--- a/infra/config/generated/builders/ci/android-fieldtrial-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-fieldtrial-rel/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-mte-arm64-rel/properties.json b/infra/config/generated/builders/ci/android-mte-arm64-rel/properties.json
index ad8f6b8..bb3f35b 100644
--- a/infra/config/generated/builders/ci/android-mte-arm64-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-mte-arm64-rel/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/android-official/properties.json b/infra/config/generated/builders/ci/android-official/properties.json
index c7fa895..c1d7ce1 100644
--- a/infra/config/generated/builders/ci/android-official/properties.json
+++ b/infra/config/generated/builders/ci/android-official/properties.json
@@ -16,7 +16,7 @@
               "builder_group": "chromium",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/android-oreo-x86-rel/properties.json b/infra/config/generated/builders/ci/android-oreo-x86-rel/properties.json
index c6ec6567..aa4066e 100644
--- a/infra/config/generated/builders/ci/android-oreo-x86-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-oreo-x86-rel/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "x86_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-perfetto-rel/properties.json b/infra/config/generated/builders/ci/android-perfetto-rel/properties.json
index 8336a4f..69c38a1 100644
--- a/infra/config/generated/builders/ci/android-perfetto-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-perfetto-rel/properties.json
@@ -16,14 +16,14 @@
               "builder_group": "chromium.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-pie-arm64-dbg/properties.json b/infra/config/generated/builders/ci/android-pie-arm64-dbg/properties.json
index 9f7d1c58..7e8212a 100644
--- a/infra/config/generated/builders/ci/android-pie-arm64-dbg/properties.json
+++ b/infra/config/generated/builders/ci/android-pie-arm64-dbg/properties.json
@@ -14,14 +14,15 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -45,14 +46,15 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-pie-arm64-rel/properties.json b/infra/config/generated/builders/ci/android-pie-arm64-rel/properties.json
index 153a543..25c409de 100644
--- a/infra/config/generated/builders/ci/android-pie-arm64-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-pie-arm64-rel/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/android-pie-x86-fyi-rel/properties.json b/infra/config/generated/builders/ci/android-pie-x86-fyi-rel/properties.json
index c4d0055e..260bb3d 100644
--- a/infra/config/generated/builders/ci/android-pie-x86-fyi-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-pie-x86-fyi-rel/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-pie-x86-rel/properties.json b/infra/config/generated/builders/ci/android-pie-x86-rel/properties.json
index eee9b44..5ba8e4e 100644
--- a/infra/config/generated/builders/ci/android-pie-x86-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-pie-x86-rel/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-webview-10-x86-rel-tests/properties.json b/infra/config/generated/builders/ci/android-webview-10-x86-rel-tests/properties.json
index e7f7a06a..295553a 100644
--- a/infra/config/generated/builders/ci/android-webview-10-x86-rel-tests/properties.json
+++ b/infra/config/generated/builders/ci/android-webview-10-x86-rel-tests/properties.json
@@ -14,11 +14,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 32,
                 "target_platform": "android"
@@ -47,11 +50,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-webview-12-x64-dbg-tests/properties.json b/infra/config/generated/builders/ci/android-webview-12-x64-dbg-tests/properties.json
index 65a821c..fd373737 100644
--- a/infra/config/generated/builders/ci/android-webview-12-x64-dbg-tests/properties.json
+++ b/infra/config/generated/builders/ci/android-webview-12-x64-dbg-tests/properties.json
@@ -14,11 +14,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -42,11 +45,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-webview-13-x64-dbg-tests/properties.json b/infra/config/generated/builders/ci/android-webview-13-x64-dbg-tests/properties.json
index 613c6259..06ba9b5 100644
--- a/infra/config/generated/builders/ci/android-webview-13-x64-dbg-tests/properties.json
+++ b/infra/config/generated/builders/ci/android-webview-13-x64-dbg-tests/properties.json
@@ -14,11 +14,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -42,11 +45,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-webview-13-x64-hostside-rel/properties.json b/infra/config/generated/builders/ci/android-webview-13-x64-hostside-rel/properties.json
index a27b288..29ca2090 100644
--- a/infra/config/generated/builders/ci/android-webview-13-x64-hostside-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-webview-13-x64-hostside-rel/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-webview-13-x64-wpt-android-specific/properties.json b/infra/config/generated/builders/ci/android-webview-13-x64-wpt-android-specific/properties.json
index 1217fea1..aab9c3b 100644
--- a/infra/config/generated/builders/ci/android-webview-13-x64-wpt-android-specific/properties.json
+++ b/infra/config/generated/builders/ci/android-webview-13-x64-wpt-android-specific/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-webview-code-coverage-native/properties.json b/infra/config/generated/builders/ci/android-webview-code-coverage-native/properties.json
index f74bdb2..e6dcc045 100644
--- a/infra/config/generated/builders/ci/android-webview-code-coverage-native/properties.json
+++ b/infra/config/generated/builders/ci/android-webview-code-coverage-native/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.coverage",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/android-webview-code-coverage/properties.json b/infra/config/generated/builders/ci/android-webview-code-coverage/properties.json
index d4c436d..39410dc0 100644
--- a/infra/config/generated/builders/ci/android-webview-code-coverage/properties.json
+++ b/infra/config/generated/builders/ci/android-webview-code-coverage/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.coverage",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/ci/android-webview-pie-x86-wpt-fyi-rel/properties.json b/infra/config/generated/builders/ci/android-webview-pie-x86-wpt-fyi-rel/properties.json
index 8a52175..5e21579 100644
--- a/infra/config/generated/builders/ci/android-webview-pie-x86-wpt-fyi-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-webview-pie-x86-wpt-fyi-rel/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-x86-code-coverage/properties.json b/infra/config/generated/builders/ci/android-x86-code-coverage/properties.json
index bc16c68..32d1447 100644
--- a/infra/config/generated/builders/ci/android-x86-code-coverage/properties.json
+++ b/infra/config/generated/builders/ci/android-x86-code-coverage/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.coverage",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "x86_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/ci/android-x86-rel/properties.json b/infra/config/generated/builders/ci/android-x86-rel/properties.json
index 743c9ba..378a531 100644
--- a/infra/config/generated/builders/ci/android-x86-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-x86-rel/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 32,
                 "target_platform": "android"
@@ -50,11 +53,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-10-arm64-rel/properties.json b/infra/config/generated/builders/try/android-10-arm64-rel/properties.json
index 3fefc9e..1a44a8a7 100644
--- a/infra/config/generated/builders/try/android-10-arm64-rel/properties.json
+++ b/infra/config/generated/builders/try/android-10-arm64-rel/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/try/android-10-x86-fyi-rel/properties.json b/infra/config/generated/builders/try/android-10-x86-fyi-rel/properties.json
index dc836a7..abbbc0a 100644
--- a/infra/config/generated/builders/try/android-10-x86-fyi-rel/properties.json
+++ b/infra/config/generated/builders/try/android-10-x86-fyi-rel/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "x86_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-10-x86-rel/properties.json b/infra/config/generated/builders/try/android-10-x86-rel/properties.json
index 44a76b7..f08a21b7 100644
--- a/infra/config/generated/builders/try/android-10-x86-rel/properties.json
+++ b/infra/config/generated/builders/try/android-10-x86-rel/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "x86_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-11-x86-rel/properties.json b/infra/config/generated/builders/try/android-11-x86-rel/properties.json
index 3ebd4d3b8..3ab053b 100644
--- a/infra/config/generated/builders/try/android-11-x86-rel/properties.json
+++ b/infra/config/generated/builders/try/android-11-x86-rel/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-12-x64-dbg/properties.json b/infra/config/generated/builders/try/android-12-x64-dbg/properties.json
index 4747eb7..16ea752 100644
--- a/infra/config/generated/builders/try/android-12-x64-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-12-x64-dbg/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -45,11 +48,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-12-x64-rel/properties.json b/infra/config/generated/builders/try/android-12-x64-rel/properties.json
index 32794d55..f084b38 100644
--- a/infra/config/generated/builders/try/android-12-x64-rel/properties.json
+++ b/infra/config/generated/builders/try/android-12-x64-rel/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-12l-landscape-x64-dbg/properties.json b/infra/config/generated/builders/try/android-12l-landscape-x64-dbg/properties.json
index 3204f0b..40c5c10 100644
--- a/infra/config/generated/builders/try/android-12l-landscape-x64-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-12l-landscape-x64-dbg/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -45,14 +48,15 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-12l-x64-dbg/properties.json b/infra/config/generated/builders/try/android-12l-x64-dbg/properties.json
index 914334b..e72fe3dc 100644
--- a/infra/config/generated/builders/try/android-12l-x64-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-12l-x64-dbg/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -45,14 +48,15 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-12l-x64-rel-cq/properties.json b/infra/config/generated/builders/try/android-12l-x64-rel-cq/properties.json
index 9b530f2..9d88369 100644
--- a/infra/config/generated/builders/try/android-12l-x64-rel-cq/properties.json
+++ b/infra/config/generated/builders/try/android-12l-x64-rel-cq/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-13-x64-fyi-rel/properties.json b/infra/config/generated/builders/try/android-13-x64-fyi-rel/properties.json
index 180593c..ff13bb0 100644
--- a/infra/config/generated/builders/try/android-13-x64-fyi-rel/properties.json
+++ b/infra/config/generated/builders/try/android-13-x64-fyi-rel/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-13-x64-rel/properties.json b/infra/config/generated/builders/try/android-13-x64-rel/properties.json
index f7113b00..9726755 100644
--- a/infra/config/generated/builders/try/android-13-x64-rel/properties.json
+++ b/infra/config/generated/builders/try/android-13-x64-rel/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-14-arm64-fyi-rel/properties.json b/infra/config/generated/builders/try/android-14-arm64-fyi-rel/properties.json
index 5164875..d041336 100644
--- a/infra/config/generated/builders/try/android-14-arm64-fyi-rel/properties.json
+++ b/infra/config/generated/builders/try/android-14-arm64-fyi-rel/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-14-arm64-rel/properties.json b/infra/config/generated/builders/try/android-14-arm64-rel/properties.json
index 372f4bce..fc2cfb69 100644
--- a/infra/config/generated/builders/try/android-14-arm64-rel/properties.json
+++ b/infra/config/generated/builders/try/android-14-arm64-rel/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/try/android-14-tablet-landscape-arm64-rel/properties.json b/infra/config/generated/builders/try/android-14-tablet-landscape-arm64-rel/properties.json
index 094575c..a25d157b 100644
--- a/infra/config/generated/builders/try/android-14-tablet-landscape-arm64-rel/properties.json
+++ b/infra/config/generated/builders/try/android-14-tablet-landscape-arm64-rel/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-14-x64-fyi-rel/properties.json b/infra/config/generated/builders/try/android-14-x64-fyi-rel/properties.json
index 9706cc6..630b789 100644
--- a/infra/config/generated/builders/try/android-14-x64-fyi-rel/properties.json
+++ b/infra/config/generated/builders/try/android-14-x64-fyi-rel/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-14-x64-rel/properties.json b/infra/config/generated/builders/try/android-14-x64-rel/properties.json
index aaad9eaa..f7a48985 100644
--- a/infra/config/generated/builders/try/android-14-x64-rel/properties.json
+++ b/infra/config/generated/builders/try/android-14-x64-rel/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-15-tablet-landscape-x64-dbg/properties.json b/infra/config/generated/builders/try/android-15-tablet-landscape-x64-dbg/properties.json
index 4270aec..febdde9 100644
--- a/infra/config/generated/builders/try/android-15-tablet-landscape-x64-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-15-tablet-landscape-x64-dbg/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -45,11 +48,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-15-tablet-landscape-x64-rel/properties.json b/infra/config/generated/builders/try/android-15-tablet-landscape-x64-rel/properties.json
index eb9426f6..9798ac4 100644
--- a/infra/config/generated/builders/try/android-15-tablet-landscape-x64-rel/properties.json
+++ b/infra/config/generated/builders/try/android-15-tablet-landscape-x64-rel/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-15-tablet-x64-dbg/properties.json b/infra/config/generated/builders/try/android-15-tablet-x64-dbg/properties.json
index 739128e..6f5a616 100644
--- a/infra/config/generated/builders/try/android-15-tablet-x64-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-15-tablet-x64-dbg/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -45,11 +48,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-15-tablet-x64-rel/properties.json b/infra/config/generated/builders/try/android-15-tablet-x64-rel/properties.json
index 14957e1..d9b84a5 100644
--- a/infra/config/generated/builders/try/android-15-tablet-x64-rel/properties.json
+++ b/infra/config/generated/builders/try/android-15-tablet-x64-rel/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-15-x64-fyi-rel/properties.json b/infra/config/generated/builders/try/android-15-x64-fyi-rel/properties.json
index c55c3a1d..b769ba8 100644
--- a/infra/config/generated/builders/try/android-15-x64-fyi-rel/properties.json
+++ b/infra/config/generated/builders/try/android-15-x64-fyi-rel/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-15-x64-rel/properties.json b/infra/config/generated/builders/try/android-15-x64-rel/properties.json
index a1744edf..62338c05 100644
--- a/infra/config/generated/builders/try/android-15-x64-rel/properties.json
+++ b/infra/config/generated/builders/try/android-15-x64-rel/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-16-x64-fyi-rel/properties.json b/infra/config/generated/builders/try/android-16-x64-fyi-rel/properties.json
index e19f0ee3..88b6ccd 100644
--- a/infra/config/generated/builders/try/android-16-x64-fyi-rel/properties.json
+++ b/infra/config/generated/builders/try/android-16-x64-fyi-rel/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-arm-compile-dbg/properties.json b/infra/config/generated/builders/try/android-arm-compile-dbg/properties.json
index e842a80..9b62d54 100644
--- a/infra/config/generated/builders/try/android-arm-compile-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-arm-compile-dbg/properties.json
@@ -17,14 +17,15 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-arm64-all-targets-dbg/properties.json b/infra/config/generated/builders/try/android-arm64-all-targets-dbg/properties.json
index aa2a976..3aac1c8 100644
--- a/infra/config/generated/builders/try/android-arm64-all-targets-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-arm64-all-targets-dbg/properties.json
@@ -17,14 +17,15 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-arm64-rel/properties.json b/infra/config/generated/builders/try/android-arm64-rel/properties.json
index 93b4c46..730f24c 100644
--- a/infra/config/generated/builders/try/android-arm64-rel/properties.json
+++ b/infra/config/generated/builders/try/android-arm64-rel/properties.json
@@ -21,7 +21,7 @@
               "builder_group": "chromium.gpu",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -53,7 +53,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -85,7 +85,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/try/android-bfcache-rel/properties.json b/infra/config/generated/builders/try/android-bfcache-rel/properties.json
index 35a4f4e..de6628e7 100644
--- a/infra/config/generated/builders/try/android-bfcache-rel/properties.json
+++ b/infra/config/generated/builders/try/android-bfcache-rel/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "x86_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-cast-arm-dbg/properties.json b/infra/config/generated/builders/try/android-cast-arm-dbg/properties.json
index 5cbb36a..427e908 100644
--- a/infra/config/generated/builders/try/android-cast-arm-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-cast-arm-dbg/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "cast_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "cast_builder",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-cast-arm-rel/properties.json b/infra/config/generated/builders/try/android-cast-arm-rel/properties.json
index a16d103..d0f9119 100644
--- a/infra/config/generated/builders/try/android-cast-arm-rel/properties.json
+++ b/infra/config/generated/builders/try/android-cast-arm-rel/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "cast_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "cast_builder",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-cast-arm64-dbg/properties.json b/infra/config/generated/builders/try/android-cast-arm64-dbg/properties.json
index 28ffa89..842cb1c 100644
--- a/infra/config/generated/builders/try/android-cast-arm64-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-cast-arm64-dbg/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "cast_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "cast_builder",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-cast-arm64-rel/properties.json b/infra/config/generated/builders/try/android-cast-arm64-rel/properties.json
index 6d0edbf..aac06f6 100644
--- a/infra/config/generated/builders/try/android-cast-arm64-rel/properties.json
+++ b/infra/config/generated/builders/try/android-cast-arm64-rel/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "cast_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "cast_builder",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-chrome-13-x64-wpt-android-specific/properties.json b/infra/config/generated/builders/try/android-chrome-13-x64-wpt-android-specific/properties.json
index 0c45ec3..b403ecdc 100644
--- a/infra/config/generated/builders/try/android-chrome-13-x64-wpt-android-specific/properties.json
+++ b/infra/config/generated/builders/try/android-chrome-13-x64-wpt-android-specific/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-chrome-pie-x86-wpt-fyi-rel/properties.json b/infra/config/generated/builders/try/android-chrome-pie-x86-wpt-fyi-rel/properties.json
index f82ef96..6f14c097 100644
--- a/infra/config/generated/builders/try/android-chrome-pie-x86-wpt-fyi-rel/properties.json
+++ b/infra/config/generated/builders/try/android-chrome-pie-x86-wpt-fyi-rel/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-clobber-rel/properties.json b/infra/config/generated/builders/try/android-clobber-rel/properties.json
index dbdf69b..f443092 100644
--- a/infra/config/generated/builders/try/android-clobber-rel/properties.json
+++ b/infra/config/generated/builders/try/android-clobber-rel/properties.json
@@ -16,7 +16,7 @@
               "builder_group": "chromium",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/try/android-code-coverage-native/properties.json b/infra/config/generated/builders/try/android-code-coverage-native/properties.json
index eeed5423..cb85c6c 100644
--- a/infra/config/generated/builders/try/android-code-coverage-native/properties.json
+++ b/infra/config/generated/builders/try/android-code-coverage-native/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.coverage",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/try/android-code-coverage/properties.json b/infra/config/generated/builders/try/android-code-coverage/properties.json
index fe8145b..b8039a9 100644
--- a/infra/config/generated/builders/try/android-code-coverage/properties.json
+++ b/infra/config/generated/builders/try/android-code-coverage/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.coverage",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/try/android-cronet-arm-dbg/properties.json b/infra/config/generated/builders/try/android-cronet-arm-dbg/properties.json
index 67522d4d..5d1b3682 100644
--- a/infra/config/generated/builders/try/android-cronet-arm-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-arm-dbg/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/try/android-cronet-arm-rel/properties.json b/infra/config/generated/builders/try/android-cronet-arm-rel/properties.json
index b5303735..cfc0b1b 100644
--- a/infra/config/generated/builders/try/android-cronet-arm-rel/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-arm-rel/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/try/android-cronet-arm64-dbg/properties.json b/infra/config/generated/builders/try/android-cronet-arm64-dbg/properties.json
index 7c902eca..8f6a2c4c 100644
--- a/infra/config/generated/builders/try/android-cronet-arm64-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-arm64-dbg/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/try/android-cronet-arm64-gn2bp-dbg/properties.json b/infra/config/generated/builders/try/android-cronet-arm64-gn2bp-dbg/properties.json
index 179f433a..47c3623 100644
--- a/infra/config/generated/builders/try/android-cronet-arm64-gn2bp-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-arm64-gn2bp-dbg/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/try/android-cronet-arm64-rel/properties.json b/infra/config/generated/builders/try/android-cronet-arm64-rel/properties.json
index 7a8ab80..3c406c4b 100644
--- a/infra/config/generated/builders/try/android-cronet-arm64-rel/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-arm64-rel/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/try/android-cronet-asan-arm-rel/properties.json b/infra/config/generated/builders/try/android-cronet-asan-arm-rel/properties.json
index e727c28..3face22 100644
--- a/infra/config/generated/builders/try/android-cronet-asan-arm-rel/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-asan-arm-rel/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/try/android-cronet-mainline-clang-arm64-dbg/properties.json b/infra/config/generated/builders/try/android-cronet-mainline-clang-arm64-dbg/properties.json
index 5b42ea3..5ea54cd 100644
--- a/infra/config/generated/builders/try/android-cronet-mainline-clang-arm64-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-mainline-clang-arm64-dbg/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/try/android-cronet-mainline-clang-arm64-rel/properties.json b/infra/config/generated/builders/try/android-cronet-mainline-clang-arm64-rel/properties.json
index e549bc8..32950a9 100644
--- a/infra/config/generated/builders/try/android-cronet-mainline-clang-arm64-rel/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-mainline-clang-arm64-rel/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/try/android-cronet-mainline-clang-riscv64-dbg/properties.json b/infra/config/generated/builders/try/android-cronet-mainline-clang-riscv64-dbg/properties.json
index 95caf14a..21f3130 100644
--- a/infra/config/generated/builders/try/android-cronet-mainline-clang-riscv64-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-mainline-clang-riscv64-dbg/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/try/android-cronet-mainline-clang-riscv64-rel/properties.json b/infra/config/generated/builders/try/android-cronet-mainline-clang-riscv64-rel/properties.json
index 9527d68..13b991a 100644
--- a/infra/config/generated/builders/try/android-cronet-mainline-clang-riscv64-rel/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-mainline-clang-riscv64-rel/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/try/android-cronet-mainline-clang-x86-dbg/properties.json b/infra/config/generated/builders/try/android-cronet-mainline-clang-x86-dbg/properties.json
index a02c1e0..dad1e4f 100644
--- a/infra/config/generated/builders/try/android-cronet-mainline-clang-x86-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-mainline-clang-x86-dbg/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -25,7 +25,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-cronet-mainline-clang-x86-rel/properties.json b/infra/config/generated/builders/try/android-cronet-mainline-clang-x86-rel/properties.json
index 37cce7b..4a2093c 100644
--- a/infra/config/generated/builders/try/android-cronet-mainline-clang-x86-rel/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-mainline-clang-x86-rel/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -25,7 +25,7 @@
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-cronet-riscv64-dbg/properties.json b/infra/config/generated/builders/try/android-cronet-riscv64-dbg/properties.json
index 1d7b610..ad72569 100644
--- a/infra/config/generated/builders/try/android-cronet-riscv64-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-riscv64-dbg/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/try/android-cronet-riscv64-rel/properties.json b/infra/config/generated/builders/try/android-cronet-riscv64-rel/properties.json
index a7c66938..b6abe6c 100644
--- a/infra/config/generated/builders/try/android-cronet-riscv64-rel/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-riscv64-rel/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/try/android-cronet-x64-dbg-12-tests/properties.json b/infra/config/generated/builders/try/android-cronet-x64-dbg-12-tests/properties.json
index 9a0fc7b6..eaa83309 100644
--- a/infra/config/generated/builders/try/android-cronet-x64-dbg-12-tests/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-x64-dbg-12-tests/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -25,7 +25,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -49,7 +49,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -57,7 +57,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-cronet-x64-dbg-13-tests/properties.json b/infra/config/generated/builders/try/android-cronet-x64-dbg-13-tests/properties.json
index 9cb1a3b..c9cae67 100644
--- a/infra/config/generated/builders/try/android-cronet-x64-dbg-13-tests/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-x64-dbg-13-tests/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -25,7 +25,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -49,7 +49,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -57,7 +57,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-cronet-x64-dbg-14-tests/properties.json b/infra/config/generated/builders/try/android-cronet-x64-dbg-14-tests/properties.json
index d79bfab8..fb34e66e 100644
--- a/infra/config/generated/builders/try/android-cronet-x64-dbg-14-tests/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-x64-dbg-14-tests/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -25,7 +25,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -49,7 +49,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -57,7 +57,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-cronet-x64-dbg-15-tests/properties.json b/infra/config/generated/builders/try/android-cronet-x64-dbg-15-tests/properties.json
index a78967f..6c1be07 100644
--- a/infra/config/generated/builders/try/android-cronet-x64-dbg-15-tests/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-x64-dbg-15-tests/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -25,7 +25,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -49,7 +49,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -57,7 +57,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-cronet-x64-dbg-16-tests/properties.json b/infra/config/generated/builders/try/android-cronet-x64-dbg-16-tests/properties.json
index c368bb2..2ff76d0c 100644
--- a/infra/config/generated/builders/try/android-cronet-x64-dbg-16-tests/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-x64-dbg-16-tests/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -25,7 +25,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -49,7 +49,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -57,7 +57,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_bits": 64,
                 "target_platform": "android"
               },
diff --git a/infra/config/generated/builders/try/android-cronet-x64-dbg/properties.json b/infra/config/generated/builders/try/android-cronet-x64-dbg/properties.json
index 0e190a83..bf7ff1d 100644
--- a/infra/config/generated/builders/try/android-cronet-x64-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-x64-dbg/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -25,7 +25,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-cronet-x64-rel/properties.json b/infra/config/generated/builders/try/android-cronet-x64-rel/properties.json
index 8b87449da..4a6e1f0 100644
--- a/infra/config/generated/builders/try/android-cronet-x64-rel/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-x64-rel/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -25,7 +25,7 @@
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-cronet-x86-dbg-10-tests/properties.json b/infra/config/generated/builders/try/android-cronet-x86-dbg-10-tests/properties.json
index 2534869..528632c 100644
--- a/infra/config/generated/builders/try/android-cronet-x86-dbg-10-tests/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-x86-dbg-10-tests/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -25,7 +25,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
@@ -49,7 +49,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -57,7 +57,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-cronet-x86-dbg-11-tests/properties.json b/infra/config/generated/builders/try/android-cronet-x86-dbg-11-tests/properties.json
index b235e8f..ba05561 100644
--- a/infra/config/generated/builders/try/android-cronet-x86-dbg-11-tests/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-x86-dbg-11-tests/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -25,7 +25,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
@@ -49,7 +49,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -57,7 +57,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-cronet-x86-dbg-marshmallow-tests/properties.json b/infra/config/generated/builders/try/android-cronet-x86-dbg-marshmallow-tests/properties.json
index a63c47f..60713c8 100644
--- a/infra/config/generated/builders/try/android-cronet-x86-dbg-marshmallow-tests/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-x86-dbg-marshmallow-tests/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -25,7 +25,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
@@ -49,7 +49,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -57,7 +57,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-cronet-x86-dbg-nougat-tests/properties.json b/infra/config/generated/builders/try/android-cronet-x86-dbg-nougat-tests/properties.json
index 57ca2b260..9dde57c 100644
--- a/infra/config/generated/builders/try/android-cronet-x86-dbg-nougat-tests/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-x86-dbg-nougat-tests/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -25,7 +25,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
@@ -49,7 +49,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -57,7 +57,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-cronet-x86-dbg-oreo-tests/properties.json b/infra/config/generated/builders/try/android-cronet-x86-dbg-oreo-tests/properties.json
index beb65a33..bf152e41 100644
--- a/infra/config/generated/builders/try/android-cronet-x86-dbg-oreo-tests/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-x86-dbg-oreo-tests/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -25,7 +25,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
@@ -49,7 +49,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -57,7 +57,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-cronet-x86-dbg-pie-tests/properties.json b/infra/config/generated/builders/try/android-cronet-x86-dbg-pie-tests/properties.json
index dea2bda..dcb56a5 100644
--- a/infra/config/generated/builders/try/android-cronet-x86-dbg-pie-tests/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-x86-dbg-pie-tests/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -25,7 +25,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
@@ -49,7 +49,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -57,7 +57,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-cronet-x86-dbg/properties.json b/infra/config/generated/builders/try/android-cronet-x86-dbg/properties.json
index 4d42bb15..08cab5f 100644
--- a/infra/config/generated/builders/try/android-cronet-x86-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-x86-dbg/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -25,7 +25,7 @@
                   "mb"
                 ],
                 "build_config": "Debug",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-cronet-x86-rel/properties.json b/infra/config/generated/builders/try/android-cronet-x86-rel/properties.json
index f99c0fb..f0b0bbd 100644
--- a/infra/config/generated/builders/try/android-cronet-x86-rel/properties.json
+++ b/infra/config/generated/builders/try/android-cronet-x86-rel/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -25,7 +25,7 @@
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-dawn-arm-rel/properties.json b/infra/config/generated/builders/try/android-dawn-arm-rel/properties.json
index f706087d..288e7d1 100644
--- a/infra/config/generated/builders/try/android-dawn-arm-rel/properties.json
+++ b/infra/config/generated/builders/try/android-dawn-arm-rel/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
@@ -47,7 +47,7 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
@@ -82,7 +82,7 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
diff --git a/infra/config/generated/builders/try/android-dawn-arm64-exp-rel/properties.json b/infra/config/generated/builders/try/android-dawn-arm64-exp-rel/properties.json
index 0f20b74..c676291b 100644
--- a/infra/config/generated/builders/try/android-dawn-arm64-exp-rel/properties.json
+++ b/infra/config/generated/builders/try/android-dawn-arm64-exp-rel/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -46,11 +49,14 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-dawn-arm64-rel/properties.json b/infra/config/generated/builders/try/android-dawn-arm64-rel/properties.json
index 2d023c84..1a13ecc 100644
--- a/infra/config/generated/builders/try/android-dawn-arm64-rel/properties.json
+++ b/infra/config/generated/builders/try/android-dawn-arm64-rel/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -46,11 +49,14 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-dawn-arm64-s24-rel/properties.json b/infra/config/generated/builders/try/android-dawn-arm64-s24-rel/properties.json
index efce2c5..dc39ed5 100644
--- a/infra/config/generated/builders/try/android-dawn-arm64-s24-rel/properties.json
+++ b/infra/config/generated/builders/try/android-dawn-arm64-s24-rel/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -46,11 +49,14 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-desktop-15-x64-fyi-rel/properties.json b/infra/config/generated/builders/try/android-desktop-15-x64-fyi-rel/properties.json
index 9a468d2..5df2297b 100644
--- a/infra/config/generated/builders/try/android-desktop-15-x64-fyi-rel/properties.json
+++ b/infra/config/generated/builders/try/android-desktop-15-x64-fyi-rel/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android.desktop.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-desktop-15-x64-rel/properties.json b/infra/config/generated/builders/try/android-desktop-15-x64-rel/properties.json
index d5eb1cb..aed245b 100644
--- a/infra/config/generated/builders/try/android-desktop-15-x64-rel/properties.json
+++ b/infra/config/generated/builders/try/android-desktop-15-x64-rel/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android.desktop",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -45,11 +48,14 @@
               "builder_group": "chromium.android.desktop",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-desktop-arm64-clobber-rel/properties.json b/infra/config/generated/builders/try/android-desktop-arm64-clobber-rel/properties.json
index dedfc40..a914966c 100644
--- a/infra/config/generated/builders/try/android-desktop-arm64-clobber-rel/properties.json
+++ b/infra/config/generated/builders/try/android-desktop-arm64-clobber-rel/properties.json
@@ -16,7 +16,7 @@
               "builder_group": "chromium",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/try/android-desktop-arm64-compile-dbg/properties.json b/infra/config/generated/builders/try/android-desktop-arm64-compile-dbg/properties.json
index c2b85e6..2233436 100644
--- a/infra/config/generated/builders/try/android-desktop-arm64-compile-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-desktop-arm64-compile-dbg/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android.desktop",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-desktop-arm64-compile-rel/properties.json b/infra/config/generated/builders/try/android-desktop-arm64-compile-rel/properties.json
index 1a74329..fdeb8ee 100644
--- a/infra/config/generated/builders/try/android-desktop-arm64-compile-rel/properties.json
+++ b/infra/config/generated/builders/try/android-desktop-arm64-compile-rel/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android.desktop",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-desktop-x64-clobber-rel/properties.json b/infra/config/generated/builders/try/android-desktop-x64-clobber-rel/properties.json
index 51a40f8..0a5bf1e 100644
--- a/infra/config/generated/builders/try/android-desktop-x64-clobber-rel/properties.json
+++ b/infra/config/generated/builders/try/android-desktop-x64-clobber-rel/properties.json
@@ -16,7 +16,7 @@
               "builder_group": "chromium",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
@@ -24,7 +24,7 @@
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-desktop-x64-compile-dbg/properties.json b/infra/config/generated/builders/try/android-desktop-x64-compile-dbg/properties.json
index 14a06bc..159682a 100644
--- a/infra/config/generated/builders/try/android-desktop-x64-compile-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-desktop-x64-compile-dbg/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android.desktop",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-desktop-x64-rel/properties.json b/infra/config/generated/builders/try/android-desktop-x64-rel/properties.json
index ef4bbaf..ace5a66 100644
--- a/infra/config/generated/builders/try/android-desktop-x64-rel/properties.json
+++ b/infra/config/generated/builders/try/android-desktop-x64-rel/properties.json
@@ -21,11 +21,14 @@
               "builder_group": "chromium.android.desktop",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -49,11 +52,14 @@
               "builder_group": "chromium.android.desktop",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-fieldtrial-rel/properties.json b/infra/config/generated/builders/try/android-fieldtrial-rel/properties.json
index 3a7db34..ee3fcdf4 100644
--- a/infra/config/generated/builders/try/android-fieldtrial-rel/properties.json
+++ b/infra/config/generated/builders/try/android-fieldtrial-rel/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-mte-arm64-rel/properties.json b/infra/config/generated/builders/try/android-mte-arm64-rel/properties.json
index 56594ed..b1f61bd7 100644
--- a/infra/config/generated/builders/try/android-mte-arm64-rel/properties.json
+++ b/infra/config/generated/builders/try/android-mte-arm64-rel/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/try/android-official/properties.json b/infra/config/generated/builders/try/android-official/properties.json
index 11db6823..11c87a47 100644
--- a/infra/config/generated/builders/try/android-official/properties.json
+++ b/infra/config/generated/builders/try/android-official/properties.json
@@ -16,7 +16,7 @@
               "builder_group": "chromium",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/try/android-oreo-arm64-dbg/properties.json b/infra/config/generated/builders/try/android-oreo-arm64-dbg/properties.json
index fac913e..a1c9031 100644
--- a/infra/config/generated/builders/try/android-oreo-arm64-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-oreo-arm64-dbg/properties.json
@@ -17,14 +17,15 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -48,14 +49,15 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-oreo-x86-rel/properties.json b/infra/config/generated/builders/try/android-oreo-x86-rel/properties.json
index b845ed0..714cf99 100644
--- a/infra/config/generated/builders/try/android-oreo-x86-rel/properties.json
+++ b/infra/config/generated/builders/try/android-oreo-x86-rel/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "x86_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-perfetto-rel/properties.json b/infra/config/generated/builders/try/android-perfetto-rel/properties.json
index 15befea..ec4694b 100644
--- a/infra/config/generated/builders/try/android-perfetto-rel/properties.json
+++ b/infra/config/generated/builders/try/android-perfetto-rel/properties.json
@@ -16,14 +16,14 @@
               "builder_group": "chromium.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-pie-arm64-dbg/properties.json b/infra/config/generated/builders/try/android-pie-arm64-dbg/properties.json
index 067b979a..799752b7 100644
--- a/infra/config/generated/builders/try/android-pie-arm64-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-pie-arm64-dbg/properties.json
@@ -17,14 +17,15 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -48,14 +49,15 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-pie-x86-rel/properties.json b/infra/config/generated/builders/try/android-pie-x86-rel/properties.json
index 832168a..04df1f1 100644
--- a/infra/config/generated/builders/try/android-pie-x86-rel/properties.json
+++ b/infra/config/generated/builders/try/android-pie-x86-rel/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-webview-10-x86-rel-tests/properties.json b/infra/config/generated/builders/try/android-webview-10-x86-rel-tests/properties.json
index eb089e0..8fc03b64 100644
--- a/infra/config/generated/builders/try/android-webview-10-x86-rel-tests/properties.json
+++ b/infra/config/generated/builders/try/android-webview-10-x86-rel-tests/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 32,
                 "target_platform": "android"
@@ -50,11 +53,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-webview-12-x64-dbg/properties.json b/infra/config/generated/builders/try/android-webview-12-x64-dbg/properties.json
index 7ccae1d1..f44a672 100644
--- a/infra/config/generated/builders/try/android-webview-12-x64-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-webview-12-x64-dbg/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -45,11 +48,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-webview-13-x64-dbg/properties.json b/infra/config/generated/builders/try/android-webview-13-x64-dbg/properties.json
index 5fee51a..9600397 100644
--- a/infra/config/generated/builders/try/android-webview-13-x64-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-webview-13-x64-dbg/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -45,11 +48,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-webview-13-x64-hostside-rel/properties.json b/infra/config/generated/builders/try/android-webview-13-x64-hostside-rel/properties.json
index 069501ec..99250a3 100644
--- a/infra/config/generated/builders/try/android-webview-13-x64-hostside-rel/properties.json
+++ b/infra/config/generated/builders/try/android-webview-13-x64-hostside-rel/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-webview-13-x64-wpt-android-specific/properties.json b/infra/config/generated/builders/try/android-webview-13-x64-wpt-android-specific/properties.json
index 3c4f179..f76e7a7 100644
--- a/infra/config/generated/builders/try/android-webview-13-x64-wpt-android-specific/properties.json
+++ b/infra/config/generated/builders/try/android-webview-13-x64-wpt-android-specific/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-webview-oreo-arm64-dbg/properties.json b/infra/config/generated/builders/try/android-webview-oreo-arm64-dbg/properties.json
index 4ad8e7e2..16d35f3d 100644
--- a/infra/config/generated/builders/try/android-webview-oreo-arm64-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-webview-oreo-arm64-dbg/properties.json
@@ -20,14 +20,15 @@
                 "apply_configs": [
                   "remove_all_system_webviews"
                 ],
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -56,14 +57,15 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-webview-pie-arm64-dbg/properties.json b/infra/config/generated/builders/try/android-webview-pie-arm64-dbg/properties.json
index bc40fa3f..806fa18 100644
--- a/infra/config/generated/builders/try/android-webview-pie-arm64-dbg/properties.json
+++ b/infra/config/generated/builders/try/android-webview-pie-arm64-dbg/properties.json
@@ -20,14 +20,15 @@
                 "apply_configs": [
                   "remove_all_system_webviews"
                 ],
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -56,14 +57,15 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-webview-pie-x86-wpt-fyi-rel/properties.json b/infra/config/generated/builders/try/android-webview-pie-x86-wpt-fyi-rel/properties.json
index 3484647b..0bc2843 100644
--- a/infra/config/generated/builders/try/android-webview-pie-x86-wpt-fyi-rel/properties.json
+++ b/infra/config/generated/builders/try/android-webview-pie-x86-wpt-fyi-rel/properties.json
@@ -17,14 +17,14 @@
               "builder_group": "chromium.android.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x86_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-x64-rel/properties.json b/infra/config/generated/builders/try/android-x64-rel/properties.json
index 87b4713b..c4fe5fa52 100644
--- a/infra/config/generated/builders/try/android-x64-rel/properties.json
+++ b/infra/config/generated/builders/try/android-x64-rel/properties.json
@@ -21,14 +21,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -52,14 +52,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -83,14 +83,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
                   "mb"
                 ],
                 "build_config": "Release",
-                "config": "x64_builder",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android-x86-rel/properties.json b/infra/config/generated/builders/try/android-x86-rel/properties.json
index 367aa8e..1f5c058a 100644
--- a/infra/config/generated/builders/try/android-x86-rel/properties.json
+++ b/infra/config/generated/builders/try/android-x86-rel/properties.json
@@ -21,11 +21,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "x86_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android_arm64_dbg_recipe/properties.json b/infra/config/generated/builders/try/android_arm64_dbg_recipe/properties.json
index 9b852c1..fe3adb1 100644
--- a/infra/config/generated/builders/try/android_arm64_dbg_recipe/properties.json
+++ b/infra/config/generated/builders/try/android_arm64_dbg_recipe/properties.json
@@ -20,14 +20,15 @@
                 "apply_configs": [
                   "remove_all_system_webviews"
                 ],
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -59,14 +60,15 @@
                 "apply_configs": [
                   "remove_all_system_webviews"
                 ],
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -95,14 +97,15 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -126,14 +129,15 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -162,14 +166,15 @@
               "builder_group": "chromium.android",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android_blink_rel/properties.json b/infra/config/generated/builders/try/android_blink_rel/properties.json
index 06e6031f..cad05a84 100644
--- a/infra/config/generated/builders/try/android_blink_rel/properties.json
+++ b/infra/config/generated/builders/try/android_blink_rel/properties.json
@@ -16,7 +16,7 @@
               "builder_group": "tryserver.chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/try/android_compile_dbg/properties.json b/infra/config/generated/builders/try/android_compile_dbg/properties.json
index b321de9..60bd383 100644
--- a/infra/config/generated/builders/try/android_compile_dbg/properties.json
+++ b/infra/config/generated/builders/try/android_compile_dbg/properties.json
@@ -17,14 +17,15 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Debug",
-                "config": "main_builder_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android_compile_x64_dbg/properties.json b/infra/config/generated/builders/try/android_compile_x64_dbg/properties.json
index f02be56..0ba8948 100644
--- a/infra/config/generated/builders/try/android_compile_x64_dbg/properties.json
+++ b/infra/config/generated/builders/try/android_compile_x64_dbg/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x64_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x64_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android_compile_x86_dbg/properties.json b/infra/config/generated/builders/try/android_compile_x86_dbg/properties.json
index aa1411a..222daa02 100644
--- a/infra/config/generated/builders/try/android_compile_x86_dbg/properties.json
+++ b/infra/config/generated/builders/try/android_compile_x86_dbg/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "x86_builder_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Debug",
-                "config": "x86_builder_mb",
+                "config": "main_builder",
                 "target_arch": "intel",
                 "target_bits": 32,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/android_optional_gpu_tests_rel/properties.json b/infra/config/generated/builders/try/android_optional_gpu_tests_rel/properties.json
index e35ccd1..c5b4cf0 100644
--- a/infra/config/generated/builders/try/android_optional_gpu_tests_rel/properties.json
+++ b/infra/config/generated/builders/try/android_optional_gpu_tests_rel/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "tryserver.chromium.android",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Debug",
diff --git a/infra/config/generated/builders/try/dawn-android-arm-deps-rel/properties.json b/infra/config/generated/builders/try/dawn-android-arm-deps-rel/properties.json
index f5e0f0c..d536169 100644
--- a/infra/config/generated/builders/try/dawn-android-arm-deps-rel/properties.json
+++ b/infra/config/generated/builders/try/dawn-android-arm-deps-rel/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
@@ -46,7 +46,7 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
@@ -80,7 +80,7 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
diff --git a/infra/config/generated/builders/try/dawn-android-arm64-deps-rel/properties.json b/infra/config/generated/builders/try/dawn-android-arm64-deps-rel/properties.json
index ad931ff..5a4e1bf 100644
--- a/infra/config/generated/builders/try/dawn-android-arm64-deps-rel/properties.json
+++ b/infra/config/generated/builders/try/dawn-android-arm64-deps-rel/properties.json
@@ -17,11 +17,14 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -45,11 +48,14 @@
               "builder_group": "chromium.dawn",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/gpu-fyi-cq-android-arm64/properties.json b/infra/config/generated/builders/try/gpu-fyi-cq-android-arm64/properties.json
index f19fe298..82a0cfa 100644
--- a/infra/config/generated/builders/try/gpu-fyi-cq-android-arm64/properties.json
+++ b/infra/config/generated/builders/try/gpu-fyi-cq-android-arm64/properties.json
@@ -16,14 +16,15 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -52,14 +53,15 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/gpu-fyi-try-android-a13-32/properties.json b/infra/config/generated/builders/try/gpu-fyi-try-android-a13-32/properties.json
index 90dcb85..509d7b0 100644
--- a/infra/config/generated/builders/try/gpu-fyi-try-android-a13-32/properties.json
+++ b/infra/config/generated/builders/try/gpu-fyi-try-android-a13-32/properties.json
@@ -16,7 +16,7 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
@@ -49,7 +49,7 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
diff --git a/infra/config/generated/builders/try/gpu-fyi-try-android-a23-32/properties.json b/infra/config/generated/builders/try/gpu-fyi-try-android-a23-32/properties.json
index 19ca1aa..3afba94 100644
--- a/infra/config/generated/builders/try/gpu-fyi-try-android-a23-32/properties.json
+++ b/infra/config/generated/builders/try/gpu-fyi-try-android-a23-32/properties.json
@@ -16,7 +16,7 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
@@ -49,7 +49,7 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
diff --git a/infra/config/generated/builders/try/gpu-fyi-try-android-m-nexus-5x-64/properties.json b/infra/config/generated/builders/try/gpu-fyi-try-android-m-nexus-5x-64/properties.json
index 7421b9a9..02b60d4 100644
--- a/infra/config/generated/builders/try/gpu-fyi-try-android-m-nexus-5x-64/properties.json
+++ b/infra/config/generated/builders/try/gpu-fyi-try-android-m-nexus-5x-64/properties.json
@@ -16,14 +16,15 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -51,14 +52,15 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/gpu-fyi-try-android-nvidia-shield-tv/properties.json b/infra/config/generated/builders/try/gpu-fyi-try-android-nvidia-shield-tv/properties.json
index 7e690d0..e09e36d 100644
--- a/infra/config/generated/builders/try/gpu-fyi-try-android-nvidia-shield-tv/properties.json
+++ b/infra/config/generated/builders/try/gpu-fyi-try-android-nvidia-shield-tv/properties.json
@@ -16,7 +16,7 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
@@ -49,7 +49,7 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
diff --git a/infra/config/generated/builders/try/gpu-fyi-try-android-p-pixel-2-32/properties.json b/infra/config/generated/builders/try/gpu-fyi-try-android-p-pixel-2-32/properties.json
index dacc369..4dc3344 100644
--- a/infra/config/generated/builders/try/gpu-fyi-try-android-p-pixel-2-32/properties.json
+++ b/infra/config/generated/builders/try/gpu-fyi-try-android-p-pixel-2-32/properties.json
@@ -16,7 +16,7 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
@@ -48,7 +48,7 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
diff --git a/infra/config/generated/builders/try/gpu-fyi-try-android-pixel-6-64-exp/properties.json b/infra/config/generated/builders/try/gpu-fyi-try-android-pixel-6-64-exp/properties.json
index 7abe9a32..5fd50c3 100644
--- a/infra/config/generated/builders/try/gpu-fyi-try-android-pixel-6-64-exp/properties.json
+++ b/infra/config/generated/builders/try/gpu-fyi-try-android-pixel-6-64-exp/properties.json
@@ -16,14 +16,15 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -52,14 +53,15 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/gpu-fyi-try-android-pixel-6-64/properties.json b/infra/config/generated/builders/try/gpu-fyi-try-android-pixel-6-64/properties.json
index a4ecb7ae..417cdea 100644
--- a/infra/config/generated/builders/try/gpu-fyi-try-android-pixel-6-64/properties.json
+++ b/infra/config/generated/builders/try/gpu-fyi-try-android-pixel-6-64/properties.json
@@ -16,14 +16,15 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -52,14 +53,15 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/gpu-fyi-try-android-r-pixel-4-32/properties.json b/infra/config/generated/builders/try/gpu-fyi-try-android-r-pixel-4-32/properties.json
index 59a505f..e2b6e08 100644
--- a/infra/config/generated/builders/try/gpu-fyi-try-android-r-pixel-4-32/properties.json
+++ b/infra/config/generated/builders/try/gpu-fyi-try-android-r-pixel-4-32/properties.json
@@ -16,7 +16,7 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
@@ -48,7 +48,7 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "build_config": "Release",
diff --git a/infra/config/generated/builders/try/gpu-fyi-try-android-s23-64/properties.json b/infra/config/generated/builders/try/gpu-fyi-try-android-s23-64/properties.json
index cf855de..58b15ee8 100644
--- a/infra/config/generated/builders/try/gpu-fyi-try-android-s23-64/properties.json
+++ b/infra/config/generated/builders/try/gpu-fyi-try-android-s23-64/properties.json
@@ -16,11 +16,14 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
+                "apply_configs": [
+                  "mb"
+                ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
@@ -49,14 +52,15 @@
               "builder_group": "chromium.gpu.fyi",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "arm64_builder_rel_mb"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
+                  "mb",
                   "download_xr_test_apks"
                 ],
                 "build_config": "Release",
-                "config": "arm64_builder_rel_mb",
+                "config": "main_builder",
                 "target_arch": "arm",
                 "target_bits": 64,
                 "target_platform": "android"
diff --git a/infra/config/generated/builders/try/gpu-try-android-m-nexus-5x-64/properties.json b/infra/config/generated/builders/try/gpu-try-android-m-nexus-5x-64/properties.json
index 045f678..d1c71b7 100644
--- a/infra/config/generated/builders/try/gpu-try-android-m-nexus-5x-64/properties.json
+++ b/infra/config/generated/builders/try/gpu-try-android-m-nexus-5x-64/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.gpu",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/try/gpu-try-android-pixel-2-64/properties.json b/infra/config/generated/builders/try/gpu-try-android-pixel-2-64/properties.json
index 26cc05e6..ba85c287 100644
--- a/infra/config/generated/builders/try/gpu-try-android-pixel-2-64/properties.json
+++ b/infra/config/generated/builders/try/gpu-try-android-pixel-2-64/properties.json
@@ -17,7 +17,7 @@
               "builder_group": "chromium.gpu",
               "execution_mode": "COMPILE_AND_TEST",
               "legacy_android_config": {
-                "config": "main_builder"
+                "config": "base_config"
               },
               "legacy_chromium_config": {
                 "apply_configs": [
diff --git a/infra/config/generated/builders/try/linux-dcheck-off-rel/targets/chromium.linux.json b/infra/config/generated/builders/try/linux-dcheck-off-rel/targets/chromium.linux.json
index e19413a..5bc20b7 100644
--- a/infra/config/generated/builders/try/linux-dcheck-off-rel/targets/chromium.linux.json
+++ b/infra/config/generated/builders/try/linux-dcheck-off-rel/targets/chromium.linux.json
@@ -2121,6 +2121,35 @@
         "test_id_prefix": "ninja://:blink_web_tests/"
       },
       {
+        "args": [
+          "--test-type=wdspec"
+        ],
+        "ci_only": true,
+        "experiment_percentage": 100,
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [
+            "--verbose"
+          ],
+          "script": "//third_party/blink/tools/merge_web_test_results.py"
+        },
+        "name": "webdriver_wpt_tests",
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "results_handler": "layout tests",
+        "swarming": {
+          "dimensions": {
+            "os": "Ubuntu-22.04"
+          },
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 2
+        },
+        "test": "chrome_wpt_tests",
+        "test_id_prefix": "ninja://:chrome_wpt_tests/"
+      },
+      {
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
diff --git a/infra/config/generated/builders/try/linux-full-remote-rel/targets/chromium.linux.json b/infra/config/generated/builders/try/linux-full-remote-rel/targets/chromium.linux.json
index e19413a..5bc20b7 100644
--- a/infra/config/generated/builders/try/linux-full-remote-rel/targets/chromium.linux.json
+++ b/infra/config/generated/builders/try/linux-full-remote-rel/targets/chromium.linux.json
@@ -2121,6 +2121,35 @@
         "test_id_prefix": "ninja://:blink_web_tests/"
       },
       {
+        "args": [
+          "--test-type=wdspec"
+        ],
+        "ci_only": true,
+        "experiment_percentage": 100,
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [
+            "--verbose"
+          ],
+          "script": "//third_party/blink/tools/merge_web_test_results.py"
+        },
+        "name": "webdriver_wpt_tests",
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "results_handler": "layout tests",
+        "swarming": {
+          "dimensions": {
+            "os": "Ubuntu-22.04"
+          },
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 2
+        },
+        "test": "chrome_wpt_tests",
+        "test_id_prefix": "ninja://:chrome_wpt_tests/"
+      },
+      {
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
diff --git a/infra/config/generated/builders/try/linux-rel-test-selection/targets/chromium.linux.json b/infra/config/generated/builders/try/linux-rel-test-selection/targets/chromium.linux.json
index e19413a..5bc20b7 100644
--- a/infra/config/generated/builders/try/linux-rel-test-selection/targets/chromium.linux.json
+++ b/infra/config/generated/builders/try/linux-rel-test-selection/targets/chromium.linux.json
@@ -2121,6 +2121,35 @@
         "test_id_prefix": "ninja://:blink_web_tests/"
       },
       {
+        "args": [
+          "--test-type=wdspec"
+        ],
+        "ci_only": true,
+        "experiment_percentage": 100,
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [
+            "--verbose"
+          ],
+          "script": "//third_party/blink/tools/merge_web_test_results.py"
+        },
+        "name": "webdriver_wpt_tests",
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "results_handler": "layout tests",
+        "swarming": {
+          "dimensions": {
+            "os": "Ubuntu-22.04"
+          },
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 2
+        },
+        "test": "chrome_wpt_tests",
+        "test_id_prefix": "ninja://:chrome_wpt_tests/"
+      },
+      {
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
diff --git a/infra/config/generated/builders/try/linux-rel/targets/chromium.linux.json b/infra/config/generated/builders/try/linux-rel/targets/chromium.linux.json
index e19413a..5bc20b7 100644
--- a/infra/config/generated/builders/try/linux-rel/targets/chromium.linux.json
+++ b/infra/config/generated/builders/try/linux-rel/targets/chromium.linux.json
@@ -2121,6 +2121,35 @@
         "test_id_prefix": "ninja://:blink_web_tests/"
       },
       {
+        "args": [
+          "--test-type=wdspec"
+        ],
+        "ci_only": true,
+        "experiment_percentage": 100,
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [
+            "--verbose"
+          ],
+          "script": "//third_party/blink/tools/merge_web_test_results.py"
+        },
+        "name": "webdriver_wpt_tests",
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "results_handler": "layout tests",
+        "swarming": {
+          "dimensions": {
+            "os": "Ubuntu-22.04"
+          },
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 2
+        },
+        "test": "chrome_wpt_tests",
+        "test_id_prefix": "ninja://:chrome_wpt_tests/"
+      },
+      {
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
diff --git a/infra/config/generated/builders/try/linux_chromium_compile_rel_ng/targets/chromium.linux.json b/infra/config/generated/builders/try/linux_chromium_compile_rel_ng/targets/chromium.linux.json
index c09f385..c6d04f53 100644
--- a/infra/config/generated/builders/try/linux_chromium_compile_rel_ng/targets/chromium.linux.json
+++ b/infra/config/generated/builders/try/linux_chromium_compile_rel_ng/targets/chromium.linux.json
@@ -2121,6 +2121,35 @@
         "test_id_prefix": "ninja://:blink_web_tests/"
       },
       {
+        "args": [
+          "--test-type=wdspec"
+        ],
+        "ci_only": true,
+        "experiment_percentage": 100,
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [
+            "--verbose"
+          ],
+          "script": "//third_party/blink/tools/merge_web_test_results.py"
+        },
+        "name": "webdriver_wpt_tests",
+        "resultdb": {
+          "enable": true,
+          "has_native_resultdb_integration": true
+        },
+        "results_handler": "layout tests",
+        "swarming": {
+          "dimensions": {
+            "os": "Ubuntu-22.04"
+          },
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
+          "shards": 2
+        },
+        "test": "chrome_wpt_tests",
+        "test_id_prefix": "ninja://:chrome_wpt_tests/"
+      },
+      {
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg
index baa8173..188dcda 100644
--- a/infra/config/generated/luci/cr-buildbucket.cfg
+++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -38919,11 +38919,14 @@
         '              "builder_group": "chromium.angle",'
         '              "execution_mode": "COMPILE_AND_TEST",'
         '              "legacy_android_config": {'
-        '                "config": "main_builder_mb"'
+        '                "config": "base_config"'
         '              },'
         '              "legacy_chromium_config": {'
+        '                "apply_configs": ['
+        '                  "mb"'
+        '                ],'
         '                "build_config": "Release",'
-        '                "config": "main_builder_mb",'
+        '                "config": "main_builder",'
         '                "target_arch": "arm",'
         '                "target_bits": 64,'
         '                "target_platform": "android"'
@@ -38948,11 +38951,14 @@
         '              "builder_group": "chromium.angle",'
         '              "execution_mode": "TEST",'
         '              "legacy_android_config": {'
-        '                "config": "main_builder_mb"'
+        '                "config": "base_config"'
         '              },'
         '              "legacy_chromium_config": {'
+        '                "apply_configs": ['
+        '                  "mb"'
+        '                ],'
         '                "build_config": "Release",'
-        '                "config": "main_builder_mb",'
+        '                "config": "main_builder",'
         '                "target_arch": "arm",'
         '                "target_bits": 64,'
         '                "target_platform": "android"'
@@ -39143,11 +39149,14 @@
         '              "builder_group": "chromium.angle",'
         '              "execution_mode": "COMPILE_AND_TEST",'
         '              "legacy_android_config": {'
-        '                "config": "main_builder_mb"'
+        '                "config": "base_config"'
         '              },'
         '              "legacy_chromium_config": {'
+        '                "apply_configs": ['
+        '                  "mb"'
+        '                ],'
         '                "build_config": "Release",'
-        '                "config": "main_builder_mb",'
+        '                "config": "main_builder",'
         '                "target_arch": "arm",'
         '                "target_bits": 64,'
         '                "target_platform": "android"'
@@ -39172,11 +39181,14 @@
         '              "builder_group": "chromium.angle",'
         '              "execution_mode": "TEST",'
         '              "legacy_android_config": {'
-        '                "config": "main_builder_mb"'
+        '                "config": "base_config"'
         '              },'
         '              "legacy_chromium_config": {'
+        '                "apply_configs": ['
+        '                  "mb"'
+        '                ],'
         '                "build_config": "Release",'
-        '                "config": "main_builder_mb",'
+        '                "config": "main_builder",'
         '                "target_arch": "arm",'
         '                "target_bits": 64,'
         '                "target_platform": "android"'
@@ -83194,11 +83206,14 @@
         '              "builder_group": "chromium.angle",'
         '              "execution_mode": "COMPILE_AND_TEST",'
         '              "legacy_android_config": {'
-        '                "config": "main_builder_mb"'
+        '                "config": "base_config"'
         '              },'
         '              "legacy_chromium_config": {'
+        '                "apply_configs": ['
+        '                  "mb"'
+        '                ],'
         '                "build_config": "Release",'
-        '                "config": "main_builder_mb",'
+        '                "config": "main_builder",'
         '                "target_arch": "arm",'
         '                "target_bits": 64,'
         '                "target_platform": "android"'
@@ -83223,11 +83238,14 @@
         '              "builder_group": "chromium.angle",'
         '              "execution_mode": "TEST",'
         '              "legacy_android_config": {'
-        '                "config": "main_builder_mb"'
+        '                "config": "base_config"'
         '              },'
         '              "legacy_chromium_config": {'
+        '                "apply_configs": ['
+        '                  "mb"'
+        '                ],'
         '                "build_config": "Release",'
-        '                "config": "main_builder_mb",'
+        '                "config": "main_builder",'
         '                "target_arch": "arm",'
         '                "target_bits": 64,'
         '                "target_platform": "android"'
diff --git a/infra/config/lib/builder_config.star b/infra/config/lib/builder_config.star
index 5c8cda9..a46ed77 100644
--- a/infra/config/lib/builder_config.star
+++ b/infra/config/lib/builder_config.star
@@ -164,7 +164,7 @@
         fail("config must be provided")
     return struct(
         config = config,
-        apply_configs = args.listify(apply_configs),
+        apply_configs = apply_configs,
     )
 
 def _skylab_upload_location(*, gs_bucket, gs_extra = None):
diff --git a/infra/config/subprojects/build/build.star b/infra/config/subprojects/build/build.star
index 822b7820..b0908da 100644
--- a/infra/config/subprojects/build/build.star
+++ b/infra/config/subprojects/build/build.star
@@ -152,7 +152,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder",
+            config = "base_config",
         ),
     ),
     gn_args = "try/android-arm64-rel",
@@ -188,7 +188,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder",
+            config = "base_config",
         ),
     ),
     gn_args = {
@@ -597,7 +597,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder",
+            config = "base_config",
         ),
     ),
     gn_args = {
diff --git a/infra/config/subprojects/chromium/ci/chromium.android.desktop.fyi.star b/infra/config/subprojects/chromium/ci/chromium.android.desktop.fyi.star
index 0e6139b8..83397e8 100644
--- a/infra/config/subprojects/chromium/ci/chromium.android.desktop.fyi.star
+++ b/infra/config/subprojects/chromium/ci/chromium.android.desktop.fyi.star
@@ -48,14 +48,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.INTEL,
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-desktop-archive",
     ),
diff --git a/infra/config/subprojects/chromium/ci/chromium.android.desktop.star b/infra/config/subprojects/chromium/ci/chromium.android.desktop.star
index 2b5e006..9c796fe 100644
--- a/infra/config/subprojects/chromium/ci/chromium.android.desktop.star
+++ b/infra/config/subprojects/chromium/ci/chromium.android.desktop.star
@@ -56,14 +56,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "main_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.DEBUG,
             target_arch = builder_config.target_arch.ARM,
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-desktop-archive",
     ),
@@ -100,14 +101,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "main_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.ARM,
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-desktop-archive",
     ),
@@ -144,14 +146,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.DEBUG,
             target_arch = builder_config.target_arch.INTEL,
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-desktop-archive",
     ),
@@ -189,14 +192,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.INTEL,
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-desktop-archive",
     ),
@@ -240,14 +244,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.INTEL,
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-desktop-archive",
     ),
diff --git a/infra/config/subprojects/chromium/ci/chromium.android.fyi.star b/infra/config/subprojects/chromium/ci/chromium.android.fyi.star
index aa60fd8f..e6b916b 100644
--- a/infra/config/subprojects/chromium/ci/chromium.android.fyi.star
+++ b/infra/config/subprojects/chromium/ci/chromium.android.fyi.star
@@ -47,14 +47,14 @@
             apply_configs = ["android"],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x86_builder",
+            config = "main_builder",
             apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.INTEL,
             target_bits = 32,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "x86_builder"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-android-archive",
     ),
     gn_args = gn_args.config(
@@ -109,14 +109,15 @@
             apply_configs = ["android"],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.INTEL,
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -162,14 +163,15 @@
             apply_configs = ["android"],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.INTEL,
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -216,14 +218,14 @@
             apply_configs = ["android"],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x86_builder",
+            config = "main_builder",
             apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.INTEL,
             target_bits = 32,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "x86_builder"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-android-archive",
     ),
     gn_args = gn_args.config(
@@ -287,14 +289,14 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x86_builder",
+            config = "main_builder",
             apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.INTEL,
             target_bits = 32,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "x86_builder"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-android-archive",
     ),
     gn_args = gn_args.config(
@@ -472,13 +474,14 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x86_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.INTEL,
             target_bits = 32,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "x86_builder_mb"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-android-archive",
     ),
     gn_args = gn_args.config(
@@ -551,13 +554,14 @@
             apply_configs = ["android"],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x86_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.INTEL,
             target_bits = 32,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "x86_builder_mb"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-android-archive",
     ),
     gn_args = gn_args.config(
@@ -630,7 +634,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder",
+            config = "main_builder",
             apply_configs = [
                 "mb",
             ],
@@ -640,7 +644,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -680,8 +684,9 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder_mb",
+            config = "main_builder",
             apply_configs = [
+                "mb",
                 "download_xr_test_apks",
             ],
             build_config = builder_config.build_config.DEBUG,
@@ -690,7 +695,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -810,14 +815,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.INTEL,
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -958,7 +964,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder",
+            config = "main_builder",
             apply_configs = [
                 "mb",
             ],
@@ -968,7 +974,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -1136,14 +1142,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "main_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.ARM,
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -1191,14 +1198,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.INTEL,
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -1256,14 +1264,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.INTEL,
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -1371,7 +1380,7 @@
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "main_builder"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-android-archive",
     ),
     gn_args = gn_args.config(
@@ -1414,14 +1423,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.DEBUG,
             target_arch = builder_config.target_arch.INTEL,
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -1458,14 +1468,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.DEBUG,
             target_arch = builder_config.target_arch.INTEL,
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -1505,14 +1516,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.DEBUG,
             target_arch = builder_config.target_arch.INTEL,
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -1546,7 +1558,7 @@
             apply_configs = ["android"],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x86_builder",
+            config = "main_builder",
             apply_configs = [
                 "cronet_builder",
                 "mb",
@@ -1557,7 +1569,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x86_builder",
+            config = "base_config",
         ),
     ),
     gn_args = gn_args.config(
diff --git a/infra/config/subprojects/chromium/ci/chromium.android.star b/infra/config/subprojects/chromium/ci/chromium.android.star
index b8cb105..348cb08 100644
--- a/infra/config/subprojects/chromium/ci/chromium.android.star
+++ b/infra/config/subprojects/chromium/ci/chromium.android.star
@@ -68,8 +68,9 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "main_builder_mb",
+            config = "main_builder",
             apply_configs = [
+                "mb",
                 "download_xr_test_apks",
             ],
             build_config = builder_config.build_config.DEBUG,
@@ -78,7 +79,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder_mb",
+            config = "base_config",
             apply_configs = [
                 "remove_all_system_webviews",
             ],
@@ -121,8 +122,9 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "main_builder_mb",
+            config = "main_builder",
             apply_configs = [
+                "mb",
                 "download_xr_test_apks",
             ],
             build_config = builder_config.build_config.DEBUG,
@@ -131,7 +133,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder_mb",
+            config = "base_config",
             apply_configs = [
                 "remove_all_system_webviews",
             ],
@@ -164,8 +166,9 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "main_builder_mb",
+            config = "main_builder",
             apply_configs = [
+                "mb",
                 "download_xr_test_apks",
             ],
             build_config = builder_config.build_config.DEBUG,
@@ -174,7 +177,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -221,8 +224,9 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "main_builder_mb",
+            config = "main_builder",
             apply_configs = [
+                "mb",
                 "download_xr_test_apks",
             ],
             build_config = builder_config.build_config.DEBUG,
@@ -231,7 +235,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -282,8 +286,9 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "main_builder_mb",
+            config = "main_builder",
             apply_configs = [
+                "mb",
                 "download_xr_test_apks",
             ],
             build_config = builder_config.build_config.DEBUG,
@@ -292,7 +297,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -371,14 +376,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.DEBUG,
             target_arch = builder_config.target_arch.INTEL,
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -420,14 +426,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x86_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.DEBUG,
             target_arch = builder_config.target_arch.INTEL,
             target_bits = 32,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x86_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -467,14 +474,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "main_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.ARM,
             target_bits = 32,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -513,14 +521,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "main_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.ARM,
             target_bits = 32,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -558,7 +567,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "cast_builder",
+            config = "main_builder",
             apply_configs = [
                 "mb",
             ],
@@ -568,7 +577,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "cast_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -615,7 +624,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "cast_builder",
+            config = "main_builder",
             apply_configs = [
                 "mb",
             ],
@@ -625,7 +634,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "cast_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -672,7 +681,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "cast_builder",
+            config = "main_builder",
             apply_configs = [
                 "mb",
             ],
@@ -682,7 +691,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "cast_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -729,7 +738,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "cast_builder",
+            config = "main_builder",
             apply_configs = [
                 "mb",
             ],
@@ -739,7 +748,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "cast_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -838,8 +847,9 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "main_builder_mb",
+            config = "main_builder",
             apply_configs = [
+                "mb",
                 "download_xr_test_apks",
             ],
             build_config = builder_config.build_config.DEBUG,
@@ -848,7 +858,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -903,7 +913,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -960,8 +970,9 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder_mb",
+            config = "main_builder",
             apply_configs = [
+                "mb",
                 "download_xr_test_apks",
             ],
             build_config = builder_config.build_config.DEBUG,
@@ -970,7 +981,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -1081,8 +1092,9 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder_mb",
+            config = "main_builder",
             apply_configs = [
+                "mb",
                 "download_xr_test_apks",
             ],
             build_config = builder_config.build_config.DEBUG,
@@ -1091,7 +1103,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -1170,7 +1182,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -1253,14 +1265,15 @@
             apply_configs = ["android"],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x86_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.INTEL,
             target_bits = 32,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x86_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -1363,7 +1376,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -1416,7 +1429,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -1468,7 +1481,7 @@
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "main_builder"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-android-archive",
     ),
     gn_args = gn_args.config(
@@ -1523,7 +1536,7 @@
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "main_builder"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-android-archive",
     ),
     gn_args = gn_args.config(
@@ -1570,7 +1583,7 @@
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "main_builder"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-android-archive",
     ),
     gn_args = gn_args.config(
@@ -1621,7 +1634,7 @@
             target_bits = 32,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "main_builder"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-android-archive",
     ),
     gn_args = gn_args.config(
@@ -1679,7 +1692,7 @@
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "main_builder"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-android-archive",
     ),
     gn_args = gn_args.config(
@@ -1726,7 +1739,7 @@
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "main_builder"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-android-archive",
     ),
     gn_args = gn_args.config(
@@ -1776,7 +1789,7 @@
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "main_builder"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-android-archive",
     ),
     gn_args = gn_args.config(
@@ -1823,7 +1836,7 @@
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "main_builder"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-android-archive",
     ),
     gn_args = gn_args.config(
@@ -1865,7 +1878,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x86_builder",
+            config = "main_builder",
             apply_configs = [
                 "cronet_builder",
                 "mb",
@@ -1876,7 +1889,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x86_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -1914,7 +1927,7 @@
             apply_configs = ["android"],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x86_builder",
+            config = "main_builder",
             apply_configs = [
                 "cronet_builder",
                 "mb",
@@ -1924,7 +1937,7 @@
             target_bits = 32,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "x86_builder"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-android-archive",
     ),
     gn_args = gn_args.config(
@@ -1974,7 +1987,7 @@
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "main_builder"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-android-archive",
     ),
     gn_args = gn_args.config(
@@ -2021,7 +2034,7 @@
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "main_builder"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-android-archive",
     ),
     gn_args = gn_args.config(
@@ -2062,7 +2075,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x86_builder",
+            config = "main_builder",
             apply_configs = [
                 "cronet_builder",
                 "mb",
@@ -2073,7 +2086,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x86_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -2124,7 +2137,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder",
+            config = "main_builder",
             apply_configs = [
                 "cronet_builder",
                 "mb",
@@ -2135,7 +2148,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -2187,7 +2200,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder",
+            config = "main_builder",
             apply_configs = [
                 "cronet_builder",
                 "mb",
@@ -2198,7 +2211,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -2235,7 +2248,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder",
+            config = "main_builder",
             apply_configs = [
                 "cronet_builder",
                 "mb",
@@ -2246,7 +2259,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -2284,7 +2297,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder",
+            config = "main_builder",
             apply_configs = [
                 "cronet_builder",
                 "mb",
@@ -2295,7 +2308,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -2334,7 +2347,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder",
+            config = "main_builder",
             apply_configs = [
                 "cronet_builder",
                 "mb",
@@ -2345,7 +2358,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -2384,7 +2397,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder",
+            config = "main_builder",
             apply_configs = [
                 "cronet_builder",
                 "mb",
@@ -2394,7 +2407,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -2433,7 +2446,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x86_builder",
+            config = "main_builder",
             apply_configs = [
                 "cronet_builder",
                 "mb",
@@ -2444,7 +2457,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x86_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -2481,7 +2494,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x86_builder",
+            config = "main_builder",
             apply_configs = [
                 "cronet_builder",
                 "mb",
@@ -2492,7 +2505,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x86_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -2529,7 +2542,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x86_builder",
+            config = "main_builder",
             apply_configs = [
                 "cronet_builder",
                 "mb",
@@ -2540,7 +2553,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x86_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -2584,7 +2597,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x86_builder",
+            config = "main_builder",
             apply_configs = [
                 "cronet_builder",
                 "mb",
@@ -2595,7 +2608,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x86_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -2641,7 +2654,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x86_builder",
+            config = "main_builder",
             apply_configs = [
                 "cronet_builder",
                 "mb",
@@ -2652,7 +2665,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x86_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -2696,7 +2709,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x86_builder",
+            config = "main_builder",
             apply_configs = [
                 "cronet_builder",
                 "mb",
@@ -2707,7 +2720,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x86_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -2740,7 +2753,7 @@
             apply_configs = ["android"],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x86_builder",
+            config = "main_builder",
             apply_configs = [
                 "cronet_builder",
                 "mb",
@@ -2750,7 +2763,7 @@
             target_bits = 32,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "x86_builder"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-android-archive",
     ),
     gn_args = gn_args.config(
@@ -2792,7 +2805,7 @@
             apply_configs = ["android"],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder",
+            config = "main_builder",
             apply_configs = [
                 "cronet_builder",
                 "mb",
@@ -2802,7 +2815,7 @@
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "x64_builder"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-android-archive",
     ),
     gn_args = gn_args.config(
@@ -2850,14 +2863,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x86_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.INTEL,
             target_bits = 32,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x86_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -3062,8 +3076,9 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "main_builder_mb",
+            config = "main_builder",
             apply_configs = [
+                "mb",
                 "download_xr_test_apks",
             ],
             build_config = builder_config.build_config.DEBUG,
@@ -3072,7 +3087,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -3113,7 +3128,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -3321,7 +3336,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x86_builder",
+            config = "main_builder",
             apply_configs = [
                 "mb",
             ],
@@ -3331,7 +3346,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x86_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -3518,13 +3533,14 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x86_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.INTEL,
             target_bits = 32,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "x86_builder_mb"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-android-archive",
     ),
     gn_args = gn_args.config(
@@ -3680,7 +3696,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x86_builder",
+            config = "main_builder",
             apply_configs = [
                 "mb",
             ],
@@ -3690,7 +3706,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x86_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -3814,7 +3830,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder",
+            config = "main_builder",
             apply_configs = [
                 "mb",
             ],
@@ -3824,7 +3840,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -3995,7 +4011,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder",
+            config = "main_builder",
             apply_configs = [
                 "mb",
             ],
@@ -4005,7 +4021,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -4148,7 +4164,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -4232,7 +4248,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder",
+            config = "main_builder",
             apply_configs = [
                 "mb",
             ],
@@ -4242,7 +4258,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -4410,14 +4426,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "main_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.ARM,
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -4538,7 +4555,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder",
+            config = "main_builder",
             apply_configs = [
                 "mb",
             ],
@@ -4548,7 +4565,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -4698,7 +4715,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder",
+            config = "main_builder",
             apply_configs = [
                 "mb",
             ],
@@ -4708,7 +4725,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -4770,7 +4787,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder",
+            config = "main_builder",
             apply_configs = [
                 "mb",
             ],
@@ -4780,7 +4797,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -4897,14 +4914,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.DEBUG,
             target_arch = builder_config.target_arch.INTEL,
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -5009,14 +5027,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.DEBUG,
             target_arch = builder_config.target_arch.INTEL,
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -5066,7 +5085,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder",
+            config = "main_builder",
             apply_configs = [
                 "mb",
             ],
@@ -5076,7 +5095,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -5136,7 +5155,7 @@
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "main_builder"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-android-archive",
         run_tests_serially = True,
     ),
diff --git a/infra/config/subprojects/chromium/ci/chromium.angle.star b/infra/config/subprojects/chromium/ci/chromium.angle.star
index 4b4e17d..3fb8d617 100644
--- a/infra/config/subprojects/chromium/ci/chromium.angle.star
+++ b/infra/config/subprojects/chromium/ci/chromium.angle.star
@@ -74,14 +74,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "main_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.ARM,
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-angle-archive",
     ),
@@ -119,14 +120,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "main_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.ARM,
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-angle-archive",
         run_tests_serially = True,
diff --git a/infra/config/subprojects/chromium/ci/chromium.clang.star b/infra/config/subprojects/chromium/ci/chromium.clang.star
index cef5591..b3abefc 100644
--- a/infra/config/subprojects/chromium/ci/chromium.clang.star
+++ b/infra/config/subprojects/chromium/ci/chromium.clang.star
@@ -334,7 +334,7 @@
             target_bits = 32,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "clang_builder_mb_x64"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-clang-archive",
     ),
     gn_args = gn_args.config(
@@ -395,7 +395,7 @@
             target_bits = 32,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "clang_builder_mb_x64"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-clang-archive",
     ),
     gn_args = gn_args.config(
@@ -438,7 +438,7 @@
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "clang_builder_mb_x64"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-clang-archive",
     ),
     gn_args = gn_args.config(
@@ -493,7 +493,7 @@
             target_bits = 32,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "clang_builder_mb_x64"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-clang-archive",
     ),
     gn_args = gn_args.config(
@@ -537,7 +537,7 @@
             target_bits = 32,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "clang_builder_mb_x64"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-clang-archive",
     ),
     gn_args = gn_args.config(
@@ -582,7 +582,7 @@
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "clang_builder_mb_x64"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-clang-archive",
     ),
     gn_args = gn_args.config(
@@ -628,7 +628,7 @@
             target_bits = 32,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "clang_builder_mb_x64"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-clang-archive",
     ),
     gn_args = gn_args.config(
diff --git a/infra/config/subprojects/chromium/ci/chromium.coverage.star b/infra/config/subprojects/chromium/ci/chromium.coverage.star
index a52d147..0f28457 100644
--- a/infra/config/subprojects/chromium/ci/chromium.coverage.star
+++ b/infra/config/subprojects/chromium/ci/chromium.coverage.star
@@ -106,7 +106,7 @@
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "main_builder"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-fyi-archive",
     ),
     gn_args = gn_args.config(
@@ -173,7 +173,7 @@
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "main_builder"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-fyi-archive",
     ),
     gn_args = gn_args.config(
@@ -232,14 +232,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x86_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.INTEL,
             target_bits = 32,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x86_builder_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-fyi-archive",
     ),
@@ -442,7 +443,7 @@
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "main_builder"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-fyi-archive",
     ),
     # No symbols to prevent linker file too large error on
@@ -581,7 +582,7 @@
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "main_builder"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-fyi-archive",
     ),
     # No symbols to prevent linker file too large error on
@@ -654,7 +655,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder",
+            config = "main_builder",
             apply_configs = [
                 "cronet_builder",
                 "mb",
@@ -664,7 +665,7 @@
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "x64_builder"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-fyi-archive",
     ),
     # No symbols to prevent linker file too large error on
@@ -722,7 +723,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder",
+            config = "main_builder",
             apply_configs = [
                 "cronet_builder",
                 "mb",
@@ -732,7 +733,7 @@
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "x64_builder"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-fyi-archive",
     ),
     # No symbols to prevent linker file too large error on
diff --git a/infra/config/subprojects/chromium/ci/chromium.dawn.star b/infra/config/subprojects/chromium/ci/chromium.dawn.star
index 0365a817..9f0ba75 100644
--- a/infra/config/subprojects/chromium/ci/chromium.dawn.star
+++ b/infra/config/subprojects/chromium/ci/chromium.dawn.star
@@ -220,7 +220,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder_rel_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-dawn-archive",
         run_tests_serially = True,
@@ -254,14 +254,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "arm64_builder_rel_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.ARM,
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "arm64_builder_rel_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-dawn-archive",
     ),
@@ -303,7 +304,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder_rel_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-dawn-archive",
         run_tests_serially = True,
@@ -347,7 +348,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder_rel_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-dawn-archive",
         run_tests_serially = True,
@@ -424,14 +425,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "arm64_builder_rel_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.ARM,
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "arm64_builder_rel_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-dawn-archive",
         run_tests_serially = True,
@@ -683,7 +685,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder_rel_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-dawn-archive",
         run_tests_serially = True,
@@ -718,14 +720,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "arm64_builder_rel_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.ARM,
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "arm64_builder_rel_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-dawn-archive",
     ),
@@ -768,7 +771,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder_rel_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-dawn-archive",
         run_tests_serially = True,
@@ -813,7 +816,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder_rel_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-dawn-archive",
         run_tests_serially = True,
@@ -891,14 +894,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "arm64_builder_rel_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.ARM,
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "arm64_builder_rel_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-dawn-archive",
         run_tests_serially = True,
@@ -973,14 +977,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "arm64_builder_rel_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.ARM,
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "arm64_builder_rel_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-dawn-archive",
         run_tests_serially = True,
@@ -1065,14 +1070,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "arm64_builder_rel_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.ARM,
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "arm64_builder_rel_mb",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-dawn-archive",
         run_tests_serially = True,
diff --git a/infra/config/subprojects/chromium/ci/chromium.fyi.star b/infra/config/subprojects/chromium/ci/chromium.fyi.star
index bf227b60..6fbbba5e 100644
--- a/infra/config/subprojects/chromium/ci/chromium.fyi.star
+++ b/infra/config/subprojects/chromium/ci/chromium.fyi.star
@@ -169,13 +169,14 @@
             apply_configs = ["android"],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "arm64_builder_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.ARM,
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
-        android_config = builder_config.android_config(config = "arm64_builder_mb"),
+        android_config = builder_config.android_config(config = "base_config"),
         build_gs_bucket = "chromium-fyi-archive",
     ),
     gn_args = gn_args.config(
@@ -707,7 +708,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x86_builder",
+            config = "main_builder",
             apply_configs = [
                 "mb",
             ],
@@ -717,7 +718,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x86_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-android-archive",
     ),
@@ -820,7 +821,7 @@
             apply_configs = ["android"],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder",
+            config = "main_builder",
             apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.INTEL,
@@ -828,7 +829,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder",
+            config = "base_config",
         ),
     ),
     gn_args = gn_args.config(
diff --git a/infra/config/subprojects/chromium/ci/chromium.gpu.fyi.star b/infra/config/subprojects/chromium/ci/chromium.gpu.fyi.star
index 42502abb..7a4f3e5 100644
--- a/infra/config/subprojects/chromium/ci/chromium.gpu.fyi.star
+++ b/infra/config/subprojects/chromium/ci/chromium.gpu.fyi.star
@@ -102,7 +102,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder_rel_mb",
+            config = "base_config",
         ),
         run_tests_serially = True,
     ),
@@ -140,8 +140,9 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "arm64_builder_rel_mb",
+            config = "main_builder",
             apply_configs = [
+                "mb",
                 "download_xr_test_apks",
             ],
             build_config = builder_config.build_config.RELEASE,
@@ -150,7 +151,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "arm64_builder_rel_mb",
+            config = "base_config",
         ),
     ),
     targets = targets.bundle(
@@ -215,7 +216,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder_rel_mb",
+            config = "base_config",
         ),
     ),
     targets = targets.bundle(
@@ -275,7 +276,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder_rel_mb",
+            config = "base_config",
         ),
     ),
     targets = targets.bundle(
@@ -376,8 +377,9 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "arm64_builder_rel_mb",
+            config = "main_builder",
             apply_configs = [
+                "mb",
                 "download_xr_test_apks",
             ],
             build_config = builder_config.build_config.RELEASE,
@@ -386,7 +388,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "arm64_builder_rel_mb",
+            config = "base_config",
         ),
         run_tests_serially = True,
     ),
@@ -440,8 +442,9 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "arm64_builder_rel_mb",
+            config = "main_builder",
             apply_configs = [
+                "mb",
                 "download_xr_test_apks",
             ],
             build_config = builder_config.build_config.RELEASE,
@@ -450,7 +453,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "arm64_builder_rel_mb",
+            config = "base_config",
         ),
         run_tests_serially = True,
     ),
@@ -517,7 +520,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder_rel_mb",
+            config = "base_config",
         ),
         run_tests_serially = True,
     ),
@@ -570,7 +573,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder_rel_mb",
+            config = "base_config",
         ),
         run_tests_serially = True,
     ),
@@ -616,14 +619,15 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "arm64_builder_rel_mb",
+            config = "main_builder",
+            apply_configs = ["mb"],
             build_config = builder_config.build_config.RELEASE,
             target_arch = builder_config.target_arch.ARM,
             target_bits = 64,
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "arm64_builder_rel_mb",
+            config = "base_config",
         ),
         run_tests_serially = True,
     ),
@@ -850,7 +854,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder_rel_mb",
+            config = "base_config",
         ),
     ),
     gn_args = gn_args.config(
@@ -885,8 +889,9 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "arm64_builder_rel_mb",
+            config = "main_builder",
             apply_configs = [
+                "mb",
                 "download_xr_test_apks",
             ],
             build_config = builder_config.build_config.RELEASE,
@@ -895,7 +900,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "arm64_builder_rel_mb",
+            config = "base_config",
         ),
     ),
     gn_args = gn_args.config(
diff --git a/infra/config/subprojects/chromium/ci/chromium.gpu.star b/infra/config/subprojects/chromium/ci/chromium.gpu.star
index 7ab62f68..d18501f5 100644
--- a/infra/config/subprojects/chromium/ci/chromium.gpu.star
+++ b/infra/config/subprojects/chromium/ci/chromium.gpu.star
@@ -81,7 +81,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-gpu-archive",
     ),
@@ -147,7 +147,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-gpu-archive",
     ),
diff --git a/infra/config/subprojects/chromium/ci/chromium.linux.star b/infra/config/subprojects/chromium/ci/chromium.linux.star
index 8d6bad4c..27e6e23 100644
--- a/infra/config/subprojects/chromium/ci/chromium.linux.star
+++ b/infra/config/subprojects/chromium/ci/chromium.linux.star
@@ -540,8 +540,9 @@
                 # crbug.com/1473501
                 retry_only_failed_tests = True,
             ),
-            "webdriver_wpt_tests": targets.remove(
-                reason = "https://crbug.com/929689, https://crbug.com/936557",
+            "webdriver_wpt_tests": targets.mixin(
+                ci_only = True,
+                experiment_percentage = 100,
             ),
         },
     ),
diff --git a/infra/config/subprojects/chromium/ci/chromium.star b/infra/config/subprojects/chromium/ci/chromium.star
index fe8bf7d..3959254 100644
--- a/infra/config/subprojects/chromium/ci/chromium.star
+++ b/infra/config/subprojects/chromium/ci/chromium.star
@@ -76,7 +76,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder",
+            config = "base_config",
         ),
     ),
     gn_args = gn_args.config(
@@ -134,7 +134,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder",
+            config = "base_config",
         ),
     ),
     gn_args = gn_args.config(
@@ -182,7 +182,7 @@
             ],
         ),
         chromium_config = builder_config.chromium_config(
-            config = "x64_builder",
+            config = "main_builder",
             apply_configs = [
                 "clobber",
                 "mb",
@@ -193,7 +193,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "x64_builder",
+            config = "base_config",
         ),
     ),
     gn_args = gn_args.config(
@@ -257,7 +257,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder",
+            config = "base_config",
         ),
     ),
     gn_args = gn_args.config(
@@ -321,7 +321,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder",
+            config = "base_config",
         ),
     ),
     gn_args = gn_args.config(
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.android.star b/infra/config/subprojects/chromium/try/tryserver.chromium.android.star
index 748050a..93499ab 100644
--- a/infra/config/subprojects/chromium/try/tryserver.chromium.android.star
+++ b/infra/config/subprojects/chromium/try/tryserver.chromium.android.star
@@ -1372,7 +1372,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder",
+            config = "base_config",
         ),
     ),
     gn_args = gn_args.config(
@@ -1635,7 +1635,7 @@
             target_platform = builder_config.target_platform.ANDROID,
         ),
         android_config = builder_config.android_config(
-            config = "main_builder",
+            config = "base_config",
         ),
         build_gs_bucket = "chromium-gpu-fyi-archive",
     ),
diff --git a/ios/chrome/app/BUILD.gn b/ios/chrome/app/BUILD.gn
index a6733f9f..58d3838 100644
--- a/ios/chrome/app/BUILD.gn
+++ b/ios/chrome/app/BUILD.gn
@@ -493,6 +493,7 @@
     "//ios/chrome/browser/shared/model/paths",
     "//ios/chrome/browser/shared/model/prefs:pref_names",
     "//ios/chrome/browser/shared/model/profile",
+    "//ios/chrome/browser/shared/model/profile:features",
     "//ios/chrome/browser/shared/model/web_state_list",
     "//ios/chrome/browser/shared/public/commands",
     "//ios/chrome/browser/shared/public/features",
diff --git a/ios/chrome/app/application_delegate/metrics_mediator.mm b/ios/chrome/app/application_delegate/metrics_mediator.mm
index 897c6c8e..a894e174 100644
--- a/ios/chrome/app/application_delegate/metrics_mediator.mm
+++ b/ios/chrome/app/application_delegate/metrics_mediator.mm
@@ -8,6 +8,7 @@
 #import <sys/sysctl.h>
 
 #import "base/functional/bind.h"
+#import "base/ios/device_util.h"
 #import "base/metrics/histogram_functions.h"
 #import "base/metrics/histogram_macros.h"
 #import "base/metrics/user_metrics_action.h"
@@ -762,13 +763,11 @@
 }
 
 + (void)logMemoryToUMA:(const std::string&)histogramName {
-  task_vm_info task_info_data;
-  mach_msg_type_number_t count = sizeof(task_vm_info) / sizeof(natural_t);
-  kern_return_t result =
-      task_info(mach_task_self(), TASK_VM_INFO,
-                reinterpret_cast<task_info_t>(&task_info_data), &count);
-  if (result == KERN_SUCCESS) {
-    mach_vm_size_t footprint_mb = task_info_data.phys_footprint / 1024 / 1024;
+  auto result = ios::device_util::GetTaskVMInfo();
+  if (result.has_value()) {
+    task_vm_info task_vm_info_data = result.value();
+    mach_vm_size_t footprint_mb =
+        task_vm_info_data.phys_footprint / 1024 / 1024;
     base::UmaHistogramMemoryLargeMB(histogramName, footprint_mb);
   }
 }
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm
index 166af03..c4ab0fb 100644
--- a/ios/chrome/app/main_controller.mm
+++ b/ios/chrome/app/main_controller.mm
@@ -111,6 +111,7 @@
 #import "ios/chrome/browser/shared/model/browser/browser_provider.h"
 #import "ios/chrome/browser/shared/model/paths/paths.h"
 #import "ios/chrome/browser/shared/model/prefs/pref_names.h"
+#import "ios/chrome/browser/shared/model/profile/features.h"
 #import "ios/chrome/browser/shared/model/profile/profile_attributes_ios.h"
 #import "ios/chrome/browser/shared/model/profile/profile_attributes_storage_ios.h"
 #import "ios/chrome/browser/shared/model/profile/profile_ios.h"
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd
index a1bfe18..1d44529d 100644
--- a/ios/chrome/app/strings/ios_strings.grd
+++ b/ios/chrome/app/strings/ios_strings.grd
@@ -2383,12 +2383,6 @@
       <message name="IDS_IOS_FEED_MANAGEMENT_HIDDEN_TEXT" desc="The 'Hidden' row title in the feed management UI.">
         Hidden
       </message>
-      <message name="IDS_IOS_FEED_MANAGEMENT_INTERESTS_TEXT" desc="The 'Interests' row title in the feed management UI.">
-        Interests
-      </message>
-      <message name="IDS_IOS_FEED_MANAGEMENT_TITLE" desc="The title of the feed management UI.">
-        Manage
-      </message>
       <message name="IDS_IOS_FEED_SORT_ACCESSIBILITY_LABEL" desc="The accessibility label for the Following feed header's sort button.">
         Sort button for Following feed.
       </message>
@@ -3211,6 +3205,15 @@
       <message name="IDS_IOS_LENS_OVERLAY_TOOLTIP_TEXT" desc="The Lens overlay tooltip displayed text.">
         Search your screen
       </message>
+      <message name="IDS_IOS_LENS_OVERLAY_TRANSLATE_ERROR_SUBTITLE" desc="The subtitle that appears in the bottom sheet of the Lens Overlay when translate fails.">
+        Make sure the text you're translating is clear and in frame.
+      </message>
+      <message name="IDS_IOS_LENS_OVERLAY_TRANSLATE_ERROR_TITLE" desc="The title of the message that appears in the bottom sheet of the Lens Overlay when translate fails.">
+        No text found
+      </message>
+      <message name="IDS_IOS_LENS_OVERLAY_TRANSLATE_INDICATION_TITLE" desc="The text that appears in the zero state after a translation took place in Lens Overlay.">
+        Translated text
+      </message>
       <message name="IDS_IOS_LENS_PRODUCT_NAME" desc="The brand name of Google Lens that will appear in menu titles as a single string.">
         Google Lens
       </message>
@@ -7370,4 +7373,4 @@
       </message>
       </messages>
   </release>
-</grit>
+</grit>
\ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_FEED_MANAGEMENT_INTERESTS_TEXT.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_FEED_MANAGEMENT_INTERESTS_TEXT.png.sha1
deleted file mode 100644
index f639ca7b..0000000
--- a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_FEED_MANAGEMENT_INTERESTS_TEXT.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-4fca7c36c5038409405982a4535ff33d0760cfb4
\ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_FEED_MANAGEMENT_TITLE.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_FEED_MANAGEMENT_TITLE.png.sha1
deleted file mode 100644
index f639ca7b..0000000
--- a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_FEED_MANAGEMENT_TITLE.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-4fca7c36c5038409405982a4535ff33d0760cfb4
\ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_LENS_OVERLAY_TRANSLATE_ERROR_SUBTITLE.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_LENS_OVERLAY_TRANSLATE_ERROR_SUBTITLE.png.sha1
new file mode 100644
index 0000000..162a447
--- /dev/null
+++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_LENS_OVERLAY_TRANSLATE_ERROR_SUBTITLE.png.sha1
@@ -0,0 +1 @@
+4851aef756e752ee076721558e1858ecf8a4c26c
\ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_LENS_OVERLAY_TRANSLATE_ERROR_TITLE.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_LENS_OVERLAY_TRANSLATE_ERROR_TITLE.png.sha1
new file mode 100644
index 0000000..162a447
--- /dev/null
+++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_LENS_OVERLAY_TRANSLATE_ERROR_TITLE.png.sha1
@@ -0,0 +1 @@
+4851aef756e752ee076721558e1858ecf8a4c26c
\ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_LENS_OVERLAY_TRANSLATE_INDICATION_TITLE.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_LENS_OVERLAY_TRANSLATE_INDICATION_TITLE.png.sha1
new file mode 100644
index 0000000..a2f6a18
--- /dev/null
+++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_LENS_OVERLAY_TRANSLATE_INDICATION_TITLE.png.sha1
@@ -0,0 +1 @@
+dcb796d6b6528dd45859e927f0a39e72912fb0ab
\ No newline at end of file
diff --git a/ios/chrome/browser/account_picker/ui_bundled/account_picker_confirmation/account_picker_confirmation_screen_mediator.mm b/ios/chrome/browser/account_picker/ui_bundled/account_picker_confirmation/account_picker_confirmation_screen_mediator.mm
index 71dd84e2..03bf48a 100644
--- a/ios/chrome/browser/account_picker/ui_bundled/account_picker_confirmation/account_picker_confirmation_screen_mediator.mm
+++ b/ios/chrome/browser/account_picker/ui_bundled/account_picker_confirmation/account_picker_confirmation_screen_mediator.mm
@@ -15,21 +15,17 @@
 #import "ios/chrome/browser/authentication/ui_bundled/signin/signin_utils.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
 #import "ios/chrome/browser/signin/model/chrome_account_manager_service.h"
-#import "ios/chrome/browser/signin/model/chrome_account_manager_service_observer_bridge.h"
 #import "ios/chrome/browser/signin/model/system_identity.h"
 
 @interface AccountPickerConfirmationScreenMediator () <
-    ChromeAccountManagerServiceObserver,
     IdentityManagerObserverBridgeDelegate> {
 }
 
 @end
 
 @implementation AccountPickerConfirmationScreenMediator {
-  // Account manager service with observer.
+  // Account manager service.
   raw_ptr<ChromeAccountManagerService> _accountManagerService;
-  std::unique_ptr<ChromeAccountManagerServiceObserverBridge>
-      _accountManagerServiceObserver;
   // Identity manager.
   raw_ptr<signin::IdentityManager> _identityManager;
   std::unique_ptr<signin::IdentityManagerObserverBridge>
@@ -49,9 +45,6 @@
     CHECK(accountManagerService);
     CHECK(identityManager);
     _accountManagerService = accountManagerService;
-    _accountManagerServiceObserver =
-        std::make_unique<ChromeAccountManagerServiceObserverBridge>(
-            self, _accountManagerService);
     _identityManager = identityManager;
     _identityManagerObserver =
         std::make_unique<signin::IdentityManagerObserverBridge>(
@@ -70,7 +63,6 @@
   _identityManager = nullptr;
   _identityManagerObserver.reset();
   _accountManagerService = nullptr;
-  _accountManagerServiceObserver.reset();
 }
 
 #pragma mark - Properties
@@ -163,14 +155,6 @@
   return NO;
 }
 
-#pragma mark - ChromeAccountManagerServiceObserver
-
-- (void)onChromeAccountManagerServiceShutdown:
-    (ChromeAccountManagerService*)accountManagerService {
-  // TODO(crbug.com/40284086): Remove `[self disconnect]`.
-  [self disconnect];
-}
-
 #pragma mark -  IdentityManagerObserver
 
 - (void)onAccountsOnDeviceChanged {
diff --git a/ios/chrome/browser/account_picker/ui_bundled/account_picker_selection/account_picker_selection_screen_mediator.mm b/ios/chrome/browser/account_picker/ui_bundled/account_picker_selection/account_picker_selection_screen_mediator.mm
index 14dcdd25..66b4d9ee 100644
--- a/ios/chrome/browser/account_picker/ui_bundled/account_picker_selection/account_picker_selection_screen_mediator.mm
+++ b/ios/chrome/browser/account_picker/ui_bundled/account_picker_selection/account_picker_selection_screen_mediator.mm
@@ -12,11 +12,9 @@
 #import "ios/chrome/browser/authentication/ui_bundled/signin/signin_utils.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
 #import "ios/chrome/browser/signin/model/chrome_account_manager_service.h"
-#import "ios/chrome/browser/signin/model/chrome_account_manager_service_observer_bridge.h"
 #import "ios/chrome/browser/signin/model/system_identity.h"
 
 @interface AccountPickerSelectionScreenMediator () <
-    ChromeAccountManagerServiceObserver,
     IdentityManagerObserverBridgeDelegate>
 
 @end
@@ -26,8 +24,6 @@
   std::unique_ptr<signin::IdentityManagerObserverBridge>
       _identityManagerObserver;
   raw_ptr<ChromeAccountManagerService> _accountManagerService;
-  std::unique_ptr<ChromeAccountManagerServiceObserverBridge>
-      _accountManagerServiceObserver;
   // Configurators based on identity list.
   __strong NSArray* _sortedIdentityItemConfigurators;
 }
@@ -45,9 +41,6 @@
         std::make_unique<signin::IdentityManagerObserverBridge>(
             _identityManager, self);
     _accountManagerService = accountManagerService;
-    _accountManagerServiceObserver =
-        std::make_unique<ChromeAccountManagerServiceObserverBridge>(
-            self, _accountManagerService);
     _selectedIdentity = selectedIdentity;
     [self loadIdentityItemConfigurators];
   }
@@ -60,7 +53,6 @@
 }
 
 - (void)disconnect {
-  _accountManagerServiceObserver.reset();
   _accountManagerService = nullptr;
   _identityManagerObserver.reset();
   _identityManager = nullptr;
@@ -143,14 +135,6 @@
   [self.consumer reloadIdentityForIdentityItemConfigurator:configurator];
 }
 
-#pragma mark - ChromeAccountManagerServiceObserver
-
-- (void)onChromeAccountManagerServiceShutdown:
-    (ChromeAccountManagerService*)accountManagerService {
-  // TODO(crbug.com/40284086): Remove `[self disconnect]`.
-  [self disconnect];
-}
-
 #pragma mark -  IdentityManagerObserver
 
 - (void)onAccountsOnDeviceChanged {
diff --git a/ios/chrome/browser/authentication/ui_bundled/BUILD.gn b/ios/chrome/browser/authentication/ui_bundled/BUILD.gn
index 1c86c00a..ed57e8d 100644
--- a/ios/chrome/browser/authentication/ui_bundled/BUILD.gn
+++ b/ios/chrome/browser/authentication/ui_bundled/BUILD.gn
@@ -57,6 +57,7 @@
     "//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/profile:features",
     "//ios/chrome/browser/shared/model/web_state_list",
     "//ios/chrome/browser/shared/public/commands",
     "//ios/chrome/browser/shared/public/features",
@@ -158,6 +159,7 @@
     "//ios/chrome/browser/shared/model/browser/test:test_support",
     "//ios/chrome/browser/shared/model/prefs:browser_prefs",
     "//ios/chrome/browser/shared/model/prefs:pref_names",
+    "//ios/chrome/browser/shared/model/profile:features",
     "//ios/chrome/browser/shared/model/profile/test",
     "//ios/chrome/browser/shared/model/web_state_list",
     "//ios/chrome/browser/shared/public/commands",
@@ -213,6 +215,7 @@
     "//ios/chrome/browser/shared/model/application_context",
     "//ios/chrome/browser/shared/model/prefs:pref_names",
     "//ios/chrome/browser/shared/model/profile",
+    "//ios/chrome/browser/shared/model/profile:features",
     "//ios/chrome/browser/shared/public/commands",
     "//ios/chrome/browser/shared/public/features",
     "//ios/chrome/browser/shared/ui/util",
diff --git a/ios/chrome/browser/authentication/ui_bundled/authentication_flow/BUILD.gn b/ios/chrome/browser/authentication/ui_bundled/authentication_flow/BUILD.gn
index 8299c48..5d71387 100644
--- a/ios/chrome/browser/authentication/ui_bundled/authentication_flow/BUILD.gn
+++ b/ios/chrome/browser/authentication/ui_bundled/authentication_flow/BUILD.gn
@@ -40,6 +40,7 @@
     "//ios/chrome/browser/shared/model/prefs",
     "//ios/chrome/browser/shared/model/prefs:pref_names",
     "//ios/chrome/browser/shared/model/profile",
+    "//ios/chrome/browser/shared/model/profile:features",
     "//ios/chrome/browser/shared/public/features",
     "//ios/chrome/browser/signin/model",
     "//ios/chrome/browser/signin/model:authentication_service",
@@ -109,6 +110,7 @@
     "//ios/chrome/browser/shared/coordinator/scene:scene_state_header",
     "//ios/chrome/browser/shared/model/application_context",
     "//ios/chrome/browser/shared/model/profile",
+    "//ios/chrome/browser/shared/model/profile:features",
     "//ios/chrome/browser/shared/public/features",
     "//ios/chrome/browser/shared/public/features:system_flags",
     "//ios/chrome/browser/shared/ui/util",
@@ -153,6 +155,7 @@
     "//ios/chrome/browser/shared/model/application_context",
     "//ios/chrome/browser/shared/model/browser/test:test_support",
     "//ios/chrome/browser/shared/model/prefs:browser_prefs",
+    "//ios/chrome/browser/shared/model/profile:features",
     "//ios/chrome/browser/shared/model/profile/test",
     "//ios/chrome/browser/shared/public/commands",
     "//ios/chrome/browser/shared/public/features",
diff --git a/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow.mm b/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow.mm
index 9a92d8a..c4e19b35 100644
--- a/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow.mm
+++ b/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow.mm
@@ -37,6 +37,7 @@
 #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/features.h"
 #import "ios/chrome/browser/shared/model/profile/profile_ios.h"
 #import "ios/chrome/browser/shared/public/commands/command_dispatcher.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
diff --git a/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow_in_profile_unittest.mm b/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow_in_profile_unittest.mm
index 1a5f95d..d9b016d 100644
--- a/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow_in_profile_unittest.mm
+++ b/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow_in_profile_unittest.mm
@@ -12,6 +12,7 @@
 #import "ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow_performer.h"
 #import "ios/chrome/browser/shared/model/application_context/application_context.h"
 #import "ios/chrome/browser/shared/model/browser/test/test_browser.h"
+#import "ios/chrome/browser/shared/model/profile/features.h"
 #import "ios/chrome/browser/shared/model/profile/test/test_profile_ios.h"
 #import "ios/chrome/browser/shared/model/profile/test/test_profile_manager_ios.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
diff --git a/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow_performer.mm b/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow_performer.mm
index f94fd69..2b38150 100644
--- a/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow_performer.mm
+++ b/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow_performer.mm
@@ -47,6 +47,7 @@
 #import "ios/chrome/browser/shared/model/browser/browser.h"
 #import "ios/chrome/browser/shared/model/browser/browser_provider.h"
 #import "ios/chrome/browser/shared/model/browser/browser_provider_interface.h"
+#import "ios/chrome/browser/shared/model/profile/features.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/command_dispatcher.h"
diff --git a/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow_unittest.mm b/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow_unittest.mm
index 9b64536a..3bcb1e0 100644
--- a/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow_unittest.mm
+++ b/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow_unittest.mm
@@ -34,6 +34,7 @@
 #import "ios/chrome/browser/shared/model/application_context/application_context.h"
 #import "ios/chrome/browser/shared/model/browser/test/test_browser.h"
 #import "ios/chrome/browser/shared/model/prefs/browser_prefs.h"
+#import "ios/chrome/browser/shared/model/profile/features.h"
 #import "ios/chrome/browser/shared/model/profile/test/test_profile_ios.h"
 #import "ios/chrome/browser/shared/model/profile/test/test_profile_manager_ios.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
diff --git a/ios/chrome/browser/authentication/ui_bundled/authentication_ui_util.mm b/ios/chrome/browser/authentication/ui_bundled/authentication_ui_util.mm
index 0b622ff7..370ce0e 100644
--- a/ios/chrome/browser/authentication/ui_bundled/authentication_ui_util.mm
+++ b/ios/chrome/browser/authentication/ui_bundled/authentication_ui_util.mm
@@ -22,10 +22,10 @@
 #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/features.h"
 #import "ios/chrome/browser/shared/model/profile/profile_attributes_storage_ios.h"
 #import "ios/chrome/browser/shared/model/profile/profile_ios.h"
 #import "ios/chrome/browser/shared/model/profile/profile_manager_ios.h"
-#import "ios/chrome/browser/shared/public/features/features.h"
 #import "ios/chrome/browser/signin/model/account_profile_mapper.h"
 #import "ios/chrome/browser/signin/model/authentication_service.h"
 #import "ios/chrome/browser/signin/model/authentication_service_factory.h"
diff --git a/ios/chrome/browser/authentication/ui_bundled/cells/BUILD.gn b/ios/chrome/browser/authentication/ui_bundled/cells/BUILD.gn
index 13c9593..f4877259 100644
--- a/ios/chrome/browser/authentication/ui_bundled/cells/BUILD.gn
+++ b/ios/chrome/browser/authentication/ui_bundled/cells/BUILD.gn
@@ -31,6 +31,7 @@
     "//ios/chrome/browser/ntp/ui_bundled",
     "//ios/chrome/browser/policy/model",
     "//ios/chrome/browser/settings/ui_bundled/cells:public",
+    "//ios/chrome/browser/shared/model/profile:features",
     "//ios/chrome/browser/shared/public/commands",
     "//ios/chrome/browser/shared/public/features",
     "//ios/chrome/browser/shared/ui/symbols",
diff --git a/ios/chrome/browser/authentication/ui_bundled/cells/table_view_account_item.mm b/ios/chrome/browser/authentication/ui_bundled/cells/table_view_account_item.mm
index f0a93e68..a4f434c8 100644
--- a/ios/chrome/browser/authentication/ui_bundled/cells/table_view_account_item.mm
+++ b/ios/chrome/browser/authentication/ui_bundled/cells/table_view_account_item.mm
@@ -6,7 +6,7 @@
 
 #import "base/apple/foundation_util.h"
 #import "ios/chrome/browser/settings/ui_bundled/cells/settings_cells_constants.h"
-#import "ios/chrome/browser/shared/public/features/features.h"
+#import "ios/chrome/browser/shared/model/profile/features.h"
 #import "ios/chrome/browser/shared/ui/symbols/symbols.h"
 #import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h"
 #import "ios/chrome/common/ui/colors/semantic_color_names.h"
diff --git a/ios/chrome/browser/authentication/ui_bundled/enterprise/managed_profile_creation/BUILD.gn b/ios/chrome/browser/authentication/ui_bundled/enterprise/managed_profile_creation/BUILD.gn
index ea973c87..e73f657 100644
--- a/ios/chrome/browser/authentication/ui_bundled/enterprise/managed_profile_creation/BUILD.gn
+++ b/ios/chrome/browser/authentication/ui_bundled/enterprise/managed_profile_creation/BUILD.gn
@@ -27,9 +27,10 @@
     "//ios/chrome/browser/keyboard/ui_bundled",
     "//ios/chrome/browser/shared/coordinator/chrome_coordinator:chrome_coordinator",
     "//ios/chrome/browser/shared/model/application_context:application_context",
-    "//ios/chrome/browser/shared/model/browser:browser",
-    "//ios/chrome/browser/shared/model/profile:profile",
-    "//ios/chrome/browser/shared/public/features:features",
+    "//ios/chrome/browser/shared/model/browser",
+    "//ios/chrome/browser/shared/model/profile",
+    "//ios/chrome/browser/shared/model/profile:features",
+    "//ios/chrome/browser/shared/public/features",
     "//ios/chrome/browser/shared/ui/elements:elements_internal",
     "//ios/chrome/browser/shared/ui/list_model:list_model",
     "//ios/chrome/browser/shared/ui/symbols:symbols",
diff --git a/ios/chrome/browser/authentication/ui_bundled/enterprise/managed_profile_creation/managed_profile_creation_mediator.mm b/ios/chrome/browser/authentication/ui_bundled/enterprise/managed_profile_creation/managed_profile_creation_mediator.mm
index e1b7f9e..ffea3ae 100644
--- a/ios/chrome/browser/authentication/ui_bundled/enterprise/managed_profile_creation/managed_profile_creation_mediator.mm
+++ b/ios/chrome/browser/authentication/ui_bundled/enterprise/managed_profile_creation/managed_profile_creation_mediator.mm
@@ -10,21 +10,17 @@
 #import "components/signin/public/identity_manager/objc/identity_manager_observer_bridge.h"
 #import "google_apis/gaia/gaia_id.h"
 #import "ios/chrome/browser/authentication/ui_bundled/enterprise/managed_profile_creation/managed_profile_creation_consumer.h"
+#import "ios/chrome/browser/shared/model/profile/features.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
 #import "ios/chrome/browser/signin/model/chrome_account_manager_service.h"
-#import "ios/chrome/browser/signin/model/chrome_account_manager_service_observer_bridge.h"
 
 @interface ManagedProfileCreationMediator () <
-    ChromeAccountManagerServiceObserver,
     IdentityManagerObserverBridgeDelegate> {
   BOOL _canShowBrowsingDataMigration;
   BOOL _browsingDataMigrationDisabledByPolicy;
   NSString* _gaiaID;
   // Account manager service to retrieve Chrome identities.
   raw_ptr<ChromeAccountManagerService> _accountManagerService;
-  // Chrome account manager service observer bridge.
-  std::unique_ptr<ChromeAccountManagerServiceObserverBridge>
-      _accountManagerServiceObserver;
 
   raw_ptr<signin::IdentityManager> _identityManager;
   std::unique_ptr<signin::IdentityManagerObserverBridge>
@@ -46,9 +42,6 @@
   self = [super init];
   if (self) {
     _accountManagerService = accountManagerService;
-    _accountManagerServiceObserver =
-        std::make_unique<ChromeAccountManagerServiceObserverBridge>(
-            self, _accountManagerService);
     _identityManager = identityManager;
     _identityManagerObserver =
         std::make_unique<signin::IdentityManagerObserverBridge>(identityManager,
@@ -74,7 +67,6 @@
   _consumer = nil;
   _delegate = nil;
   _accountManagerService = nullptr;
-  _accountManagerServiceObserver.reset();
   _identityManager = nullptr;
   _identityManagerObserver.reset();
 }
@@ -102,13 +94,6 @@
   [self.consumer setKeepBrowsingDataSeparate:self.keepBrowsingDataSeparate];
 }
 
-#pragma mark - ChromeAccountManagerServiceObserver
-
-- (void)onChromeAccountManagerServiceShutdown:
-    (ChromeAccountManagerService*)accountManagerService {
-  [self disconnect];
-}
-
 #pragma mark - IdentityManagerObserverBridgeDelegate
 
 - (void)onAccountsOnDeviceChanged {
diff --git a/ios/chrome/browser/authentication/ui_bundled/history_sync/history_sync_mediator.mm b/ios/chrome/browser/authentication/ui_bundled/history_sync/history_sync_mediator.mm
index f751a0b..40b4973 100644
--- a/ios/chrome/browser/authentication/ui_bundled/history_sync/history_sync_mediator.mm
+++ b/ios/chrome/browser/authentication/ui_bundled/history_sync/history_sync_mediator.mm
@@ -18,21 +18,17 @@
 #import "ios/chrome/browser/shared/public/features/features.h"
 #import "ios/chrome/browser/signin/model/authentication_service.h"
 #import "ios/chrome/browser/signin/model/chrome_account_manager_service.h"
-#import "ios/chrome/browser/signin/model/chrome_account_manager_service_observer_bridge.h"
 #import "ios/chrome/grit/ios_strings.h"
 #import "ui/base/l10n/l10n_util.h"
 
 // Mediator that handles the sync operations.
-@interface HistorySyncMediator () <ChromeAccountManagerServiceObserver,
-                                   IdentityManagerObserverBridgeDelegate>
+@interface HistorySyncMediator () <IdentityManagerObserverBridgeDelegate>
 @end
 
 @implementation HistorySyncMediator {
   raw_ptr<AuthenticationService> _authenticationService;
-  // Account manager service with observer.
+  // Account manager service.
   raw_ptr<ChromeAccountManagerService> _accountManagerService;
-  std::unique_ptr<ChromeAccountManagerServiceObserverBridge>
-      _accountManagerServiceObserver;
   raw_ptr<signin::IdentityManager> _identityManager;
   // Observer for `IdentityManager`.
   std::unique_ptr<signin::IdentityManagerObserverBridge>
@@ -59,9 +55,6 @@
   if (self) {
     _authenticationService = authenticationService;
     _accountManagerService = chromeAccountManagerService;
-    _accountManagerServiceObserver =
-        std::make_unique<ChromeAccountManagerServiceObserverBridge>(
-            self, _accountManagerService);
     _identityManager = identityManager;
     _identityManagerObserver =
         std::make_unique<signin::IdentityManagerObserverBridge>(identityManager,
@@ -76,7 +69,6 @@
 }
 
 - (void)disconnect {
-  _accountManagerServiceObserver.reset();
   _identityManagerObserver.reset();
   [_capabilitiesFetcher shutdown];
   _capabilitiesFetcher = nil;
@@ -139,14 +131,6 @@
           [_capabilitiesFetcher canShowUnrestrictedOptInsCapability]];
 }
 
-#pragma mark - ChromeAccountManagerServiceObserver
-
-- (void)onChromeAccountManagerServiceShutdown:
-    (ChromeAccountManagerService*)accountManagerService {
-  // TODO(crbug.com/40284086): Remove `[self disconnect]`.
-  [self disconnect];
-}
-
 #pragma mark - IdentityManagerObserverBridgeDelegate
 
 - (void)onPrimaryAccountChanged:
diff --git a/ios/chrome/browser/authentication/ui_bundled/identity_chooser/identity_chooser_mediator.mm b/ios/chrome/browser/authentication/ui_bundled/identity_chooser/identity_chooser_mediator.mm
index e4ca79a4..5dffcc3 100644
--- a/ios/chrome/browser/authentication/ui_bundled/identity_chooser/identity_chooser_mediator.mm
+++ b/ios/chrome/browser/authentication/ui_bundled/identity_chooser/identity_chooser_mediator.mm
@@ -12,13 +12,9 @@
 #import "ios/chrome/browser/authentication/ui_bundled/signin/signin_utils.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
 #import "ios/chrome/browser/signin/model/chrome_account_manager_service.h"
-#import "ios/chrome/browser/signin/model/chrome_account_manager_service_observer_bridge.h"
 #import "ios/chrome/browser/signin/model/system_identity.h"
 
-@interface IdentityChooserMediator () <ChromeAccountManagerServiceObserver,
-                                       IdentityManagerObserverBridgeDelegate> {
-  std::unique_ptr<ChromeAccountManagerServiceObserverBridge>
-      _accountManagerServiceObserver;
+@interface IdentityChooserMediator () <IdentityManagerObserverBridgeDelegate> {
   std::unique_ptr<signin::IdentityManagerObserverBridge>
       _identityManagerObserver;
 }
@@ -54,9 +50,6 @@
 }
 
 - (void)start {
-  _accountManagerServiceObserver =
-      std::make_unique<ChromeAccountManagerServiceObserverBridge>(
-          self, _accountManagerService);
   _identityManagerObserver =
       std::make_unique<signin::IdentityManagerObserverBridge>(_identityManager,
                                                               self);
@@ -64,7 +57,6 @@
 }
 
 - (void)disconnect {
-  _accountManagerServiceObserver.reset();
   _accountManagerService = nullptr;
   _identityManagerObserver.reset();
   _identityManager = nullptr;
@@ -163,14 +155,6 @@
   [self updateTableViewIdentityItem:item withIdentity:identity];
 }
 
-#pragma mark - ChromeAccountManagerServiceObserver
-
-- (void)onChromeAccountManagerServiceShutdown:
-    (ChromeAccountManagerService*)accountManagerService {
-  // TODO(crbug.com/40284086): Remove `[self disconnect]`.
-  [self disconnect];
-}
-
 #pragma mark - IdentityManagerObserverBridgeDelegate
 
 - (void)onExtendedAccountInfoUpdated:(const AccountInfo&)info {
diff --git a/ios/chrome/browser/authentication/ui_bundled/signin/BUILD.gn b/ios/chrome/browser/authentication/ui_bundled/signin/BUILD.gn
index 43dd7371..f112660 100644
--- a/ios/chrome/browser/authentication/ui_bundled/signin/BUILD.gn
+++ b/ios/chrome/browser/authentication/ui_bundled/signin/BUILD.gn
@@ -88,6 +88,7 @@
     "//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:features",
     "//ios/chrome/browser/shared/public/features",
     "//ios/chrome/browser/shared/public/features:system_flags",
     "//ios/chrome/browser/signin/model",
diff --git a/ios/chrome/browser/authentication/ui_bundled/signin/account_menu/account_menu_mediator.mm b/ios/chrome/browser/authentication/ui_bundled/signin/account_menu/account_menu_mediator.mm
index 8043cae..abfa3dd 100644
--- a/ios/chrome/browser/authentication/ui_bundled/signin/account_menu/account_menu_mediator.mm
+++ b/ios/chrome/browser/authentication/ui_bundled/signin/account_menu/account_menu_mediator.mm
@@ -30,11 +30,9 @@
 #import "ios/chrome/browser/shared/model/application_context/application_context.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
 #import "ios/chrome/browser/signin/model/authentication_service.h"
-#import "ios/chrome/browser/signin/model/chrome_account_manager_service_observer_bridge.h"
 #import "ios/chrome/browser/sync/model/sync_observer_bridge.h"
 
-@interface AccountMenuMediator () <ChromeAccountManagerServiceObserver,
-                                   IdentityManagerObserverBridgeDelegate,
+@interface AccountMenuMediator () <IdentityManagerObserverBridgeDelegate,
                                    SyncObserverModelBridge>
 
 // Whether the account menu’s interaction is blocked.
@@ -45,9 +43,6 @@
 @implementation AccountMenuMediator {
   // Account manager service to retrieve Chrome identities.
   raw_ptr<ChromeAccountManagerService> _accountManagerService;
-  // Chrome account manager service observer bridge.
-  std::unique_ptr<ChromeAccountManagerServiceObserverBridge>
-      _accountManagerServiceObserver;
   raw_ptr<AuthenticationService> _authenticationService;
   raw_ptr<signin::IdentityManager> _identityManager;
   std::unique_ptr<signin::IdentityManagerObserverBridge>
@@ -91,9 +86,6 @@
     _userInteractionsBlocked = NO;
     _identities = [NSMutableArray array];
     _accountManagerService = accountManagerService;
-    _accountManagerServiceObserver =
-        std::make_unique<ChromeAccountManagerServiceObserverBridge>(
-            self, _accountManagerService);
     _authenticationService = authService;
     _identityManager = identityManager;
     _identityManagerObserver =
@@ -113,7 +105,6 @@
 - (void)disconnect {
   _blockUpdates = YES;
   _accountManagerService = nullptr;
-  _accountManagerServiceObserver.reset();
   _authenticationService = nullptr;
   _identityManagerObserver.reset();
   _identityManager = nullptr;
@@ -185,15 +176,6 @@
   return _error;
 }
 
-#pragma mark - ChromeAccountManagerServiceObserver
-
-- (void)onChromeAccountManagerServiceShutdown:
-    (ChromeAccountManagerService*)accountManagerService {
-  // TODO(crbug.com/40067367): This method can be removed once
-  // crbug.com/40067367 is fixed.
-  [self disconnect];
-}
-
 #pragma mark - IdentityManagerObserverBridgeDelegate
 
 - (void)onEndBatchOfPrimaryAccountChanges {
diff --git a/ios/chrome/browser/authentication/ui_bundled/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_mediator.mm b/ios/chrome/browser/authentication/ui_bundled/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_mediator.mm
index 254af76..6c3ffb6 100644
--- a/ios/chrome/browser/authentication/ui_bundled/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_mediator.mm
+++ b/ios/chrome/browser/authentication/ui_bundled/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_mediator.mm
@@ -13,15 +13,11 @@
 #import "ios/chrome/browser/authentication/ui_bundled/signin/signin_utils.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
 #import "ios/chrome/browser/signin/model/chrome_account_manager_service.h"
-#import "ios/chrome/browser/signin/model/chrome_account_manager_service_observer_bridge.h"
 #import "ios/chrome/browser/signin/model/system_identity.h"
 
 @interface ConsistencyAccountChooserMediator () <
-    ChromeAccountManagerServiceObserver,
     IdentityManagerObserverBridgeDelegate> {
   raw_ptr<ChromeAccountManagerService> _accountManagerService;
-  std::unique_ptr<ChromeAccountManagerServiceObserverBridge>
-      _accountManagerServiceObserver;
   raw_ptr<signin::IdentityManager> _identityManager;
   std::unique_ptr<signin::IdentityManagerObserverBridge>
       _identityManagerObserver;
@@ -48,9 +44,6 @@
 
     CHECK(accountManagerService);
     _accountManagerService = accountManagerService;
-    _accountManagerServiceObserver =
-        std::make_unique<ChromeAccountManagerServiceObserverBridge>(
-            self, _accountManagerService);
 
     _selectedIdentity = selectedIdentity;
 
@@ -67,7 +60,6 @@
 - (void)disconnect {
   _identityManagerObserver.reset();
   _identityManager = nullptr;
-  _accountManagerServiceObserver.reset();
   _accountManagerService = nullptr;
 }
 
@@ -159,14 +151,6 @@
   [self.consumer reloadAllIdentities];
 }
 
-#pragma mark - ChromeAccountManagerServiceObserver
-
-- (void)onChromeAccountManagerServiceShutdown:
-    (ChromeAccountManagerService*)accountManagerService {
-  // TODO(crbug.com/40284086): Remove `[self disconnect]`.
-  [self disconnect];
-}
-
 #pragma mark -  IdentityManagerObserver
 
 - (void)onAccountsOnDeviceChanged {
diff --git a/ios/chrome/browser/authentication/ui_bundled/signin/consistency_promo_signin/consistency_default_account/consistency_default_account_mediator.mm b/ios/chrome/browser/authentication/ui_bundled/signin/consistency_promo_signin/consistency_default_account/consistency_default_account_mediator.mm
index 9baa8e89..4b47058 100644
--- a/ios/chrome/browser/authentication/ui_bundled/signin/consistency_promo_signin/consistency_default_account/consistency_default_account_mediator.mm
+++ b/ios/chrome/browser/authentication/ui_bundled/signin/consistency_promo_signin/consistency_default_account/consistency_default_account_mediator.mm
@@ -19,7 +19,6 @@
 #import "ios/chrome/browser/authentication/ui_bundled/signin/signin_utils.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
 #import "ios/chrome/browser/signin/model/chrome_account_manager_service.h"
-#import "ios/chrome/browser/signin/model/chrome_account_manager_service_observer_bridge.h"
 #import "ios/chrome/browser/signin/model/system_identity.h"
 #import "ios/chrome/grit/ios_branded_strings.h"
 #import "ios/chrome/grit/ios_strings.h"
@@ -150,6 +149,7 @@
     case signin_metrics::AccessPoint::kGlicLaunchButton:
     case signin_metrics::AccessPoint::kHistoryPage:
     case signin_metrics::AccessPoint::kCollaborationJoinTabGroup:
+    case signin_metrics::AccessPoint::kHistorySyncOptinExpansionPill:
       // Nothing prevents instantiating ConsistencyDefaultAccountViewController
       // with an arbitrary entry point, API-wise. In doubt, no label is a good,
       // generic default that fits all entry points.
@@ -160,12 +160,9 @@
 }  // namespace
 
 @interface ConsistencyDefaultAccountMediator () <
-    ChromeAccountManagerServiceObserver,
     IdentityManagerObserverBridgeDelegate> {
   std::unique_ptr<signin::IdentityManagerObserverBridge>
       _identityManagerObserver;
-  std::unique_ptr<ChromeAccountManagerServiceObserverBridge>
-      _accountManagerServiceObserver;
   signin_metrics::AccessPoint _accessPoint;
   raw_ptr<syncer::SyncService> _syncService;
 }
@@ -197,9 +194,6 @@
     _identityManagerObserver =
         std::make_unique<signin::IdentityManagerObserverBridge>(
             _identityManager, self);
-    _accountManagerServiceObserver =
-        std::make_unique<ChromeAccountManagerServiceObserverBridge>(
-            self, _accountManagerService);
   }
   return self;
 }
@@ -215,7 +209,6 @@
   _accountManagerService = nullptr;
   _syncService = nullptr;
   _identityManagerObserver.reset();
-  _accountManagerServiceObserver.reset();
 }
 
 #pragma mark - Properties
@@ -320,13 +313,6 @@
                                 }));
   return NO;
 }
-#pragma mark - ChromeAccountManagerServiceObserver
-
-- (void)onChromeAccountManagerServiceShutdown:
-    (ChromeAccountManagerService*)accountManagerService {
-  // TODO(crbug.com/40284086): Remove `[self disconnect]`.
-  [self disconnect];
-}
 
 #pragma mark -  IdentityManagerObserver
 
diff --git a/ios/chrome/browser/authentication/ui_bundled/signin/signin_utils.mm b/ios/chrome/browser/authentication/ui_bundled/signin/signin_utils.mm
index 253df93..1392f12c 100644
--- a/ios/chrome/browser/authentication/ui_bundled/signin/signin_utils.mm
+++ b/ios/chrome/browser/authentication/ui_bundled/signin/signin_utils.mm
@@ -38,6 +38,7 @@
 #import "ios/chrome/browser/shared/model/browser/browser_provider.h"
 #import "ios/chrome/browser/shared/model/browser/browser_provider_interface.h"
 #import "ios/chrome/browser/shared/model/prefs/pref_names.h"
+#import "ios/chrome/browser/shared/model/profile/features.h"
 #import "ios/chrome/browser/shared/model/profile/profile_attributes_storage_ios.h"
 #import "ios/chrome/browser/shared/model/profile/profile_ios.h"
 #import "ios/chrome/browser/shared/model/profile/profile_manager_ios.h"
diff --git a/ios/chrome/browser/authentication/ui_bundled/signin_earl_grey_app_interface.mm b/ios/chrome/browser/authentication/ui_bundled/signin_earl_grey_app_interface.mm
index 4a2a947..f48288a8 100644
--- a/ios/chrome/browser/authentication/ui_bundled/signin_earl_grey_app_interface.mm
+++ b/ios/chrome/browser/authentication/ui_bundled/signin_earl_grey_app_interface.mm
@@ -29,6 +29,7 @@
 #import "ios/chrome/browser/shared/coordinator/scene/scene_controller.h"
 #import "ios/chrome/browser/shared/model/application_context/application_context.h"
 #import "ios/chrome/browser/shared/model/prefs/pref_names.h"
+#import "ios/chrome/browser/shared/model/profile/features.h"
 #import "ios/chrome/browser/shared/model/profile/profile_ios.h"
 #import "ios/chrome/browser/shared/public/commands/show_signin_command.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
diff --git a/ios/chrome/browser/authentication/ui_bundled/signin_promo_view_mediator.mm b/ios/chrome/browser/authentication/ui_bundled/signin_promo_view_mediator.mm
index 2ea851b..dbd7bae 100644
--- a/ios/chrome/browser/authentication/ui_bundled/signin_promo_view_mediator.mm
+++ b/ios/chrome/browser/authentication/ui_bundled/signin_promo_view_mediator.mm
@@ -33,7 +33,6 @@
 #import "ios/chrome/browser/shared/public/features/system_flags.h"
 #import "ios/chrome/browser/signin/model/authentication_service.h"
 #import "ios/chrome/browser/signin/model/chrome_account_manager_service.h"
-#import "ios/chrome/browser/signin/model/chrome_account_manager_service_observer_bridge.h"
 #import "ios/chrome/browser/signin/model/system_identity.h"
 #import "ios/chrome/browser/sync/model/sync_observer_bridge.h"
 #import "ios/chrome/grit/ios_strings.h"
@@ -132,6 +131,7 @@
     case signin_metrics::AccessPoint::kGlicLaunchButton:
     case signin_metrics::AccessPoint::kHistoryPage:
     case signin_metrics::AccessPoint::kCollaborationJoinTabGroup:
+    case signin_metrics::AccessPoint::kHistorySyncOptinExpansionPill:
       return false;
   }
 }
@@ -224,6 +224,7 @@
     case signin_metrics::AccessPoint::kGlicLaunchButton:
     case signin_metrics::AccessPoint::kHistoryPage:
     case signin_metrics::AccessPoint::kCollaborationJoinTabGroup:
+    case signin_metrics::AccessPoint::kHistorySyncOptinExpansionPill:
       NOTREACHED() << "Unexpected value for access point "
                    << static_cast<int>(access_point);
   }
@@ -317,6 +318,7 @@
     case signin_metrics::AccessPoint::kGlicLaunchButton:
     case signin_metrics::AccessPoint::kHistoryPage:
     case signin_metrics::AccessPoint::kCollaborationJoinTabGroup:
+    case signin_metrics::AccessPoint::kHistorySyncOptinExpansionPill:
       NOTREACHED() << "Unexpected value for access point "
                    << static_cast<int>(access_point);
   }
@@ -399,6 +401,7 @@
     case signin_metrics::AccessPoint::kGlicLaunchButton:
     case signin_metrics::AccessPoint::kHistoryPage:
     case signin_metrics::AccessPoint::kCollaborationJoinTabGroup:
+    case signin_metrics::AccessPoint::kHistorySyncOptinExpansionPill:
       return nullptr;
   }
 }
@@ -480,6 +483,7 @@
     case signin_metrics::AccessPoint::kGlicLaunchButton:
     case signin_metrics::AccessPoint::kHistoryPage:
     case signin_metrics::AccessPoint::kCollaborationJoinTabGroup:
+    case signin_metrics::AccessPoint::kHistorySyncOptinExpansionPill:
       return nullptr;
   }
 }
@@ -527,8 +531,7 @@
 
 }  // namespace
 
-@interface SigninPromoViewMediator () <ChromeAccountManagerServiceObserver,
-                                       IdentityManagerObserverBridgeDelegate,
+@interface SigninPromoViewMediator () <IdentityManagerObserverBridgeDelegate,
                                        SyncObserverModelBridge>
 
 // Redefined to be readwrite. See documentation in the header file.
@@ -571,8 +574,6 @@
   raw_ptr<AuthenticationService> _authService;
   // AccountManager Service used to retrive identities.
   raw_ptr<ChromeAccountManagerService> _accountManagerService;
-  std::unique_ptr<ChromeAccountManagerServiceObserverBridge>
-      _accountManagerServiceObserver;
   // IdentityManager used to retrive identities.
   raw_ptr<signin::IdentityManager> _identityManager;
   std::unique_ptr<signin::IdentityManagerObserverBridge>
@@ -690,9 +691,6 @@
     _dataTypeToWaitForInitialSync = syncer::DataType::UNSPECIFIED;
     _signinPresenter = signinPresenter;
     _accountSettingsPresenter = accountSettingsPresenter;
-    _accountManagerServiceObserver =
-        std::make_unique<ChromeAccountManagerServiceObserverBridge>(
-            self, _accountManagerService);
     _identityManagerObserver =
         std::make_unique<signin::IdentityManagerObserverBridge>(
             _identityManager, self);
@@ -860,7 +858,6 @@
   _identityManager = nullptr;
   _authService = nullptr;
   _syncService = nullptr;
-  _accountManagerServiceObserver.reset();
   _identityManagerObserver.reset();
   _syncObserverBridge.reset();
 }
@@ -1048,14 +1045,6 @@
   [self sendConsumerNotificationWithIdentityChanged:NO];
 }
 
-#pragma mark - ChromeAccountManagerServiceObserver
-
-- (void)onChromeAccountManagerServiceShutdown:
-    (ChromeAccountManagerService*)accountManagerService {
-  // TODO(crbug.com/40284086): Remove `[self disconnect]`.
-  [self disconnect];
-}
-
 #pragma mark -  IdentityManagerObserver
 
 - (void)onAccountsOnDeviceChanged {
diff --git a/ios/chrome/browser/authentication/ui_bundled/signin_promo_view_mediator_unittest.mm b/ios/chrome/browser/authentication/ui_bundled/signin_promo_view_mediator_unittest.mm
index a1a441b6..531ad1e 100644
--- a/ios/chrome/browser/authentication/ui_bundled/signin_promo_view_mediator_unittest.mm
+++ b/ios/chrome/browser/authentication/ui_bundled/signin_promo_view_mediator_unittest.mm
@@ -28,13 +28,13 @@
 #import "ios/chrome/browser/shared/model/browser/test/test_browser.h"
 #import "ios/chrome/browser/shared/model/prefs/browser_prefs.h"
 #import "ios/chrome/browser/shared/model/prefs/pref_names.h"
+#import "ios/chrome/browser/shared/model/profile/features.h"
 #import "ios/chrome/browser/shared/model/profile/test/test_profile_ios.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
 #import "ios/chrome/browser/shared/ui/symbols/symbols.h"
 #import "ios/chrome/browser/signin/model/authentication_service.h"
 #import "ios/chrome/browser/signin/model/authentication_service_factory.h"
 #import "ios/chrome/browser/signin/model/chrome_account_manager_service_factory.h"
-#import "ios/chrome/browser/signin/model/chrome_account_manager_service_observer_bridge.h"
 #import "ios/chrome/browser/signin/model/fake_authentication_service_delegate.h"
 #import "ios/chrome/browser/signin/model/fake_system_identity.h"
 #import "ios/chrome/browser/signin/model/fake_system_identity_manager.h"
diff --git a/ios/chrome/browser/authentication/ui_bundled/signout_action_sheet/BUILD.gn b/ios/chrome/browser/authentication/ui_bundled/signout_action_sheet/BUILD.gn
index bae5647..b020e3b 100644
--- a/ios/chrome/browser/authentication/ui_bundled/signout_action_sheet/BUILD.gn
+++ b/ios/chrome/browser/authentication/ui_bundled/signout_action_sheet/BUILD.gn
@@ -20,7 +20,7 @@
     "//ios/chrome/browser/authentication/ui_bundled/signin:signin_headers",
     "//ios/chrome/browser/ntp/ui_bundled:feature_flags",
     "//ios/chrome/browser/shared/model/browser",
-    "//ios/chrome/browser/shared/model/profile",
+    "//ios/chrome/browser/shared/model/profile:features",
     "//ios/chrome/browser/shared/public/commands",
     "//ios/chrome/browser/shared/public/features",
     "//ios/chrome/browser/shared/ui/util",
@@ -54,6 +54,8 @@
     "//ios/chrome/browser/shared/model/application_context",
     "//ios/chrome/browser/shared/model/browser/test:test_support",
     "//ios/chrome/browser/shared/model/prefs:pref_names",
+    "//ios/chrome/browser/shared/model/profile",
+    "//ios/chrome/browser/shared/model/profile:features",
     "//ios/chrome/browser/shared/model/profile/test",
     "//ios/chrome/browser/shared/public/commands",
     "//ios/chrome/browser/shared/public/features",
diff --git a/ios/chrome/browser/authentication/ui_bundled/signout_action_sheet/signout_action_sheet_coordinator_unittest.mm b/ios/chrome/browser/authentication/ui_bundled/signout_action_sheet/signout_action_sheet_coordinator_unittest.mm
index 8963820f..d283d77 100644
--- a/ios/chrome/browser/authentication/ui_bundled/signout_action_sheet/signout_action_sheet_coordinator_unittest.mm
+++ b/ios/chrome/browser/authentication/ui_bundled/signout_action_sheet/signout_action_sheet_coordinator_unittest.mm
@@ -24,6 +24,7 @@
 #import "ios/chrome/browser/shared/model/application_context/application_context.h"
 #import "ios/chrome/browser/shared/model/browser/test/test_browser.h"
 #import "ios/chrome/browser/shared/model/prefs/pref_names.h"
+#import "ios/chrome/browser/shared/model/profile/features.h"
 #import "ios/chrome/browser/shared/model/profile/test/test_profile_ios.h"
 #import "ios/chrome/browser/shared/model/profile/test/test_profile_manager_ios.h"
 #import "ios/chrome/browser/shared/public/commands/command_dispatcher.h"
diff --git a/ios/chrome/browser/authentication/ui_bundled/views/BUILD.gn b/ios/chrome/browser/authentication/ui_bundled/views/BUILD.gn
index 4876baf3..f70193a0 100644
--- a/ios/chrome/browser/authentication/ui_bundled/views/BUILD.gn
+++ b/ios/chrome/browser/authentication/ui_bundled/views/BUILD.gn
@@ -17,6 +17,7 @@
     "//ios/chrome/app/strings",
     "//ios/chrome/browser/authentication/ui_bundled:authentication_constants",
     "//ios/chrome/browser/authentication/ui_bundled/views/resources",
+    "//ios/chrome/browser/shared/model/profile:features",
     "//ios/chrome/browser/shared/public/features:features",
     "//ios/chrome/browser/shared/ui/symbols:symbols",
     "//ios/chrome/browser/shared/ui/util",
diff --git a/ios/chrome/browser/authentication/ui_bundled/views/identity_view.mm b/ios/chrome/browser/authentication/ui_bundled/views/identity_view.mm
index 923895e..424fd2ba 100644
--- a/ios/chrome/browser/authentication/ui_bundled/views/identity_view.mm
+++ b/ios/chrome/browser/authentication/ui_bundled/views/identity_view.mm
@@ -7,7 +7,7 @@
 #import "base/check.h"
 #import "base/check_op.h"
 #import "base/notreached.h"
-#import "ios/chrome/browser/shared/public/features/features.h"
+#import "ios/chrome/browser/shared/model/profile/features.h"
 #import "ios/chrome/browser/shared/ui/symbols/symbols.h"
 #import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h"
 #import "ios/chrome/common/ui/colors/semantic_color_names.h"
diff --git a/ios/chrome/browser/autofill/model/bottom_sheet/bottom_sheet.ts b/ios/chrome/browser/autofill/model/bottom_sheet/bottom_sheet.ts
index d223e14..0a35e1d 100644
--- a/ios/chrome/browser/autofill/model/bottom_sheet/bottom_sheet.ts
+++ b/ios/chrome/browser/autofill/model/bottom_sheet/bottom_sheet.ts
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 import {sendWebKitMessage} from '//ios/web/public/js_messaging/resources/utils.js';
 
 /**
@@ -43,7 +43,7 @@
   // Verify that the window's layout viewport has a height and a width and also
   // that the element is visible.
   return window.innerHeight > 0 && window.innerWidth > 0 &&
-      gCrWeb.fill.isVisibleNode(focusedElement);
+      gCrWebLegacy.fill.isVisibleNode(focusedElement);
 }
 
 /*
@@ -65,16 +65,16 @@
     form = lastBlurredElement_;
   }
 
-  // TODO(crbug.com/40261693): convert these "gCrWeb.fill" and "gCrWeb.form"
-  // calls to import and call the functions directly once the conversion to
-  // TypeScript is done.
+  // TODO(crbug.com/40261693): convert these "gCrWebLegacy.fill" and
+  // "gCrWebLegacy.form" calls to import and call the functions directly once
+  // the conversion to TypeScript is done.
 
   const msg = {
-    'frameID': gCrWeb.message.getFrameId(),
-    'formName': gCrWeb.form.getFormIdentifier(form),
-    'formRendererID': gCrWeb.fill.getUniqueID(form),
-    'fieldIdentifier': gCrWeb.form.getFieldIdentifier(field),
-    'fieldRendererID': gCrWeb.fill.getUniqueID(field),
+    'frameID': gCrWebLegacy.message.getFrameId(),
+    'formName': gCrWebLegacy.form.getFormIdentifier(form),
+    'formRendererID': gCrWebLegacy.fill.getUniqueID(form),
+    'fieldIdentifier': gCrWebLegacy.form.getFieldIdentifier(field),
+    'fieldRendererID': gCrWebLegacy.fill.getUniqueID(field),
     'fieldType': fieldType,
     'type': 'focus',
     'value': fieldValue,
@@ -118,7 +118,7 @@
  */
 function detachListenersInternal(rendererIds: number[]): void {
   for (const rendererId of rendererIds) {
-    const element = gCrWeb.fill.getElementByUniqueID(rendererId);
+    const element = gCrWebLegacy.fill.getElementByUniqueID(rendererId);
     const index = observedElements_.indexOf(element);
     if (index > -1) {
       element.removeEventListener('focus', focusEventHandler, true);
@@ -138,14 +138,14 @@
   let elementToBlur: HTMLElement|null = null;
   const elementsToObserve: Element[] = [];
   for (const renderer_id of rendererIds) {
-    const element = gCrWeb.fill.getElementByUniqueID(renderer_id);
+    const element = gCrWebLegacy.fill.getElementByUniqueID(renderer_id);
     // Only add element to list of observed elements if we aren't already
     // observing it.
     if (element && isObservable(element) &&
         !observedElements_.find(elem => elem === element)) {
       const autofocused = document.activeElement === element;
       if (allowAutofocus || !autofocused ||
-          !gCrWeb.autofill_form_features
+          !gCrWebLegacy.autofill_form_features
                .isAutofillFixPaymentSheetSpamEnabled()) {
         // Observe element if eligible.
         elementsToObserve.push(element);
@@ -205,7 +205,7 @@
   }
 }
 
-gCrWeb.bottomSheet = {
+gCrWebLegacy.bottomSheet = {
   attachListeners,
   detachListeners,
   refocusLastBlurredElement,
diff --git a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_view_controller.mm b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_view_controller.mm
index 9fbf685..54784fbf 100644
--- a/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_view_controller.mm
+++ b/ios/chrome/browser/autofill/ui_bundled/bottom_sheet/save_card_bottom_sheet_view_controller.mm
@@ -57,7 +57,7 @@
   // iOS-specific symbol is used to get an optimized image with better
   // resolution.
   return MakeSymbolMulticolor(
-      CustomSymbolWithPointSize(kGooglePaySymbol, kGooglePayIconHeight));
+      CustomSymbolWithPointSize(kGooglePaySymbol, kGooglePayLogoHeight));
 #endif
   return _aboveTitleImage;
 }
diff --git a/ios/chrome/browser/autofill/ui_bundled/form_input_accessory/BUILD.gn b/ios/chrome/browser/autofill/ui_bundled/form_input_accessory/BUILD.gn
index 9df9b0d9..7566731a 100644
--- a/ios/chrome/browser/autofill/ui_bundled/form_input_accessory/BUILD.gn
+++ b/ios/chrome/browser/autofill/ui_bundled/form_input_accessory/BUILD.gn
@@ -82,16 +82,20 @@
   deps = [
     ":form_input_accessory",
     "//base/test:test_support",
+    "//components/autofill/core/browser",
+    "//components/autofill/ios/browser",
     "//components/autofill/ios/common",
     "//components/autofill/ios/form_util",
     "//components/autofill/ios/form_util:form_util_feature",
     "//components/autofill/ios/form_util:test_support",
+    "//ios/chrome/browser/autofill/model:features",
     "//ios/chrome/browser/autofill/model:model_shared",
     "//ios/chrome/browser/autofill/model/bottom_sheet",
     "//ios/chrome/browser/shared/model/browser/test:test_support",
     "//ios/chrome/browser/shared/model/profile/test",
     "//ios/chrome/browser/shared/model/web_state_list",
     "//ios/chrome/browser/shared/model/web_state_list/test:test_support",
+    "//ios/chrome/common/ui/reauthentication",
     "//ios/chrome/test:test_support",
     "//ios/web/public/test",
     "//ios/web/public/test/fakes",
diff --git a/ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_input_accessory_mediator.h b/ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_input_accessory_mediator.h
index 1cb1148..6529de9 100644
--- a/ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_input_accessory_mediator.h
+++ b/ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_input_accessory_mediator.h
@@ -87,6 +87,9 @@
 // Replaces the object in charge of providing suggestions.
 - (void)injectProvider:(id<FormInputSuggestionsProvider>)provider;
 
+// Replaces the current provider selected by the mediator.
+- (void)injectCurrentProvider:(id<FormInputSuggestionsProvider>)provider;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_AUTOFILL_UI_BUNDLED_FORM_INPUT_ACCESSORY_FORM_INPUT_ACCESSORY_MEDIATOR_H_
diff --git a/ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_input_accessory_mediator.mm b/ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_input_accessory_mediator.mm
index cba6e27..919d3e4 100644
--- a/ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_input_accessory_mediator.mm
+++ b/ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_input_accessory_mediator.mm
@@ -94,6 +94,12 @@
              : true;
 }
 
+// Returns true if the FormSuggestionController (the provider for this KA
+// mediator) is in stateless mode.
+bool IsStateless() {
+  return base::FeatureList::IsEnabled(kStatelessFormSuggestionController);
+}
+
 }  // namespace
 
 @interface FormInputAccessoryMediator () <AutofillBottomSheetObserving,
@@ -187,6 +193,10 @@
 
   // Whether the keyboard height change notifications are enabled.
   BOOL _keyboardHeightChangeNotificationsEnabled;
+
+  // The current FormSuggestionProvider that matches the current suggestions.
+  // Set to nil if there are no current suggestions. Only used when Stateless.
+  __weak id<FormSuggestionProvider> _currentSuggestionProvider;
 }
 
 - (instancetype)
@@ -300,6 +310,8 @@
       // Initialize to the current value.
       [self booleanDidChange:_bottomOmniboxEnabled];
     }
+
+    _currentSuggestionProvider = nil;
   }
   return self;
 }
@@ -352,8 +364,8 @@
 }
 
 - (autofill::FillingProduct)currentProviderMainFillingProduct {
-  return self.currentProvider ? self.currentProvider.mainFillingProduct
-                              : autofill::FillingProduct::kNone;
+  return IsStateless() ? _currentSuggestionProvider.mainFillingProduct
+                       : self.currentProvider.mainFillingProduct;
 }
 
 #pragma mark - KeyboardNotification
@@ -686,6 +698,7 @@
 
   self.suggestionsEnabled = YES;
   self.currentProvider = nil;
+  _currentSuggestionProvider = nil;
 }
 
 // Asynchronously queries the providers for an accessory view. Sends it to
@@ -726,30 +739,44 @@
 // Post the passed `suggestions` to the consumer.
 - (void)updateWithProvider:(id<FormInputSuggestionsProvider>)provider
                suggestions:(NSArray<FormSuggestion*>*)suggestions {
+  FormSuggestion* firstSuggestion = suggestions.firstObject;
+
+  // Set the `mainFillingProduct` from the `suggestions` when stateless.
+  // Defaults to autofill::FillingProduct::kNone by default if there are no
+  // suggestions available in which case `provider.mainFillingProduct` is also
+  // likely to give back autofill::FillingProduct::kNone since suggestions
+  // aren't available.
+  autofill::FillingProduct mainFillingProduct =
+      IsStateless() ? firstSuggestion.provider.mainFillingProduct
+                    : provider.mainFillingProduct;
+
   if (!self.suggestionsEnabled) {
     if (self.formInputInteractionDelegate) {
       [self.formInputInteractionDelegate
-          focusDidChangedWithFillingProduct:provider.mainFillingProduct];
+          focusDidChangedWithFillingProduct:mainFillingProduct];
     }
     return;
   }
 
   // If suggestions are enabled, update `currentProvider`.
   self.currentProvider = provider;
+  // Use the first suggestion to represent all suggestions since they are all
+  // tied to the same provider.
+  _currentSuggestionProvider = firstSuggestion.provider;
 
   // Post it to the consumer.
-  self.consumer.mainFillingProduct = provider.mainFillingProduct;
+  self.consumer.mainFillingProduct = mainFillingProduct;
   self.consumer.currentFieldId = _lastSeenParams.field_renderer_id;
   [self.consumer showAccessorySuggestions:suggestions];
-  if (suggestions.count) {
-    if (provider.type == SuggestionProviderTypeAutofill) {
+  if (firstSuggestion) {
+    SuggestionProviderType providerType =
+        [self getProviderTypeFromSuggestion:firstSuggestion];
+    if (providerType == SuggestionProviderTypeAutofill) {
       default_browser::NotifyAutofillSuggestionsShown(self.engagementTracker);
 
-      if (suggestions.firstObject.featureForIPH !=
-          SuggestionFeatureForIPH::kUnknown) {
+      if (firstSuggestion.featureForIPH != SuggestionFeatureForIPH::kUnknown) {
         [self.handler
-            showAutofillSuggestionIPHIfNeededFor:suggestions.firstObject
-                                                     .featureForIPH];
+            showAutofillSuggestionIPHIfNeededFor:firstSuggestion.featureForIPH];
       }
     }
   }
@@ -762,12 +789,15 @@
 
 // Logs information about what type of suggestion the user selected.
 - (void)logReauthenticationEvent:(ReauthenticationEvent)reauthenticationEvent
-                            type:(autofill::SuggestionType)type {
+                   forSuggestion:(FormSuggestion*)suggestion {
+  SuggestionProviderType providerType =
+      [self getProviderTypeFromSuggestion:suggestion];
+
   std::string histogramName;
-  if (self.currentProvider.type == SuggestionProviderTypePassword) {
+  if (providerType == SuggestionProviderTypePassword) {
     histogramName = "IOS.Reauth.Password.Autofill";
-  } else if (self.currentProvider.type == SuggestionProviderTypeAutofill) {
-    switch (type) {
+  } else if (providerType == SuggestionProviderTypeAutofill) {
+    switch (suggestion.type) {
       case autofill::SuggestionType::kCreditCardEntry:
       case autofill::SuggestionType::kVirtualCreditCardEntry:
         histogramName = "IOS.Reauth.CreditCard.Autofill";
@@ -788,7 +818,8 @@
 // suggestion among the available suggestions.
 - (void)handleSuggestion:(FormSuggestion*)formSuggestion
                  atIndex:(NSInteger)index {
-  if (self.currentProvider.type == SuggestionProviderTypePassword) {
+  if ([self getProviderTypeFromSuggestion:formSuggestion] ==
+      SuggestionProviderTypePassword) {
     default_browser::NotifyPasswordAutofillSuggestionUsed(
         self.engagementTracker);
   } else if (formSuggestion.featureForIPH !=
@@ -812,7 +843,7 @@
 
 - (void)didSelectSuggestion:(FormSuggestion*)formSuggestion
                     atIndex:(NSInteger)index {
-  if (base::FeatureList::IsEnabled(kStatelessFormSuggestionController)) {
+  if (IsStateless()) {
     // When using the stateless FormSuggestionsController, ensure the params
     // attached to the suggestion are the same as the ones held by this mediator
     // to keep the status quo as this mediator should be the source of truth
@@ -824,11 +855,11 @@
   }
 
   [self logReauthenticationEvent:ReauthenticationEvent::kAttempt
-                            type:formSuggestion.type];
+                   forSuggestion:formSuggestion];
 
   if (!formSuggestion.requiresReauth) {
     [self logReauthenticationEvent:ReauthenticationEvent::kSuccess
-                              type:formSuggestion.type];
+                     forSuggestion:formSuggestion];
     [self handleSuggestion:formSuggestion atIndex:index];
     return;
   }
@@ -837,11 +868,11 @@
     auto completionHandler = ^(ReauthenticationResult result) {
       if (result != ReauthenticationResult::kFailure) {
         [self logReauthenticationEvent:ReauthenticationEvent::kSuccess
-                                  type:formSuggestion.type];
+                         forSuggestion:formSuggestion];
         [self handleSuggestion:formSuggestion atIndex:index];
       } else {
         [self logReauthenticationEvent:ReauthenticationEvent::kFailure
-                                  type:formSuggestion.type];
+                         forSuggestion:formSuggestion];
       }
     };
 
@@ -851,7 +882,7 @@
                                  handler:completionHandler];
   } else {
     [self logReauthenticationEvent:ReauthenticationEvent::kMissingPasscode
-                              type:formSuggestion.type];
+                     forSuggestion:formSuggestion];
     [self handleSuggestion:formSuggestion atIndex:index];
   }
 }
@@ -901,4 +932,17 @@
   self.provider = provider;
 }
 
+- (void)injectCurrentProvider:(id<FormInputSuggestionsProvider>)provider {
+  self.currentProvider = provider;
+}
+
+#pragma mark - Private
+
+// Returns the SuggestionProviderType for the `suggestion` based on whether or
+// not the FormSuggestionController is stateless.
+- (SuggestionProviderType)getProviderTypeFromSuggestion:
+    (FormSuggestion*)suggestion {
+  return IsStateless() ? suggestion.provider.type : self.currentProvider.type;
+}
+
 @end
diff --git a/ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_input_accessory_mediator_unittest.mm b/ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_input_accessory_mediator_unittest.mm
index 5047c0a..339815c4 100644
--- a/ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_input_accessory_mediator_unittest.mm
+++ b/ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_input_accessory_mediator_unittest.mm
@@ -4,10 +4,17 @@
 
 #import "ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_input_accessory_mediator.h"
 
+#import "base/metrics/histogram_base.h"
+#import "base/test/metrics/histogram_tester.h"
+#import "base/test/scoped_feature_list.h"
+#import "components/autofill/core/browser/filling/filling_product.h"
+#import "components/autofill/ios/browser/form_suggestion.h"
+#import "components/autofill/ios/browser/form_suggestion_provider.h"
 #import "components/autofill/ios/common/javascript_feature_util.h"
 #import "components/autofill/ios/form_util/form_activity_params.h"
 #import "components/autofill/ios/form_util/test_form_activity_tab_helper.h"
 #import "ios/chrome/browser/autofill/model/bottom_sheet/autofill_bottom_sheet_tab_helper.h"
+#import "ios/chrome/browser/autofill/model/features.h"
 #import "ios/chrome/browser/autofill/model/form_input_suggestions_provider.h"
 #import "ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_input_accessory_consumer.h"
 #import "ios/chrome/browser/autofill/ui_bundled/form_input_accessory/form_input_accessory_mediator_handler.h"
@@ -16,6 +23,7 @@
 #import "ios/chrome/browser/shared/model/web_state_list/test/fake_web_state_list_delegate.h"
 #import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h"
 #import "ios/chrome/browser/shared/model/web_state_list/web_state_opener.h"
+#import "ios/chrome/common/ui/reauthentication/reauthentication_event.h"
 #import "ios/chrome/test/ios_chrome_scoped_testing_local_state.h"
 #import "ios/web/public/test/fakes/fake_navigation_manager.h"
 #import "ios/web/public/test/fakes/fake_web_frame.h"
@@ -43,6 +51,54 @@
 
 }  // namespace
 
+// Test implementation of FormSuggestionProvider.
+@interface TestFormSuggestionProvider : NSObject <FormSuggestionProvider>
+@end
+
+@implementation TestFormSuggestionProvider
+
+#pragma mark - Public
+
+// Sets the SuggestionProviderType returned when using the -type getter.
+- (void)setType:(SuggestionProviderType)type {
+  _type = type;
+}
+
+// Sets the FillingProduct returned when using the -mainFillingProduct getter.
+- (void)setMainFillingProduct:(autofill::FillingProduct)mainFillingProduct {
+  _mainFillingProduct = mainFillingProduct;
+}
+
+#pragma mark - FormSuggestionProvider
+
+@synthesize type = _type;
+@synthesize mainFillingProduct = _mainFillingProduct;
+
+- (void)checkIfSuggestionsAvailableForForm:
+            (FormSuggestionProviderQuery*)formQuery
+                            hasUserGesture:(BOOL)hasUserGesture
+                                  webState:(web::WebState*)webState
+                         completionHandler:
+                             (SuggestionsAvailableCompletion)completion {
+}
+
+- (void)retrieveSuggestionsForForm:(FormSuggestionProviderQuery*)formQuery
+                          webState:(web::WebState*)webState
+                 completionHandler:(SuggestionsReadyCompletion)completion {
+}
+
+- (void)didSelectSuggestion:(FormSuggestion*)suggestion
+                    atIndex:(NSInteger)index
+                       form:(NSString*)formName
+             formRendererID:(autofill::FormRendererId)formRendererID
+            fieldIdentifier:(NSString*)fieldIdentifier
+            fieldRendererID:(autofill::FieldRendererId)fieldRendererID
+                    frameID:(NSString*)frameID
+          completionHandler:(SuggestionHandledCompletion)completion {
+}
+
+@end
+
 class FormInputAccessoryMediatorTest : public PlatformTest {
  protected:
   FormInputAccessoryMediatorTest()
@@ -83,7 +139,7 @@
                                         accountPasswordStore:nullptr
                                         securityAlertHandler:nil
                                       reauthenticationModule:nil
-                                           engagementTracker:nil];
+                                           engagementTracker:nullptr];
   }
 
   void TearDown() override {
@@ -146,6 +202,8 @@
         [invocation getArgument:&completion atIndex:4];
         suggestionsQueryCompletion = [completion copy];
       });
+  OCMStub([providerMock mainFillingProduct])
+      .andReturn(autofill::FillingProduct::kAutocomplete);
 
   // Emit a form registration event to trigger the show suggestions code path.
   test_form_activity_tab_helper_.FormActivityRegistered(main_frame_.get(),
@@ -167,6 +225,69 @@
   // in the view model.
   suggestionsQueryCompletion(suggestions, providerMock);
 
+  EXPECT_EQ(autofill::FillingProduct::kAutocomplete,
+            mediator_.currentProviderMainFillingProduct);
+
+  EXPECT_OCMOCK_VERIFY(consumer_);
+}
+
+// Tests showing suggestions when Stateless is enabled.
+TEST_F(FormInputAccessoryMediatorTest, ShowSuggestions_WhenStateless) {
+  base::test::ScopedFeatureList scoped_feature_list{
+      kStatelessFormSuggestionController};
+
+  id providerMock = OCMProtocolMock(@protocol(FormInputSuggestionsProvider));
+  [mediator_ injectProvider:providerMock];
+
+  TestFormSuggestionProvider* testSuggestionProvider =
+      [[TestFormSuggestionProvider alloc] init];
+  // Set a provider type that doesn't reach a code path that can't be handled in
+  // test.
+  [testSuggestionProvider
+      setType:SuggestionProviderType::SuggestionProviderTypeUnknown];
+  [testSuggestionProvider
+      setMainFillingProduct:autofill::FillingProduct::kAutocomplete];
+
+  FormActivityParams params = CreateFormActivityParams(/*field_type=*/"text");
+
+  __block FormSuggestionsReadyCompletion suggestionsQueryCompletion;
+
+  OCMStub([providerMock
+              retrieveSuggestionsForForm:params
+                                webState:web_state_list_.GetActiveWebState()
+                accessoryViewUpdateBlock:OCMOCK_ANY])
+      .andDo(^(NSInvocation* invocation) {
+        __weak FormSuggestionsReadyCompletion completion;
+        [invocation getArgument:&completion atIndex:4];
+        suggestionsQueryCompletion = [completion copy];
+      });
+
+  // Emit a form registration event to trigger the show suggestions code path.
+  test_form_activity_tab_helper_.FormActivityRegistered(main_frame_.get(),
+                                                        params);
+
+  FormSuggestion* suggestion = [FormSuggestion
+      suggestionWithValue:@"value"
+       displayDescription:@"display-description"
+                     icon:nil
+                     type:autofill::SuggestionType::kAutocompleteEntry
+                  payload:autofill::Suggestion::Payload()
+           requiresReauth:NO];
+  suggestion = [FormSuggestion copy:suggestion
+                       andSetParams:params
+                           provider:testSuggestionProvider];
+  NSArray<FormSuggestion*>* suggestions = [NSArray arrayWithObject:suggestion];
+
+  // Expect to update the view model with the suggestions from the query.
+  OCMExpect([consumer_ showAccessorySuggestions:suggestions]);
+
+  // Run the completion block to trigger the code path that updates suggestion
+  // in the view model.
+  suggestionsQueryCompletion(suggestions, providerMock);
+
+  EXPECT_EQ(autofill::FillingProduct::kAutocomplete,
+            mediator_.currentProviderMainFillingProduct);
+
   EXPECT_OCMOCK_VERIFY(consumer_);
 }
 
@@ -235,3 +356,58 @@
 
   EXPECT_OCMOCK_VERIFY(consumer_);
 }
+
+// Tests that selecting a suggestion when Stateless is enabled is correctly
+// handled when no reauthentication is needed.
+TEST_F(FormInputAccessoryMediatorTest, DidSelectSuggestion_NoReauth) {
+  base::test::ScopedFeatureList scoped_feature_list{
+      kStatelessFormSuggestionController};
+
+  base::HistogramTester histogram_tester;
+
+  id formInputSuggestionProviderMock =
+      OCMProtocolMock(@protocol(FormInputSuggestionsProvider));
+  [mediator_ injectCurrentProvider:formInputSuggestionProviderMock];
+
+  // Make a credit card suggestion that wraps all the information needed by
+  // Stateless.
+  FormActivityParams params = CreateFormActivityParams(/*field_type=*/"text");
+  TestFormSuggestionProvider* testSuggestionProvider =
+      [[TestFormSuggestionProvider alloc] init];
+  [testSuggestionProvider
+      setType:SuggestionProviderType::SuggestionProviderTypeAutofill];
+  FormSuggestion* suggestion = [FormSuggestion
+      suggestionWithValue:@"value"
+       displayDescription:@"display-description"
+                     icon:nil
+                     type:autofill::SuggestionType::kCreditCardEntry
+                  payload:autofill::Suggestion::Payload()
+           requiresReauth:NO];
+  suggestion = [FormSuggestion copy:suggestion
+                       andSetParams:params
+                           provider:testSuggestionProvider];
+
+  const NSInteger suggestionIndex = 0;
+
+  OCMExpect([formInputSuggestionProviderMock
+      didSelectSuggestion:[OCMArg any]
+                  atIndex:suggestionIndex]);
+
+  [mediator_ didSelectSuggestion:suggestion atIndex:suggestionIndex];
+
+  // Look the authentication metrics associated with the type of the selected
+  // provided are correctly recorded.
+  histogram_tester.ExpectTotalCount("IOS.Reauth.CreditCard.Autofill", 2);
+  histogram_tester.ExpectBucketCount("IOS.Reauth.CreditCard.Autofill",
+                                     /*sample=*/
+                                     static_cast<base::HistogramBase::Sample32>(
+                                         ReauthenticationEvent::kAttempt),
+                                     /*expected_count=*/1);
+  histogram_tester.ExpectBucketCount("IOS.Reauth.CreditCard.Autofill",
+                                     /*sample=*/
+                                     static_cast<base::HistogramBase::Sample32>(
+                                         ReauthenticationEvent::kSuccess),
+                                     /*expected_count=*/1);
+
+  EXPECT_OCMOCK_VERIFY(formInputSuggestionProviderMock);
+}
diff --git a/ios/chrome/browser/banner_promo/model/BUILD.gn b/ios/chrome/browser/banner_promo/model/BUILD.gn
index e409acc7..71655a1f 100644
--- a/ios/chrome/browser/banner_promo/model/BUILD.gn
+++ b/ios/chrome/browser/banner_promo/model/BUILD.gn
@@ -6,12 +6,15 @@
   sources = [
     "default_browser_banner_promo_app_agent.h",
     "default_browser_banner_promo_app_agent.mm",
+    "default_browser_banner_promo_scene_observer.h",
+    "default_browser_banner_promo_scene_observer.mm",
   ]
   deps = [
     "//base",
     "//components/feature_engagement/public",
     "//components/feature_engagement/public:feature_constants",
     "//components/google/core/common",
+    "//ios/chrome/app/application_delegate:app_state",
     "//ios/chrome/app/application_delegate:observing_app_state_agent",
     "//ios/chrome/app/profile",
     "//ios/chrome/browser/default_browser/model:utils",
diff --git a/ios/chrome/browser/banner_promo/model/default_browser_banner_promo_app_agent.h b/ios/chrome/browser/banner_promo/model/default_browser_banner_promo_app_agent.h
index 3fd2f84..557940d2 100644
--- a/ios/chrome/browser/banner_promo/model/default_browser_banner_promo_app_agent.h
+++ b/ios/chrome/browser/banner_promo/model/default_browser_banner_promo_app_agent.h
@@ -44,6 +44,12 @@
 // Alerts the app agent that the promo's close button was tapped.
 - (void)promoCloseButtonTapped;
 
+// Updates the promo state based on the current active URLs.
+- (void)updatePromoState;
+
+// Alerts the app agent that the given scene was disconnected.
+- (void)onSceneDisconnected:(SceneState*)sceneState;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_BANNER_PROMO_MODEL_DEFAULT_BROWSER_BANNER_PROMO_APP_AGENT_H_
diff --git a/ios/chrome/browser/banner_promo/model/default_browser_banner_promo_app_agent.mm b/ios/chrome/browser/banner_promo/model/default_browser_banner_promo_app_agent.mm
index 45db3d3..722f17e 100644
--- a/ios/chrome/browser/banner_promo/model/default_browser_banner_promo_app_agent.mm
+++ b/ios/chrome/browser/banner_promo/model/default_browser_banner_promo_app_agent.mm
@@ -9,21 +9,15 @@
 #import "components/feature_engagement/public/feature_constants.h"
 #import "components/feature_engagement/public/tracker.h"
 #import "components/google/core/common/google_util.h"
+#import "ios/chrome/app/application_delegate/app_state.h"
 #import "ios/chrome/app/profile/profile_state.h"
+#import "ios/chrome/browser/banner_promo/model/default_browser_banner_promo_scene_observer.h"
 #import "ios/chrome/browser/default_browser/model/utils.h"
 #import "ios/chrome/browser/feature_engagement/model/tracker_factory.h"
-#import "ios/chrome/browser/shared/coordinator/scene/scene_state.h"
-#import "ios/chrome/browser/shared/model/browser/browser.h"
-#import "ios/chrome/browser/shared/model/browser/browser_provider.h"
-#import "ios/chrome/browser/shared/model/browser/browser_provider_interface.h"
 #import "ios/chrome/browser/shared/model/url/url_util.h"
-#import "ios/chrome/browser/shared/model/web_state_list/active_web_state_observation_forwarder.h"
-#import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h"
-#import "ios/chrome/browser/shared/model/web_state_list/web_state_list_observer_bridge.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
 #import "ios/web/public/navigation/navigation_context.h"
-#import "ios/web/public/web_state.h"
-#import "ios/web/public/web_state_observer_bridge.h"
+#import "url/gurl.h"
 
 @interface DefaultBrowserBannerAppAgentObserverList
     : CRBProtocolObservers <DefaultBrowserBannerAppAgentObserver>
@@ -31,23 +25,10 @@
 @implementation DefaultBrowserBannerAppAgentObserverList
 @end
 
-@interface DefaultBrowserBannerPromoAppAgent () <CRWWebStateObserver,
-                                                 WebStateListObserving>
-
-@end
-
 @implementation DefaultBrowserBannerPromoAppAgent {
-  // Observer bridge for observing web state lists.
-  std::unique_ptr<WebStateListObserverBridge> _webStateListObserverBridge;
-
-  // Observer bridge for observing web states.
-  std::unique_ptr<web::WebStateObserverBridge> _webStateObserverBridge;
-
-  // Stores the last URL visited for each web state to track navigations.
-  std::map<web::WebStateID, GURL> _lastNavigatedURLs;
-
-  // Stores the last observed foreground state for SceneState.
-  NSMapTable<SceneState*, NSNumber*>* _sceneStateForegroundCachedValue;
+  // Stores the scene observer for each scene.
+  NSMapTable<SceneState*, DefaultBrowserBannerPromoSceneObserver*>*
+      _sceneObservers;
 
   // Stored observers.
   DefaultBrowserBannerAppAgentObserverList* _observers;
@@ -66,12 +47,7 @@
 - (instancetype)init {
   self = [super init];
   if (self) {
-    _webStateListObserverBridge =
-        std::make_unique<WebStateListObserverBridge>(self);
-    _webStateObserverBridge =
-        std::make_unique<web::WebStateObserverBridge>(self);
-
-    _sceneStateForegroundCachedValue = [NSMapTable weakToStrongObjectsMapTable];
+    _sceneObservers = [NSMapTable weakToStrongObjectsMapTable];
 
     _observers = [DefaultBrowserBannerAppAgentObserverList
         observersWithProtocol:@protocol(DefaultBrowserBannerAppAgentObserver)];
@@ -115,126 +91,8 @@
   [self endPromoSession];
 }
 
-#pragma mark - Private
-
-- (BOOL)navigationOccuredInWebState:(web::WebState*)webState
-                  navigationContext:(web::NavigationContext*)navigationContext {
-  auto iterator = _lastNavigatedURLs.find(webState->GetUniqueIdentifier());
-  // New tabs are added with a blank GURL. Those should automatically count as
-  // a navigation.
-  if (iterator == _lastNavigatedURLs.end() || iterator->second == GURL()) {
-    return YES;
-  }
-
-  // New url counts as a navigation.
-  return iterator->second != navigationContext->GetUrl().GetWithoutRef() ||
-         !navigationContext->IsSameDocument();
-}
-
-// Observes the given webstate and handles other tracking related to this.
-- (void)startObservingWebState:(web::WebState*)webState {
-  webState->AddObserver(_webStateObserverBridge.get());
-  const GURL& currentURL = webState->GetLastCommittedURL().GetWithoutRef();
-  _lastNavigatedURLs.insert_or_assign(webState->GetUniqueIdentifier(),
-                                      currentURL);
-}
-
-// Stops observing the given webstate and cleans up other tracking related to
-// this.
-- (void)stopObservingWebState:(web::WebState*)webState {
-  webState->RemoveObserver(_webStateObserverBridge.get());
-  _lastNavigatedURLs.erase(webState->GetUniqueIdentifier());
-}
-
-// Handles scene state changes and updates the UI and observations as necessary.
-- (void)sceneStateChangedData:(SceneState*)sceneState {
-  if (!sceneState.UIEnabled) {
-    return;
-  }
-
-  Browser* mainBrowser =
-      sceneState.browserProviderInterface.mainBrowserProvider.browser;
-  if (!mainBrowser) {
-    return;
-  }
-
-  WebStateList* webStateList = mainBrowser->GetWebStateList();
-  if (!webStateList) {
-    return;
-  }
-
-  web::WebState* activeMainWebState = webStateList->GetActiveWebState();
-
-  const BOOL isForeground = [self isSceneStateInForeground:sceneState];
-  if (isForeground && !sceneState.incognitoContentVisible) {
-    webStateList->AddObserver(_webStateListObserverBridge.get());
-    // Sometimes, like when opening a link in a new window, the scene state
-    // doesn't start with an active web state. In this case, the first active
-    // web state will be observed via the WebStateList observer methods.
-    if (activeMainWebState) {
-      [self startObservingWebState:activeMainWebState];
-      [self updatePromoState];
-    }
-  } else {
-    webStateList->RemoveObserver(_webStateListObserverBridge.get());
-    if (activeMainWebState) {
-      [self stopObservingWebState:activeMainWebState];
-    }
-
-    [self updatePromoState];
-  }
-}
-
-// Makes sure the promo is shown and alerts observers if this causes a state
-// change.
-- (void)ensurePromoShown {
-  if (!self.promoCurrentlyShown) {
-    self.promoCurrentlyShown = YES;
-    [_observers displayPromoFromAppAgent:self];
-  }
-}
-
-// Makes sure the promo is hidden and alerts observers if this causes a state
-// change.
-- (void)ensurePromoHidden {
-  if (self.promoCurrentlyShown) {
-    feature_engagement::Tracker* engagementTracker =
-        feature_engagement::TrackerFactory::GetForProfile(
-            _mainProfileState.profile);
-    if (engagementTracker && _shouldAlertEngagementTrackerOfDismissal) {
-      _shouldAlertEngagementTrackerOfDismissal = NO;
-      engagementTracker->Dismissed(
-          feature_engagement::kIPHiOSDefaultBrowserBannerPromoFeature);
-    }
-    self.promoCurrentlyShown = NO;
-    [_observers hidePromoFromAppAgent:self];
-  }
-}
-
-// Ends any in-progress promo session and makes sure the promo UI is hidden.
-- (void)endPromoSession {
-  _sessionDisplayCount = 0;
-  [self ensurePromoHidden];
-}
-
-// Checks if the promo can be displayed on all currently active pages.
-- (BOOL)promoIsSuppressedOnCurrentURLs {
-  // There must be at least one active URL to have a promo.
-  if (_lastNavigatedURLs.size() == 0) {
-    return true;
-  }
-
-  for (const auto& [webStateID, url] : _lastNavigatedURLs) {
-    if (IsUrlNtp(url) || google_util::IsGoogleSearchUrl(url)) {
-      return true;
-    }
-  }
-  return false;
-}
-
-// Updates the promo state based on the current active URLs.
 - (void)updatePromoState {
-  for (const auto& [webStateID, url] : _lastNavigatedURLs) {
+  for (const auto& url : [self lastNavigatedURLs]) {
     // Tabs opened in new windows can start with a blank URL. Hold off on
     // changing state until it gets filled in from a navigation
     if (url == GURL()) {
@@ -282,6 +140,80 @@
   }
 }
 
+- (void)onSceneDisconnected:(SceneState*)sceneState {
+  [_sceneObservers removeObjectForKey:sceneState];
+}
+
+- (void)setAppState:(AppState*)appState {
+  [super setAppState:appState];
+  for (SceneState* sceneState : [self.appState connectedScenes]) {
+    [self appState:self.appState sceneConnected:sceneState];
+  }
+}
+
+#pragma mark - Private
+
+// Returns all the last navigated URLs from all of the current active scenes.
+- (std::vector<GURL>)lastNavigatedURLs {
+  std::vector<GURL> urls;
+  for (SceneState* sceneState : _sceneObservers) {
+    DefaultBrowserBannerPromoSceneObserver* observer =
+        [_sceneObservers objectForKey:sceneState];
+    if (observer.lastNavigatedURL) {
+      urls.push_back(observer.lastNavigatedURL.value());
+    }
+  }
+  return urls;
+}
+
+// Makes sure the promo is shown and alerts observers if this causes a state
+// change.
+- (void)ensurePromoShown {
+  if (!self.promoCurrentlyShown) {
+    self.promoCurrentlyShown = YES;
+    [_observers displayPromoFromAppAgent:self];
+  }
+}
+
+// Makes sure the promo is hidden and alerts observers if this causes a state
+// change.
+- (void)ensurePromoHidden {
+  if (self.promoCurrentlyShown) {
+    feature_engagement::Tracker* engagementTracker =
+        feature_engagement::TrackerFactory::GetForProfile(
+            _mainProfileState.profile);
+    if (engagementTracker && _shouldAlertEngagementTrackerOfDismissal) {
+      _shouldAlertEngagementTrackerOfDismissal = NO;
+      engagementTracker->Dismissed(
+          feature_engagement::kIPHiOSDefaultBrowserBannerPromoFeature);
+    }
+    self.promoCurrentlyShown = NO;
+    [_observers hidePromoFromAppAgent:self];
+  }
+}
+
+// Ends any in-progress promo session and makes sure the promo UI is hidden.
+- (void)endPromoSession {
+  _sessionDisplayCount = 0;
+  [self ensurePromoHidden];
+}
+
+// Checks if the promo can be displayed on all currently active pages.
+- (BOOL)promoIsSuppressedOnCurrentURLs {
+  std::vector<GURL> lastNavigatedURLs = [self lastNavigatedURLs];
+  // There must be at least one active URL to have a promo.
+  if (lastNavigatedURLs.size() == 0) {
+    return true;
+  }
+
+  for (const auto& url : lastNavigatedURLs) {
+    if (IsUrlNtp(url) || google_util::IsGoogleSearchUrl(url)) {
+      return true;
+    }
+  }
+  return false;
+}
+
 // Checks if there is an in-progress promo session and if it should be ended
 // based on current stats. Returns `YES` if a session was ended, and `NO` if
 // there was no in-progress session or it did not end.
@@ -297,7 +229,7 @@
         "IOS.DefaultBrowserBannerPromo.PromoSessionEnded",
         IOSDefaultBrowserBannerPromoPromoSessionEndedReason::kChromeNowDefault);
   } else if ([self promoIsSuppressedOnCurrentURLs]) {
-    for (const auto& [webStateID, url] : _lastNavigatedURLs) {
+    for (const auto& url : [self lastNavigatedURLs]) {
       if (IsUrlNtp(url)) {
         base::UmaHistogramEnumeration(
             "IOS.DefaultBrowserBannerPromo.PromoSessionEnded",
@@ -326,15 +258,6 @@
   return YES;
 }
 
-#pragma mark - AppStateObserver
-
-- (void)appState:(AppState*)appState sceneConnected:(SceneState*)sceneState {
-  [super appState:appState sceneConnected:sceneState];
-  const BOOL isForeground =
-      sceneState.activationLevel >= SceneActivationLevelForegroundInactive;
-  [self setIsForeground:isForeground forSceneState:sceneState];
-}
-
 #pragma mark - SceneStateObserver
 
 - (void)sceneState:(SceneState*)sceneState
@@ -345,102 +268,15 @@
   _mainProfileState = profileState;
 }
 
-- (void)sceneState:(SceneState*)sceneState
-    transitionedToActivationLevel:(SceneActivationLevel)level {
-  [super sceneState:sceneState transitionedToActivationLevel:level];
-  if (!IsDefaultBrowserBannerPromoEnabled()) {
-    return;
-  }
+#pragma mark - AppStateObserver
 
-  BOOL sceneIsForeground = level >= SceneActivationLevelForegroundInactive;
-
-  // If no change in foreground state has happened, stop here.
-  const BOOL wasForeground = [self isSceneStateInForeground:sceneState];
-  if (wasForeground == sceneIsForeground) {
-    return;
-  }
-
-  [self setIsForeground:sceneIsForeground forSceneState:sceneState];
-  [self sceneStateChangedData:sceneState];
-}
-
-- (void)sceneState:(SceneState*)sceneState
-    isDisplayingIncognitoContent:(BOOL)incognitoContentVisible {
-  if (!IsDefaultBrowserBannerPromoEnabled()) {
-    return;
-  }
-
-  [self sceneStateChangedData:sceneState];
-}
-
-- (void)sceneStateDidEnableUI:(SceneState*)sceneState {
-  if (!IsDefaultBrowserBannerPromoEnabled()) {
-    return;
-  }
-
-  // If the scene is not in the foreground yet, skip this change.
-  if (![self isSceneStateInForeground:sceneState]) {
-    return;
-  }
-
-  [self sceneStateChangedData:sceneState];
-}
-
-#pragma mark - WebStateListObserving
-
-- (void)didChangeWebStateList:(WebStateList*)webStateList
-                       change:(const WebStateListChange&)change
-                       status:(const WebStateListStatus&)status {
-  if (!status.active_web_state_change()) {
-    return;
-  }
-
-  if (status.old_active_web_state) {
-    [self stopObservingWebState:status.old_active_web_state];
-  }
-  if (status.new_active_web_state) {
-    [self startObservingWebState:status.new_active_web_state];
-  }
-
-  // Make sure the promo state is correct now that a new web state is active.
-  [self updatePromoState];
-}
-
-- (void)webStateListDestroyed:(WebStateList*)webStateList {
-  webStateList->RemoveObserver(_webStateListObserverBridge.get());
-
-  web::WebState* activeWebState = webStateList->GetActiveWebState();
-  if (activeWebState) {
-    [self stopObservingWebState:activeWebState];
-  }
-
-  [self updatePromoState];
-}
-
-#pragma mark - CRWWebStateObserver
-
-- (void)webState:(web::WebState*)webState
-    didFinishNavigation:(web::NavigationContext*)navigationContext {
-  if (![self navigationOccuredInWebState:webState
-                       navigationContext:navigationContext]) {
-    return;
-  }
-
-  _lastNavigatedURLs.insert_or_assign(
-      webState->GetUniqueIdentifier(),
-      navigationContext->GetUrl().GetWithoutRef());
-
-  [self updatePromoState];
-}
-
-#pragma mark - Get / set cached foreground value for SceneState.
-
-- (void)setIsForeground:(BOOL)foreground forSceneState:(SceneState*)sceneState {
-  [_sceneStateForegroundCachedValue setObject:@(foreground) forKey:sceneState];
-}
-
-- (BOOL)isSceneStateInForeground:(SceneState*)sceneState {
-  return [[_sceneStateForegroundCachedValue objectForKey:sceneState] boolValue];
+- (void)appState:(AppState*)appState sceneConnected:(SceneState*)sceneState {
+  [super appState:appState sceneConnected:sceneState];
+  DefaultBrowserBannerPromoSceneObserver* observer =
+      [[DefaultBrowserBannerPromoSceneObserver alloc]
+          initWithSceneState:sceneState
+                    appAgent:self];
+  [_sceneObservers setObject:observer forKey:sceneState];
 }
 
 @end
diff --git a/ios/chrome/browser/banner_promo/model/default_browser_banner_promo_scene_observer.h b/ios/chrome/browser/banner_promo/model/default_browser_banner_promo_scene_observer.h
new file mode 100644
index 0000000..0222464c
--- /dev/null
+++ b/ios/chrome/browser/banner_promo/model/default_browser_banner_promo_scene_observer.h
@@ -0,0 +1,29 @@
+// 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_BANNER_PROMO_MODEL_DEFAULT_BROWSER_BANNER_PROMO_SCENE_OBSERVER_H_
+#define IOS_CHROME_BROWSER_BANNER_PROMO_MODEL_DEFAULT_BROWSER_BANNER_PROMO_SCENE_OBSERVER_H_
+
+#import <optional>
+
+#import "ios/chrome/browser/shared/coordinator/scene/scene_state_observer.h"
+
+@class DefaultBrowserBannerPromoAppAgent;
+class GURL;
+@class SceneState;
+
+// Observer for an individual scene, web state list, and active web state  for
+// the Default Browser Banner Promo.
+@interface DefaultBrowserBannerPromoSceneObserver
+    : NSObject <SceneStateObserver>
+
+- (instancetype)initWithSceneState:(SceneState*)sceneState
+                          appAgent:(DefaultBrowserBannerPromoAppAgent*)appAgent;
+
+// The last URL that the current active web state navigated to, if one exists.
+@property(nonatomic) std::optional<GURL> lastNavigatedURL;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_BANNER_PROMO_MODEL_DEFAULT_BROWSER_BANNER_PROMO_SCENE_OBSERVER_H_
diff --git a/ios/chrome/browser/banner_promo/model/default_browser_banner_promo_scene_observer.mm b/ios/chrome/browser/banner_promo/model/default_browser_banner_promo_scene_observer.mm
new file mode 100644
index 0000000..73357fa
--- /dev/null
+++ b/ios/chrome/browser/banner_promo/model/default_browser_banner_promo_scene_observer.mm
@@ -0,0 +1,232 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/banner_promo/model/default_browser_banner_promo_scene_observer.h"
+
+#import "base/scoped_observation.h"
+#import "ios/chrome/browser/banner_promo/model/default_browser_banner_promo_app_agent.h"
+#import "ios/chrome/browser/shared/coordinator/scene/scene_state.h"
+#import "ios/chrome/browser/shared/model/browser/browser.h"
+#import "ios/chrome/browser/shared/model/browser/browser_provider.h"
+#import "ios/chrome/browser/shared/model/browser/browser_provider_interface.h"
+#import "ios/chrome/browser/shared/model/web_state_list/active_web_state_observation_forwarder.h"
+#import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h"
+#import "ios/chrome/browser/shared/model/web_state_list/web_state_list_observer_bridge.h"
+#import "ios/chrome/browser/shared/public/features/features.h"
+#import "ios/web/public/navigation/navigation_context.h"
+#import "ios/web/public/web_state_observer_bridge.h"
+
+@interface DefaultBrowserBannerPromoSceneObserver () <CRWWebStateObserver,
+                                                      WebStateListObserving>
+@end
+
+@implementation DefaultBrowserBannerPromoSceneObserver {
+  // The scene state this observer is observing.
+  __weak SceneState* _sceneState;
+  // The app agent that owns this observer and that this observer should alert
+  // of changes.
+  __weak DefaultBrowserBannerPromoAppAgent* _appAgent;
+
+  // Whether the scene is currently in the foreground.
+  BOOL _sceneIsForeground;
+
+  // Bridge to allow this object to observe web states.
+  std::unique_ptr<web::WebStateObserverBridge> _webStateObserver;
+  // Forwarder that forwards web state events in the active web state here.
+  std::unique_ptr<ActiveWebStateObservationForwarder>
+      _activeWebStateObservationForwarder;
+
+  // Bridge to allow this object to observe web state lists.
+  std::unique_ptr<WebStateListObserverBridge> _webStateListObserver;
+  // Scoped observation for web state lists.
+  std::unique_ptr<
+      base::ScopedObservation<WebStateList, WebStateListObserverBridge>>
+      _webStateListObservation;
+}
+
+- (instancetype)initWithSceneState:(SceneState*)sceneState
+                          appAgent:
+                              (DefaultBrowserBannerPromoAppAgent*)appAgent {
+  self = [super init];
+  if (self) {
+    _sceneState = sceneState;
+    _appAgent = appAgent;
+
+    [_sceneState addObserver:self];
+
+    _sceneIsForeground =
+        sceneState.activationLevel >= SceneActivationLevelForegroundInactive;
+
+    _webStateObserver = std::make_unique<web::WebStateObserverBridge>(self);
+
+    _webStateListObserver = std::make_unique<WebStateListObserverBridge>(self);
+    _webStateListObservation = std::make_unique<
+        base::ScopedObservation<WebStateList, WebStateListObserverBridge>>(
+        _webStateListObserver.get());
+  }
+  return self;
+}
+
+#pragma mark - Private
+
+// Returns whether the current navigation context changes should count as a
+// navigation for this feature.
+- (BOOL)navigationOccuredInNavigationContext:
+    (web::NavigationContext*)navigationContext {
+  // New tabs are added with a blank GURL. Those should automatically count as
+  // a navigation.
+  if (!self.lastNavigatedURL || self.lastNavigatedURL == GURL()) {
+    return YES;
+  }
+
+  // New url counts as a navigation.
+  return self.lastNavigatedURL != navigationContext->GetUrl().GetWithoutRef() ||
+         !navigationContext->IsSameDocument();
+}
+
+// Updates all necessary observation and state when the scene state's status
+// changes.
+- (void)sceneStateChangedData {
+  if (!_sceneState.UIEnabled) {
+    return;
+  }
+
+  Browser* mainBrowser =
+      _sceneState.browserProviderInterface.mainBrowserProvider.browser;
+  if (!mainBrowser) {
+    return;
+  }
+
+  WebStateList* webStateList = mainBrowser->GetWebStateList();
+  if (!webStateList) {
+    return;
+  }
+
+  web::WebState* activeMainWebState = webStateList->GetActiveWebState();
+
+  if (_sceneIsForeground && !_sceneState.incognitoContentVisible) {
+    _webStateListObservation->Observe(webStateList);
+    _activeWebStateObservationForwarder =
+        std::make_unique<ActiveWebStateObservationForwarder>(
+            webStateList, _webStateObserver.get());
+    // Sometimes, like when opening a link in a new window, the scene state
+    // doesn't start with an active web state. In this case, the first active
+    // web state will be observed via the WebStateList observer methods.
+    if (activeMainWebState) {
+      [self webStateActivated:activeMainWebState];
+      [_appAgent updatePromoState];
+    }
+  } else {
+    _webStateListObservation->Reset();
+    _activeWebStateObservationForwarder.reset();
+    if (activeMainWebState) {
+      [self webStateDeactivated:activeMainWebState];
+    }
+
+    [_appAgent updatePromoState];
+  }
+}
+
+- (void)webStateActivated:(web::WebState*)webState {
+  const GURL& currentURL = webState->GetLastCommittedURL().GetWithoutRef();
+  self.lastNavigatedURL = currentURL;
+}
+
+- (void)webStateDeactivated:(web::WebState*)webState {
+  self.lastNavigatedURL = std::nullopt;
+}
+
+#pragma mark - SceneStateObserver
+
+- (void)sceneState:(SceneState*)sceneState
+    transitionedToActivationLevel:(SceneActivationLevel)level {
+  if (!IsDefaultBrowserBannerPromoEnabled()) {
+    return;
+  }
+
+  // Alert the owning app agent so it can clean up this observer.
+  if (level == SceneActivationLevelDisconnected) {
+    [_appAgent onSceneDisconnected:_sceneState];
+    return;
+  }
+
+  BOOL sceneIsForeground = level >= SceneActivationLevelForegroundInactive;
+
+  // If no change in foreground state has happened, stop here.
+  if (_sceneIsForeground == sceneIsForeground) {
+    return;
+  }
+
+  _sceneIsForeground = sceneIsForeground;
+  [self sceneStateChangedData];
+}
+
+- (void)sceneState:(SceneState*)sceneState
+    isDisplayingIncognitoContent:(BOOL)incognitoContentVisible {
+  if (!IsDefaultBrowserBannerPromoEnabled()) {
+    return;
+  }
+
+  [self sceneStateChangedData];
+}
+
+- (void)sceneStateDidEnableUI:(SceneState*)sceneState {
+  if (!IsDefaultBrowserBannerPromoEnabled()) {
+    return;
+  }
+
+  // If the scene is not in the foreground yet, skip this change.
+  if (!_sceneIsForeground) {
+    return;
+  }
+
+  [self sceneStateChangedData];
+}
+
+#pragma mark - WebStateListObserving
+
+- (void)didChangeWebStateList:(WebStateList*)webStateList
+                       change:(const WebStateListChange&)change
+                       status:(const WebStateListStatus&)status {
+  if (!status.active_web_state_change()) {
+    return;
+  }
+
+  if (status.old_active_web_state) {
+    [self webStateDeactivated:status.old_active_web_state];
+  }
+  if (status.new_active_web_state) {
+    [self webStateActivated:status.new_active_web_state];
+  }
+
+  // Make sure the promo state is correct now that a new web state is active.
+  [_appAgent updatePromoState];
+}
+
+- (void)webStateListDestroyed:(WebStateList*)webStateList {
+  _webStateListObservation->Reset();
+  _activeWebStateObservationForwarder.reset();
+
+  web::WebState* activeWebState = webStateList->GetActiveWebState();
+  if (activeWebState) {
+    [self webStateDeactivated:activeWebState];
+  }
+
+  [_appAgent updatePromoState];
+}
+
+#pragma mark - CRWWebStateObserver
+
+- (void)webState:(web::WebState*)webState
+    didFinishNavigation:(web::NavigationContext*)navigationContext {
+  if (![self navigationOccuredInNavigationContext:navigationContext]) {
+    return;
+  }
+
+  self.lastNavigatedURL = navigationContext->GetUrl().GetWithoutRef();
+
+  [_appAgent updatePromoState];
+}
+
+@end
diff --git a/ios/chrome/browser/bookmarks/ui_bundled/home/bookmarks_home_view_controller.mm b/ios/chrome/browser/bookmarks/ui_bundled/home/bookmarks_home_view_controller.mm
index 9b3f664..a383370 100644
--- a/ios/chrome/browser/bookmarks/ui_bundled/home/bookmarks_home_view_controller.mm
+++ b/ios/chrome/browser/bookmarks/ui_bundled/home/bookmarks_home_view_controller.mm
@@ -1744,22 +1744,28 @@
 // Show scrim overlay and hide toolbar.
 - (void)showScrim {
   self.navigationController.toolbarHidden = YES;
-  self.scrimView.alpha = 0.0f;
-  [self.tableView addSubview:self.scrimView];
+  UIView* scrimView = self.scrimView;
+  UITableView* tableView = self.tableView;
+  UIView* superview = tableView.superview;
+  scrimView.alpha = 0.0f;
+  [tableView addSubview:scrimView];
   // We attach our constraints to the superview because the tableView is
   // a scrollView and it seems that we get an empty frame when attaching to it.
-  AddSameConstraints(self.scrimView, self.view.superview);
-  self.tableView.accessibilityElementsHidden = YES;
-  self.tableView.scrollEnabled = NO;
-  __weak BookmarksHomeViewController* weakSelf = self;
+  [NSLayoutConstraint activateConstraints:@[
+    [scrimView.leadingAnchor constraintEqualToAnchor:superview.leadingAnchor],
+    [scrimView.trailingAnchor constraintEqualToAnchor:superview.trailingAnchor],
+    [scrimView.bottomAnchor constraintEqualToAnchor:superview.bottomAnchor],
+    [scrimView.topAnchor
+        constraintEqualToAnchor:self.navigationController.navigationBar
+                                    .bottomAnchor],
+
+  ]];
+  tableView.accessibilityElementsHidden = YES;
+  tableView.scrollEnabled = NO;
   [UIView animateWithDuration:kTableViewNavigationScrimFadeDuration
                    animations:^{
-                     BookmarksHomeViewController* strongSelf = weakSelf;
-                     if (!strongSelf) {
-                       return;
-                     }
-                     strongSelf.scrimView.alpha = 1.0f;
-                     [strongSelf.view layoutIfNeeded];
+                     scrimView.alpha = 1.0f;
+                     [superview layoutIfNeeded];
                    }];
 }
 
diff --git a/ios/chrome/browser/bubble/ui_bundled/bubble_presenter.mm b/ios/chrome/browser/bubble/ui_bundled/bubble_presenter.mm
index 17a1062..7e454c1 100644
--- a/ios/chrome/browser/bubble/ui_bundled/bubble_presenter.mm
+++ b/ios/chrome/browser/bubble/ui_bundled/bubble_presenter.mm
@@ -201,9 +201,6 @@
 #pragma mark - Bubble presenter methods
 
 - (void)presentDiscoverFeedMenuTipBubble {
-  BubbleArrowDirection arrowDirection = IsHomeCustomizationEnabled()
-                                            ? BubbleArrowDirectionUp
-                                            : BubbleArrowDirectionDown;
   NSString* text =
       l10n_util::GetNSStringWithFixup(IDS_IOS_DISCOVER_FEED_HEADER_IPH);
 
@@ -219,22 +216,16 @@
       [menuButton.superview convertPoint:menuButton.frame.origin toView:nil];
 
   // Slightly move IPH to ensure that the bubble doesn't bleed out the screen.
-  if (IsHomeCustomizationEnabled()) {
-    discoverFeedMenuAnchor.x += menuButton.frame.size.width / 2;
-    discoverFeedMenuAnchor.y += menuButton.frame.size.height;
-  } else {
-    discoverFeedMenuAnchor.x += menuButton.frame.size.width / 3;
-  }
+  discoverFeedMenuAnchor.x += menuButton.frame.size.width / 2;
+  discoverFeedMenuAnchor.y += menuButton.frame.size.height;
 
   // If the feature engagement tracker does not consider it valid to display
   // the tip, then end early to prevent the potential reassignment of the
   // existing `discoverFeedHeaderMenuTipBubblePresenter` to nil.
   BubbleViewControllerPresenter* presenter = [self
       presentBubbleForFeature:feature_engagement::kIPHDiscoverFeedHeaderFeature
-                    direction:arrowDirection
-                    alignment:IsHomeCustomizationEnabled()
-                                  ? BubbleAlignmentTopOrLeading
-                                  : BubbleAlignmentBottomOrTrailing
+                    direction:BubbleArrowDirectionUp
+                    alignment:BubbleAlignmentTopOrLeading
                          text:text
         voiceOverAnnouncement:text
                   anchorPoint:discoverFeedMenuAnchor];
diff --git a/ios/chrome/browser/content_suggestions/ui_bundled/BUILD.gn b/ios/chrome/browser/content_suggestions/ui_bundled/BUILD.gn
index 5f8dac5..111cc81 100644
--- a/ios/chrome/browser/content_suggestions/ui_bundled/BUILD.gn
+++ b/ios/chrome/browser/content_suggestions/ui_bundled/BUILD.gn
@@ -200,12 +200,6 @@
   sources = [
     "content_suggestions_view_controller.h",
     "content_suggestions_view_controller.mm",
-    "magic_stack_half_sheet_consumer.h",
-    "magic_stack_half_sheet_mediator.h",
-    "magic_stack_half_sheet_mediator.mm",
-    "magic_stack_half_sheet_model_delegate.h",
-    "magic_stack_half_sheet_table_view_controller.h",
-    "magic_stack_half_sheet_table_view_controller.mm",
     "user_account_image_update_delegate.h",
   ]
   deps = [
@@ -338,8 +332,6 @@
     "content_suggestions_collection_utils_unittest.mm",
     "content_suggestions_coordinator_unittest.mm",
     "content_suggestions_mediator_unittest.mm",
-    "magic_stack_half_sheet_mediator_unittest.mm",
-    "magic_stack_half_sheet_table_view_controller_unittest.mm",
   ]
   deps = [
     ":constants",
diff --git a/ios/chrome/browser/content_suggestions/ui_bundled/content_suggestions_collection_utils.mm b/ios/chrome/browser/content_suggestions/ui_bundled/content_suggestions_collection_utils.mm
index 82985501..942972b 100644
--- a/ios/chrome/browser/content_suggestions/ui_bundled/content_suggestions_collection_utils.mm
+++ b/ios/chrome/browser/content_suggestions/ui_bundled/content_suggestions_collection_utils.mm
@@ -262,7 +262,7 @@
 }
 
 CGFloat HeaderBottomPadding(UITraitCollection* trait_collection) {
-  if (IsHomeCustomizationEnabled() && IsSplitToolbarMode(trait_collection)) {
+  if (IsSplitToolbarMode(trait_collection)) {
     return GetDeprecateFeedHeaderParameterValueAsDouble(
         kDeprecateFeedHeaderParameterHeaderBottomPadding, 0);
   }
diff --git a/ios/chrome/browser/content_suggestions/ui_bundled/content_suggestions_collection_utils_unittest.mm b/ios/chrome/browser/content_suggestions/ui_bundled/content_suggestions_collection_utils_unittest.mm
index d3914d7..084d8ec 100644
--- a/ios/chrome/browser/content_suggestions/ui_bundled/content_suggestions_collection_utils_unittest.mm
+++ b/ios/chrome/browser/content_suggestions/ui_bundled/content_suggestions_collection_utils_unittest.mm
@@ -88,8 +88,7 @@
   base::FieldTrialParams large_fakebox_params = {
       {kDeprecateFeedHeaderParameterEnlargeLogoAndFakebox, "true"}};
   scoped_feature_list.InitWithFeaturesAndParameters(
-      /*enabled_features=*/{{kHomeCustomization, {}},
-                            {kDeprecateFeedHeader, large_fakebox_params}},
+      /*enabled_features=*/{{kDeprecateFeedHeader, large_fakebox_params}},
       /*disabled_features=*/{});
   CGFloat heightLargeLogo =
       DoodleHeight(YES, NO, IPhonePortraitTraitCollection());
@@ -125,8 +124,7 @@
   base::FieldTrialParams large_fakebox_params = {
       {kDeprecateFeedHeaderParameterEnlargeLogoAndFakebox, "true"}};
   scoped_feature_list.InitWithFeaturesAndParameters(
-      /*enabled_features=*/{{kHomeCustomization, {}},
-                            {kDeprecateFeedHeader, large_fakebox_params}},
+      /*enabled_features=*/{{kDeprecateFeedHeader, large_fakebox_params}},
       /*disabled_features=*/{});
   CGFloat heightLargeLogo =
       DoodleHeight(YES, NO, IPhonePortraitTraitCollection());
@@ -229,8 +227,7 @@
   base::FieldTrialParams large_fakebox_params = {
       {kDeprecateFeedHeaderParameterEnlargeLogoAndFakebox, "true"}};
   scoped_feature_list.InitWithFeaturesAndParameters(
-      /*enabled_features=*/{{kHomeCustomization, {}},
-                            {kDeprecateFeedHeader, large_fakebox_params}},
+      /*enabled_features=*/{{kDeprecateFeedHeader, large_fakebox_params}},
       /*disabled_features=*/{});
   EXPECT_EQ(65, FakeOmniboxHeight());
 }
@@ -241,8 +238,7 @@
   base::FieldTrialParams large_fakebox_params = {
       {kDeprecateFeedHeaderParameterEnlargeLogoAndFakebox, "true"}};
   scoped_feature_list.InitWithFeaturesAndParameters(
-      /*enabled_features=*/{{kHomeCustomization, {}},
-                            {kDeprecateFeedHeader, large_fakebox_params}},
+      /*enabled_features=*/{{kDeprecateFeedHeader, large_fakebox_params}},
       /*disabled_features=*/{});
   EXPECT_EQ(48, PinnedFakeOmniboxHeight());
 }
@@ -253,8 +249,7 @@
   base::FieldTrialParams large_fakebox_params = {
       {kDeprecateFeedHeaderParameterEnlargeLogoAndFakebox, "true"}};
   scoped_feature_list.InitWithFeaturesAndParameters(
-      /*enabled_features=*/{{kHomeCustomization, {}},
-                            {kDeprecateFeedHeader, large_fakebox_params}},
+      /*enabled_features=*/{{kDeprecateFeedHeader, large_fakebox_params}},
       /*disabled_features=*/{});
   EXPECT_EQ(62, FakeToolbarHeight());
 }
diff --git a/ios/chrome/browser/content_suggestions/ui_bundled/content_suggestions_coordinator.mm b/ios/chrome/browser/content_suggestions/ui_bundled/content_suggestions_coordinator.mm
index 39458790..cfbcfff 100644
--- a/ios/chrome/browser/content_suggestions/ui_bundled/content_suggestions_coordinator.mm
+++ b/ios/chrome/browser/content_suggestions/ui_bundled/content_suggestions_coordinator.mm
@@ -56,8 +56,6 @@
 #import "ios/chrome/browser/content_suggestions/ui_bundled/magic_stack/magic_stack_module_container_delegate.h"
 #import "ios/chrome/browser/content_suggestions/ui_bundled/magic_stack/magic_stack_ranking_model.h"
 #import "ios/chrome/browser/content_suggestions/ui_bundled/magic_stack/magic_stack_utils.h"
-#import "ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_mediator.h"
-#import "ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_table_view_controller.h"
 #import "ios/chrome/browser/content_suggestions/ui_bundled/ntp_home_constant.h"
 #import "ios/chrome/browser/content_suggestions/ui_bundled/price_tracking_promo/price_tracking_promo_action_delegate.h"
 #import "ios/chrome/browser/content_suggestions/ui_bundled/price_tracking_promo/price_tracking_promo_mediator.h"
@@ -199,7 +197,6 @@
     ContentSuggestionsCommands,
     ContentSuggestionsViewControllerAudience,
     MagicStackCollectionViewControllerAudience,
-    MagicStackHalfSheetTableViewControllerDelegate,
     MagicStackModuleContainerDelegate,
     TipsPasswordsCoordinatorDelegate,
     NotificationsOptInAlertCoordinatorDelegate,
@@ -243,11 +240,6 @@
   // The coordinator for displaying tips related to Passwords.
   TipsPasswordsCoordinator* _tipsPasswordsCoordinator;
 
-  // The edit half sheet for toggling all Magic Stack modules.
-  MagicStackHalfSheetTableViewController*
-      _magicStackHalfSheetTableViewController;
-  MagicStackHalfSheetMediator* _magicStackHalfSheetMediator;
-
   // Displays alert giving the user the option to turn notifications
   // on for the app. This is for the third opt in flow where notifications
   // have previously been turned off.
@@ -572,12 +564,6 @@
   self.contentSuggestionsViewController = nil;
   [_defaultBrowserPromoCoordinator stop];
   _defaultBrowserPromoCoordinator = nil;
-  [_magicStackHalfSheetMediator disconnect];
-  _magicStackHalfSheetMediator = nil;
-  [_magicStackHalfSheetTableViewController.presentingViewController
-      dismissViewControllerAnimated:NO
-                         completion:nil];
-  _magicStackHalfSheetTableViewController = nil;
   [_notificationsOptInAlertCoordinator stop];
   _notificationsOptInAlertCoordinator = nil;
   [self.browser->GetCommandDispatcher()
@@ -755,38 +741,7 @@
 
 - (void)didTapMagicStackEditButton {
   base::RecordAction(base::UserMetricsAction("IOSMagicStackSettingsOpened"));
-  if (IsHomeCustomizationEnabled()) {
-    [self.delegate openMagicStackCustomizationMenu];
-  } else {
-    _magicStackHalfSheetTableViewController =
-        [[MagicStackHalfSheetTableViewController alloc] init];
-
-    _magicStackHalfSheetMediator = [[MagicStackHalfSheetMediator alloc]
-        initWithLocalState:GetApplicationContext()->GetLocalState()
-        profilePrefService:self.profile->GetPrefs()];
-    _magicStackHalfSheetMediator.consumer =
-        _magicStackHalfSheetTableViewController;
-    _magicStackHalfSheetTableViewController.delegate = self;
-    _magicStackHalfSheetTableViewController.modelDelegate =
-        _magicStackHalfSheetMediator;
-
-    UINavigationController* navViewController = [[UINavigationController alloc]
-        initWithRootViewController:_magicStackHalfSheetTableViewController];
-
-    navViewController.modalPresentationStyle = UIModalPresentationPageSheet;
-    UISheetPresentationController* presentationController =
-        navViewController.sheetPresentationController;
-    presentationController.prefersEdgeAttachedInCompactHeight = YES;
-    presentationController.widthFollowsPreferredContentSizeWhenEdgeAttached =
-        YES;
-    presentationController.detents = @[
-      [UISheetPresentationControllerDetent mediumDetent],
-      [UISheetPresentationControllerDetent largeDetent]
-    ];
-    [_magicStackCollectionView presentViewController:navViewController
-                                            animated:YES
-                                          completion:nil];
-  }
+  [self.delegate openMagicStackCustomizationMenu];
 }
 
 - (void)logEphemeralCardVisibility:(ContentSuggestionsModuleType)card {
@@ -1071,17 +1026,6 @@
   [self didTapMagicStackEditButton];
 }
 
-#pragma mark - MagicStackHalfSheetTableViewControllerDelegate
-
-- (void)dismissMagicStackHalfSheet {
-  [_magicStackHalfSheetMediator disconnect];
-  _magicStackHalfSheetMediator = nil;
-  [_magicStackHalfSheetTableViewController.presentingViewController
-      dismissViewControllerAnimated:YES
-                         completion:nil];
-  _magicStackHalfSheetTableViewController = nil;
-}
-
 #pragma mark - TipsPasswordsCoordinatorDelegate
 
 - (void)tipsPasswordsCoordinatorDidFinish:
diff --git a/ios/chrome/browser/content_suggestions/ui_bundled/content_suggestions_egtest.mm b/ios/chrome/browser/content_suggestions/ui_bundled/content_suggestions_egtest.mm
index 360902b..3ebc089 100644
--- a/ios/chrome/browser/content_suggestions/ui_bundled/content_suggestions_egtest.mm
+++ b/ios/chrome/browser/content_suggestions/ui_bundled/content_suggestions_egtest.mm
@@ -482,12 +482,6 @@
 // Set Up List, returns to the Magic Stack and ensures Set Up List is not in the
 // Magic Stack anymore.
 - (void)testMagicStackEditButton {
-  // Enable customization.
-  AppLaunchConfiguration config = [self appConfigurationForTestCase];
-  config.relaunch_policy = ForceRelaunchByCleanShutdown;
-  config.features_enabled.push_back(kHomeCustomization);
-  [[AppLaunchManager sharedManager] ensureAppLaunchedWithConfiguration:config];
-
   [self prepareToTestSetUpListInMagicStack];
   TapMagicStackEditButton();
 
diff --git a/ios/chrome/browser/content_suggestions/ui_bundled/content_suggestions_view_controller.mm b/ios/chrome/browser/content_suggestions/ui_bundled/content_suggestions_view_controller.mm
index 54cf5a05..2421c179 100644
--- a/ios/chrome/browser/content_suggestions/ui_bundled/content_suggestions_view_controller.mm
+++ b/ios/chrome/browser/content_suggestions/ui_bundled/content_suggestions_view_controller.mm
@@ -78,10 +78,7 @@
                        constant:content_suggestions::HeaderBottomPadding(
                                     self.traitCollection)],
     [self.verticalStackView.bottomAnchor
-        constraintEqualToAnchor:self.view.bottomAnchor
-                       constant:(IsHomeCustomizationEnabled()
-                                     ? 0
-                                     : -kBottomMagicStackPadding)]
+        constraintEqualToAnchor:self.view.bottomAnchor]
   ]];
 
   if (_mostVisitedTileConfig.mostVisitedItems.count > 0) {
@@ -155,10 +152,6 @@
 - (void)createAndInsertMostVisitedModule {
   [self.verticalStackView insertArrangedSubview:self.mostVisitedModuleContainer
                                         atIndex:0];
-  [self.verticalStackView
-      setCustomSpacing:(IsHomeCustomizationEnabled() ? 0
-                                                     : kMostVisitedBottomMargin)
-             afterView:self.mostVisitedModuleContainer];
   [NSLayoutConstraint activateConstraints:@[
     [self.mostVisitedModuleContainer.widthAnchor
         constraintEqualToAnchor:self.view.widthAnchor],
diff --git a/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack/magic_stack_constants.h b/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack/magic_stack_constants.h
index e98426f..64918b0 100644
--- a/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack/magic_stack_constants.h
+++ b/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack/magic_stack_constants.h
@@ -22,9 +22,6 @@
 extern const CGFloat kMagicStackPeekInset;
 extern const CGFloat kMagicStackPeekInsetLandscape;
 
-// The bottom spacing underneath the Magic Stack.
-extern const float kBottomMagicStackPadding;
-
 // The minimum scroll velocity in order to swipe between modules in the Magic
 // Stack.
 extern const float kMagicStackMinimumPaginationScrollVelocity;
diff --git a/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack/magic_stack_constants.mm b/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack/magic_stack_constants.mm
index c7cc66c..33487f7aa 100644
--- a/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack/magic_stack_constants.mm
+++ b/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack/magic_stack_constants.mm
@@ -16,8 +16,6 @@
 const CGFloat kMagicStackPeekInset = kMagicStackSpacing + 10;
 const CGFloat kMagicStackPeekInsetLandscape = kMagicStackSpacing * 2 + 28;
 
-const float kBottomMagicStackPadding = 14.0f;
-
 const float kMagicStackMinimumPaginationScrollVelocity = 0.2f;
 
 const float kMagicStackEditButtonWidth = 61;
diff --git a/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_consumer.h b/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_consumer.h
deleted file mode 100644
index 483d2234..0000000
--- a/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_consumer.h
+++ /dev/null
@@ -1,38 +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 IOS_CHROME_BROWSER_CONTENT_SUGGESTIONS_UI_BUNDLED_MAGIC_STACK_HALF_SHEET_CONSUMER_H_
-#define IOS_CHROME_BROWSER_CONTENT_SUGGESTIONS_UI_BUNDLED_MAGIC_STACK_HALF_SHEET_CONSUMER_H_
-
-#import <UIKit/UIKit.h>
-
-// Consumer of the MagicStackHalfSheetMediator.
-@protocol MagicStackHalfSheetConsumer
-
-// Indicates to the consumer whether to display the toggle for most visited
-// tiles.
-- (void)showMostVisitedSitesToggle:(BOOL)show;
-
-// Indicates to the consumer that `mostVisitedSitesEnabled`. Should only be
-// invoked when the most visited sites tile is in magic stack.
-- (void)setMostVisitedSitesEnabled:(BOOL)mostVisitedSitesEnabled;
-
-// Indicates to the consumer whether to `showSetUpList`.
-- (void)showSetUpList:(BOOL)showSetUpList;
-
-// Indicates to the consumer that `setUpListDisabled`.
-- (void)setSetUpListDisabled:(BOOL)setUpListDisabled;
-
-// Indicates to the consumer that `safetyCheckDisabled`.
-- (void)setSafetyCheckDisabled:(BOOL)safetyCheckDisabled;
-
-// Indicates to the consumer that `tabResumptionDisabled`.
-- (void)setTabResumptionDisabled:(BOOL)tabResumptionDisabled;
-
-// Indicates to the consumer that `parcelTrackingDisabled`.
-- (void)setParcelTrackingDisabled:(BOOL)parcelTrackingDisabled;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_CONTENT_SUGGESTIONS_UI_BUNDLED_MAGIC_STACK_HALF_SHEET_CONSUMER_H_
diff --git a/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_mediator.h b/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_mediator.h
deleted file mode 100644
index 3368728f..0000000
--- a/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_mediator.h
+++ /dev/null
@@ -1,31 +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 IOS_CHROME_BROWSER_CONTENT_SUGGESTIONS_UI_BUNDLED_MAGIC_STACK_HALF_SHEET_MEDIATOR_H_
-#define IOS_CHROME_BROWSER_CONTENT_SUGGESTIONS_UI_BUNDLED_MAGIC_STACK_HALF_SHEET_MEDIATOR_H_
-
-#import <UIKit/UIKit.h>
-
-#import "ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_model_delegate.h"
-
-@protocol MagicStackHalfSheetConsumer;
-class PrefService;
-
-// Mediator for the Magic Stack Half Sheet.
-@interface MagicStackHalfSheetMediator
-    : NSObject <MagicStackHalfSheetModelDelegate>
-
-// Initializes this class with the appropriate localState and profile prefs.
-- (instancetype)initWithLocalState:(PrefService*)localState
-                profilePrefService:(PrefService*)profilePrefs;
-
-// Disconnects the mediator.
-- (void)disconnect;
-
-// Consumer for this mediator.
-@property(nonatomic, weak) id<MagicStackHalfSheetConsumer> consumer;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_CONTENT_SUGGESTIONS_UI_BUNDLED_MAGIC_STACK_HALF_SHEET_MEDIATOR_H_
diff --git a/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_mediator.mm b/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_mediator.mm
deleted file mode 100644
index 7b0811c..0000000
--- a/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_mediator.mm
+++ /dev/null
@@ -1,165 +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 "ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_mediator.h"
-
-#import "base/memory/raw_ptr.h"
-#import "ios/chrome/browser/content_suggestions/ui_bundled/content_suggestions_constants.h"
-#import "ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_consumer.h"
-#import "ios/chrome/browser/content_suggestions/ui_bundled/safety_check/safety_check_prefs.h"
-#import "ios/chrome/browser/content_suggestions/ui_bundled/set_up_list/utils.h"
-#import "ios/chrome/browser/ntp/model/set_up_list_prefs.h"
-#import "ios/chrome/browser/ntp/shared/metrics/feed_metrics_utils.h"
-#import "ios/chrome/browser/ntp_tiles/model/tab_resumption/tab_resumption_prefs.h"
-#import "ios/chrome/browser/parcel_tracking/features.h"
-#import "ios/chrome/browser/parcel_tracking/parcel_tracking_prefs.h"
-#import "ios/chrome/browser/shared/model/prefs/pref_backed_boolean.h"
-#import "ios/chrome/browser/shared/model/prefs/pref_names.h"
-#import "ios/chrome/browser/shared/model/utils/observable_boolean.h"
-#import "ios/chrome/browser/shared/public/features/features.h"
-
-@interface MagicStackHalfSheetMediator () <BooleanObserver>
-@end
-
-@implementation MagicStackHalfSheetMediator {
-  raw_ptr<PrefService> _localState;
-  raw_ptr<PrefService> _profilePrefs;
-
-  PrefBackedBoolean* _mostVisitedSitesEnabled;
-  PrefBackedBoolean* _setUpListDisabled;
-  PrefBackedBoolean* _safetyCheckDisabled;
-  PrefBackedBoolean* _tabResumptionDisabled;
-  PrefBackedBoolean* _parcelTrackingDisabled;
-}
-
-- (instancetype)initWithLocalState:(PrefService*)localState
-                profilePrefService:(PrefService*)profilePrefs {
-  if ((self = [super init])) {
-    CHECK(localState);
-    CHECK(profilePrefs);
-    _localState = localState;
-    _profilePrefs = profilePrefs;
-    if (ShouldPutMostVisitedSitesInMagicStack(
-            FeedActivityBucketForPrefs(_profilePrefs))) {
-      _mostVisitedSitesEnabled = [[PrefBackedBoolean alloc]
-          initWithPrefService:_profilePrefs
-                     prefName:prefs::kHomeCustomizationMostVisitedEnabled];
-      [_mostVisitedSitesEnabled setObserver:self];
-    }
-    if (set_up_list_utils::IsSetUpListActive(_localState, _profilePrefs,
-                                             false)) {
-      _setUpListDisabled = [[PrefBackedBoolean alloc]
-          initWithPrefService:_localState
-                     prefName:set_up_list_prefs::kDisabled];
-      [_setUpListDisabled setObserver:self];
-    }
-    if (IsSafetyCheckMagicStackEnabled()) {
-      _safetyCheckDisabled = [[PrefBackedBoolean alloc]
-          initWithPrefService:_profilePrefs
-                     prefName:safety_check_prefs::
-                                  kSafetyCheckInMagicStackDisabledPref];
-      [_safetyCheckDisabled setObserver:self];
-    }
-    if (IsTabResumptionEnabled()) {
-      _tabResumptionDisabled = [[PrefBackedBoolean alloc]
-          initWithPrefService:_profilePrefs
-                     prefName:tab_resumption_prefs::kTabResumptionDisabledPref];
-      [_tabResumptionDisabled setObserver:self];
-    }
-    if (IsIOSParcelTrackingEnabled()) {
-      _parcelTrackingDisabled = [[PrefBackedBoolean alloc]
-          initWithPrefService:_localState
-                     prefName:kParcelTrackingDisabled];
-      [_parcelTrackingDisabled setObserver:self];
-    }
-  }
-  return self;
-}
-
-- (void)disconnect {
-  [_mostVisitedSitesEnabled stop];
-  [_mostVisitedSitesEnabled setObserver:nil];
-  _mostVisitedSitesEnabled = nil;
-
-  [_setUpListDisabled stop];
-  [_setUpListDisabled setObserver:nil];
-  _setUpListDisabled = nil;
-
-  [_safetyCheckDisabled stop];
-  [_safetyCheckDisabled setObserver:nil];
-  _safetyCheckDisabled = nil;
-
-  [_tabResumptionDisabled stop];
-  [_tabResumptionDisabled setObserver:nil];
-  _tabResumptionDisabled = nil;
-
-  [_parcelTrackingDisabled stop];
-  [_parcelTrackingDisabled setObserver:nil];
-  _parcelTrackingDisabled = nil;
-
-  _localState = nil;
-  _profilePrefs = nil;
-}
-
-- (void)setConsumer:(id<MagicStackHalfSheetConsumer>)consumer {
-  _consumer = consumer;
-  if (_mostVisitedSitesEnabled) {
-    [self.consumer showMostVisitedSitesToggle:YES];
-    [self.consumer setMostVisitedSitesEnabled:_mostVisitedSitesEnabled.value];
-  }
-  if (_setUpListDisabled) {
-    [self.consumer showSetUpList:YES];
-    [self.consumer setSetUpListDisabled:_setUpListDisabled.value];
-  }
-  if (_safetyCheckDisabled) {
-    [self.consumer setSafetyCheckDisabled:_safetyCheckDisabled.value];
-  }
-  if (_tabResumptionDisabled) {
-    [self.consumer setTabResumptionDisabled:_tabResumptionDisabled.value];
-  }
-  if (_parcelTrackingDisabled) {
-    [self.consumer setParcelTrackingDisabled:_parcelTrackingDisabled.value];
-  }
-}
-
-#pragma mark - Boolean Observer
-
-- (void)booleanDidChange:(id<ObservableBoolean>)observableBoolean {
-  if (observableBoolean == _mostVisitedSitesEnabled) {
-    [self.consumer setMostVisitedSitesEnabled:_mostVisitedSitesEnabled.value];
-  } else if (observableBoolean == _setUpListDisabled) {
-    [self.consumer setSetUpListDisabled:_setUpListDisabled.value];
-  } else if (observableBoolean == _safetyCheckDisabled) {
-    [self.consumer setSafetyCheckDisabled:_safetyCheckDisabled.value];
-  } else if (observableBoolean == _tabResumptionDisabled) {
-    [self.consumer setTabResumptionDisabled:_tabResumptionDisabled.value];
-  } else if (observableBoolean == _parcelTrackingDisabled) {
-    [self.consumer setParcelTrackingDisabled:_parcelTrackingDisabled.value];
-  }
-}
-
-#pragma mark - MagicStackHalfSheetDelegate
-
-- (void)mostVisitedSitesEnabledChanged:(BOOL)mostVisitedSitesEnabled {
-  CHECK(_mostVisitedSitesEnabled);
-  [_mostVisitedSitesEnabled setValue:mostVisitedSitesEnabled];
-}
-
-- (void)setUpListEnabledChanged:(BOOL)setUpListEnabled {
-  [_setUpListDisabled setValue:!setUpListEnabled];
-}
-
-- (void)safetyCheckEnabledChanged:(BOOL)safetyCheckEnabled {
-  [_safetyCheckDisabled setValue:!safetyCheckEnabled];
-}
-
-- (void)tabResumptionEnabledChanged:(BOOL)tabResumptionEnabled {
-  [_tabResumptionDisabled setValue:!tabResumptionEnabled];
-}
-
-- (void)parcelTrackingEnabledChanged:(BOOL)parcelTrackingEnabled {
-  [_parcelTrackingDisabled setValue:!parcelTrackingEnabled];
-}
-
-@end
diff --git a/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_mediator_unittest.mm b/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_mediator_unittest.mm
deleted file mode 100644
index 4292707..0000000
--- a/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_mediator_unittest.mm
+++ /dev/null
@@ -1,137 +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 "ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_mediator.h"
-
-#import "base/files/file.h"
-#import "base/test/scoped_feature_list.h"
-#import "components/prefs/pref_registry_simple.h"
-#import "ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_consumer.h"
-#import "ios/chrome/browser/content_suggestions/ui_bundled/safety_check/safety_check_prefs.h"
-#import "ios/chrome/browser/content_suggestions/ui_bundled/set_up_list/utils.h"
-#import "ios/chrome/browser/default_browser/model/utils_test_support.h"
-#import "ios/chrome/browser/first_run/model/first_run.h"
-#import "ios/chrome/browser/first_run/ui_bundled/first_run_util.h"
-#import "ios/chrome/browser/metrics/model/constants.h"
-#import "ios/chrome/browser/ntp/model/set_up_list_prefs.h"
-#import "ios/chrome/browser/ntp_tiles/model/tab_resumption/tab_resumption_prefs.h"
-#import "ios/chrome/browser/shared/model/application_context/application_context.h"
-#import "ios/chrome/browser/shared/model/prefs/pref_names.h"
-#import "ios/chrome/browser/shared/public/features/features.h"
-#import "ios/chrome/test/ios_chrome_scoped_testing_local_state.h"
-#import "ios/web/public/test/web_task_environment.h"
-#import "testing/platform_test.h"
-#import "third_party/ocmock/OCMock/OCMock.h"
-#import "third_party/ocmock/gtest_support.h"
-
-using startup_metric_utils::FirstRunSentinelCreationResult;
-
-// Tests the MagicStackHalfSheetMediator functionality.
-class MagicStackHalfSheetMediatorTest : public PlatformTest {
- public:
-  void SetUp() override {
-    scoped_feature_list_.InitWithFeatures({kTabResumption, kNewFeedPositioning},
-                                          {});
-    pref_service_ = std::make_unique<TestingPrefServiceSimple>();
-
-    // Necessary set up for kIOSSetUpList.
-    local_state()->ClearPref(set_up_list_prefs::kDisabled);
-    ClearDefaultBrowserPromoData();
-    pref_service_->registry()->RegisterIntegerPref(kActivityBucketKey, 3);
-    pref_service_->registry()->RegisterBooleanPref(
-        prefs::kHomeCustomizationMostVisitedEnabled, true);
-    pref_service_->registry()->RegisterBooleanPref(
-        safety_check_prefs::kSafetyCheckInMagicStackDisabledPref, false);
-    pref_service_->registry()->RegisterBooleanPref(
-        tab_resumption_prefs::kTabResumptionDisabledPref, false);
-    pref_service_->registry()->RegisterBooleanPref(
-        prefs::kHomeCustomizationMagicStackSetUpListEnabled, true);
-
-    consumer_ = OCMStrictProtocolMock(@protocol(MagicStackHalfSheetConsumer));
-  }
-
-  PrefService* local_state() {
-    return GetApplicationContext()->GetLocalState();
-  }
-
-  PrefService* profile_prefs() { return pref_service_.get(); }
-
- protected:
-  // Clears and re-writes the FirstRun sentinel file, in order to allow Set Up
-  // List to display.
-  void WriteFirstRunSentinel() {
-    base::ScopedAllowBlockingForTesting allow_blocking;
-    FirstRun::RemoveSentinel();
-    base::File::Error file_error = base::File::FILE_OK;
-    FirstRunSentinelCreationResult sentinel_created =
-        FirstRun::CreateSentinel(&file_error);
-    ASSERT_EQ(sentinel_created, FirstRunSentinelCreationResult::kSuccess)
-        << "Error creating FirstRun sentinel: "
-        << base::File::ErrorToString(file_error);
-    FirstRun::LoadSentinelInfo();
-    FirstRun::ClearStateForTesting();
-    EXPECT_FALSE(set_up_list_prefs::IsSetUpListDisabled(profile_prefs()));
-    EXPECT_FALSE(FirstRun::IsChromeFirstRun());
-    EXPECT_TRUE(
-        set_up_list_utils::IsSetUpListActive(local_state(), profile_prefs()));
-  }
-
-  web::WebTaskEnvironment task_environment_;
-  base::test::ScopedFeatureList scoped_feature_list_;
-  IOSChromeScopedTestingLocalState scoped_testing_local_state_;
-  std::unique_ptr<TestingPrefServiceSimple> pref_service_;
-  MagicStackHalfSheetMediator* mediator_;
-  id consumer_;
-};
-
-// Tests that the mediator makes the proper consumer calls.
-TEST_F(MagicStackHalfSheetMediatorTest, TestConsumer) {
-  // Removes the First Run Sentinel in case it is set.
-  if (FirstRun::RemoveSentinel()) {
-    FirstRun::LoadSentinelInfo();
-    FirstRun::ClearStateForTesting();
-    FirstRun::IsChromeFirstRun();
-  }
-
-  // Set Up List should not be shown.
-  mediator_ =
-      [[MagicStackHalfSheetMediator alloc] initWithLocalState:local_state()
-                                           profilePrefService:profile_prefs()];
-  OCMExpect([consumer_ showMostVisitedSitesToggle:YES]);
-  OCMExpect([consumer_ setMostVisitedSitesEnabled:YES]);
-  OCMExpect([consumer_ setSafetyCheckDisabled:NO]);
-  OCMExpect([consumer_ setTabResumptionDisabled:NO]);
-
-  mediator_.consumer = consumer_;
-  EXPECT_OCMOCK_VERIFY(consumer_);
-
-  WriteFirstRunSentinel();
-  mediator_ =
-      [[MagicStackHalfSheetMediator alloc] initWithLocalState:local_state()
-                                           profilePrefService:profile_prefs()];
-
-  OCMExpect([consumer_ showSetUpList:YES]);
-  OCMExpect([consumer_ setSetUpListDisabled:NO]);
-  OCMExpect([consumer_ showMostVisitedSitesToggle:YES]);
-  OCMExpect([consumer_ setMostVisitedSitesEnabled:YES]);
-  OCMExpect([consumer_ setSafetyCheckDisabled:NO]);
-  OCMExpect([consumer_ setTabResumptionDisabled:NO]);
-
-  mediator_.consumer = consumer_;
-  EXPECT_OCMOCK_VERIFY(consumer_);
-
-  mediator_ =
-      [[MagicStackHalfSheetMediator alloc] initWithLocalState:local_state()
-                                           profilePrefService:profile_prefs()];
-
-  OCMExpect([consumer_ showSetUpList:YES]);
-  OCMExpect([consumer_ setSetUpListDisabled:NO]);
-  OCMExpect([consumer_ showMostVisitedSitesToggle:YES]);
-  OCMExpect([consumer_ setMostVisitedSitesEnabled:YES]);
-  OCMExpect([consumer_ setSafetyCheckDisabled:NO]);
-  OCMExpect([consumer_ setTabResumptionDisabled:NO]);
-
-  mediator_.consumer = consumer_;
-  EXPECT_OCMOCK_VERIFY(consumer_);
-}
diff --git a/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_model_delegate.h b/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_model_delegate.h
deleted file mode 100644
index a310fe8b..0000000
--- a/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_model_delegate.h
+++ /dev/null
@@ -1,32 +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 IOS_CHROME_BROWSER_CONTENT_SUGGESTIONS_UI_BUNDLED_MAGIC_STACK_HALF_SHEET_MODEL_DELEGATE_H_
-#define IOS_CHROME_BROWSER_CONTENT_SUGGESTIONS_UI_BUNDLED_MAGIC_STACK_HALF_SHEET_MODEL_DELEGATE_H_
-
-#import <UIKit/UIKit.h>
-
-// Model delegate for the Magic Stack Half Sheet.
-@protocol MagicStackHalfSheetModelDelegate
-
-// Indicate to the model delegate that the combined most visited sites tile
-// enabled state changed.
-- (void)mostVisitedSitesEnabledChanged:(BOOL)mostVisitedSitesEnabled;
-
-// Indicate to the model delegate that the Set Up List enabled state changed.
-- (void)setUpListEnabledChanged:(BOOL)setUpListEnabled;
-
-// Indicate to the model delegate that the Safety Check enabled state changed.
-- (void)safetyCheckEnabledChanged:(BOOL)safetyCheckEnabled;
-
-// Indicate to the model delegate that the Tab Resumption enabled state changed.
-- (void)tabResumptionEnabledChanged:(BOOL)tabResumptionEnabled;
-
-// Indicates to the model delegate that the Parcel Tracking enabled state
-// changed.
-- (void)parcelTrackingEnabledChanged:(BOOL)parcelTrackingEnabled;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_CONTENT_SUGGESTIONS_UI_BUNDLED_MAGIC_STACK_HALF_SHEET_MODEL_DELEGATE_H_
diff --git a/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_table_view_controller.h b/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_table_view_controller.h
deleted file mode 100644
index 8528c28b..0000000
--- a/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_table_view_controller.h
+++ /dev/null
@@ -1,38 +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 IOS_CHROME_BROWSER_CONTENT_SUGGESTIONS_UI_BUNDLED_MAGIC_STACK_HALF_SHEET_TABLE_VIEW_CONTROLLER_H_
-#define IOS_CHROME_BROWSER_CONTENT_SUGGESTIONS_UI_BUNDLED_MAGIC_STACK_HALF_SHEET_TABLE_VIEW_CONTROLLER_H_
-
-#import "ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_consumer.h"
-#import "ios/chrome/browser/shared/ui/table_view/legacy_chrome_table_view_controller.h"
-
-@protocol MagicStackHalfSheetModelDelegate;
-class PrefService;
-
-// Delegate for MagicStackHalfSheetTableViewController actions.
-@protocol MagicStackHalfSheetTableViewControllerDelegate
-
-// Indicates that the half sheet should be dismissed.
-- (void)dismissMagicStackHalfSheet;
-
-@end
-
-// Presents a module disable customization page for the Magic Stack.
-@interface MagicStackHalfSheetTableViewController
-    : LegacyChromeTableViewController <MagicStackHalfSheetConsumer>
-
-// Initializer for this class.
-- (instancetype)init;
-
-// Delegate for this ViewController.
-@property(nonatomic, weak) id<MagicStackHalfSheetTableViewControllerDelegate>
-    delegate;
-
-// Model delegate for this ViewController.
-@property(nonatomic, weak) id<MagicStackHalfSheetModelDelegate> modelDelegate;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_CONTENT_SUGGESTIONS_UI_BUNDLED_MAGIC_STACK_HALF_SHEET_TABLE_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_table_view_controller.mm b/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_table_view_controller.mm
deleted file mode 100644
index ee49ba8..0000000
--- a/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_table_view_controller.mm
+++ /dev/null
@@ -1,275 +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 "ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_table_view_controller.h"
-
-#import "base/apple/foundation_util.h"
-#import "ios/chrome/browser/content_suggestions/ui_bundled/content_suggestions_collection_utils.h"
-#import "ios/chrome/browser/content_suggestions/ui_bundled/content_suggestions_constants.h"
-#import "ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_model_delegate.h"
-#import "ios/chrome/browser/parcel_tracking/features.h"
-#import "ios/chrome/browser/shared/public/features/features.h"
-#import "ios/chrome/browser/shared/ui/symbols/symbols.h"
-#import "ios/chrome/browser/shared/ui/table_view/cells/table_view_switch_cell.h"
-#import "ios/chrome/browser/shared/ui/table_view/cells/table_view_switch_item.h"
-#import "ios/chrome/browser/shared/ui/table_view/table_view_utils.h"
-#import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h"
-#import "ios/chrome/common/ui/colors/semantic_color_names.h"
-#import "ios/chrome/common/ui/util/constraints_ui_util.h"
-#import "ios/chrome/grit/ios_branded_strings.h"
-#import "ios/chrome/grit/ios_strings.h"
-#import "ui/base/l10n/l10n_util_mac.h"
-
-namespace {
-
-// The point size of the icons.
-const CGFloat kIconPointSize = 18;
-
-enum SectionIdentifier : NSInteger {
-  SectionIdentifierOptions = kSectionIdentifierEnumZero,
-};
-
-enum ItemType : NSInteger {
-  ItemTypeToggleSetUpList = kItemTypeEnumZero,
-  ItemTypeToggleSafetyCheck,
-  ItemTypeToggleTabResumption,
-  ItemTypeToggleParcelTracking,
-  ItemTypeToggleMostVisitedSites,
-};
-
-}  // namespace
-
-@interface MagicStackHalfSheetTableViewController ()
-@end
-
-@implementation MagicStackHalfSheetTableViewController {
-  BOOL _showMostVisitedSitesToggle;
-  BOOL _mostVisitedSitesEnabled;
-  BOOL _showSetUpList;
-  BOOL _setUpListDisabled;
-  BOOL _safetyCheckDisabled;
-  BOOL _tabResumptionDisabled;
-  BOOL _parcelTrackingDisabled;
-
-  TableViewSwitchItem* _mostVisitedSitesTileToggle;
-  TableViewSwitchItem* _setUpListToggle;
-  TableViewSwitchItem* _safetyCheckToggle;
-  TableViewSwitchItem* _tabResumptionToggle;
-  TableViewSwitchItem* _parcelTrackingToggle;
-}
-
-- (instancetype)init {
-  UITableViewStyle style = ChromeTableViewStyle();
-  return [super initWithStyle:style];
-}
-
-- (void)viewDidLoad {
-  [super viewDidLoad];
-  self.title = l10n_util::GetNSString(IDS_IOS_MAGIC_STACK_EDIT_MODAL_TITLE);
-  UIBarButtonItem* dismissButton = [[UIBarButtonItem alloc]
-      initWithBarButtonSystemItem:UIBarButtonSystemItemDone
-                           target:self.delegate
-                           action:@selector(dismissMagicStackHalfSheet)];
-  dismissButton.accessibilityIdentifier =
-      kMagicStackEditHalfSheetDoneButtonAccessibilityIdentifier;
-  self.navigationItem.rightBarButtonItem = dismissButton;
-
-  [self loadModel];
-}
-
-#pragma mark - MagicStackHalfSheetConsumer
-
-- (void)showMostVisitedSitesToggle:(BOOL)show {
-  _showMostVisitedSitesToggle = show;
-}
-
-- (void)setMostVisitedSitesEnabled:(BOOL)mostVisitedSitesEnabled {
-  DCHECK(_showMostVisitedSitesToggle);
-  if (_mostVisitedSitesEnabled == mostVisitedSitesEnabled) {
-    return;
-  }
-  _mostVisitedSitesEnabled = mostVisitedSitesEnabled;
-  _mostVisitedSitesTileToggle.on = _mostVisitedSitesEnabled;
-}
-
-- (void)showSetUpList:(BOOL)showSetUpList {
-  _showSetUpList = showSetUpList;
-}
-
-- (void)setSetUpListDisabled:(BOOL)setUpListDisabled {
-  if (_setUpListDisabled == setUpListDisabled) {
-    return;
-  }
-  _setUpListDisabled = setUpListDisabled;
-  _setUpListToggle.on = !_setUpListDisabled;
-}
-
-- (void)setSafetyCheckDisabled:(BOOL)safetyCheckDisabled {
-  if (_safetyCheckDisabled == safetyCheckDisabled) {
-    return;
-  }
-  _safetyCheckDisabled = safetyCheckDisabled;
-  _safetyCheckToggle.on = !_safetyCheckDisabled;
-}
-
-- (void)setTabResumptionDisabled:(BOOL)tabResumptionDisabled {
-  if (_tabResumptionDisabled == tabResumptionDisabled) {
-    return;
-  }
-  _tabResumptionDisabled = tabResumptionDisabled;
-  _tabResumptionToggle.on = !_tabResumptionDisabled;
-}
-
-- (void)setParcelTrackingDisabled:(BOOL)parcelTrackingDisabled {
-  if (_parcelTrackingDisabled == parcelTrackingDisabled) {
-    return;
-  }
-  _parcelTrackingDisabled = parcelTrackingDisabled;
-  _parcelTrackingToggle.on = !_parcelTrackingDisabled;
-}
-
-#pragma mark - LegacyChromeTableViewController
-
-- (void)loadModel {
-  [super loadModel];
-
-  [self.tableViewModel addSectionWithIdentifier:SectionIdentifierOptions];
-
-  if (_showMostVisitedSitesToggle) {
-    NSString* listSymbolName = kHistorySymbol;
-    NSString* title = l10n_util::GetNSString(
-        IDS_IOS_CONTENT_SUGGESTIONS_MOST_VISITED_MODULE_TITLE);
-    _mostVisitedSitesTileToggle =
-        [self switchItemWithType:ItemTypeToggleMostVisitedSites
-                           title:title
-                          symbol:DefaultSymbolWithPointSize(listSymbolName,
-                                                            kIconPointSize)];
-    _mostVisitedSitesTileToggle.on = _mostVisitedSitesEnabled;
-    [self.tableViewModel addItem:_mostVisitedSitesTileToggle
-         toSectionWithIdentifier:SectionIdentifierOptions];
-  }
-  if (_showSetUpList) {
-    NSString* listSymbolName = kListBulletClipboardSymbol;
-    _setUpListToggle =
-        [self switchItemWithType:ItemTypeToggleSetUpList
-                           title:content_suggestions::SetUpListTitleString()
-                          symbol:DefaultSymbolWithPointSize(listSymbolName,
-                                                            kIconPointSize)];
-    _setUpListToggle.on = !_setUpListDisabled;
-    [self.tableViewModel addItem:_setUpListToggle
-         toSectionWithIdentifier:SectionIdentifierOptions];
-  }
-  if (IsSafetyCheckMagicStackEnabled()) {
-    _safetyCheckToggle = [self
-        switchItemWithType:ItemTypeToggleSafetyCheck
-                     title:l10n_util::GetNSString(IDS_IOS_SAFETY_CHECK_TITLE)
-                    symbol:DefaultSymbolWithPointSize(kCheckmarkShieldSymbol,
-                                                      kIconPointSize)];
-    _safetyCheckToggle.on = !_safetyCheckDisabled;
-    [self.tableViewModel addItem:_safetyCheckToggle
-         toSectionWithIdentifier:SectionIdentifierOptions];
-  }
-  if (IsTabResumptionEnabled()) {
-    NSString* listSymbolName = kMacbookAndIPhoneSymbol;
-    _tabResumptionToggle = [self
-        switchItemWithType:ItemTypeToggleTabResumption
-                     title:l10n_util::GetNSString(IDS_IOS_TAB_RESUMPTION_TITLE)
-                    symbol:DefaultSymbolWithPointSize(listSymbolName,
-                                                      kIconPointSize)];
-    _tabResumptionToggle.on = !_tabResumptionDisabled;
-    [self.tableViewModel addItem:_tabResumptionToggle
-         toSectionWithIdentifier:SectionIdentifierOptions];
-  }
-  if (IsIOSParcelTrackingEnabled()) {
-    _parcelTrackingToggle = [self
-        switchItemWithType:ItemTypeToggleParcelTracking
-                     title:
-                         l10n_util::GetNSString(
-                             IDS_IOS_CONTENT_SUGGESTIONS_PARCEL_TRACKING_MODULE_TITLE)
-                    symbol:DefaultSymbolWithPointSize(kShippingBoxSymbol,
-                                                      kIconPointSize)];
-    _parcelTrackingToggle.on = !_parcelTrackingDisabled;
-    [self.tableViewModel addItem:_parcelTrackingToggle
-         toSectionWithIdentifier:SectionIdentifierOptions];
-  }
-}
-
-#pragma mark - UITableViewDataSource
-
-- (UITableViewCell*)tableView:(UITableView*)tableView
-        cellForRowAtIndexPath:(NSIndexPath*)indexPath {
-  UITableViewCell* cell = [super tableView:tableView
-                     cellForRowAtIndexPath:indexPath];
-
-  ItemType itemType = static_cast<ItemType>(
-      [self.tableViewModel itemTypeForIndexPath:indexPath]);
-
-  TableViewSwitchCell* switchCell =
-      base::apple::ObjCCastStrict<TableViewSwitchCell>(cell);
-  switch (itemType) {
-    case ItemTypeToggleMostVisitedSites:
-      [switchCell.switchView
-                 addTarget:self
-                    action:@selector(mostVisitedSitesEnabledChanged:)
-          forControlEvents:UIControlEventValueChanged];
-      break;
-    case ItemTypeToggleSetUpList:
-      [switchCell.switchView addTarget:self
-                                action:@selector(setUpListEnabledChanged:)
-                      forControlEvents:UIControlEventValueChanged];
-      break;
-    case ItemTypeToggleSafetyCheck:
-      [switchCell.switchView addTarget:self
-                                action:@selector(safetyCheckEnabledChanged:)
-                      forControlEvents:UIControlEventValueChanged];
-      break;
-    case ItemTypeToggleTabResumption:
-      [switchCell.switchView addTarget:self
-                                action:@selector(tabResumptionEnabledChanged:)
-                      forControlEvents:UIControlEventValueChanged];
-      break;
-    case ItemTypeToggleParcelTracking:
-      [switchCell.switchView addTarget:self
-                                action:@selector(parcelTrackingEnabledChanged:)
-                      forControlEvents:UIControlEventValueChanged];
-      break;
-  }
-  return cell;
-}
-
-#pragma mark - Private
-
-- (TableViewSwitchItem*)switchItemWithType:(NSInteger)type
-                                     title:(NSString*)title
-                                    symbol:(UIImage*)symbol {
-  TableViewSwitchItem* switchItem =
-      [[TableViewSwitchItem alloc] initWithType:type];
-  switchItem.text = title;
-  switchItem.iconImage = symbol;
-  switchItem.iconTintColor = [UIColor colorNamed:kSolidBlackColor];
-  switchItem.accessibilityIdentifier = title;
-  return switchItem;
-}
-
-- (void)mostVisitedSitesEnabledChanged:(UISwitch*)switchView {
-  [self.modelDelegate mostVisitedSitesEnabledChanged:switchView.isOn];
-}
-
-- (void)setUpListEnabledChanged:(UISwitch*)switchView {
-  [self.modelDelegate setUpListEnabledChanged:switchView.isOn];
-}
-
-- (void)safetyCheckEnabledChanged:(UISwitch*)switchView {
-  [self.modelDelegate safetyCheckEnabledChanged:switchView.isOn];
-}
-
-- (void)tabResumptionEnabledChanged:(UISwitch*)switchView {
-  [self.modelDelegate tabResumptionEnabledChanged:switchView.isOn];
-}
-
-- (void)parcelTrackingEnabledChanged:(UISwitch*)switchView {
-  [self.modelDelegate parcelTrackingEnabledChanged:switchView.isOn];
-}
-
-@end
diff --git a/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_table_view_controller_unittest.mm b/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_table_view_controller_unittest.mm
deleted file mode 100644
index 4d4e0d2..0000000
--- a/ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_table_view_controller_unittest.mm
+++ /dev/null
@@ -1,56 +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 "ios/chrome/browser/content_suggestions/ui_bundled/magic_stack_half_sheet_table_view_controller.h"
-
-#import "base/test/scoped_feature_list.h"
-#import "ios/chrome/browser/shared/public/features/features.h"
-#import "ios/chrome/browser/shared/ui/table_view/cells/table_view_switch_item.h"
-#import "ios/chrome/browser/shared/ui/table_view/table_view_utils.h"
-#import "ios/chrome/test/ios_chrome_scoped_testing_local_state.h"
-#import "ios/web/public/test/web_task_environment.h"
-#import "testing/platform_test.h"
-#import "ui/base/l10n/l10n_util_mac.h"
-
-// Tests the MagicStackHalfSheetTableViewController's core functionality.
-class MagicStackHalfSheetTableViewControllerUnittest : public PlatformTest {
- public:
-  void SetUp() override {
-    scoped_feature_list_.InitWithFeatures({kTabResumption}, {});
-
-    view_controller_ = [[MagicStackHalfSheetTableViewController alloc] init];
-  }
-
- protected:
-  web::WebTaskEnvironment task_environment_;
-  base::test::ScopedFeatureList scoped_feature_list_;
-  IOSChromeScopedTestingLocalState scoped_testing_local_state_;
-  MagicStackHalfSheetTableViewController* view_controller_;
-};
-
-// Tests that all of the module disable settings are configured correctly on
-// initial load.
-TEST_F(MagicStackHalfSheetTableViewControllerUnittest, TestLoadModel) {
-  [view_controller_ showSetUpList:YES];
-  [view_controller_ setSetUpListDisabled:NO];
-  [view_controller_ setSafetyCheckDisabled:NO];
-  [view_controller_ setTabResumptionDisabled:NO];
-
-  [view_controller_ loadViewIfNeeded];
-
-  TableViewModel* model = view_controller_.tableViewModel;
-  ASSERT_TRUE([model numberOfItemsInSection:0] == 3);
-
-  TableViewSwitchItem* setUpListItem = static_cast<TableViewSwitchItem*>(
-      [model itemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]]);
-  EXPECT_TRUE(setUpListItem.on);
-
-  TableViewSwitchItem* safetyCheckItem = static_cast<TableViewSwitchItem*>(
-      [model itemAtIndexPath:[NSIndexPath indexPathForItem:1 inSection:0]]);
-  EXPECT_TRUE(safetyCheckItem.on);
-
-  TableViewSwitchItem* tabResumptionItem = static_cast<TableViewSwitchItem*>(
-      [model itemAtIndexPath:[NSIndexPath indexPathForItem:2 inSection:0]]);
-  EXPECT_TRUE(tabResumptionItem.on);
-}
diff --git a/ios/chrome/browser/content_suggestions/ui_bundled/new_tab_page_app_interface.mm b/ios/chrome/browser/content_suggestions/ui_bundled/new_tab_page_app_interface.mm
index a55edf4a..566e3a9c 100644
--- a/ios/chrome/browser/content_suggestions/ui_bundled/new_tab_page_app_interface.mm
+++ b/ios/chrome/browser/content_suggestions/ui_bundled/new_tab_page_app_interface.mm
@@ -18,7 +18,6 @@
 #import "ios/chrome/browser/shared/model/application_context/application_context.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/public/features/features.h"
 #import "ios/chrome/browser/shared/public/features/system_flags.h"
 #import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h"
 #import "ios/chrome/test/app/chrome_test_util.h"
@@ -57,23 +56,15 @@
 }
 
 + (void)disableSetUpList {
-  PrefService* prefService =
-      IsHomeCustomizationEnabled()
-          ? chrome_test_util::GetOriginalProfile()->GetPrefs()
-          : GetApplicationContext()->GetLocalState();
-  set_up_list_prefs::DisableSetUpList(prefService);
+  set_up_list_prefs::DisableSetUpList(
+      chrome_test_util::GetOriginalProfile()->GetPrefs());
 }
 
 + (void)resetSetUpListPrefs {
   PrefService* localState = GetApplicationContext()->GetLocalState();
-  if (IsHomeCustomizationEnabled()) {
-    PrefService* prefService =
-        chrome_test_util::GetOriginalProfile()->GetPrefs();
-    prefService->SetBoolean(prefs::kHomeCustomizationMagicStackSetUpListEnabled,
-                            true);
-  } else {
-    localState->ClearPref(set_up_list_prefs::kDisabled);
-  }
+  PrefService* prefService = chrome_test_util::GetOriginalProfile()->GetPrefs();
+  prefService->SetBoolean(prefs::kHomeCustomizationMagicStackSetUpListEnabled,
+                          true);
   SetUpListItemState unknown = SetUpListItemState::kUnknown;
   set_up_list_prefs::SetItemState(localState, SetUpListItemType::kSignInSync,
                                   unknown);
diff --git a/ios/chrome/browser/content_suggestions/ui_bundled/ntp_home_egtest.mm b/ios/chrome/browser/content_suggestions/ui_bundled/ntp_home_egtest.mm
index 774153f..d0b48a929 100644
--- a/ios/chrome/browser/content_suggestions/ui_bundled/ntp_home_egtest.mm
+++ b/ios/chrome/browser/content_suggestions/ui_bundled/ntp_home_egtest.mm
@@ -227,8 +227,6 @@
     [NTPHomeTestCase setUpHelper];
   }
   [ChromeEarlGrey setBoolValue:YES forUserPref:prefs::kArticlesForYouEnabled];
-  [ChromeEarlGrey setBoolValue:YES
-                   forUserPref:feed::prefs::kArticlesListVisible];
 
   self.defaultSearchEngine = [SearchEnginesAppInterface defaultSearchEngine];
   [NewTabPageAppInterface disableSetUpList];
@@ -1415,12 +1413,6 @@
 // Tests the "new search" menu item from the new tab menu after disabling the
 // feed.
 - (void)testNewSearchFromNewTabMenuAfterTogglingFeed {
-  // Enable customization.
-  AppLaunchConfiguration config = [self appConfigurationForTestCase];
-  config.relaunch_policy = ForceRelaunchByCleanShutdown;
-  config.features_enabled.push_back(kHomeCustomization);
-  [[AppLaunchManager sharedManager] ensureAppLaunchedWithConfiguration:config];
-
   if ([ChromeEarlGrey isIPadIdiom]) {
     EARL_GREY_TEST_SKIPPED(@"New Search is only available in phone layout.");
   }
@@ -1617,11 +1609,9 @@
 // Tests that the customization menu can be used to toggle the visibility of
 // Home surface modules.
 - (void)testToggleModuleVisiblityInCustomizationMenu {
-  // Enable customization.
+  // Tests most visited tiles visibility separately.
   AppLaunchConfiguration config = [self appConfigurationForTestCase];
   config.relaunch_policy = ForceRelaunchByCleanShutdown;
-  config.features_enabled.push_back(kHomeCustomization);
-  // Tests most visited tiles visibility separately.
   config.features_disabled.push_back(kNewFeedPositioning);
   [[AppLaunchManager sharedManager] ensureAppLaunchedWithConfiguration:config];
 
@@ -1731,11 +1721,9 @@
 // Tests that the toggles in the main page of the customization menu can be used
 // to navigate to their respective submenus.
 - (void)testNavigateInCustomizationMenu {
-  // Enable customization.
+  // Tests most visited tiles visibility separately.
   AppLaunchConfiguration config = [self appConfigurationForTestCase];
   config.relaunch_policy = ForceRelaunchByCleanShutdown;
-  config.features_enabled.push_back(kHomeCustomization);
-  // Tests most visited tiles visibility separately.
   config.features_disabled.push_back(kNewFeedPositioning);
   [[AppLaunchManager sharedManager] ensureAppLaunchedWithConfiguration:config];
 
@@ -1790,12 +1778,6 @@
 
 // Tests the Discover submenu of the Home customization menu.
 - (void)testCustomizationDiscoverSubmenu {
-  // Enable customization.
-  AppLaunchConfiguration config = [self appConfigurationForTestCase];
-  config.relaunch_policy = ForceRelaunchByCleanShutdown;
-  config.features_enabled.push_back(kHomeCustomization);
-  [[AppLaunchManager sharedManager] ensureAppLaunchedWithConfiguration:config];
-
   [self resetCustomizationPrefs];
 
   // Open the Home customization menu.
@@ -1957,31 +1939,6 @@
       performAction:grey_scrollToContentEdge(kGREYContentEdgeTop)];
 }
 
-- (void)hideFeedFromNTPMenu {
-  bool feed_visible =
-      [ChromeEarlGrey userBooleanPref:feed::prefs::kArticlesListVisible];
-  GREYAssertTrue(feed_visible, @"Expect feed to be visible!");
-
-  // The feed header button may be offscreen, so scroll to find it if needed.
-  id<GREYMatcher> headerButton =
-      grey_allOf(grey_accessibilityID(kNTPFeedHeaderManagementButtonIdentifier),
-                 grey_sufficientlyVisible(), nil);
-  [[[EarlGrey selectElementWithMatcher:headerButton]
-         usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, 100.0f)
-      onElementWithMatcher:chrome_test_util::NTPCollectionView()]
-      performAction:grey_tap()];
-
-  [[EarlGrey
-      selectElementWithMatcher:chrome_test_util::NTPFeedMenuDisableButton()]
-      performAction:grey_tap()];
-  // This ensures that the app is given time to update the pref before checking
-  // its state.
-  [ChromeEarlGreyUI waitForAppToIdle];
-  feed_visible =
-      [ChromeEarlGrey userBooleanPref:feed::prefs::kArticlesListVisible];
-  GREYAssertFalse(feed_visible, @"Expect feed to be hidden!");
-}
-
 // Resets the preferences related to Home customization.
 - (void)resetCustomizationPrefs {
   [ChromeEarlGrey setBoolValue:YES
diff --git a/ios/chrome/browser/content_suggestions/ui_bundled/safety_check/safety_check_magic_stack_mediator.mm b/ios/chrome/browser/content_suggestions/ui_bundled/safety_check/safety_check_magic_stack_mediator.mm
index 9881dbb3..a69eceb 100644
--- a/ios/chrome/browser/content_suggestions/ui_bundled/safety_check/safety_check_magic_stack_mediator.mm
+++ b/ios/chrome/browser/content_suggestions/ui_bundled/safety_check/safety_check_magic_stack_mediator.mm
@@ -137,11 +137,9 @@
           safety_check_prefs::kSafetyCheckInMagicStackDisabledPref,
           &_userPrefChangeRegistrar);
 
-      if (IsHomeCustomizationEnabled()) {
-        _prefObserverBridge->ObserveChangesForPreference(
-            prefs::kHomeCustomizationMagicStackSafetyCheckEnabled,
-            &_userPrefChangeRegistrar);
-      }
+      _prefObserverBridge->ObserveChangesForPreference(
+          prefs::kHomeCustomizationMagicStackSafetyCheckEnabled,
+          &_userPrefChangeRegistrar);
 
       _safetyCheckState = [self initialSafetyCheckState];
 
@@ -369,7 +367,6 @@
                  prefs::kHomeCustomizationMagicStackSafetyCheckEnabled &&
              !_userState->GetBoolean(
                  prefs::kHomeCustomizationMagicStackSafetyCheckEnabled)) {
-    CHECK(IsHomeCustomizationEnabled());
     [self.delegate removeSafetyCheckModule];
   }
 }
diff --git a/ios/chrome/browser/content_suggestions/ui_bundled/safety_check/safety_check_prefs.mm b/ios/chrome/browser/content_suggestions/ui_bundled/safety_check/safety_check_prefs.mm
index 83b9abf..7ab61f88 100644
--- a/ios/chrome/browser/content_suggestions/ui_bundled/safety_check/safety_check_prefs.mm
+++ b/ios/chrome/browser/content_suggestions/ui_bundled/safety_check/safety_check_prefs.mm
@@ -19,21 +19,13 @@
 }
 
 bool IsSafetyCheckInMagicStackDisabled(PrefService* prefs) {
-  if (IsHomeCustomizationEnabled()) {
-    return !prefs->GetBoolean(
-        prefs::kHomeCustomizationMagicStackSafetyCheckEnabled);
-  } else {
-    return prefs->GetBoolean(kSafetyCheckInMagicStackDisabledPref);
-  }
+  return !prefs->GetBoolean(
+      prefs::kHomeCustomizationMagicStackSafetyCheckEnabled);
 }
 
 void DisableSafetyCheckInMagicStack(PrefService* prefs) {
-  if (IsHomeCustomizationEnabled()) {
-    prefs->SetBoolean(prefs::kHomeCustomizationMagicStackSafetyCheckEnabled,
-                      false);
-  } else {
-    prefs->SetBoolean(kSafetyCheckInMagicStackDisabledPref, true);
-  }
+  prefs->SetBoolean(prefs::kHomeCustomizationMagicStackSafetyCheckEnabled,
+                    false);
 }
 
 }  // namespace safety_check_prefs
diff --git a/ios/chrome/browser/content_suggestions/ui_bundled/safety_check/safety_check_view_egtest.mm b/ios/chrome/browser/content_suggestions/ui_bundled/safety_check/safety_check_view_egtest.mm
index b9c2223..9ebcc38 100644
--- a/ios/chrome/browser/content_suggestions/ui_bundled/safety_check/safety_check_view_egtest.mm
+++ b/ios/chrome/browser/content_suggestions/ui_bundled/safety_check/safety_check_view_egtest.mm
@@ -73,7 +73,6 @@
 - (AppLaunchConfiguration)appConfigurationForTestCase {
   AppLaunchConfiguration config;
   config.relaunch_policy = ForceRelaunchByCleanShutdown;
-  config.features_enabled.push_back(kHomeCustomization);
   config.additional_args.push_back("--test-ios-module-ranker=safety_check");
 
   return config;
diff --git a/ios/chrome/browser/content_suggestions/ui_bundled/set_up_list/set_up_list_mediator.mm b/ios/chrome/browser/content_suggestions/ui_bundled/set_up_list/set_up_list_mediator.mm
index ad61d6c..24106af5 100644
--- a/ios/chrome/browser/content_suggestions/ui_bundled/set_up_list/set_up_list_mediator.mm
+++ b/ios/chrome/browser/content_suggestions/ui_bundled/set_up_list/set_up_list_mediator.mm
@@ -166,14 +166,10 @@
     _prefObserverBridge->ObserveChangesForPreference(
         prefs::kIosDefaultBrowserPromoLastAction,
         &_localStatePrefChangeRegistrar);
-    _prefObserverBridge->ObserveChangesForPreference(
-        set_up_list_prefs::kDisabled, &_localStatePrefChangeRegistrar);
 
-    if (IsHomeCustomizationEnabled()) {
-      _prefObserverBridge->ObserveChangesForPreference(
-          prefs::kHomeCustomizationMagicStackSetUpListEnabled,
-          &_prefChangeRegistrar);
-    }
+    _prefObserverBridge->ObserveChangesForPreference(
+        prefs::kHomeCustomizationMagicStackSetUpListEnabled,
+        &_prefChangeRegistrar);
 
     if (IsIOSTipsNotificationsEnabled()) {
       _prefObserverBridge->ObserveChangesForPreference(
@@ -274,8 +270,7 @@
 }
 
 - (void)disableModule {
-  set_up_list_prefs::DisableSetUpList(
-      IsHomeCustomizationEnabled() ? _prefService : _localState);
+  set_up_list_prefs::DisableSetUpList(_prefService);
 }
 
 - (BOOL)shouldShowSetUpList {
@@ -427,9 +422,6 @@
   } else if (preferenceName == prefs::kIosDefaultBrowserPromoLastAction &&
              DefaultBrowserPromoCompleted()) {
     [self markSetUpListItemPrefComplete:SetUpListItemType::kDefaultBrowser];
-  } else if (preferenceName == set_up_list_prefs::kDisabled &&
-             set_up_list_prefs::IsSetUpListDisabled(_localState)) {
-    [self hideSetUpList];
   } else if (preferenceName == prefs::kAppLevelPushNotificationPermissions ||
              preferenceName == prefs::kFeaturePushNotificationPermissions) {
     CHECK(IsIOSTipsNotificationsEnabled());
@@ -440,7 +432,6 @@
                  prefs::kHomeCustomizationMagicStackSetUpListEnabled &&
              !_prefService->GetBoolean(
                  prefs::kHomeCustomizationMagicStackSetUpListEnabled)) {
-    CHECK(IsHomeCustomizationEnabled());
     [self hideSetUpList];
   } else if (preferenceName == prefs::kBottomOmnibox) {
     [self markSetUpListItemPrefComplete:SetUpListItemType::kAddressBar];
diff --git a/ios/chrome/browser/content_suggestions/ui_bundled/set_up_list/utils.mm b/ios/chrome/browser/content_suggestions/ui_bundled/set_up_list/utils.mm
index 5296b29..0af0730 100644
--- a/ios/chrome/browser/content_suggestions/ui_bundled/set_up_list/utils.mm
+++ b/ios/chrome/browser/content_suggestions/ui_bundled/set_up_list/utils.mm
@@ -17,16 +17,9 @@
 bool IsSetUpListActive(PrefService* local_prefs,
                        PrefService* user_prefs,
                        bool include_disable_pref) {
-  if (IsHomeCustomizationEnabled()) {
-    if (!user_prefs->GetBoolean(
-            prefs::kHomeCustomizationMagicStackSetUpListEnabled)) {
-      return false;
-    }
-  } else {
-    if (include_disable_pref &&
-        set_up_list_prefs::IsSetUpListDisabled(local_prefs)) {
-      return false;
-    }
+  if (!user_prefs->GetBoolean(
+          prefs::kHomeCustomizationMagicStackSetUpListEnabled)) {
+    return false;
   }
   // Check if we are within the duration of the Set Up List, relevant to the
   // FRE.
diff --git a/ios/chrome/browser/content_suggestions/ui_bundled/tab_resumption/tab_resumption_mediator.mm b/ios/chrome/browser/content_suggestions/ui_bundled/tab_resumption/tab_resumption_mediator.mm
index d958854..c0d75de 100644
--- a/ios/chrome/browser/content_suggestions/ui_bundled/tab_resumption/tab_resumption_mediator.mm
+++ b/ios/chrome/browser/content_suggestions/ui_bundled/tab_resumption/tab_resumption_mediator.mm
@@ -298,19 +298,11 @@
     _webStateList = _browser->GetWebStateList();
     _isOffTheRecord = _browser->GetProfile()->IsOffTheRecord();
 
-    if (IsHomeCustomizationEnabled()) {
-      _tabResumptionDisabled = [[PrefBackedBoolean alloc]
-          initWithPrefService:_profilePrefs
-                     prefName:
-                         prefs::
-                             kHomeCustomizationMagicStackTabResumptionEnabled];
-      [_tabResumptionDisabled setObserver:self];
-    } else {
-      _tabResumptionDisabled = [[PrefBackedBoolean alloc]
-          initWithPrefService:_profilePrefs
-                     prefName:tab_resumption_prefs::kTabResumptionDisabledPref];
-      [_tabResumptionDisabled setObserver:self];
-    }
+    _tabResumptionDisabled = [[PrefBackedBoolean alloc]
+        initWithPrefService:_profilePrefs
+                   prefName:
+                       prefs::kHomeCustomizationMagicStackTabResumptionEnabled];
+    [_tabResumptionDisabled setObserver:self];
 
     ProfileIOS* profile = _browser->GetProfile();
     _sessionSyncService = SessionSyncServiceFactory::GetForProfile(profile);
@@ -452,8 +444,7 @@
 
 - (void)booleanDidChange:(id<ObservableBoolean>)observableBoolean {
   if (observableBoolean == _tabResumptionDisabled) {
-    if ((IsHomeCustomizationEnabled() && !observableBoolean.value) ||
-        (!IsHomeCustomizationEnabled() && observableBoolean.value)) {
+    if (!observableBoolean.value) {
       [self.delegate removeTabResumptionModule];
     }
   }
diff --git a/ios/chrome/browser/content_suggestions/ui_bundled/tips/tips_magic_stack_mediator.mm b/ios/chrome/browser/content_suggestions/ui_bundled/tips/tips_magic_stack_mediator.mm
index c3d31998..d9c84eb 100644
--- a/ios/chrome/browser/content_suggestions/ui_bundled/tips/tips_magic_stack_mediator.mm
+++ b/ios/chrome/browser/content_suggestions/ui_bundled/tips/tips_magic_stack_mediator.mm
@@ -91,9 +91,7 @@
       _profilePrefChangeRegistrar.Init(profilePrefService);
 
       _prefObserverBridge->ObserveChangesForPreference(
-          (IsHomeCustomizationEnabled()
-               ? prefs::kHomeCustomizationMagicStackTipsEnabled
-               : tips_prefs::kTipsInMagicStackDisabledPref),
+          (prefs::kHomeCustomizationMagicStackTipsEnabled),
           &_profilePrefChangeRegistrar);
     }
   }
diff --git a/ios/chrome/browser/content_suggestions/ui_bundled/tips/tips_prefs.mm b/ios/chrome/browser/content_suggestions/ui_bundled/tips/tips_prefs.mm
index f0c2dd8..3cddb48 100644
--- a/ios/chrome/browser/content_suggestions/ui_bundled/tips/tips_prefs.mm
+++ b/ios/chrome/browser/content_suggestions/ui_bundled/tips/tips_prefs.mm
@@ -20,19 +20,11 @@
 }
 
 bool IsTipsInMagicStackDisabled(PrefService* prefs) {
-  if (IsHomeCustomizationEnabled()) {
-    return !prefs->GetBoolean(prefs::kHomeCustomizationMagicStackTipsEnabled);
-  } else {
-    return prefs->GetBoolean(kTipsInMagicStackDisabledPref);
-  }
+  return !prefs->GetBoolean(prefs::kHomeCustomizationMagicStackTipsEnabled);
 }
 
 void DisableTipsInMagicStack(PrefService* prefs) {
-  if (IsHomeCustomizationEnabled()) {
-    prefs->SetBoolean(prefs::kHomeCustomizationMagicStackTipsEnabled, false);
-  } else {
-    prefs->SetBoolean(kTipsInMagicStackDisabledPref, true);
-  }
+  prefs->SetBoolean(prefs::kHomeCustomizationMagicStackTipsEnabled, false);
 }
 
 }  // namespace tips_prefs
diff --git a/ios/chrome/browser/credential_provider/model/BUILD.gn b/ios/chrome/browser/credential_provider/model/BUILD.gn
index 3cff0bb5..2b5539b 100644
--- a/ios/chrome/browser/credential_provider/model/BUILD.gn
+++ b/ios/chrome/browser/credential_provider/model/BUILD.gn
@@ -53,6 +53,7 @@
       "//ios/chrome/browser/shared/model/application_context",
       "//ios/chrome/browser/shared/model/browser",
       "//ios/chrome/browser/shared/model/profile",
+      "//ios/chrome/browser/shared/model/profile:features",
       "//ios/chrome/browser/shared/model/profile:profile_keyed_service_factory",
       "//ios/chrome/browser/shared/model/web_state_list",
       "//ios/chrome/browser/shared/public/commands",
diff --git a/ios/chrome/browser/credential_provider/model/credential_provider_service.mm b/ios/chrome/browser/credential_provider/model/credential_provider_service.mm
index ca8134b2..c2c6f637 100644
--- a/ios/chrome/browser/credential_provider/model/credential_provider_service.mm
+++ b/ios/chrome/browser/credential_provider/model/credential_provider_service.mm
@@ -33,6 +33,7 @@
 #import "ios/chrome/browser/credential_provider/model/credential_provider_util.h"
 #import "ios/chrome/browser/credential_provider/model/features.h"
 #import "ios/chrome/browser/shared/model/application_context/application_context.h"
+#import "ios/chrome/browser/shared/model/profile/features.h"
 #import "ios/chrome/browser/shared/model/profile/profile_attributes_ios.h"
 #import "ios/chrome/browser/shared/model/profile/profile_attributes_storage_ios.h"
 #import "ios/chrome/browser/shared/model/profile/profile_manager_ios.h"
diff --git a/ios/chrome/browser/default_browser/model/default_status/default_status_helper.h b/ios/chrome/browser/default_browser/model/default_status/default_status_helper.h
index a4bd83bab..aba5b6d 100644
--- a/ios/chrome/browser/default_browser/model/default_status/default_status_helper.h
+++ b/ios/chrome/browser/default_browser/model/default_status/default_status_helper.h
@@ -63,8 +63,10 @@
 
 // Converts the system's default status enum value to the one used by this
 // helper.
+#if defined(__IPHONE_18_2) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_18_2
 DefaultStatusAPIResult SystemToLocalEnum(
     UIApplicationCategoryDefaultStatus system_enum) API_AVAILABLE(ios(18.4));
+#endif
 
 // Returns the retention type based on the previous and current default status
 // result.
@@ -77,9 +79,11 @@
 
 // Use in tests only. The specified callback will be invoked instead of making a
 // real call to the default status API.
+#if defined(__IPHONE_18_2) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_18_2
 void OverrideSystemCallForTesting(
     base::OnceCallback<UIApplicationCategoryDefaultStatus(NSError**)> cb)
     API_AVAILABLE(ios(18.4));
+#endif
 
 }  // namespace internal
 
diff --git a/ios/chrome/browser/default_browser/model/default_status/default_status_helper.mm b/ios/chrome/browser/default_browser/model/default_status/default_status_helper.mm
index 8fe109e..20d6e0d 100644
--- a/ios/chrome/browser/default_browser/model/default_status/default_status_helper.mm
+++ b/ios/chrome/browser/default_browser/model/default_status/default_status_helper.mm
@@ -32,6 +32,7 @@
 
 // Gets the system call to use/override for testing. Uses a function so the
 // static variable can be contained inside the function.
+#if defined(__IPHONE_18_2) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_18_2
 base::OnceCallback<UIApplicationCategoryDefaultStatus(NSError**)>&
 GetSystemCallForTesting() API_AVAILABLE(ios(18.4)) {
   static base::NoDestructor<
@@ -39,9 +40,11 @@
       g_system_call_for_testing;
   return *g_system_call_for_testing;
 }
+#endif
 
 // Performs the actual system call to the default status check API. Wrapped in
 // its own function to facilitate mocking in tests.
+#if defined(__IPHONE_18_2) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_18_2
 UIApplicationCategoryDefaultStatus MakeSystemCall(NSError** error)
     API_AVAILABLE(ios(18.4)) {
   if (GetSystemCallForTesting()) {
@@ -52,6 +55,7 @@
       defaultStatusForCategory:UIApplicationCategoryWebBrowser
                          error:error];
 }
+#endif
 
 }  // namespace
 
@@ -141,6 +145,7 @@
   local_state->SetTime(kDefaultStatusAPINextRetry, next_retry);
 }
 
+#if defined(__IPHONE_18_2) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_18_2
 DefaultStatusAPIResult SystemToLocalEnum(
     UIApplicationCategoryDefaultStatus system_enum) API_AVAILABLE(ios(18.4)) {
   switch (system_enum) {
@@ -156,6 +161,7 @@
       return DefaultStatusAPIResult::kUnknown;
   }
 }
+#endif
 
 DefaultStatusRetention DetermineRetentionStatus(
     DefaultStatusAPIResult previous,
@@ -178,6 +184,7 @@
 }
 
 void QueryDefaultStatusIfReadyAndLogResults(PrefService* local_state) {
+#if defined(__IPHONE_18_2) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_18_2
   if (@available(iOS 18.4, *)) {
     int cohort_number = local_state->GetInteger(kDefaultStatusAPICohort);
     DUMP_WILL_BE_CHECK(cohort_number > 0 && cohort_number <= kCohortCount);
@@ -245,14 +252,17 @@
       local_state->SetTime(kDefaultStatusAPINextRetry, next_retry);
     }
   }
+#endif
 }
 
+#if defined(__IPHONE_18_2) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_18_2
 void OverrideSystemCallForTesting(  // IN-TEST
     base::OnceCallback<UIApplicationCategoryDefaultStatus(NSError**)> cb)
     API_AVAILABLE(ios(18.4)) {
   CHECK_IS_TEST();
   internal::GetSystemCallForTesting() = std::move(cb);
 }
+#endif
 
 }  // namespace internal
 
diff --git a/ios/chrome/browser/discover_feed/model/discover_feed_view_controller_configuration.h b/ios/chrome/browser/discover_feed/model/discover_feed_view_controller_configuration.h
index 643d8e6..fcf05dd 100644
--- a/ios/chrome/browser/discover_feed/model/discover_feed_view_controller_configuration.h
+++ b/ios/chrome/browser/discover_feed/model/discover_feed_view_controller_configuration.h
@@ -8,7 +8,6 @@
 #import <Foundation/Foundation.h>
 
 class Browser;
-@protocol DiscoverFeedManageDelegate;
 @protocol DiscoverFeedPreviewDelegate;
 @protocol FeedSignInPromoDelegate;
 @protocol UIScrollViewDelegate;
@@ -26,9 +25,6 @@
 // DiscoverFeedPreviewDelegate used by Discover Feed ViewController.
 @property(nonatomic, weak) id<DiscoverFeedPreviewDelegate> previewDelegate;
 
-// DiscoverFeedManageDelegate used by Discover Feed ViewController.
-@property(nonatomic, weak) id<DiscoverFeedManageDelegate> manageDelegate;
-
 // FeedSignInPromoDelegate used by Discover Feed ViewController.
 @property(nonatomic, weak) id<FeedSignInPromoDelegate> signInPromoDelegate;
 
diff --git a/ios/chrome/browser/first_run/ui_bundled/signin/signin_screen_mediator.mm b/ios/chrome/browser/first_run/ui_bundled/signin/signin_screen_mediator.mm
index 99fd8f2..ede8f15b 100644
--- a/ios/chrome/browser/first_run/ui_bundled/signin/signin_screen_mediator.mm
+++ b/ios/chrome/browser/first_run/ui_bundled/signin/signin_screen_mediator.mm
@@ -27,7 +27,6 @@
 #import "ios/chrome/browser/policy/model/policy_util.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
 #import "ios/chrome/browser/signin/model/authentication_service.h"
-#import "ios/chrome/browser/signin/model/chrome_account_manager_service_observer_bridge.h"
 #import "ios/chrome/browser/signin/model/system_identity.h"
 #import "ios/chrome/browser/sync/model/enterprise_utils.h"
 
@@ -43,8 +42,7 @@
 };
 }  // namespace
 
-@interface SigninScreenMediator () <ChromeAccountManagerServiceObserver,
-                                    IdentityManagerObserverBridgeDelegate> {
+@interface SigninScreenMediator () <IdentityManagerObserverBridgeDelegate> {
 }
 
 // Application local pref.
@@ -71,8 +69,6 @@
   raw_ptr<AuthenticationService> _authenticationService;
   // Identity manager to retrieve Chrome identities.
   raw_ptr<signin::IdentityManager> _identityManager;
-  std::unique_ptr<ChromeAccountManagerServiceObserverBridge>
-      _accountManagerServiceObserver;
   std::unique_ptr<signin::IdentityManagerObserverBridge>
       _identityManagerObserver;
   // State of the sign-in screen.
@@ -101,9 +97,6 @@
     _UMAReportingUserChoice = kDefaultMetricsReportingCheckboxValue;
     _accountManagerService = accountManagerService;
     _authenticationService = authenticationService;
-    _accountManagerServiceObserver =
-        std::make_unique<ChromeAccountManagerServiceObserverBridge>(
-            self, _accountManagerService);
     _identityManager = identityManager;
     _identityManagerObserver =
         std::make_unique<signin::IdentityManagerObserverBridge>(
@@ -162,7 +155,6 @@
   self.localPrefService = nullptr;
   self.prefService = nullptr;
   self.syncService = nullptr;
-  _accountManagerServiceObserver.reset();
   _identityManagerObserver.reset();
 }
 
@@ -375,14 +367,6 @@
   return NO;
 }
 
-#pragma mark - ChromeAccountManagerServiceObserver
-
-- (void)onChromeAccountManagerServiceShutdown:
-    (ChromeAccountManagerService*)accountManagerService {
-  // TODO(crbug.com/40284086): Remove `[self disconnect]`.
-  [self disconnect];
-}
-
 #pragma mark -  IdentityManagerObserver
 
 - (void)onAccountsOnDeviceChanged {
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm
index 4c73cac..2226462e 100644
--- a/ios/chrome/browser/flags/about_flags.mm
+++ b/ios/chrome/browser/flags/about_flags.mm
@@ -2126,9 +2126,6 @@
      flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(
          autofill::features::kAutofillShowManualFillForVirtualCards)},
-    {"home-customization", flag_descriptions::kHomeCustomizationName,
-     flag_descriptions::kHomeCustomizationDescription, flags_ui::kOsIos,
-     FEATURE_VALUE_TYPE(kHomeCustomization)},
     {"safety-check-notifications",
      flag_descriptions::kSafetyCheckNotificationsName,
      flag_descriptions::kSafetyCheckNotificationsDescription, flags_ui::kOsIos,
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
index 78e32824..653a804 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -528,10 +528,6 @@
     "When enabled, the web view's insets are updated for scoll events. If "
     "disabled, the the web view's frame are updated.";
 
-const char kHomeCustomizationName[] = "Home Customization";
-const char kHomeCustomizationDescription[] =
-    "When enabled, adds a menu to personalize the Home surface.";
-
 const char kHomeMemoryImprovementsName[] = "Home Memory Improvements";
 const char kHomeMemoryImprovementsDescription[] =
     "When enabled, uses code that aims to improve the memory footprint in "
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
index f910ab8..9e54293 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -306,9 +306,6 @@
 extern const char kFullscreenSmoothScrollingName[];
 extern const char kFullscreenSmoothScrollingDescription[];
 
-extern const char kHomeCustomizationName[];
-extern const char kHomeCustomizationDescription[];
-
 extern const char kHomeMemoryImprovementsName[];
 extern const char kHomeMemoryImprovementsDescription[];
 
diff --git a/ios/chrome/browser/follow/model/follow_browser_agent.mm b/ios/chrome/browser/follow/model/follow_browser_agent.mm
index cc70854..083d4bb3 100644
--- a/ios/chrome/browser/follow/model/follow_browser_agent.mm
+++ b/ios/chrome/browser/follow/model/follow_browser_agent.mm
@@ -244,10 +244,6 @@
     pref_service->SetBoolean(prefs::kArticlesForYouEnabled, true);
   }
 
-  if (!pref_service->GetBoolean(feed::prefs::kArticlesListVisible)) {
-    pref_service->SetBoolean(feed::prefs::kArticlesListVisible, true);
-  }
-
   // Display the First Follow modal UI if needed.
   const bool is_overflow_menu_source = source == FollowSource::OverflowMenu;
   if (is_overflow_menu_source && ShouldShowFirstFollowUI(pref_service)) {
diff --git a/ios/chrome/browser/follow/model/resources/rss_link.ts b/ios/chrome/browser/follow/model/resources/rss_link.ts
index 3d351e1..a4a5fd30 100644
--- a/ios/chrome/browser/follow/model/resources/rss_link.ts
+++ b/ios/chrome/browser/follow/model/resources/rss_link.ts
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 
 /**
  * @fileoverview Functions used to parse RSS links from a web page.
@@ -27,4 +27,4 @@
   return rssLinks;
 }
 
-gCrWeb.rssLink = {getRSSLinks};
+gCrWebLegacy.rssLink = {getRSSLinks};
diff --git a/ios/chrome/browser/home_customization/coordinator/home_customization_coordinator_unittest.mm b/ios/chrome/browser/home_customization/coordinator/home_customization_coordinator_unittest.mm
index 6dbfdc0..2058597 100644
--- a/ios/chrome/browser/home_customization/coordinator/home_customization_coordinator_unittest.mm
+++ b/ios/chrome/browser/home_customization/coordinator/home_customization_coordinator_unittest.mm
@@ -24,8 +24,6 @@
 class HomeCustomizationCoordinatorUnitTest : public PlatformTest {
  public:
   void SetUp() override {
-    scoped_feature_list_.InitWithFeatures({kHomeCustomization}, {});
-
     profile_ = TestProfileIOS::Builder().Build();
     browser_ = std::make_unique<TestBrowser>(profile_.get());
     base_view_controller_ = [[UIViewController alloc] init];
@@ -37,7 +35,6 @@
 
  protected:
   web::WebTaskEnvironment task_environment_;
-  base::test::ScopedFeatureList scoped_feature_list_;
   HomeCustomizationCoordinator* coordinator_;
   std::unique_ptr<TestProfileIOS> profile_;
   std::unique_ptr<TestBrowser> browser_;
diff --git a/ios/chrome/browser/lens_overlay/model/lens_overlay_detents_manager.h b/ios/chrome/browser/lens_overlay/model/lens_overlay_detents_manager.h
index 6bbeb954..c1538e7 100644
--- a/ios/chrome/browser/lens_overlay/model/lens_overlay_detents_manager.h
+++ b/ios/chrome/browser/lens_overlay/model/lens_overlay_detents_manager.h
@@ -37,6 +37,9 @@
 // Current sheet dimension.
 @property(nonatomic, readonly) SheetDimensionState sheetDimension;
 
+// The height of the info message in points.
+@property(nonatomic, assign) CGFloat infoMessageHeight;
+
 // The strategy to use when presenting.
 //
 // Changing the presentation strategy adjusts the detents for unrestricted
diff --git a/ios/chrome/browser/lens_overlay/model/lens_overlay_detents_manager.mm b/ios/chrome/browser/lens_overlay/model/lens_overlay_detents_manager.mm
index e2886f9..288fa4e 100644
--- a/ios/chrome/browser/lens_overlay/model/lens_overlay_detents_manager.mm
+++ b/ios/chrome/browser/lens_overlay/model/lens_overlay_detents_manager.mm
@@ -26,9 +26,6 @@
 // The detent height in points for the 'peak' state of the bottom sheet.
 const CGFloat kPeakDetentHeight = 100.0;
 
-// The detent height in points for the error message state of the bottom sheet.
-const CGFloat kinfoMessageDetentHeight = 160.0;
-
 // The percentage of the screen that will be covered by the bottom sheet in
 // translate mode.
 const CGFloat kTranslateSheetHeightRatio = 0.33;
@@ -305,9 +302,10 @@
 }
 
 - (UISheetPresentationControllerDetent*)infoMessageDetent {
+  __weak __typeof(self) weakSelf = self;
   auto infoMessageHeightResolver = ^CGFloat(
       id<UISheetPresentationControllerDetentResolutionContext> context) {
-    return kinfoMessageDetentHeight;
+    return weakSelf.infoMessageHeight;
   };
   return [UISheetPresentationControllerDetent
       customDetentWithIdentifier:kInfoMessageSheetDetentIdentifier
diff --git a/ios/chrome/browser/lens_overlay/ui/BUILD.gn b/ios/chrome/browser/lens_overlay/ui/BUILD.gn
index f9f20a9a..0687780 100644
--- a/ios/chrome/browser/lens_overlay/ui/BUILD.gn
+++ b/ios/chrome/browser/lens_overlay/ui/BUILD.gn
@@ -69,6 +69,10 @@
 
 source_set("view_controller") {
   sources = [
+    "info_message/lens_translate_error_view_controller.h",
+    "info_message/lens_translate_error_view_controller.mm",
+    "info_message/lens_translate_indication_view_controller.h",
+    "info_message/lens_translate_indication_view_controller.mm",
     "lens_overlay_consent_view_controller.h",
     "lens_overlay_consent_view_controller.mm",
     "lens_overlay_container_view_controller.h",
diff --git a/ios/chrome/browser/lens_overlay/ui/info_message/lens_translate_error_view_controller.h b/ios/chrome/browser/lens_overlay/ui/info_message/lens_translate_error_view_controller.h
new file mode 100644
index 0000000..1824bf3
--- /dev/null
+++ b/ios/chrome/browser/lens_overlay/ui/info_message/lens_translate_error_view_controller.h
@@ -0,0 +1,15 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_LENS_OVERLAY_UI_INFO_MESSAGE_LENS_TRANSLATE_ERROR_VIEW_CONTROLLER_H_
+#define IOS_CHROME_BROWSER_LENS_OVERLAY_UI_INFO_MESSAGE_LENS_TRANSLATE_ERROR_VIEW_CONTROLLER_H_
+
+#import <UIKit/UIKit.h>
+
+// The UI for the translate error informational message.
+@interface LensTranslateErrorViewController : UIViewController
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_LENS_OVERLAY_UI_INFO_MESSAGE_LENS_TRANSLATE_ERROR_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/lens_overlay/ui/info_message/lens_translate_error_view_controller.mm b/ios/chrome/browser/lens_overlay/ui/info_message/lens_translate_error_view_controller.mm
new file mode 100644
index 0000000..09658df
--- /dev/null
+++ b/ios/chrome/browser/lens_overlay/ui/info_message/lens_translate_error_view_controller.mm
@@ -0,0 +1,114 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/lens_overlay/ui/info_message/lens_translate_error_view_controller.h"
+
+#import "ios/chrome/common/ui/colors/semantic_color_names.h"
+#import "ios/chrome/common/ui/util/constraints_ui_util.h"
+#import "ios/chrome/grit/ios_strings.h"
+#import "ui/base/l10n/l10n_util.h"
+
+namespace {
+
+// The image to be displayed on the leading edge of the UI.
+NSString* const kLensTranslateErrorImage = @"lens_translate_error";
+
+// The size of the translate error image.
+const CGFloat kLensTranslateErrorImageSize = 60.0;
+
+// The lateral padding for the translate error view.
+const CGFloat kLateralPadding = 22.0;
+
+// Top padding for the view content.
+const CGFloat kViewTopPadding = 36.0;
+
+// Ammount of spacing from the trailing edge of the image, in points.
+const CGFloat kImageHorizontalSpacing = 22.0;
+
+// The height of the translate error message.
+const CGFloat kPreferredContentHeight = 130.0;
+
+}  // namespace
+
+@implementation LensTranslateErrorViewController
+
+#pragma mark - UIViewController
+
+- (CGSize)preferredContentSize {
+  CGFloat fittingWidth = self.view.safeAreaLayoutGuide.layoutFrame.size.width;
+  return CGSizeMake(fittingWidth, kPreferredContentHeight);
+}
+
+- (void)loadView {
+  [super loadView];
+  self.view.backgroundColor = [UIColor colorNamed:kPrimaryBackgroundColor];
+
+  UILabel* titleLabel = [self createTitleLabel];
+  UILabel* subtitleLabel = [self createSubtitleLabel];
+  UIImageView* imageView = [self createImageView];
+
+  UIStackView* textStackView = [[UIStackView alloc] initWithArrangedSubviews:@[
+    titleLabel,
+    subtitleLabel,
+  ]];
+  textStackView.translatesAutoresizingMaskIntoConstraints = NO;
+  textStackView.axis = UILayoutConstraintAxisVertical;
+  textStackView.spacing = 4;
+
+  UIStackView* mainStackView = [[UIStackView alloc]
+      initWithArrangedSubviews:@[ imageView, textStackView ]];
+  mainStackView.translatesAutoresizingMaskIntoConstraints = NO;
+  mainStackView.distribution = UIStackViewDistributionFill;
+  mainStackView.spacing = kImageHorizontalSpacing;
+  mainStackView.alignment = UIStackViewAlignmentCenter;
+  mainStackView.axis = UILayoutConstraintAxisHorizontal;
+
+  [self.view addSubview:mainStackView];
+
+  AddSizeConstraints(imageView, CGSizeMake(kLensTranslateErrorImageSize,
+                                           kLensTranslateErrorImageSize));
+  LayoutSides sides =
+      LayoutSides::kTop | LayoutSides::kTrailing | LayoutSides::kLeading;
+  NSDirectionalEdgeInsets insets = NSDirectionalEdgeInsetsMake(
+      kViewTopPadding, kLateralPadding, 0, kLateralPadding);
+  AddSameConstraintsToSidesWithInsets(mainStackView, self.view, sides, insets);
+}
+
+#pragma mark - Private Methods
+
+- (UILabel*)createTitleLabel {
+  UILabel* label = [[UILabel alloc] init];
+  label.translatesAutoresizingMaskIntoConstraints = NO;
+  label.adjustsFontForContentSizeCategory = YES;
+  label.lineBreakMode = NSLineBreakByWordWrapping;
+  label.numberOfLines = 0;
+  label.font = [UIFont preferredFontForTextStyle:UIFontTextStyleTitle3];
+  label.text =
+      l10n_util::GetNSString(IDS_IOS_LENS_OVERLAY_TRANSLATE_ERROR_TITLE);
+  label.textColor = [UIColor colorNamed:kTextPrimaryColor];
+  return label;
+}
+
+- (UILabel*)createSubtitleLabel {
+  UILabel* label = [[UILabel alloc] init];
+  label.translatesAutoresizingMaskIntoConstraints = NO;
+  label.adjustsFontForContentSizeCategory = YES;
+  label.lineBreakMode = NSLineBreakByWordWrapping;
+  label.numberOfLines = 0;
+  label.font = [UIFont preferredFontForTextStyle:UIFontTextStyleCallout];
+  label.text =
+      l10n_util::GetNSString(IDS_IOS_LENS_OVERLAY_TRANSLATE_ERROR_SUBTITLE);
+  label.textColor =
+      [UIColor colorNamed:kLensOverlayConsentDialogDescriptionColor];
+  return label;
+}
+
+- (UIImageView*)createImageView {
+  UIImageView* imageView = [[UIImageView alloc] init];
+  imageView.translatesAutoresizingMaskIntoConstraints = NO;
+  imageView.image = [UIImage imageNamed:kLensTranslateErrorImage];
+  return imageView;
+}
+
+@end
diff --git a/ios/chrome/browser/lens_overlay/ui/info_message/lens_translate_indication_view_controller.h b/ios/chrome/browser/lens_overlay/ui/info_message/lens_translate_indication_view_controller.h
new file mode 100644
index 0000000..e82615b
--- /dev/null
+++ b/ios/chrome/browser/lens_overlay/ui/info_message/lens_translate_indication_view_controller.h
@@ -0,0 +1,15 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_LENS_OVERLAY_UI_INFO_MESSAGE_LENS_TRANSLATE_INDICATION_VIEW_CONTROLLER_H_
+#define IOS_CHROME_BROWSER_LENS_OVERLAY_UI_INFO_MESSAGE_LENS_TRANSLATE_INDICATION_VIEW_CONTROLLER_H_
+
+#import <UIKit/UIKit.h>
+
+// The UI for the translate indication informational message.
+@interface LensTranslateIndicationViewController : UIViewController
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_LENS_OVERLAY_UI_INFO_MESSAGE_LENS_TRANSLATE_INDICATION_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/lens_overlay/ui/info_message/lens_translate_indication_view_controller.mm b/ios/chrome/browser/lens_overlay/ui/info_message/lens_translate_indication_view_controller.mm
new file mode 100644
index 0000000..3929ae7e
--- /dev/null
+++ b/ios/chrome/browser/lens_overlay/ui/info_message/lens_translate_indication_view_controller.mm
@@ -0,0 +1,57 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/lens_overlay/ui/info_message/lens_translate_indication_view_controller.h"
+
+#import "ios/chrome/common/ui/colors/semantic_color_names.h"
+#import "ios/chrome/common/ui/util/constraints_ui_util.h"
+#import "ios/chrome/grit/ios_strings.h"
+#import "ui/base/l10n/l10n_util.h"
+
+namespace {
+
+// The lateral padding for the translate error view.
+const CGFloat kLateralPadding = 22.0;
+
+// Top padding for the view content.
+const CGFloat kViewTopPadding = 36.0;
+
+// The height of the translate error message.
+const CGFloat kPreferredContentHeight = 80.0;
+
+}  // namespace
+
+@implementation LensTranslateIndicationViewController
+
+#pragma mark - UIViewController
+
+- (CGSize)preferredContentSize {
+  CGFloat fittingWidth = self.view.safeAreaLayoutGuide.layoutFrame.size.width;
+  return CGSizeMake(fittingWidth, kPreferredContentHeight);
+}
+
+- (void)loadView {
+  [super loadView];
+  self.view.backgroundColor = [UIColor colorNamed:kPrimaryBackgroundColor];
+
+  UILabel* label = [[UILabel alloc] init];
+  label.translatesAutoresizingMaskIntoConstraints = NO;
+  label.adjustsFontForContentSizeCategory = YES;
+  label.lineBreakMode = NSLineBreakByWordWrapping;
+  label.numberOfLines = 0;
+  label.font = [UIFont preferredFontForTextStyle:UIFontTextStyleTitle3];
+  label.text =
+      l10n_util::GetNSString(IDS_IOS_LENS_OVERLAY_TRANSLATE_INDICATION_TITLE);
+  label.textColor = [UIColor colorNamed:kTextPrimaryColor];
+
+  [self.view addSubview:label];
+
+  LayoutSides sides =
+      LayoutSides::kTop | LayoutSides::kTrailing | LayoutSides::kLeading;
+  NSDirectionalEdgeInsets insets = NSDirectionalEdgeInsetsMake(
+      kViewTopPadding, kLateralPadding, 0, kLateralPadding);
+  AddSameConstraintsToSidesWithInsets(label, self.view, sides, insets);
+}
+
+@end
diff --git a/ios/chrome/browser/lens_overlay/ui/lens_overlay_results_page_presenter.mm b/ios/chrome/browser/lens_overlay/ui/lens_overlay_results_page_presenter.mm
index 0dac9a4d..4eee46d 100644
--- a/ios/chrome/browser/lens_overlay/ui/lens_overlay_results_page_presenter.mm
+++ b/ios/chrome/browser/lens_overlay/ui/lens_overlay_results_page_presenter.mm
@@ -9,6 +9,8 @@
 #import "base/task/sequenced_task_runner.h"
 #import "ios/chrome/browser/lens_overlay/model/lens_overlay_detents_manager.h"
 #import "ios/chrome/browser/lens_overlay/model/lens_overlay_pan_tracker.h"
+#import "ios/chrome/browser/lens_overlay/ui/info_message/lens_translate_error_view_controller.h"
+#import "ios/chrome/browser/lens_overlay/ui/info_message/lens_translate_indication_view_controller.h"
 #import "ios/chrome/browser/lens_overlay/ui/lens_overlay_results_page_presenter_delegate.h"
 #import "ios/chrome/browser/lens_overlay/ui/lens_result_page_view_controller.h"
 #import "ios/chrome/browser/shared/coordinator/scene/scene_state.h"
@@ -250,11 +252,22 @@
 }
 
 - (void)showInfoMessage:(LensOverlayBottomSheetInfoMessageType)infoMessageType {
-  [_detentsManager adjustDetentsForState:SheetDetentStateInfoMessage];
+  UIViewController* infoMessageViewController;
+  switch (infoMessageType) {
+    case LensOverlayBottomSheetInfoMessageType::kImageTranslatedIndication:
+      infoMessageViewController =
+          [[LensTranslateIndicationViewController alloc] init];
+      break;
+    case LensOverlayBottomSheetInfoMessageType::kNoTranslatableTextWarning:
+      infoMessageViewController =
+          [[LensTranslateErrorViewController alloc] init];
+      break;
+  }
 
-  // TODO(crbug.com/405199044): Replace with the real UI once built.
-  UIViewController* infoMessageViewController = [[UIViewController alloc] init];
-  infoMessageViewController.view.backgroundColor = [UIColor whiteColor];
+  _detentsManager.infoMessageHeight =
+      infoMessageViewController.preferredContentSize.height;
+
+  [_detentsManager adjustDetentsForState:SheetDetentStateInfoMessage];
   [_presentationNavigationController
       pushViewController:infoMessageViewController
                 animated:YES];
diff --git a/ios/chrome/browser/lens_overlay/ui/resources/Assets.xcassets/lens_translate_error.imageset/Contents.json b/ios/chrome/browser/lens_overlay/ui/resources/Assets.xcassets/lens_translate_error.imageset/Contents.json
new file mode 100644
index 0000000..34378d9b
--- /dev/null
+++ b/ios/chrome/browser/lens_overlay/ui/resources/Assets.xcassets/lens_translate_error.imageset/Contents.json
@@ -0,0 +1,89 @@
+{
+  "images" : [
+    {
+      "filename" : "lens_translate_error@1x.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "appearances" : [
+        {
+          "appearance" : "luminosity",
+          "value" : "light"
+        }
+      ],
+      "filename" : "lens_translate_error@1x.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "appearances" : [
+        {
+          "appearance" : "luminosity",
+          "value" : "dark"
+        }
+      ],
+      "filename" : "lens_translate_error_dark@1x.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "lens_translate_error@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "appearances" : [
+        {
+          "appearance" : "luminosity",
+          "value" : "light"
+        }
+      ],
+      "filename" : "lens_translate_error@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "appearances" : [
+        {
+          "appearance" : "luminosity",
+          "value" : "dark"
+        }
+      ],
+      "filename" : "lens_translate_error_dark@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "lens_translate_error@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    },
+    {
+      "appearances" : [
+        {
+          "appearance" : "luminosity",
+          "value" : "light"
+        }
+      ],
+      "filename" : "lens_translate_error@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    },
+    {
+      "appearances" : [
+        {
+          "appearance" : "luminosity",
+          "value" : "dark"
+        }
+      ],
+      "filename" : "lens_translate_error_dark@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/ios/chrome/browser/lens_overlay/ui/resources/Assets.xcassets/lens_translate_error.imageset/lens_translate_error@1x.png b/ios/chrome/browser/lens_overlay/ui/resources/Assets.xcassets/lens_translate_error.imageset/lens_translate_error@1x.png
new file mode 100644
index 0000000..a9e95cf
--- /dev/null
+++ b/ios/chrome/browser/lens_overlay/ui/resources/Assets.xcassets/lens_translate_error.imageset/lens_translate_error@1x.png
Binary files differ
diff --git a/ios/chrome/browser/lens_overlay/ui/resources/Assets.xcassets/lens_translate_error.imageset/lens_translate_error@2x.png b/ios/chrome/browser/lens_overlay/ui/resources/Assets.xcassets/lens_translate_error.imageset/lens_translate_error@2x.png
new file mode 100644
index 0000000..6d1841b
--- /dev/null
+++ b/ios/chrome/browser/lens_overlay/ui/resources/Assets.xcassets/lens_translate_error.imageset/lens_translate_error@2x.png
Binary files differ
diff --git a/ios/chrome/browser/lens_overlay/ui/resources/Assets.xcassets/lens_translate_error.imageset/lens_translate_error@3x.png b/ios/chrome/browser/lens_overlay/ui/resources/Assets.xcassets/lens_translate_error.imageset/lens_translate_error@3x.png
new file mode 100644
index 0000000..50a2e5d1
--- /dev/null
+++ b/ios/chrome/browser/lens_overlay/ui/resources/Assets.xcassets/lens_translate_error.imageset/lens_translate_error@3x.png
Binary files differ
diff --git a/ios/chrome/browser/lens_overlay/ui/resources/Assets.xcassets/lens_translate_error.imageset/lens_translate_error_dark@1x.png b/ios/chrome/browser/lens_overlay/ui/resources/Assets.xcassets/lens_translate_error.imageset/lens_translate_error_dark@1x.png
new file mode 100644
index 0000000..349f151
--- /dev/null
+++ b/ios/chrome/browser/lens_overlay/ui/resources/Assets.xcassets/lens_translate_error.imageset/lens_translate_error_dark@1x.png
Binary files differ
diff --git a/ios/chrome/browser/lens_overlay/ui/resources/Assets.xcassets/lens_translate_error.imageset/lens_translate_error_dark@2x.png b/ios/chrome/browser/lens_overlay/ui/resources/Assets.xcassets/lens_translate_error.imageset/lens_translate_error_dark@2x.png
new file mode 100644
index 0000000..08a2900
--- /dev/null
+++ b/ios/chrome/browser/lens_overlay/ui/resources/Assets.xcassets/lens_translate_error.imageset/lens_translate_error_dark@2x.png
Binary files differ
diff --git a/ios/chrome/browser/lens_overlay/ui/resources/Assets.xcassets/lens_translate_error.imageset/lens_translate_error_dark@3x.png b/ios/chrome/browser/lens_overlay/ui/resources/Assets.xcassets/lens_translate_error.imageset/lens_translate_error_dark@3x.png
new file mode 100644
index 0000000..7c79e21c
--- /dev/null
+++ b/ios/chrome/browser/lens_overlay/ui/resources/Assets.xcassets/lens_translate_error.imageset/lens_translate_error_dark@3x.png
Binary files differ
diff --git a/ios/chrome/browser/lens_overlay/ui/resources/BUILD.gn b/ios/chrome/browser/lens_overlay/ui/resources/BUILD.gn
index a566d36..888f8f6 100644
--- a/ios/chrome/browser/lens_overlay/ui/resources/BUILD.gn
+++ b/ios/chrome/browser/lens_overlay/ui/resources/BUILD.gn
@@ -19,5 +19,12 @@
     "Assets.xcassets/lens_overlay_onboarding_illustration.imageset/Contents.json",
     "Assets.xcassets/lens_overlay_onboarding_illustration.imageset/lens_overlay_onboarding_illustration@2x.png",
     "Assets.xcassets/lens_overlay_onboarding_illustration.imageset/lens_overlay_onboarding_illustration@3x.png",
+    "Assets.xcassets/lens_translate_error.imageset/Contents.json",
+    "Assets.xcassets/lens_translate_error.imageset/lens_translate_error@1x.png",
+    "Assets.xcassets/lens_translate_error.imageset/lens_translate_error@2x.png",
+    "Assets.xcassets/lens_translate_error.imageset/lens_translate_error@3x.png",
+    "Assets.xcassets/lens_translate_error.imageset/lens_translate_error_dark@1x.png",
+    "Assets.xcassets/lens_translate_error.imageset/lens_translate_error_dark@2x.png",
+    "Assets.xcassets/lens_translate_error.imageset/lens_translate_error_dark@3x.png",
   ]
 }
diff --git a/ios/chrome/browser/link_to_text/model/resources/link_to_text.ts b/ios/chrome/browser/link_to_text/model/resources/link_to_text.ts
index 0924f116..ddf01a2e 100644
--- a/ios/chrome/browser/link_to_text/model/resources/link_to_text.ts
+++ b/ios/chrome/browser/link_to_text/model/resources/link_to_text.ts
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 import * as utils from '//third_party/text-fragments-polyfill/src/src/fragment-generation-utils.js';
 
 /**
@@ -42,4 +42,4 @@
   };
 }
 
-gCrWeb.linkToText =  { getLinkToText };
+gCrWebLegacy.linkToText = {getLinkToText};
diff --git a/ios/chrome/browser/memory/model/memory_metrics.cc b/ios/chrome/browser/memory/model/memory_metrics.cc
index def76b07..80e7887a 100644
--- a/ios/chrome/browser/memory/model/memory_metrics.cc
+++ b/ios/chrome/browser/memory/model/memory_metrics.cc
@@ -12,6 +12,7 @@
 #include <memory>
 
 #include "base/apple/scoped_mach_port.h"
+#include "base/ios/device_util.h"
 #include "base/logging.h"
 #include "base/process/process_handle.h"
 #include "base/process/process_metrics.h"
@@ -48,16 +49,12 @@
 }
 
 uint64_t GetRealMemoryUsedInBytes() {
-  task_vm_info task_info_data;
-  mach_msg_type_number_t count = sizeof(task_vm_info) / sizeof(natural_t);
-  kern_return_t kr =
-      task_info(mach_task_self(), TASK_VM_INFO,
-                reinterpret_cast<task_info_t>(&task_info_data), &count);
-  if (kr != KERN_SUCCESS) {
-    return 0;
+  auto result = ios::device_util::GetTaskVMInfo();
+  if (result.has_value()) {
+    task_vm_info task_vm_info_data = result.value();
+    return task_vm_info_data.resident_size - task_vm_info_data.reusable;
   }
-
-  return task_info_data.resident_size - task_info_data.reusable;
+  return 0;
 }
 
 uint64_t GetDirtyVMBytes() {
@@ -86,17 +83,12 @@
 }
 
 uint64_t GetInternalVMBytes() {
-  task_vm_info_data_t task_vm_info;
-  mach_msg_type_number_t count = TASK_VM_INFO_COUNT;
-  kern_return_t result =
-      task_info(mach_task_self(), TASK_VM_INFO,
-                reinterpret_cast<task_info_t>(&task_vm_info), &count);
-  if (result != KERN_SUCCESS) {
-    LOG(ERROR) << "Calling task_info failed.";
-    return 0;
+  auto result = ios::device_util::GetTaskVMInfo();
+  if (result.has_value()) {
+    task_vm_info task_vm_info_data = result.value();
+    return static_cast<uint64_t>(task_vm_info_data.internal);
   }
-
-  return static_cast<uint64_t>(task_vm_info.internal);
+  LOG(ERROR) << "Calling task_info failed.";
+  return 0;
 }
-
 }  // namespace memory_util
diff --git a/ios/chrome/browser/metrics/model/BUILD.gn b/ios/chrome/browser/metrics/model/BUILD.gn
index cb190b49..cd11dae 100644
--- a/ios/chrome/browser/metrics/model/BUILD.gn
+++ b/ios/chrome/browser/metrics/model/BUILD.gn
@@ -239,6 +239,7 @@
     "//ios/chrome/browser/shared/model/application_context",
     "//ios/chrome/browser/shared/model/prefs:browser_prefs",
     "//ios/chrome/browser/shared/model/prefs:pref_names",
+    "//ios/chrome/browser/shared/model/profile:features",
     "//ios/chrome/browser/shared/model/profile/test",
     "//ios/chrome/browser/shared/public/features",
     "//ios/chrome/browser/signin/model",
diff --git a/ios/chrome/browser/metrics/model/ios_chrome_metrics_service_client.mm b/ios/chrome/browser/metrics/model/ios_chrome_metrics_service_client.mm
index fc2a067..f6e1303e 100644
--- a/ios/chrome/browser/metrics/model/ios_chrome_metrics_service_client.mm
+++ b/ios/chrome/browser/metrics/model/ios_chrome_metrics_service_client.mm
@@ -20,6 +20,7 @@
 #import "base/files/file_path.h"
 #import "base/functional/bind.h"
 #import "base/functional/callback.h"
+#import "base/ios/device_util.h"
 #import "base/metrics/histogram_functions.h"
 #import "base/metrics/histogram_macros.h"
 #import "base/metrics/persistent_histogram_allocator.h"
@@ -404,14 +405,11 @@
 
 void IOSChromeMetricsServiceClient::CollectFinalHistograms() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
-  task_vm_info task_info_data;
-  mach_msg_type_number_t count = sizeof(task_vm_info) / sizeof(natural_t);
-  kern_return_t kr =
-      task_info(mach_task_self(), TASK_VM_INFO,
-                reinterpret_cast<task_info_t>(&task_info_data), &count);
-  if (kr == KERN_SUCCESS) {
-    mach_vm_size_t footprint_mb = task_info_data.phys_footprint / 1024 / 1024;
+  auto result = ios::device_util::GetTaskVMInfo();
+  if (result.has_value()) {
+    task_vm_info task_vm_info_data = result.value();
+    mach_vm_size_t footprint_mb =
+        task_vm_info_data.phys_footprint / 1024 / 1024;
     base::UmaHistogramMemoryLargeMB("Memory.Browser.MemoryFootprint",
                                     footprint_mb);
     // The pseudo metric of Memory.Browser.MemoryFootprint. Only used to
@@ -419,7 +417,8 @@
     base::UmaHistogramMemoryLargeMB(
         "UMA.Pseudo.Memory.Browser.MemoryFootprint",
         metrics::GetPseudoMetricsSample(
-            static_cast<double>(task_info_data.phys_footprint) / 1024 / 1024));
+            static_cast<double>(task_vm_info_data.phys_footprint) / 1024 /
+            1024));
 
     switch (UIApplication.sharedApplication.applicationState) {
       case UIApplicationStateActive:
@@ -449,7 +448,7 @@
     static crash_reporter::CrashKeyString<4> task_info_kern_return(
         "task-info-kern-return");
     char kr_buf[4];
-    base::strings::SafeSPrintf(kr_buf, "%d", kr);
+    base::strings::SafeSPrintf(kr_buf, "%d", result.error());
     task_info_kern_return.Set(kr_buf);
     base::debug::DumpWithoutCrashing();
   }
diff --git a/ios/chrome/browser/metrics/model/ios_feed_enabled_metrics_provider.mm b/ios/chrome/browser/metrics/model/ios_feed_enabled_metrics_provider.mm
index 2f1c2be3..3d3d52e 100644
--- a/ios/chrome/browser/metrics/model/ios_feed_enabled_metrics_provider.mm
+++ b/ios/chrome/browser/metrics/model/ios_feed_enabled_metrics_provider.mm
@@ -19,9 +19,7 @@
 // Returns whether the Feed can be displayed according for `prefs`.
 bool CanDisplayFeed(PrefService* prefs) {
   BOOL is_feed_enabled_by_user =
-      prefs->GetBoolean(prefs::kArticlesForYouEnabled) &&
-      (IsHomeCustomizationEnabled() ||
-       prefs->GetBoolean(feed::prefs::kArticlesListVisible));
+      prefs->GetBoolean(prefs::kArticlesForYouEnabled);
   return is_feed_enabled_by_user &&
          prefs->GetBoolean(prefs::kNTPContentSuggestionsEnabled) &&
          !IsFeedAblationEnabled();
diff --git a/ios/chrome/browser/metrics/model/ios_push_notifications_metrics_provider_unittest.mm b/ios/chrome/browser/metrics/model/ios_push_notifications_metrics_provider_unittest.mm
index 051181e1..4b58865 100644
--- a/ios/chrome/browser/metrics/model/ios_push_notifications_metrics_provider_unittest.mm
+++ b/ios/chrome/browser/metrics/model/ios_push_notifications_metrics_provider_unittest.mm
@@ -12,6 +12,7 @@
 #import "ios/chrome/browser/metrics/model/constants.h"
 #import "ios/chrome/browser/push_notification/model/push_notification_util.h"
 #import "ios/chrome/browser/shared/model/application_context/application_context.h"
+#import "ios/chrome/browser/shared/model/profile/features.h"
 #import "ios/chrome/browser/shared/model/profile/test/test_profile_ios.h"
 #import "ios/chrome/browser/shared/model/profile/test/test_profile_manager_ios.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
diff --git a/ios/chrome/browser/ntp/model/set_up_list.mm b/ios/chrome/browser/ntp/model/set_up_list.mm
index f569fbe..326cdb0a 100644
--- a/ios/chrome/browser/ntp/model/set_up_list.mm
+++ b/ios/chrome/browser/ntp/model/set_up_list.mm
@@ -222,13 +222,7 @@
                    syncService:(syncer::SyncService*)syncService
          authenticationService:(AuthenticationService*)authService
     contentNotificationEnabled:(BOOL)isContentNotificationEnabled {
-  if (IsHomeCustomizationEnabled() &&
-      !prefs->GetBoolean(prefs::kHomeCustomizationMagicStackSetUpListEnabled)) {
-    return nil;
-  }
-
-  if (!IsHomeCustomizationEnabled() &&
-      set_up_list_prefs::IsSetUpListDisabled(localState)) {
+  if (!prefs->GetBoolean(prefs::kHomeCustomizationMagicStackSetUpListEnabled)) {
     return nil;
   }
 
diff --git a/ios/chrome/browser/ntp/model/set_up_list_prefs.mm b/ios/chrome/browser/ntp/model/set_up_list_prefs.mm
index 3ba75bb..288be96 100644
--- a/ios/chrome/browser/ntp/model/set_up_list_prefs.mm
+++ b/ios/chrome/browser/ntp/model/set_up_list_prefs.mm
@@ -107,12 +107,7 @@
 }
 
 void DisableSetUpList(PrefService* prefs) {
-  if (IsHomeCustomizationEnabled()) {
-    prefs->SetBoolean(prefs::kHomeCustomizationMagicStackSetUpListEnabled,
-                      false);
-  } else {
-    prefs->SetBoolean(kDisabled, true);
-  }
+  prefs->SetBoolean(prefs::kHomeCustomizationMagicStackSetUpListEnabled, false);
 }
 
 void RecordInteraction(PrefService* prefs) {
diff --git a/ios/chrome/browser/ntp/shared/metrics/feed_metrics_recorder.h b/ios/chrome/browser/ntp/shared/metrics/feed_metrics_recorder.h
index f423aab..c67cc184 100644
--- a/ios/chrome/browser/ntp/shared/metrics/feed_metrics_recorder.h
+++ b/ios/chrome/browser/ntp/shared/metrics/feed_metrics_recorder.h
@@ -66,34 +66,14 @@
 // Record metrics for when the user has tapped on the feed preview.
 - (void)recordDiscoverFeedPreviewTapped;
 
-// Record metrics for when the user selects the 'Learn More' item in the feed
-// header menu.
-- (void)recordHeaderMenuLearnMoreTapped;
-
 // Record metrics for when the user selects the 'Manage' item in the feed header
 // menu.
 - (void)recordHeaderMenuManageTapped;
 
-// Record metrics for when the user selects the 'Manage Activity' item in the
-// feed header menu.
-- (void)recordHeaderMenuManageActivityTapped;
-
 // Record metrics for when the user selects the 'Following' item in the feed
 // header menu.
 - (void)recordHeaderMenuManageFollowingTapped;
 
-// Record metrics for when the user selects the 'Hidden' item in the feed
-// management UI.
-- (void)recordHeaderMenuManageHiddenTapped;
-
-// Record metrics for when the user selects the 'Following' item in the feed
-// management UI.
-- (void)recordHeaderMenuManageFollowingTapped;
-
-// Record metrics for when the user toggles the feed visibility from the feed
-// header menu.
-- (void)recordDiscoverFeedVisibilityChanged:(BOOL)visible;
-
 // Records metrics for when a user opens an article in the same tab.
 - (void)recordOpenURLInSameTab;
 
diff --git a/ios/chrome/browser/ntp/shared/metrics/feed_metrics_recorder.mm b/ios/chrome/browser/ntp/shared/metrics/feed_metrics_recorder.mm
index 60f998b..85d114e 100644
--- a/ios/chrome/browser/ntp/shared/metrics/feed_metrics_recorder.mm
+++ b/ios/chrome/browser/ntp/shared/metrics/feed_metrics_recorder.mm
@@ -291,14 +291,6 @@
       base::UserMetricsAction(kDiscoverFeedUserActionPreviewTapped));
 }
 
-- (void)recordHeaderMenuLearnMoreTapped {
-  [self
-      recordDiscoverFeedUserActionHistogram:FeedUserActionType::kTappedLearnMore
-                              asInteraction:NO];
-  base::RecordAction(
-      base::UserMetricsAction(kDiscoverFeedUserActionLearnMoreTapped));
-}
-
 - (void)recordHeaderMenuManageTapped {
   [self recordDiscoverFeedUserActionHistogram:FeedUserActionType::kTappedManage
                                 asInteraction:NO];
@@ -306,22 +298,6 @@
       base::UserMetricsAction(kDiscoverFeedUserActionManageTapped));
 }
 
-- (void)recordHeaderMenuManageActivityTapped {
-  [self recordDiscoverFeedUserActionHistogram:FeedUserActionType::
-                                                  kTappedManageActivity
-                                asInteraction:NO];
-  base::RecordAction(
-      base::UserMetricsAction(kDiscoverFeedUserActionManageActivityTapped));
-}
-
-- (void)recordHeaderMenuManageHiddenTapped {
-  [self recordDiscoverFeedUserActionHistogram:FeedUserActionType::
-                                                  kTappedManageHidden
-                                asInteraction:NO];
-  base::RecordAction(
-      base::UserMetricsAction(kDiscoverFeedUserActionManageHiddenTapped));
-}
-
 - (void)recordHeaderMenuManageFollowingTapped {
   [self recordDiscoverFeedUserActionHistogram:FeedUserActionType::
                                                   kTappedManageFollowing
@@ -330,20 +306,6 @@
       base::UserMetricsAction(kDiscoverFeedUserActionManageFollowingTapped));
 }
 
-- (void)recordDiscoverFeedVisibilityChanged:(BOOL)visible {
-  if (visible) {
-    [self
-        recordDiscoverFeedUserActionHistogram:FeedUserActionType::kTappedTurnOn
-                                asInteraction:NO];
-    base::RecordAction(base::UserMetricsAction(kDiscoverFeedUserActionTurnOn));
-  } else {
-    [self
-        recordDiscoverFeedUserActionHistogram:FeedUserActionType::kTappedTurnOff
-                                asInteraction:NO];
-    base::RecordAction(base::UserMetricsAction(kDiscoverFeedUserActionTurnOff));
-  }
-}
-
 - (void)recordOpenURLInSameTab {
   [self recordDiscoverFeedUserActionHistogram:FeedUserActionType::kTappedOnCard
                                 asInteraction:YES];
diff --git a/ios/chrome/browser/ntp/ui_bundled/BUILD.gn b/ios/chrome/browser/ntp/ui_bundled/BUILD.gn
index fc66cf7..c7ce0ee 100644
--- a/ios/chrome/browser/ntp/ui_bundled/BUILD.gn
+++ b/ios/chrome/browser/ntp/ui_bundled/BUILD.gn
@@ -4,7 +4,6 @@
 
 source_set("ui_bundled") {
   sources = [
-    "discover_feed_manage_delegate.h",
     "discover_feed_preview_delegate.h",
     "feed_control_delegate.h",
     "feed_sign_in_promo_delegate.h",
@@ -93,7 +92,6 @@
     ":component_factory_protocol",
     ":constants",
     ":feature_flags",
-    ":feed_menu",
     ":logo",
     ":ntp_internal",
     ":ui_bundled",
@@ -132,7 +130,6 @@
     "//ios/chrome/browser/ntp/shared/metrics",
     "//ios/chrome/browser/ntp/shared/metrics:constants",
     "//ios/chrome/browser/ntp/shared/metrics:home_metrics",
-    "//ios/chrome/browser/ntp/ui_bundled/feed_management",
     "//ios/chrome/browser/ntp/ui_bundled/feed_top_section",
     "//ios/chrome/browser/ntp/ui_bundled/incognito",
     "//ios/chrome/browser/overscroll_actions/ui_bundled",
@@ -146,6 +143,7 @@
     "//ios/chrome/browser/shared/model/prefs",
     "//ios/chrome/browser/shared/model/prefs:pref_names",
     "//ios/chrome/browser/shared/model/profile",
+    "//ios/chrome/browser/shared/model/profile:features",
     "//ios/chrome/browser/shared/model/web_state_list",
     "//ios/chrome/browser/shared/public/commands",
     "//ios/chrome/browser/shared/public/features",
@@ -177,7 +175,6 @@
   sources = [
     "feed_header_view_controller.h",
     "feed_header_view_controller.mm",
-    "feed_menu_commands.h",
     "feed_wrapper_view_controller.h",
     "feed_wrapper_view_controller.mm",
     "new_tab_page_consumer.h",
@@ -234,7 +231,6 @@
     "//ios/chrome/browser/ntp/shared/metrics",
     "//ios/chrome/browser/ntp/shared/metrics:constants",
     "//ios/chrome/browser/ntp/shared/metrics:home_metrics",
-    "//ios/chrome/browser/ntp/ui_bundled/feed_management:navigation_delegate",
     "//ios/chrome/browser/ntp/ui_bundled/resources",
     "//ios/chrome/browser/omnibox/public:features",
     "//ios/chrome/browser/omnibox/ui_bundled:omnibox_internal",
@@ -245,6 +241,7 @@
     "//ios/chrome/browser/regional_capabilities/model",
     "//ios/chrome/browser/search_engines/model",
     "//ios/chrome/browser/shared/model/prefs:pref_names",
+    "//ios/chrome/browser/shared/model/profile:features",
     "//ios/chrome/browser/shared/model/url:constants",
     "//ios/chrome/browser/shared/model/utils",
     "//ios/chrome/browser/shared/model/web_state_list",
@@ -284,29 +281,6 @@
   ]
 }
 
-source_set("feed_menu") {
-  sources = [
-    "feed_menu_coordinator.h",
-    "feed_menu_coordinator.mm",
-  ]
-  deps = [
-    ":ntp_internal",
-    "//components/feed/core/v2/public/ios:feed_ios_public",
-    "//components/prefs",
-    "//ios/chrome/app/strings",
-    "//ios/chrome/browser/shared/coordinator/alert",
-    "//ios/chrome/browser/shared/coordinator/chrome_coordinator",
-    "//ios/chrome/browser/shared/model/browser",
-    "//ios/chrome/browser/shared/model/profile",
-    "//ios/chrome/browser/shared/public/commands",
-    "//ios/chrome/browser/shared/public/features",
-    "//ios/chrome/browser/shared/ui/symbols",
-    "//ios/chrome/browser/signin/model:authentication_service",
-    "//ios/chrome/browser/signin/model:authentication_service_factory",
-    "//ui/strings",
-  ]
-}
-
 source_set("unit_tests") {
   testonly = true
   sources = [
@@ -318,7 +292,6 @@
     ":component_factory",
     ":coordinator",
     ":feature_flags",
-    ":feed_menu",
     ":logo",
     ":ntp_internal",
     ":ui_bundled",
diff --git a/ios/chrome/browser/ntp/ui_bundled/DEPS b/ios/chrome/browser/ntp/ui_bundled/DEPS
index d030bc1..7d76c1a 100644
--- a/ios/chrome/browser/ntp/ui_bundled/DEPS
+++ b/ios/chrome/browser/ntp/ui_bundled/DEPS
@@ -50,7 +50,6 @@
   "+ios/chrome/browser/regional_capabilities/model/regional_capabilities_service_factory.h",
   "+ios/chrome/browser/signin/model/chrome_account_manager_service.h",
   "+ios/chrome/browser/signin/model/chrome_account_manager_service_factory.h",
-  "+ios/chrome/browser/signin/model/chrome_account_manager_service_observer_bridge.h",
   "+ios/chrome/browser/signin/model/identity_manager_factory.h",
   "+ios/chrome/browser/signin/model/system_identity_manager.h",
   "+ios/chrome/browser/supervised_user/model/family_link_user_capabilities_observer_bridge.h",
diff --git a/ios/chrome/browser/ntp/ui_bundled/feed_header_view_controller.h b/ios/chrome/browser/ntp/ui_bundled/feed_header_view_controller.h
index 10a7eff..ed2bba2d 100644
--- a/ios/chrome/browser/ntp/ui_bundled/feed_header_view_controller.h
+++ b/ios/chrome/browser/ntp/ui_bundled/feed_header_view_controller.h
@@ -10,15 +10,11 @@
 #import "ios/chrome/browser/discover_feed/model/feed_constants.h"
 
 @protocol FeedControlDelegate;
-@protocol FeedMenuCommands;
 @class FeedMetricsRecorder;
 @protocol NewTabPageDelegate;
 
 @interface FeedHeaderViewController : UIViewController
 
-// Button for opening top-level feed management menu.
-@property(nonatomic, readonly, strong) UIButton* managementButton;
-
 // Delegate for controlling the presented feed.
 @property(nonatomic, weak) id<FeedControlDelegate> feedControlDelegate;
 
@@ -31,9 +27,6 @@
 // Feed metrics recorder.
 @property(nonatomic, weak) FeedMetricsRecorder* feedMetricsRecorder;
 
-// Object that can open the feed menu.
-@property(nonatomic, weak) id<FeedMenuCommands> feedMenuHandler;
-
 - (instancetype)init NS_DESIGNATED_INITIALIZER;
 - (instancetype)initWithNibName:(NSString*)nibNameOrNil
                          bundle:(NSBundle*)nibBundleOrNil NS_UNAVAILABLE;
diff --git a/ios/chrome/browser/ntp/ui_bundled/feed_header_view_controller.mm b/ios/chrome/browser/ntp/ui_bundled/feed_header_view_controller.mm
index 367cb48..bb26be2 100644
--- a/ios/chrome/browser/ntp/ui_bundled/feed_header_view_controller.mm
+++ b/ios/chrome/browser/ntp/ui_bundled/feed_header_view_controller.mm
@@ -8,7 +8,6 @@
 #import "ios/chrome/browser/ntp/shared/metrics/feed_metrics_recorder.h"
 #import "ios/chrome/browser/ntp/ui_bundled/discover_feed_constants.h"
 #import "ios/chrome/browser/ntp/ui_bundled/feed_control_delegate.h"
-#import "ios/chrome/browser/ntp/ui_bundled/feed_menu_commands.h"
 #import "ios/chrome/browser/ntp/ui_bundled/new_tab_page_constants.h"
 #import "ios/chrome/browser/ntp/ui_bundled/new_tab_page_delegate.h"
 #import "ios/chrome/browser/ntp/ui_bundled/new_tab_page_feature.h"
@@ -51,10 +50,6 @@
 // The size of feed symbol images.
 NSInteger kFeedSymbolPointSize = 17;
 
-// The distance between the custom search engine label and the management
-// button, if both are present.
-const CGFloat kCustomSearchEngineLabelTrailingMargin = 9;
-
 }  // namespace
 
 @interface FeedHeaderViewController ()
@@ -65,10 +60,6 @@
 // Title label element for the feed.
 @property(nonatomic, strong) UILabel* titleLabel;
 
-// Button for opening top-level feed management menu.
-// Redefined to not be readonly.
-@property(nonatomic, strong) UIButton* managementButton;
-
 // Button for sorting feed content. Only used for Following feed.
 @property(nonatomic, strong) UIButton* sortButton;
 
@@ -91,13 +82,7 @@
 @implementation FeedHeaderViewController
 
 - (instancetype)init {
-  self = [super initWithNibName:nil bundle:nil];
-  if (self) {
-    // The menu button is created early so that it can be assigned a tap action
-    // before the view loads.
-    _managementButton = [[UIButton alloc] init];
-  }
-  return self;
+  return [super initWithNibName:nil bundle:nil];
 }
 
 - (void)viewDidLoad {
@@ -115,9 +100,6 @@
   self.view.translatesAutoresizingMaskIntoConstraints = NO;
   self.container.translatesAutoresizingMaskIntoConstraints = NO;
 
-  if (!IsHomeCustomizationEnabled()) {
-    [self configureManagementButton:self.managementButton];
-  }
   [self configureHeaderViews];
 
   [self.view addSubview:self.container];
@@ -193,9 +175,6 @@
 }
 
 - (void)updateForFeedVisibilityChanged {
-  // When feed visibility changes, the menu content is recreated.
-  [self.feedMenuHandler configureManagementMenu:self.managementButton];
-
   if (![self.feedControlDelegate isFollowingFeedAvailable]) {
     [self.titleLabel setText:[self feedHeaderTitleText]];
     [self.titleLabel setNeedsDisplay];
@@ -217,18 +196,6 @@
   [self resetView];
   [self.titleLabel removeFromSuperview];
 
-  // The management button is different for the Following feed header, so it's
-  // recreated.
-  if (self.managementButton) {
-    [self.managementButton removeFromSuperview];
-    self.managementButton = nil;
-  }
-  if (!IsHomeCustomizationEnabled()) {
-    self.managementButton = [[UIButton alloc] init];
-    [self configureManagementButton:self.managementButton];
-    [self.feedMenuHandler configureManagementMenu:self.managementButton];
-  }
-
   [self configureHeaderViews];
   [self applyHeaderConstraints];
 }
@@ -268,9 +235,6 @@
     self.titleLabel = [self createTitleLabel];
     [self.container addSubview:self.titleLabel];
   }
-  if (!IsHomeCustomizationEnabled()) {
-    [self.feedMenuHandler configureManagementMenu:self.managementButton];
-  }
   if (![self.NTPDelegate isGoogleDefaultSearchEngine]) {
     [self addCustomSearchEngineView];
   }
@@ -313,33 +277,6 @@
   return [UIMenu menuWithTitle:@"" children:sortActions];
 }
 
-// Configures the feed header's menu button.
-- (void)configureManagementButton:(UIButton*)managementButton {
-  UIButtonConfiguration* buttonConfiguration =
-      [UIButtonConfiguration plainButtonConfiguration];
-  buttonConfiguration.image =
-      DefaultSymbolTemplateWithPointSize(kMenuSymbol, kFeedSymbolPointSize);
-  if (![self.feedControlDelegate isFollowingFeedAvailable]) {
-    buttonConfiguration.baseForegroundColor =
-        [UIColor colorNamed:kGrey600Color];
-  }
-
-  managementButton.translatesAutoresizingMaskIntoConstraints = NO;
-  managementButton.showsMenuAsPrimaryAction = YES;
-  [managementButton addTarget:self.feedMenuHandler
-                       action:@selector(configureManagementMenu:)
-             forControlEvents:UIControlEventTouchDown];
-
-  managementButton.accessibilityIdentifier =
-      kNTPFeedHeaderManagementButtonIdentifier;
-  managementButton.accessibilityLabel =
-      l10n_util::GetNSString(IDS_IOS_DISCOVER_FEED_MENU_ACCESSIBILITY_LABEL);
-  managementButton.clipsToBounds = YES;
-
-  [self.container addSubview:managementButton];
-  managementButton.configuration = buttonConfiguration;
-}
-
 // Configures and returns the feed header's sorting button.
 - (UIButton*)createSortButton {
   CHECK([self.feedControlDelegate isFollowingFeedAvailable]);
@@ -481,9 +418,6 @@
   self.feedHeaderConstraints = [[NSMutableArray alloc] init];
 
   [self anchorContainer];
-  if (!IsHomeCustomizationEnabled()) {
-    [self anchorManagementButton];
-  }
   if ([self.feedControlDelegate isFollowingFeedAvailable]) {
     [self anchorSegmentedControlAndSortButton];
   } else {
@@ -518,28 +452,6 @@
   ]];
 }
 
-// Anchor management button.
-- (void)anchorManagementButton {
-  CHECK(!IsHomeCustomizationEnabled());
-  NSLayoutConstraint* verticalConstraint;
-  if ([self.feedControlDelegate isFollowingFeedAvailable]) {
-    verticalConstraint = [self.managementButton.centerYAnchor
-        constraintEqualToAnchor:self.container.centerYAnchor];
-  } else {
-    verticalConstraint = [self.managementButton.bottomAnchor
-        constraintEqualToAnchor:self.container.bottomAnchor];
-  }
-  [self.feedHeaderConstraints addObjectsFromArray:@[
-    verticalConstraint,
-    [self.managementButton.trailingAnchor
-        constraintEqualToAnchor:self.container.trailingAnchor
-                       constant:-kButtonHorizontalMargin],
-    // Set menu button size.
-    [self.managementButton.heightAnchor constraintEqualToConstant:kButtonSize],
-    [self.managementButton.widthAnchor constraintEqualToConstant:kButtonSize],
-  ]];
-}
-
 // Anchors the segmented control.
 - (void)anchorSegmentedControl {
   // Anchor segmented control.
@@ -552,14 +464,6 @@
         constraintEqualToAnchor:self.sortButton.trailingAnchor
                        constant:kButtonHorizontalMargin],
   ]];
-
-  if (!IsHomeCustomizationEnabled()) {
-    [self.feedHeaderConstraints addObjectsFromArray:@[
-      [self.segmentedControl.trailingAnchor
-          constraintLessThanOrEqualToAnchor:self.managementButton.leadingAnchor
-                                   constant:-kButtonHorizontalMargin],
-    ]];
-  }
 }
 
 // Anchors feed header elements that should be shown when following feed is
@@ -600,15 +504,12 @@
           [self.NTPDelegate isGoogleDefaultSearchEngine])) {
     return;
   }
-  NSLayoutAnchor* trailingAnchor = IsHomeCustomizationEnabled()
-                                       ? self.container.trailingAnchor
-                                       : self.managementButton.leadingAnchor;
   [self.feedHeaderConstraints addObjectsFromArray:@[
     [self.titleLabel.leadingAnchor
         constraintEqualToAnchor:self.container.leadingAnchor
                        constant:kTitleHorizontalMargin],
     [self.titleLabel.trailingAnchor
-        constraintLessThanOrEqualToAnchor:trailingAnchor],
+        constraintLessThanOrEqualToAnchor:self.container.trailingAnchor],
     [self.titleLabel.bottomAnchor
         constraintEqualToAnchor:self.container.bottomAnchor]
   ]];
@@ -632,18 +533,12 @@
           constraintEqualToAnchor:self.container.topAnchor],
     ]];
   } else {
-    NSLayoutAnchor* trailingAnchor = IsHomeCustomizationEnabled()
-                                         ? self.container.trailingAnchor
-                                         : self.managementButton.leadingAnchor;
-    CGFloat trailingConstant = IsHomeCustomizationEnabled()
-                                   ? kButtonHorizontalMargin
-                                   : kCustomSearchEngineLabelTrailingMargin;
     [self.feedHeaderConstraints addObjectsFromArray:@[
       [self.customSearchEngineView.heightAnchor
           constraintEqualToConstant:kCustomSearchEngineLabelHeight],
       [self.customSearchEngineView.trailingAnchor
-          constraintEqualToAnchor:trailingAnchor
-                         constant:-trailingConstant],
+          constraintEqualToAnchor:self.container.trailingAnchor
+                         constant:-kButtonHorizontalMargin],
       [self.customSearchEngineView.bottomAnchor
           constraintEqualToAnchor:self.container.bottomAnchor]
     ]];
diff --git a/ios/chrome/browser/ntp/ui_bundled/feed_management/BUILD.gn b/ios/chrome/browser/ntp/ui_bundled/feed_management/BUILD.gn
deleted file mode 100644
index 1e28c5d4..0000000
--- a/ios/chrome/browser/ntp/ui_bundled/feed_management/BUILD.gn
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright 2022 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-source_set("feed_management") {
-  sources = [
-    "feed_management_coordinator.h",
-    "feed_management_coordinator.mm",
-  ]
-  deps = [
-    ":feed_management_ui",
-    "//ios/chrome/browser/favicon/model",
-    "//ios/chrome/browser/follow/model:browser_agent",
-    "//ios/chrome/browser/follow/ui_bundled",
-    "//ios/chrome/browser/net/model:crurl",
-    "//ios/chrome/browser/ntp/shared/metrics",
-    "//ios/chrome/browser/shared/coordinator/chrome_coordinator",
-    "//ios/chrome/browser/shared/model/browser",
-    "//ios/chrome/browser/shared/ui/table_view",
-  ]
-  public_deps = [ ":navigation_delegate" ]
-}
-
-source_set("feed_management_ui") {
-  sources = [
-    "feed_management_view_controller.h",
-    "feed_management_view_controller.mm",
-  ]
-  deps = [
-    ":navigation_delegate",
-    "//ios/chrome/app/strings",
-    "//ios/chrome/browser/shared/ui/table_view",
-    "//ios/chrome/browser/shared/ui/table_view/cells",
-    "//ui/base",
-  ]
-}
-
-source_set("navigation_delegate") {
-  sources = [ "feed_management_navigation_delegate.h" ]
-}
diff --git a/ios/chrome/browser/ntp/ui_bundled/feed_management/OWNERS b/ios/chrome/browser/ntp/ui_bundled/feed_management/OWNERS
deleted file mode 100644
index 212313cc..0000000
--- a/ios/chrome/browser/ntp/ui_bundled/feed_management/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-edchin@google.com
-adamta@google.com
-tinazwang@chromium.org
\ No newline at end of file
diff --git a/ios/chrome/browser/ntp/ui_bundled/feed_management/feed_management_coordinator.h b/ios/chrome/browser/ntp/ui_bundled/feed_management/feed_management_coordinator.h
deleted file mode 100644
index 80bba0e43..0000000
--- a/ios/chrome/browser/ntp/ui_bundled/feed_management/feed_management_coordinator.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2022 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_NTP_UI_BUNDLED_FEED_MANAGEMENT_FEED_MANAGEMENT_COORDINATOR_H_
-#define IOS_CHROME_BROWSER_NTP_UI_BUNDLED_FEED_MANAGEMENT_FEED_MANAGEMENT_COORDINATOR_H_
-
-#import "ios/chrome/browser/shared/coordinator/chrome_coordinator/chrome_coordinator.h"
-
-@protocol FeedManagementNavigationDelegate;
-@class FeedMetricsRecorder;
-
-// The top-level owner of the Feed Management component. It serves to connect
-// the various independent pieces such as the Feed Management UI, the Follow
-// Management UI, and mediators.
-@interface FeedManagementCoordinator : ChromeCoordinator
-
-// Delegate for handling web navigation actions.
-@property(nonatomic, weak) id<FeedManagementNavigationDelegate>
-    navigationDelegate;
-
-// Feed metrics recorder.
-@property(nonatomic, weak) FeedMetricsRecorder* feedMetricsRecorder;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_NTP_UI_BUNDLED_FEED_MANAGEMENT_FEED_MANAGEMENT_COORDINATOR_H_
diff --git a/ios/chrome/browser/ntp/ui_bundled/feed_management/feed_management_coordinator.mm b/ios/chrome/browser/ntp/ui_bundled/feed_management/feed_management_coordinator.mm
deleted file mode 100644
index 0e70dba7..0000000
--- a/ios/chrome/browser/ntp/ui_bundled/feed_management/feed_management_coordinator.mm
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2022 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/chrome/browser/ntp/ui_bundled/feed_management/feed_management_coordinator.h"
-
-#import "ios/chrome/browser/favicon/model/ios_chrome_favicon_loader_factory.h"
-#import "ios/chrome/browser/follow/model/follow_browser_agent.h"
-#import "ios/chrome/browser/ntp/shared/metrics/feed_metrics_recorder.h"
-#import "ios/chrome/browser/ntp/ui_bundled/feed_management/feed_management_view_controller.h"
-#import "ios/chrome/browser/shared/ui/table_view/table_view_navigation_controller.h"
-
-@interface FeedManagementCoordinator ()
-
-// The navigation controller into which management UI will be placed. This is a
-// weak reference because we don't want to keep it in memory if it has been
-// dismissed.
-@property(nonatomic, weak) TableViewNavigationController* navigationController;
-
-@end
-
-@implementation FeedManagementCoordinator
-
-- (void)start {
-  FeedManagementViewController* feedManagementViewController =
-      [[FeedManagementViewController alloc]
-          initWithStyle:UITableViewStyleInsetGrouped];
-  feedManagementViewController.navigationDelegate = self.navigationDelegate;
-  TableViewNavigationController* navigationController =
-      [[TableViewNavigationController alloc]
-          initWithTable:feedManagementViewController];
-  self.navigationController = navigationController;
-  [self.baseViewController presentViewController:self.navigationController
-                                        animated:YES
-                                      completion:nil];
-}
-
-- (void)stop {
-  if (self.baseViewController.presentedViewController) {
-    [self.baseViewController dismissViewControllerAnimated:NO completion:nil];
-  }
-  self.navigationController = nil;
-}
-
-@end
diff --git a/ios/chrome/browser/ntp/ui_bundled/feed_management/feed_management_navigation_delegate.h b/ios/chrome/browser/ntp/ui_bundled/feed_management/feed_management_navigation_delegate.h
deleted file mode 100644
index 14d78f2..0000000
--- a/ios/chrome/browser/ntp/ui_bundled/feed_management/feed_management_navigation_delegate.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2022 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_NTP_UI_BUNDLED_FEED_MANAGEMENT_FEED_MANAGEMENT_NAVIGATION_DELEGATE_H_
-#define IOS_CHROME_BROWSER_NTP_UI_BUNDLED_FEED_MANAGEMENT_FEED_MANAGEMENT_NAVIGATION_DELEGATE_H_
-
-class GURL;
-
-// Delegate for handling navigation actions.
-@protocol FeedManagementNavigationDelegate
-
-// Navigate to activity.
-- (void)handleNavigateToActivity;
-
-// Navigate to follow manager.
-- (void)handleNavigateToFollowing;
-
-// Navigate to hidden.
-- (void)handleNavigateToHidden;
-
-// Navigate to `url` of a followed site.
-- (void)handleNavigateToFollowedURL:(const GURL&)url;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_NTP_UI_BUNDLED_FEED_MANAGEMENT_FEED_MANAGEMENT_NAVIGATION_DELEGATE_H_
diff --git a/ios/chrome/browser/ntp/ui_bundled/feed_management/feed_management_view_controller.h b/ios/chrome/browser/ntp/ui_bundled/feed_management/feed_management_view_controller.h
deleted file mode 100644
index 4f7fc027..0000000
--- a/ios/chrome/browser/ntp/ui_bundled/feed_management/feed_management_view_controller.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2022 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_NTP_UI_BUNDLED_FEED_MANAGEMENT_FEED_MANAGEMENT_VIEW_CONTROLLER_H_
-#define IOS_CHROME_BROWSER_NTP_UI_BUNDLED_FEED_MANAGEMENT_FEED_MANAGEMENT_VIEW_CONTROLLER_H_
-
-#import "ios/chrome/browser/shared/ui/table_view/legacy_chrome_table_view_controller.h"
-
-@protocol FeedManagementNavigationDelegate;
-
-// The UI that displays various settings for the feed (e.g., following,
-// interests, hidden, activity).
-@interface FeedManagementViewController : LegacyChromeTableViewController
-
-// Delegate to execute user actions related to navigation.
-@property(nonatomic, weak) id<FeedManagementNavigationDelegate>
-    navigationDelegate;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_NTP_UI_BUNDLED_FEED_MANAGEMENT_FEED_MANAGEMENT_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ntp/ui_bundled/feed_management/feed_management_view_controller.mm b/ios/chrome/browser/ntp/ui_bundled/feed_management/feed_management_view_controller.mm
deleted file mode 100644
index 496ae9e..0000000
--- a/ios/chrome/browser/ntp/ui_bundled/feed_management/feed_management_view_controller.mm
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright 2022 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/chrome/browser/ntp/ui_bundled/feed_management/feed_management_view_controller.h"
-
-#import "ios/chrome/browser/ntp/ui_bundled/feed_management/feed_management_navigation_delegate.h"
-#import "ios/chrome/browser/shared/ui/table_view/cells/table_view_detail_text_item.h"
-#import "ios/chrome/grit/ios_strings.h"
-#import "ui/base/l10n/l10n_util_mac.h"
-
-namespace {
-
-// These values are used in the TableViewModel to indicate sections of the
-// table.
-typedef NS_ENUM(NSInteger, SectionIdentifier) {
-  FeedManagementSectionIdentifier = kSectionIdentifierEnumZero,
-};
-
-// These values are used in the TableViewModel to indicate specific rows.
-typedef NS_ENUM(NSInteger, ItemType) {
-  FollowingItemType = kItemTypeEnumZero,
-  HiddenItemType,
-  ActivityItemType,
-};
-
-}  // namespace
-
-@implementation FeedManagementViewController
-
-- (void)viewDidLoad {
-  [super viewDidLoad];
-  self.tableView.separatorInset =
-      UIEdgeInsetsMake(0, kTableViewSeparatorInset, 0, 0);
-  self.title = l10n_util::GetNSString(IDS_IOS_FEED_MANAGEMENT_TITLE);
-  self.navigationController.navigationBar.prefersLargeTitles = YES;
-
-  UIBarButtonItem* doneButton = [[UIBarButtonItem alloc]
-      initWithBarButtonSystemItem:UIBarButtonSystemItemDone
-                    primaryAction:[UIAction
-                                      actionWithHandler:^(UIAction* action) {
-                                        [self.parentViewController
-                                            dismissViewControllerAnimated:YES
-                                                               completion:nil];
-                                      }]];
-  self.navigationItem.rightBarButtonItem = doneButton;
-
-  [self loadModel];
-}
-
-- (void)viewWillAppear:(BOOL)animated {
-  [super viewWillAppear:animated];
-  self.navigationController.toolbarHidden = YES;
-}
-
-- (void)loadModel {
-  [super loadModel];
-  TableViewModel* model = self.tableViewModel;
-
-  [model addSectionWithIdentifier:FeedManagementSectionIdentifier];
-
-  TableViewDetailTextItem* followingItem =
-      [[TableViewDetailTextItem alloc] initWithType:FollowingItemType];
-  followingItem.text =
-      l10n_util::GetNSString(IDS_IOS_FEED_MANAGEMENT_FOLLOWING_TEXT);
-  followingItem.detailText =
-      l10n_util::GetNSString(IDS_IOS_FEED_MANAGEMENT_FOLLOWING_DETAIL);
-  followingItem.accessorySymbol =
-      TableViewDetailTextCellAccessorySymbolExternalLink;
-  followingItem.allowMultilineDetailText = YES;
-  [model addItem:followingItem
-      toSectionWithIdentifier:FeedManagementSectionIdentifier];
-
-  TableViewDetailTextItem* hiddenItem =
-      [[TableViewDetailTextItem alloc] initWithType:HiddenItemType];
-  hiddenItem.text = l10n_util::GetNSString(IDS_IOS_FEED_MANAGEMENT_HIDDEN_TEXT);
-  hiddenItem.detailText =
-      l10n_util::GetNSString(IDS_IOS_FEED_MANAGEMENT_HIDDEN_DETAIL);
-  hiddenItem.accessorySymbol =
-      TableViewDetailTextCellAccessorySymbolExternalLink;
-  hiddenItem.allowMultilineDetailText = YES;
-  [model addItem:hiddenItem
-      toSectionWithIdentifier:FeedManagementSectionIdentifier];
-
-  TableViewDetailTextItem* activityItem =
-      [[TableViewDetailTextItem alloc] initWithType:ActivityItemType];
-  activityItem.text =
-      l10n_util::GetNSString(IDS_IOS_FEED_MANAGEMENT_ACTIVITY_TEXT);
-  activityItem.detailText =
-      l10n_util::GetNSString(IDS_IOS_FEED_MANAGEMENT_ACTIVITY_DETAIL);
-  activityItem.accessorySymbol =
-      TableViewDetailTextCellAccessorySymbolExternalLink;
-  activityItem.allowMultilineDetailText = YES;
-  [model addItem:activityItem
-      toSectionWithIdentifier:FeedManagementSectionIdentifier];
-}
-
-#pragma mark UITableViewDelegate
-
-- (void)tableView:(UITableView*)tableView
-    didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
-  NSInteger itemType = [self.tableViewModel itemTypeForIndexPath:indexPath];
-  __weak FeedManagementViewController* weakSelf = self;
-  switch (itemType) {
-    case FollowingItemType: {
-      [self dismissViewControllerAnimated:YES
-                               completion:^{
-                                 [weakSelf.navigationDelegate
-                                         handleNavigateToFollowing];
-                               }];
-      break;
-    }
-    case HiddenItemType: {
-      [self dismissViewControllerAnimated:YES
-                               completion:^{
-                                 [weakSelf.navigationDelegate
-                                         handleNavigateToHidden];
-                               }];
-      break;
-    }
-    case ActivityItemType: {
-      [self dismissViewControllerAnimated:YES
-                               completion:^{
-                                 [weakSelf.navigationDelegate
-                                         handleNavigateToActivity];
-                               }];
-      break;
-    }
-  }
-}
-
-@end
diff --git a/ios/chrome/browser/ntp/ui_bundled/feed_management/resources/Assets.xcassets/Contents.json b/ios/chrome/browser/ntp/ui_bundled/feed_management/resources/Assets.xcassets/Contents.json
deleted file mode 100644
index 73c0059..0000000
--- a/ios/chrome/browser/ntp/ui_bundled/feed_management/resources/Assets.xcassets/Contents.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-  "info" : {
-    "author" : "xcode",
-    "version" : 1
-  }
-}
diff --git a/ios/chrome/browser/ntp/ui_bundled/feed_management/resources/Assets.xcassets/following_empty.imageset/Contents.json b/ios/chrome/browser/ntp/ui_bundled/feed_management/resources/Assets.xcassets/following_empty.imageset/Contents.json
deleted file mode 100644
index f29b509..0000000
--- a/ios/chrome/browser/ntp/ui_bundled/feed_management/resources/Assets.xcassets/following_empty.imageset/Contents.json
+++ /dev/null
@@ -1,25 +0,0 @@
-{
-  "images" : [
-    {
-      "filename" : "following_empty.pdf",
-      "idiom" : "universal"
-    },
-    {
-      "appearances" : [
-        {
-          "appearance" : "luminosity",
-          "value" : "dark"
-        }
-      ],
-      "filename" : "following_empty_dark.pdf",
-      "idiom" : "universal"
-    }
-  ],
-  "info" : {
-    "author" : "xcode",
-    "version" : 1
-  },
-  "properties" : {
-    "preserves-vector-representation" : true
-  }
-}
\ No newline at end of file
diff --git a/ios/chrome/browser/ntp/ui_bundled/feed_management/resources/Assets.xcassets/following_empty.imageset/following_empty.pdf b/ios/chrome/browser/ntp/ui_bundled/feed_management/resources/Assets.xcassets/following_empty.imageset/following_empty.pdf
deleted file mode 100644
index 42beb69e..0000000
--- a/ios/chrome/browser/ntp/ui_bundled/feed_management/resources/Assets.xcassets/following_empty.imageset/following_empty.pdf
+++ /dev/null
Binary files differ
diff --git a/ios/chrome/browser/ntp/ui_bundled/feed_management/resources/Assets.xcassets/following_empty.imageset/following_empty_dark.pdf b/ios/chrome/browser/ntp/ui_bundled/feed_management/resources/Assets.xcassets/following_empty.imageset/following_empty_dark.pdf
deleted file mode 100644
index 426e4cd..0000000
--- a/ios/chrome/browser/ntp/ui_bundled/feed_management/resources/Assets.xcassets/following_empty.imageset/following_empty_dark.pdf
+++ /dev/null
Binary files differ
diff --git a/ios/chrome/browser/ntp/ui_bundled/feed_management/resources/BUILD.gn b/ios/chrome/browser/ntp/ui_bundled/feed_management/resources/BUILD.gn
deleted file mode 100644
index 2af0e75..0000000
--- a/ios/chrome/browser/ntp/ui_bundled/feed_management/resources/BUILD.gn
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright 2022 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//build/config/ios/rules.gni")
-
-bundle_data_xcassets("resources") {
-  catalog = "Assets.xcassets"
-  sources = [
-    "Assets.xcassets/Contents.json",
-    "Assets.xcassets/following_empty.imageset/Contents.json",
-    "Assets.xcassets/following_empty.imageset/following_empty.pdf",
-    "Assets.xcassets/following_empty.imageset/following_empty_dark.pdf",
-  ]
-}
diff --git a/ios/chrome/browser/ntp/ui_bundled/feed_menu_commands.h b/ios/chrome/browser/ntp/ui_bundled/feed_menu_commands.h
deleted file mode 100644
index 87ff57a7..0000000
--- a/ios/chrome/browser/ntp/ui_bundled/feed_menu_commands.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2021 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_NTP_UI_BUNDLED_FEED_MENU_COMMANDS_H_
-#define IOS_CHROME_BROWSER_NTP_UI_BUNDLED_FEED_MENU_COMMANDS_H_
-
-#import <UIKit/UIKit.h>
-
-// Protocol for actions relating to the NTP feed top-level control menu.
-@protocol FeedMenuCommands
-
-// Creates feed management menu for a `button`.
-- (void)configureManagementMenu:(UIButton*)button;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_NTP_UI_BUNDLED_FEED_MENU_COMMANDS_H_
diff --git a/ios/chrome/browser/ntp/ui_bundled/feed_menu_coordinator.h b/ios/chrome/browser/ntp/ui_bundled/feed_menu_coordinator.h
deleted file mode 100644
index 12d63802..0000000
--- a/ios/chrome/browser/ntp/ui_bundled/feed_menu_coordinator.h
+++ /dev/null
@@ -1,40 +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 IOS_CHROME_BROWSER_NTP_UI_BUNDLED_FEED_MENU_COORDINATOR_H_
-#define IOS_CHROME_BROWSER_NTP_UI_BUNDLED_FEED_MENU_COORDINATOR_H_
-
-#import "ios/chrome/browser/ntp/ui_bundled/feed_menu_commands.h"
-#import "ios/chrome/browser/shared/coordinator/chrome_coordinator/chrome_coordinator.h"
-
-// An enum of all the Feed Menu item types.
-enum class FeedMenuItemType {
-  kTurnOff,
-  kTurnOn,
-  kManage,
-  kManageActivity,
-  kManageFollowing,
-  kLearnMore,
-
-  kMaxValue = kLearnMore,
-};
-
-// Defines callbacks that the FeedMenuCoordinator will send.
-@protocol FeedMenuCoordinatorDelegate
-
-// Called when a Feed Menu item is selected by the user.
-- (void)didSelectFeedMenuItem:(FeedMenuItemType)item;
-
-@end
-
-// A coordinator which can display the Feed Menu and notify the delegate when
-// an item is selected.
-@interface FeedMenuCoordinator : ChromeCoordinator <FeedMenuCommands>
-
-// A delegate to receive callbacks when a Feed Menu item is selected.
-@property(nonatomic, weak) id<FeedMenuCoordinatorDelegate> delegate;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_NTP_UI_BUNDLED_FEED_MENU_COORDINATOR_H_
diff --git a/ios/chrome/browser/ntp/ui_bundled/feed_menu_coordinator.mm b/ios/chrome/browser/ntp/ui_bundled/feed_menu_coordinator.mm
deleted file mode 100644
index 92bace8..0000000
--- a/ios/chrome/browser/ntp/ui_bundled/feed_menu_coordinator.mm
+++ /dev/null
@@ -1,143 +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 "ios/chrome/browser/ntp/ui_bundled/feed_menu_coordinator.h"
-
-#import "components/feed/core/v2/public/ios/pref_names.h"
-#import "components/prefs/pref_service.h"
-#import "ios/chrome/browser/shared/coordinator/alert/action_sheet_coordinator.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/public/commands/command_dispatcher.h"
-#import "ios/chrome/browser/shared/public/features/features.h"
-#import "ios/chrome/browser/shared/ui/symbols/symbols.h"
-#import "ios/chrome/browser/signin/model/authentication_service.h"
-#import "ios/chrome/browser/signin/model/authentication_service_factory.h"
-#import "ios/chrome/grit/ios_strings.h"
-#import "ui/base/l10n/l10n_util_mac.h"
-#import "ui/strings/grit/ui_strings.h"
-
-namespace {
-// The size of the icons in the management context menu.
-const CGFloat kManagementContextMenuIconSize = 18;
-}  // namespace
-
-@implementation FeedMenuCoordinator
-
-#pragma mark - ChromeCoordinator
-
-- (void)start {
-  [self.browser->GetCommandDispatcher()
-      startDispatchingToTarget:self
-                   forProtocol:@protocol(FeedMenuCommands)];
-}
-
-- (void)stop {
-  [self.browser->GetCommandDispatcher()
-      stopDispatchingForProtocol:@protocol(FeedMenuCommands)];
-  self.delegate = nil;
-}
-
-#pragma mark - FeedMenuCommands
-
-- (void)configureManagementMenu:(UIButton*)button {
-  NSMutableArray<UIAction*>* feedActions = [NSMutableArray array];
-
-  FeedMenuItemType toggle = [self isFeedExpanded] ? FeedMenuItemType::kTurnOff
-                                                  : FeedMenuItemType::kTurnOn;
-  [feedActions addObject:[self createMenuAction:toggle]];
-
-  if ([self isSignedIn]) {
-    if (IsWebChannelsEnabled()) {
-      // Following feed is available.
-      [feedActions addObject:[self createMenuAction:FeedMenuItemType::kManage]];
-    } else {
-      [feedActions
-          addObject:[self createMenuAction:FeedMenuItemType::kManageActivity]];
-      [feedActions
-          addObject:[self createMenuAction:FeedMenuItemType::kManageFollowing]];
-    }
-  }
-
-  [feedActions addObject:[self createMenuAction:FeedMenuItemType::kLearnMore]];
-
-  button.menu = [UIMenu menuWithTitle:@"" children:feedActions];
-}
-
-#pragma mark - Private methods
-
-// True if the feed is currently expanded. When not expanded, the feed header
-// is shown, but not any of the feed content.
-- (bool)isFeedExpanded {
-  if (IsHomeCustomizationEnabled()) {
-    return YES;
-  }
-  PrefService* prefService = self.profile->GetPrefs();
-  return prefService->GetBoolean(feed::prefs::kArticlesListVisible);
-}
-
-// True if the user is signed in.
-- (bool)isSignedIn {
-  AuthenticationService* authService =
-      AuthenticationServiceFactory::GetForProfile(self.profile);
-  return authService->HasPrimaryIdentity(signin::ConsentLevel::kSignin);
-}
-
-// Returns the message id to use for the title for an item of the given `type`.
-- (int)titleMessageIdForMenuAction:(FeedMenuItemType)type {
-  switch (type) {
-    case FeedMenuItemType::kTurnOff:
-      return IDS_IOS_DISCOVER_FEED_MENU_TURN_OFF_ITEM;
-    case FeedMenuItemType::kTurnOn:
-      return IDS_IOS_DISCOVER_FEED_MENU_TURN_ON_ITEM;
-    case FeedMenuItemType::kManage:
-      return IDS_IOS_DISCOVER_FEED_MENU_MANAGE_ITEM;
-    case FeedMenuItemType::kManageActivity:
-      return IDS_IOS_DISCOVER_FEED_MENU_MANAGE_ACTIVITY_ITEM;
-    case FeedMenuItemType::kManageFollowing:
-      return IDS_IOS_DISCOVER_FEED_MENU_MANAGE_INTERESTS_ITEM;
-    case FeedMenuItemType::kLearnMore:
-      return IDS_IOS_DISCOVER_FEED_MENU_LEARN_MORE_ITEM;
-  }
-}
-
-// Returns an image icon for the context menu item.
-- (UIImage*)iconForMenuAction:(FeedMenuItemType)type {
-  switch (type) {
-    case FeedMenuItemType::kTurnOff:
-      return DefaultSymbolWithPointSize(kMinusInCircleSymbol,
-                                        kManagementContextMenuIconSize);
-    case FeedMenuItemType::kTurnOn:
-      return DefaultSymbolWithPointSize(kPlusInCircleSymbol,
-                                        kManagementContextMenuIconSize);
-    case FeedMenuItemType::kManage:
-      return DefaultSymbolWithPointSize(kSliderHorizontalSymbol,
-                                        kManagementContextMenuIconSize);
-    case FeedMenuItemType::kManageActivity:
-      return DefaultSymbolWithPointSize(kSliderHorizontalSymbol,
-                                        kManagementContextMenuIconSize);
-    case FeedMenuItemType::kManageFollowing:
-      return DefaultSymbolWithPointSize(kSliderHorizontalSymbol,
-                                        kManagementContextMenuIconSize);
-    case FeedMenuItemType::kLearnMore:
-      return DefaultSymbolWithPointSize(kInfoCircleSymbol,
-                                        kManagementContextMenuIconSize);
-  }
-}
-
-// Creates an action to be added to the management menu.
-- (UIAction*)createMenuAction:(FeedMenuItemType)type {
-  __weak __typeof(self) weakSelf = self;
-  UIAction* menuAction =
-      [UIAction actionWithTitle:l10n_util::GetNSString(
-                                    [self titleMessageIdForMenuAction:type])
-                          image:[self iconForMenuAction:type]
-                     identifier:nil
-                        handler:^(UIAction* action) {
-                          [weakSelf.delegate didSelectFeedMenuItem:type];
-                        }];
-  return menuAction;
-}
-
-@end
diff --git a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_constants.h b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_constants.h
index c7b06bc..cc5b8de 100644
--- a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_constants.h
+++ b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_constants.h
@@ -19,9 +19,6 @@
 // Represents the feed header container.
 extern NSString* const kNTPFeedHeaderIdentifier;
 
-// Represents the management button of the feed header.
-extern NSString* const kNTPFeedHeaderManagementButtonIdentifier;
-
 // Represents the sort button of the feed header.
 extern NSString* const kNTPFeedHeaderSortButtonIdentifier;
 
@@ -48,4 +45,7 @@
 // entrypoint.
 extern const NSInteger kCustomizationNewBadgeMaxImpressionCount;
 
+// The bottom spacing underneath the Magic Stack.
+extern const float kBottomMagicStackPadding;
+
 #endif  // IOS_CHROME_BROWSER_NTP_UI_BUNDLED_NEW_TAB_PAGE_CONSTANTS_H_
diff --git a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_constants.mm b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_constants.mm
index 58d7da3..e7eb3f7 100644
--- a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_constants.mm
+++ b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_constants.mm
@@ -12,9 +12,6 @@
 
 NSString* const kNTPFeedHeaderIdentifier = @"kNTPFeedHeaderIdentifier";
 
-NSString* const kNTPFeedHeaderManagementButtonIdentifier =
-    @"kNTPFeedHeaderManagementButtonIdentifier";
-
 NSString* const kNTPFeedHeaderSortButtonIdentifier =
     @"kNTPFeedHeaderSortButtonIdentifier";
 
@@ -34,3 +31,5 @@
 const CGFloat kHomeModuleMinimumPadding = 4;
 
 const NSInteger kCustomizationNewBadgeMaxImpressionCount = 3;
+
+const float kBottomMagicStackPadding = 14.0f;
diff --git a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_coordinator.mm b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_coordinator.mm
index f097c8b9..d08c294 100644
--- a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_coordinator.mm
+++ b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_coordinator.mm
@@ -56,12 +56,9 @@
 #import "ios/chrome/browser/ntp/shared/metrics/new_tab_page_metrics_constants.h"
 #import "ios/chrome/browser/ntp/shared/metrics/new_tab_page_metrics_recorder.h"
 #import "ios/chrome/browser/ntp/ui_bundled/discover_feed_constants.h"
-#import "ios/chrome/browser/ntp/ui_bundled/discover_feed_manage_delegate.h"
 #import "ios/chrome/browser/ntp/ui_bundled/discover_feed_preview_delegate.h"
 #import "ios/chrome/browser/ntp/ui_bundled/feed_control_delegate.h"
 #import "ios/chrome/browser/ntp/ui_bundled/feed_header_view_controller.h"
-#import "ios/chrome/browser/ntp/ui_bundled/feed_management/feed_management_coordinator.h"
-#import "ios/chrome/browser/ntp/ui_bundled/feed_menu_coordinator.h"
 #import "ios/chrome/browser/ntp/ui_bundled/feed_sign_in_promo_delegate.h"
 #import "ios/chrome/browser/ntp/ui_bundled/feed_top_section/feed_top_section_coordinator.h"
 #import "ios/chrome/browser/ntp/ui_bundled/feed_wrapper_view_controller.h"
@@ -89,6 +86,7 @@
 #import "ios/chrome/browser/shared/model/browser/browser.h"
 #import "ios/chrome/browser/shared/model/prefs/pref_backed_boolean.h"
 #import "ios/chrome/browser/shared/model/prefs/pref_names.h"
+#import "ios/chrome/browser/shared/model/profile/features.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/application_commands.h"
@@ -133,11 +131,9 @@
 @interface NewTabPageCoordinator () <AuthenticationServiceObserving,
                                      BooleanObserver,
                                      ContentSuggestionsDelegate,
-                                     DiscoverFeedManageDelegate,
                                      DiscoverFeedObserverBridgeDelegate,
                                      DiscoverFeedPreviewDelegate,
                                      FeedControlDelegate,
-                                     FeedMenuCoordinatorDelegate,
                                      FeedSignInPromoDelegate,
                                      FeedWrapperViewControllerDelegate,
                                      HomeCustomizationDelegate,
@@ -206,10 +202,6 @@
 // PrefService used by this Coordinator.
 @property(nonatomic, assign) PrefService* prefService;
 
-// Whether the feed is expanded or collapsed. Collapsed
-// means the feed header is shown, but not any of the feed content.
-@property(nonatomic, strong) PrefBackedBoolean* feedExpandedPref;
-
 // The view controller representing the selected feed, such as the Discover or
 // Following feed.
 @property(nonatomic, weak) UIViewController* feedViewController;
@@ -221,9 +213,6 @@
 // The view controller representing the NTP feed header.
 @property(nonatomic, strong) FeedHeaderViewController* feedHeaderViewController;
 
-// Coordinator for handling the feed menu.
-@property(nonatomic, strong) FeedMenuCoordinator* feedMenuCoordinator;
-
 // Authentication Service for the user's signed-in state.
 @property(nonatomic, assign) AuthenticationService* authService;
 
@@ -240,10 +229,6 @@
 @property(nonatomic, strong)
     NewTabPageHeaderViewController* headerViewController;
 
-// The coordinator for handling feed management.
-@property(nonatomic, strong)
-    FeedManagementCoordinator* feedManagementCoordinator;
-
 // Coordinator for Feed top section.
 @property(nonatomic, strong)
     FeedTopSectionCoordinator* feedTopSectionCoordinator;
@@ -400,8 +385,6 @@
   [_tabGroupIndicatorCoordinator stop];
   _tabGroupIndicatorCoordinator = nil;
 
-  [self.feedManagementCoordinator stop];
-  self.feedManagementCoordinator = nil;
   [self.contentSuggestionsCoordinator stop];
   self.contentSuggestionsCoordinator = nil;
   self.headerViewController = nil;
@@ -439,13 +422,6 @@
   self.feedMetricsRecorder.NTPActionsDelegate = nil;
   self.feedMetricsRecorder = nil;
 
-  [self.feedExpandedPref stop];
-  [self.feedExpandedPref setObserver:nil];
-  self.feedExpandedPref = nil;
-
-  [self.feedMenuCoordinator stop];
-  self.feedMenuCoordinator = nil;
-
   _familyLinkUserCapabilitiesObserverBridge.reset();
   _discoverFeedObserverBridge.reset();
   _identityObserverBridge.reset();
@@ -497,9 +473,7 @@
 }
 
 - (void)focusFakebox {
-  if (IsHomeCustomizationEnabled()) {
-    [self dismissCustomizationMenu];
-  }
+  [self dismissCustomizationMenu];
   _fakeboxTapped = NO;
   [self.NTPViewController focusOmnibox];
 }
@@ -533,12 +507,9 @@
   if (self.profile->IsOffTheRecord()) {
     return;
   }
-  UIView* viewToConstrain =
-      IsHomeCustomizationEnabled()
-          ? [self.headerViewController customizationMenuButton]
-          : self.feedHeaderViewController.managementButton;
-  [LayoutGuideCenterForBrowser(self.browser) referenceView:viewToConstrain
-                                                 underName:kFeedIPHNamedGuide];
+  [LayoutGuideCenterForBrowser(self.browser)
+      referenceView:[self.headerViewController customizationMenuButton]
+          underName:kFeedIPHNamedGuide];
 }
 
 - (void)updateFollowingFeedHasUnseenContent:(BOOL)hasUnseenContent {
@@ -568,9 +539,7 @@
 
 - (void)didNavigateAwayFromNTP {
   [self cancelOmniboxEdit];
-  if (IsHomeCustomizationEnabled()) {
-    [self dismissCustomizationMenu];
-  }
+  [self dismissCustomizationMenu];
   [self saveNTPState];
   [self updateNTPIsVisible:NO];
   [self updateStartForVisibilityChange:NO];
@@ -635,12 +604,6 @@
   DCHECK(self.prefService);
   DCHECK(self.headerViewController);
 
-  self.feedExpandedPref = [[PrefBackedBoolean alloc]
-      initWithPrefService:self.prefService
-                 prefName:feed::prefs::kArticlesListVisible];
-  // Observer is necessary for multiwindow NTPs to remain in sync.
-  [self.feedExpandedPref setObserver:self];
-
   // Start observing IdentityManager.
   signin::IdentityManager* identityManager =
       IdentityManagerFactory::GetForProfile(self.profile);
@@ -694,13 +657,6 @@
   if (!self.feedHeaderViewController) {
     self.feedHeaderViewController =
         [self.componentFactory feedHeaderViewController];
-    self.feedMenuCoordinator = [[FeedMenuCoordinator alloc]
-        initWithBaseViewController:self.NTPViewController
-                           browser:self.browser];
-    self.feedMenuCoordinator.delegate = self;
-    [self.feedMenuCoordinator start];
-    self.feedHeaderViewController.feedMenuHandler = HandlerForProtocol(
-        self.browser->GetCommandDispatcher(), FeedMenuCommands);
   }
 
   self.feedHeaderViewController.feedControlDelegate = self;
@@ -895,9 +851,7 @@
 }
 
 - (void)fakeboxTapped {
-  if (IsHomeCustomizationEnabled()) {
-    [self dismissCustomizationMenu];
-  }
+  [self dismissCustomizationMenu];
   _fakeboxTapped = YES;
   [self.NTPViewController focusOmnibox];
 }
@@ -907,9 +861,7 @@
     // Double tap, or tap before dismissing of the previous one is complete.
     return;
   }
-  if (IsHomeCustomizationEnabled()) {
-    [self dismissCustomizationMenu];
-  }
+  [self dismissCustomizationMenu];
   [self.NTPMetricsRecorder recordIdentityDiscTapped];
   id<ApplicationCommands> handler = HandlerForProtocol(
       self.browser->GetCommandDispatcher(), ApplicationCommands);
@@ -977,37 +929,6 @@
   [self openCustomizationMenuAtPage:CustomizationMenuPage::kMain animated:YES];
 }
 
-#pragma mark - FeedMenuCoordinatorDelegate
-
-- (void)didSelectFeedMenuItem:(FeedMenuItemType)item {
-  switch (item) {
-    case FeedMenuItemType::kTurnOff:
-      [self setFeedVisibleFromHeader:NO];
-      break;
-    case FeedMenuItemType::kTurnOn:
-      [self setFeedVisibleFromHeader:YES];
-      break;
-    case FeedMenuItemType::kManage:
-      [self handleFeedManageTapped];
-      break;
-    case FeedMenuItemType::kManageActivity:
-      [self.NTPMediator handleNavigateToActivity];
-      break;
-    case FeedMenuItemType::kManageFollowing:
-      [self.NTPMediator handleNavigateToFollowing];
-      break;
-    case FeedMenuItemType::kLearnMore:
-      [self.NTPMediator handleFeedLearnMoreTapped];
-      break;
-  }
-}
-
-#pragma mark - DiscoverFeedManageDelegate
-
-- (void)didTapDiscoverFeedManage {
-  [self handleFeedManageTapped];
-}
-
 #pragma mark - DiscoverFeedPreviewDelegate
 
 - (UIViewController*)discoverFeedPreviewWithURL:(const GURL)URL {
@@ -1088,8 +1009,7 @@
 }
 
 - (BOOL)shouldFeedBeVisible {
-  return self.NTPMediator.feedHeaderVisible &&
-         ([self.feedExpandedPref value] || IsHomeCustomizationEnabled());
+  return self.NTPMediator.feedHeaderVisible;
 }
 
 - (BOOL)isFollowingFeedAvailable {
@@ -1461,7 +1381,7 @@
 
 - (BOOL)shouldAllowOverscrollActionsForOverscrollActionsController:
     (OverscrollActionsController*)controller {
-  return !IsHomeCustomizationEnabled() || !_customizationCoordinator;
+  return !_customizationCoordinator;
 }
 
 - (UIView*)toolbarSnapshotViewForOverscrollActionsController:
@@ -1707,21 +1627,11 @@
   viewControllerConfig.browser = self.browser;
   viewControllerConfig.scrollDelegate = self.NTPViewController;
   viewControllerConfig.previewDelegate = self;
-  viewControllerConfig.manageDelegate = self;
   viewControllerConfig.signInPromoDelegate = self;
 
   return viewControllerConfig;
 }
 
-// Toggles feed visibility between hidden or expanded using the feed header
-// menu. A hidden feed will continue to show the header, with a modified label.
-// TODO(crbug.com/1304382): Modify this comment when Web Channels is launched.
-- (void)setFeedVisibleFromHeader:(BOOL)visible {
-  [self.feedExpandedPref setValue:visible];
-  [self.feedMetricsRecorder recordDiscoverFeedVisibilityChanged:visible];
-  [self updateModuleVisibility];
-}
-
 // Configures and returns the feed top section coordinator.
 - (FeedTopSectionCoordinator*)createFeedTopSectionCoordinator {
   DCHECK(self.NTPViewController);
@@ -1734,20 +1644,6 @@
   return feedTopSectionCoordinator;
 }
 
-// Handles the feed management button being tapped.
-- (void)handleFeedManageTapped {
-  [self.feedMetricsRecorder recordHeaderMenuManageTapped];
-  [self.feedManagementCoordinator stop];
-  self.feedManagementCoordinator = nil;
-
-  self.feedManagementCoordinator = [[FeedManagementCoordinator alloc]
-      initWithBaseViewController:self.NTPViewController
-                         browser:self.browser];
-  self.feedManagementCoordinator.navigationDelegate = self.NTPMediator;
-  self.feedManagementCoordinator.feedMetricsRecorder = self.feedMetricsRecorder;
-  [self.feedManagementCoordinator start];
-}
-
 // Private setter for the `webState` property.
 - (void)setWebState:(web::WebState*)webState {
   if (_webState == webState) {
@@ -1775,42 +1671,33 @@
     if (visible) {
       self.didAppearTime = base::TimeTicks::Now();
 
-      if (IsHomeCustomizationEnabled()) {
-        [self.NTPMetricsRecorder
-            recordCustomizationState:[self currentCustomizationState]];
+      [self.NTPMetricsRecorder
+          recordCustomizationState:[self currentCustomizationState]];
 
-        PrefService* prefService = self.prefService;
-        BOOL safetyCheckEnabled = prefService->GetBoolean(
-            prefs::kHomeCustomizationMagicStackSafetyCheckEnabled);
-        BOOL setUpListEnabled = prefService->GetBoolean(
-            prefs::kHomeCustomizationMagicStackSetUpListEnabled);
-        BOOL tabResumptionEnabled = prefService->GetBoolean(
-            prefs::kHomeCustomizationMagicStackTabResumptionEnabled);
-        BOOL parcelTrackingEnabled = prefService->GetBoolean(
-            prefs::kHomeCustomizationMagicStackParcelTrackingEnabled);
-        BOOL tipsEnabled = prefService->GetBoolean(
-            prefs::kHomeCustomizationMagicStackTipsEnabled);
-        [self.NTPMetricsRecorder
-            recordMagicStackCustomizationStateWithSetUpList:setUpListEnabled
-                                                safetyCheck:safetyCheckEnabled
-                                              tabResumption:tabResumptionEnabled
-                                             parcelTracking:
-                                                 parcelTrackingEnabled
-                                                       tips:tipsEnabled];
-      }
+      PrefService* prefService = self.prefService;
+      BOOL safetyCheckEnabled = prefService->GetBoolean(
+          prefs::kHomeCustomizationMagicStackSafetyCheckEnabled);
+      BOOL setUpListEnabled = prefService->GetBoolean(
+          prefs::kHomeCustomizationMagicStackSetUpListEnabled);
+      BOOL tabResumptionEnabled = prefService->GetBoolean(
+          prefs::kHomeCustomizationMagicStackTabResumptionEnabled);
+      BOOL parcelTrackingEnabled = prefService->GetBoolean(
+          prefs::kHomeCustomizationMagicStackParcelTrackingEnabled);
+      BOOL tipsEnabled = prefService->GetBoolean(
+          prefs::kHomeCustomizationMagicStackTipsEnabled);
+      [self.NTPMetricsRecorder
+          recordMagicStackCustomizationStateWithSetUpList:setUpListEnabled
+                                              safetyCheck:safetyCheckEnabled
+                                            tabResumption:tabResumptionEnabled
+                                           parcelTracking:parcelTrackingEnabled
+                                                     tips:tipsEnabled];
 
       // TODO(crbug.com/350990359): Deprecate IOS.NTP.Impression when Home
       // Customization launches.
       if (self.NTPMediator.feedHeaderVisible) {
-        if ([self.feedExpandedPref value] || IsHomeCustomizationEnabled()) {
-          [self.NTPMetricsRecorder
-              recordHomeImpression:IOSNTPImpressionType::kFeedVisible
-                    isStartSurface:[self isStartSurface]];
-        } else {
-          [self.NTPMetricsRecorder
-              recordHomeImpression:IOSNTPImpressionType::kFeedCollapsed
-                    isStartSurface:[self isStartSurface]];
-        }
+        [self.NTPMetricsRecorder
+            recordHomeImpression:IOSNTPImpressionType::kFeedVisible
+                  isStartSurface:[self isStartSurface]];
       } else {
         [self.NTPMetricsRecorder
             recordHomeImpression:IOSNTPImpressionType::kFeedDisabled
@@ -1877,7 +1764,6 @@
 // Returns the current customization state represnting the visibility of NTP
 // components.
 - (IOSNTPImpressionCustomizationState)currentCustomizationState {
-  CHECK(IsHomeCustomizationEnabled());
   PrefService* prefService = self.prefService;
   BOOL MVTEnabled =
       prefService->GetBoolean(prefs::kHomeCustomizationMostVisitedEnabled);
diff --git a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_feature.h b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_feature.h
index 63fa434..5be9dbe 100644
--- a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_feature.h
+++ b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_feature.h
@@ -136,9 +136,6 @@
     const std::string& param_name,
     double default_value);
 
-// YES if the account particle disc on the NTP should open the account menu.
-bool IsIdentityDiscAccountMenuEnabled();
-
 // YES if the account menu is enabled without the three-dot menu.
 bool IdentityDiscAccountMenuEnabledWithoutEllipsis();
 
diff --git a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_feature.mm b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_feature.mm
index 8bfd1a66..69eaa15 100644
--- a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_feature.mm
+++ b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_feature.mm
@@ -156,13 +156,6 @@
                                                    param_name, default_value);
 }
 
-bool IsIdentityDiscAccountMenuEnabled() {
-  if (AreSeparateProfilesForManagedAccountsEnabled()) {
-    return true;
-  }
-  return base::FeatureList::IsEnabled(kIdentityDiscAccountMenu);
-}
-
 bool IdentityDiscAccountMenuEnabledWithoutEllipsis() {
   if (base::FeatureList::IsEnabled(kIdentityDiscAccountMenu)) {
     return base::GetFieldTrialParamByFeatureAsBool(
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 101b74f9..fdd02bb6 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
@@ -23,6 +23,7 @@
 #import "ios/chrome/browser/omnibox/ui_bundled/omnibox_constants.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/omnibox_container_view.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/omnibox_text_field_ios.h"
+#import "ios/chrome/browser/shared/model/profile/features.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
 #import "ios/chrome/browser/shared/ui/elements/extended_touch_target_button.h"
 #import "ios/chrome/browser/shared/ui/elements/new_feature_badge_view.h"
diff --git a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_header_view_controller.mm b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_header_view_controller.mm
index 072a931..403a0078 100644
--- a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_header_view_controller.mm
+++ b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_header_view_controller.mm
@@ -29,6 +29,7 @@
 #import "ios/chrome/browser/ntp/ui_bundled/new_tab_page_header_constants.h"
 #import "ios/chrome/browser/ntp/ui_bundled/new_tab_page_header_view.h"
 #import "ios/chrome/browser/ntp/ui_bundled/new_tab_page_header_view_controller_delegate.h"
+#import "ios/chrome/browser/shared/model/profile/features.h"
 #import "ios/chrome/browser/shared/public/commands/application_commands.h"
 #import "ios/chrome/browser/shared/public/commands/browser_coordinator_commands.h"
 #import "ios/chrome/browser/shared/public/commands/lens_commands.h"
@@ -321,9 +322,7 @@
     // needs to respond to user taps first.
     [self addIdentityDisc];
 
-    if (IsHomeCustomizationEnabled()) {
-      [self addCustomizationMenu];
-    }
+    [self addCustomizationMenu];
 
     UIEdgeInsets safeAreaInsets = self.baseViewController.view.safeAreaInsets;
     width = std::max<CGFloat>(
@@ -366,7 +365,6 @@
 }
 
 - (void)hideBadgeOnCustomizationMenu {
-  CHECK(IsHomeCustomizationEnabled());
   [self.headerView hideBadgeOnCustomizationMenu];
 }
 
diff --git a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_header_view_controller_unittest.mm b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_header_view_controller_unittest.mm
index 978928ee..481d165 100644
--- a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_header_view_controller_unittest.mm
+++ b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_header_view_controller_unittest.mm
@@ -28,8 +28,6 @@
 class NewTabPageHeaderViewControllerUnitTest : public PlatformTest {
  public:
   void SetUp() override {
-    scoped_feature_list_.InitWithFeatures({kHomeCustomization}, {});
-
     view_controller_ = [[NewTabPageHeaderViewController alloc]
         initWithUseNewBadgeForLensButton:YES
          useNewBadgeForCustomizationMenu:YES];
@@ -37,7 +35,6 @@
 
  protected:
   web::WebTaskEnvironment task_environment_;
-  base::test::ScopedFeatureList scoped_feature_list_;
   NewTabPageHeaderViewController* view_controller_;
 };
 
diff --git a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_mediator.h b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_mediator.h
index bdb8b48..080e6ddb 100644
--- a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_mediator.h
+++ b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_mediator.h
@@ -7,7 +7,6 @@
 
 #import <UIKit/UIKit.h>
 
-#import "ios/chrome/browser/ntp/ui_bundled/feed_management/feed_management_navigation_delegate.h"
 #import "ios/chrome/browser/ntp/ui_bundled/new_tab_page_mutator.h"
 
 namespace regional_capabilities {
@@ -39,8 +38,7 @@
 
 // Mediator for the NTP Home panel, handling the interactions with the
 // suggestions.
-@interface NewTabPageMediator
-    : NSObject <FeedManagementNavigationDelegate, NewTabPageMutator>
+@interface NewTabPageMediator : NSObject <NewTabPageMutator>
 
 - (instancetype)
      initWithTemplateURLService:(TemplateURLService*)templateURLService
@@ -87,10 +85,6 @@
 // Restores the current state of the NTP.
 - (void)restoreNTPStateForWebState:(web::WebState*)webState;
 
-// Handles the actions following a tap on the "Learn More" item in the Discover
-// feed menu.
-- (void)handleFeedLearnMoreTapped;
-
 @end
 
 #endif  // IOS_CHROME_BROWSER_NTP_UI_BUNDLED_NEW_TAB_PAGE_MEDIATOR_H_
diff --git a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_mediator.mm b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_mediator.mm
index 5e151b48..4cc50a1 100644
--- a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_mediator.mm
+++ b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_mediator.mm
@@ -43,7 +43,6 @@
 #import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h"
 #import "ios/chrome/browser/signin/model/authentication_service.h"
 #import "ios/chrome/browser/signin/model/chrome_account_manager_service.h"
-#import "ios/chrome/browser/signin/model/chrome_account_manager_service_observer_bridge.h"
 #import "ios/chrome/browser/sync/model/sync_observer_bridge.h"
 #import "ios/chrome/browser/url_loading/model/url_loading_browser_agent.h"
 #import "ios/chrome/browser/url_loading/model/url_loading_params.h"
@@ -57,21 +56,6 @@
 #import "ui/base/l10n/l10n_util.h"
 #import "url/gurl.h"
 
-namespace {
-// URL for 'Manage Activity' item in the Discover feed menu.
-const char kFeedManageActivityURL[] =
-    "https://myactivity.google.com/myactivity?product=50";
-// URL for 'Manage Interests' item in the Discover feed menu.
-const char kFeedManageInterestsURL[] =
-    "https://google.com/preferences/interests/yourinterests";
-// URL for 'Manage Hidden' item in the Discover feed menu.
-const char kFeedManageHiddenURL[] =
-    "https://google.com/preferences/interests/hidden";
-// URL for 'Learn More' item in the Discover feed menu;
-const char kFeedLearnMoreURL[] = "https://support.google.com/chrome/"
-                                 "?p=new_tab&co=GENIE.Platform%3DiOS&oco=1";
-}  // namespace
-
 @interface NewTabPageMediator () <IdentityManagerObserverBridgeDelegate,
                                   PrefObserverDelegate,
                                   SearchEngineObserving,
@@ -195,11 +179,6 @@
   self.feedControlDelegate = nil;
 }
 
-- (void)handleFeedLearnMoreTapped {
-  [self.feedMetricsRecorder recordHeaderMenuLearnMoreTapped];
-  [self openMenuItemWebPage:GURL(kFeedLearnMoreURL)];
-}
-
 - (void)saveNTPStateForWebState:(web::WebState*)webState {
   NewTabPageState* NTPState = [[NewTabPageState alloc]
       initWithScrollPosition:self.scrollPositionToSave
@@ -227,28 +206,6 @@
   }
 }
 
-#pragma mark - FeedManagementNavigationDelegate
-
-- (void)handleNavigateToActivity {
-  [self.feedMetricsRecorder recordHeaderMenuManageActivityTapped];
-  [self openMenuItemWebPage:GURL(kFeedManageActivityURL)];
-}
-
-- (void)handleNavigateToFollowing {
-  [self.feedMetricsRecorder recordHeaderMenuManageFollowingTapped];
-  [self openMenuItemWebPage:GURL(kFeedManageInterestsURL)];
-}
-
-- (void)handleNavigateToHidden {
-  [self.feedMetricsRecorder recordHeaderMenuManageHiddenTapped];
-  [self openMenuItemWebPage:GURL(kFeedManageHiddenURL)];
-}
-
-- (void)handleNavigateToFollowedURL:(const GURL&)url {
-  // TODO(crbug.com/40227407): Add metrics.
-  [self openMenuItemWebPage:url];
-}
-
 #pragma mark - SearchEngineObserving
 
 - (void)searchEngineChanged {
diff --git a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_mediator_unittest.mm b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_mediator_unittest.mm
index bc526db..8d2ceca 100644
--- a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_mediator_unittest.mm
+++ b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_mediator_unittest.mm
@@ -197,47 +197,6 @@
   EXPECT_OCMOCK_VERIFY(header_consumer_);
 }
 
-// Tests that the FeedManagementNavigationDelegate methods load URLs and
-// record metrics.
-TEST_F(NewTabPageMediatorTest, TestFeedManagementNavigationDelegate) {
-  [mediator_ handleNavigateToActivity];
-  EXPECT_URL_LOAD("https://myactivity.google.com/myactivity");
-  histogram_tester_->ExpectUniqueSample(
-      kDiscoverFeedUserActionHistogram,
-      FeedUserActionType::kTappedManageActivity, 1);
-
-  histogram_tester_.reset(new base::HistogramTester());
-  [mediator_ handleNavigateToFollowing];
-  EXPECT_URL_LOAD("https://google.com/preferences/interests");
-  histogram_tester_->ExpectUniqueSample(
-      kDiscoverFeedUserActionHistogram,
-      FeedUserActionType::kTappedManageFollowing, 1);
-
-  histogram_tester_.reset(new base::HistogramTester());
-  [mediator_ handleNavigateToHidden];
-  EXPECT_URL_LOAD("https://google.com/preferences/interests/hidden");
-  histogram_tester_->ExpectUniqueSample(kDiscoverFeedUserActionHistogram,
-                                        FeedUserActionType::kTappedManageHidden,
-                                        1);
-
-  histogram_tester_.reset(new base::HistogramTester());
-  GURL followed_url("https://example.org");
-  [mediator_ handleNavigateToFollowedURL:followed_url];
-  EXPECT_URL_LOAD(followed_url.spec().c_str());
-  // TODO(crbug.com/40227407): Add metrics.
-}
-
-// Tests that the handleFeedLearnMoreTapped loads the correct URL and records
-// metrics.
-TEST_F(NewTabPageMediatorTest, TestHandleFeedLearnMoreTapped) {
-  [mediator_ handleFeedLearnMoreTapped];
-  EXPECT_URL_LOAD("https://support.google.com/chrome/"
-                  "?p=new_tab&co=GENIE.Platform%3DiOS&oco=1");
-  histogram_tester_->ExpectUniqueSample(kDiscoverFeedUserActionHistogram,
-                                        FeedUserActionType::kTappedLearnMore,
-                                        1);
-}
-
 // Tests that the feed will be hidden when a non-Google search engine is chosen,
 // but only in EEA countries.
 TEST_F(NewTabPageMediatorTest, TestHideFeedWithSearchChoiceTargeted) {
diff --git a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_view_controller.mm b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_view_controller.mm
index 1873848..28b239a0 100644
--- a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_view_controller.mm
+++ b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_view_controller.mm
@@ -313,7 +313,7 @@
   [self.helpHandler
       presentInProductHelpWithType:InProductHelpType::kDiscoverFeedMenu];
 
-  if (IsHomeCustomizationEnabled() && !IsFirstRunRecent(base::Days(3))) {
+  if (!IsFirstRunRecent(base::Days(3))) {
     [self.helpHandler
         presentInProductHelpWithType:InProductHelpType::kHomeCustomizationMenu];
   }
@@ -501,12 +501,11 @@
     [self addViewControllerAboveFeed:self.feedHeaderViewController];
   }
 
-  if (!IsHomeCustomizationEnabled() || self.magicStackVisible) {
+  if (self.magicStackVisible) {
     [self addViewControllerAboveFeed:self.magicStackCollectionView];
   }
 
-  if (self.contentSuggestionsViewController &&
-      (!IsHomeCustomizationEnabled() || self.mostVisitedVisible)) {
+  if (self.contentSuggestionsViewController && self.mostVisitedVisible) {
     [self addViewControllerAboveFeed:self.contentSuggestionsViewController];
   }
 
@@ -644,22 +643,12 @@
 
     // If the current view controller represents a module, account for the
     // vertical spacing between modules.
-    if (IsHomeCustomizationEnabled() &&
-        (viewController == self.magicStackCollectionView ||
-         viewController == self.contentSuggestionsViewController ||
-         viewController == self.feedHeaderViewController)) {
+    if (viewController == self.magicStackCollectionView ||
+        viewController == self.contentSuggestionsViewController ||
+        viewController == self.feedHeaderViewController) {
       heightAboveFeed += SpaceBetweenModules();
     }
   }
-  if (!IsHomeCustomizationEnabled()) {
-    if (self.feedHeaderViewController) {
-      heightAboveFeed += kBottomMagicStackPadding;
-    }
-    if (!self.contentSuggestionsViewController) {
-      heightAboveFeed +=
-          content_suggestions::HeaderBottomPadding(self.traitCollection);
-    }
-  }
   return heightAboveFeed;
 }
 
@@ -1219,41 +1208,21 @@
 - (void)setInitialFakeOmniboxConstraints {
   [NSLayoutConstraint deactivateConstraints:self.fakeOmniboxConstraints];
 
-  if (IsHomeCustomizationEnabled()) {
-    // If all modules are disabled, the fake omnibox doesn't need additional
-    // constraints.
-    if ([self.viewControllersAboveFeed lastObject] ==
-        self.headerViewController) {
-      self.fakeOmniboxConstraints = @[];
-    } else {
-      // Otherwise, anchor the header to the module below it.
-      NSInteger headerIndex = [self.viewControllersAboveFeed
-          indexOfObject:self.headerViewController];
-      UIView* viewBelowHeader =
-          [self.viewControllersAboveFeed objectAtIndex:(headerIndex + 1)].view;
-      self.fakeOmniboxConstraints = @[
-        [viewBelowHeader.topAnchor
-            constraintEqualToAnchor:self.headerViewController.view.bottomAnchor
-                           constant:SpaceBetweenModules()],
-      ];
-    }
+  // If all modules are disabled, the fake omnibox doesn't need additional
+  // constraints.
+  if ([self.viewControllersAboveFeed lastObject] == self.headerViewController) {
+    self.fakeOmniboxConstraints = @[];
   } else {
-    if (self.contentSuggestionsViewController) {
-      self.fakeOmniboxConstraints = @[
-        [self.contentSuggestionsViewController.view.topAnchor
-            constraintEqualToAnchor:self.headerViewController.view
-                                        .bottomAnchor],
-      ];
-    } else {
-      // If `contentSuggestionsViewController` is nil, that means MVTs are in
-      // the Magic Stack.
-      self.fakeOmniboxConstraints = @[
-        [self.magicStackCollectionView.view.topAnchor
-            constraintEqualToAnchor:self.headerViewController.view.bottomAnchor
-                           constant:content_suggestions::HeaderBottomPadding(
-                                        self.traitCollection)],
-      ];
-    }
+    // Otherwise, anchor the header to the module below it.
+    NSInteger headerIndex =
+        [self.viewControllersAboveFeed indexOfObject:self.headerViewController];
+    UIView* viewBelowHeader =
+        [self.viewControllersAboveFeed objectAtIndex:(headerIndex + 1)].view;
+    self.fakeOmniboxConstraints = @[
+      [viewBelowHeader.topAnchor
+          constraintEqualToAnchor:self.headerViewController.view.bottomAnchor
+                         constant:SpaceBetweenModules()],
+    ];
   }
   [NSLayoutConstraint activateConstraints:self.fakeOmniboxConstraints];
 }
@@ -1417,23 +1386,6 @@
       [self.feedHeaderViewController.view.widthAnchor
           constraintEqualToAnchor:self.moduleLayoutGuide.widthAnchor],
     ]];
-    if (!IsHomeCustomizationEnabled()) {
-      // If Feed top section is enabled, the header bottom anchor should be set
-      // to its top anchor instead of the feed collection's top anchor.
-      UIView* bottomView = self.collectionView;
-      if (self.feedTopSectionViewController) {
-        bottomView = self.feedTopSectionViewController.view;
-      }
-      [NSLayoutConstraint activateConstraints:@[
-        [self.feedHeaderViewController.view.topAnchor
-            constraintEqualToAnchor:self.magicStackCollectionView.view
-                                        .bottomAnchor
-                           constant:kBottomMagicStackPadding],
-        [bottomView.topAnchor
-            constraintEqualToAnchor:self.feedHeaderViewController.view
-                                        .bottomAnchor],
-      ]];
-    }
     if (self.feedTopSectionViewController) {
       [NSLayoutConstraint activateConstraints:@[
         [self.feedTopSectionViewController.view.centerXAnchor
@@ -1448,22 +1400,12 @@
                                         .bottomAnchor],
       ]];
     }
-  } else {
-    if (!IsHomeCustomizationEnabled()) {
-      [NSLayoutConstraint activateConstraints:@[
-        [self.collectionView.topAnchor
-            constraintEqualToAnchor:self.magicStackCollectionView.view
-                                        .bottomAnchor],
-      ]];
-    }
   }
-  if (IsHomeCustomizationEnabled()) {
-    UIView* lastView = [self.viewControllersAboveFeed lastObject].view;
-    [NSLayoutConstraint activateConstraints:@[
-      [self.collectionView.topAnchor
-          constraintEqualToAnchor:lastView.bottomAnchor],
-    ]];
-  }
+  UIView* lastView = [self.viewControllersAboveFeed lastObject].view;
+  [NSLayoutConstraint activateConstraints:@[
+    [self.collectionView.topAnchor
+        constraintEqualToAnchor:lastView.bottomAnchor],
+  ]];
 
   if (_feedContainer) {
     [NSLayoutConstraint activateConstraints:@[
@@ -1483,8 +1425,7 @@
     [[self containerView].safeAreaLayoutGuide.trailingAnchor
         constraintEqualToAnchor:self.headerViewController.view.trailingAnchor],
   ]];
-  if (self.contentSuggestionsViewController &&
-      (!IsHomeCustomizationEnabled() || self.mostVisitedVisible)) {
+  if (self.contentSuggestionsViewController && self.mostVisitedVisible) {
     [NSLayoutConstraint activateConstraints:@[
       [self.contentSuggestionsViewController.view.leadingAnchor
           constraintEqualToAnchor:self.moduleLayoutGuide.leadingAnchor],
@@ -1492,7 +1433,7 @@
           constraintEqualToAnchor:self.moduleLayoutGuide.trailingAnchor],
     ]];
   }
-  if (!IsHomeCustomizationEnabled() || self.magicStackVisible) {
+  if (self.magicStackVisible) {
     [NSLayoutConstraint activateConstraints:@[
       [self.magicStackCollectionView.view.leadingAnchor
           constraintEqualToAnchor:self.moduleLayoutGuide.leadingAnchor],
@@ -1500,18 +1441,10 @@
           constraintEqualToAnchor:self.moduleLayoutGuide.trailingAnchor],
     ]];
   }
-  if (self.contentSuggestionsViewController && !IsHomeCustomizationEnabled()) {
-    [NSLayoutConstraint activateConstraints:@[
-      [self.magicStackCollectionView.view.topAnchor
-          constraintEqualToAnchor:self.contentSuggestionsViewController.view
-                                      .bottomAnchor],
-    ]];
-  }
 
   // Anchor each module except the one directly below the header, since it will
   // dynamically update its top anchor when the fake omnibox is pinned.
-  if (IsHomeCustomizationEnabled() &&
-      [self.viewControllersAboveFeed lastObject] != self.headerViewController) {
+  if ([self.viewControllersAboveFeed lastObject] != self.headerViewController) {
     // Start with the bottom module's index, which is either the feed header if
     // enabled, or the last object of the module array if not.
     NSUInteger startIndex =
@@ -1751,7 +1684,7 @@
       [self.contentSuggestionsViewController.view removeFromSuperview];
       [self.contentSuggestionsViewController didMoveToParentViewController:nil];
 
-      if (!IsHomeCustomizationEnabled() || self.mostVisitedVisible) {
+      if (self.mostVisitedVisible) {
         // Add child VC to new parent.
         [self.contentSuggestionsViewController
             willMoveToParentViewController:self.feedWrapperViewController
diff --git a/ios/chrome/browser/ntp_tiles/model/tab_resumption/tab_resumption_prefs.mm b/ios/chrome/browser/ntp_tiles/model/tab_resumption/tab_resumption_prefs.mm
index 04b4866..4338556 100644
--- a/ios/chrome/browser/ntp_tiles/model/tab_resumption/tab_resumption_prefs.mm
+++ b/ios/chrome/browser/ntp_tiles/model/tab_resumption/tab_resumption_prefs.mm
@@ -37,22 +37,15 @@
 }
 
 bool IsTabResumptionDisabled(PrefService* prefs) {
-  if (IsHomeCustomizationEnabled()) {
-    return !prefs->GetBoolean(
-        prefs::kHomeCustomizationMagicStackTabResumptionEnabled);
-  }
-  return prefs->GetBoolean(kTabResumptionDisabledPref);
+  return !prefs->GetBoolean(
+      prefs::kHomeCustomizationMagicStackTabResumptionEnabled);
 }
 
 void DisableTabResumption(PrefService* prefs) {
   UMA_HISTOGRAM_ENUMERATION(kMagicStackModuleDisabledHistogram,
                             ContentSuggestionsModuleType::kTabResumption);
-  if (IsHomeCustomizationEnabled()) {
-    prefs->SetBoolean(prefs::kHomeCustomizationMagicStackTabResumptionEnabled,
-                      false);
-  } else {
-    prefs->SetBoolean(kTabResumptionDisabledPref, true);
-  }
+  prefs->SetBoolean(prefs::kHomeCustomizationMagicStackTabResumptionEnabled,
+                    false);
 }
 
 bool IsLastOpenedURL(GURL URL, PrefService* prefs) {
diff --git a/ios/chrome/browser/omnibox/model/BUILD.gn b/ios/chrome/browser/omnibox/model/BUILD.gn
index 3be3ffc..4eca063 100644
--- a/ios/chrome/browser/omnibox/model/BUILD.gn
+++ b/ios/chrome/browser/omnibox/model/BUILD.gn
@@ -7,28 +7,37 @@
 # TODO(crbug.com/394567614): Remove this target once model files have been moved.
 source_set("ui_bundled_interface") {
   sources = [
+    "autocomplete_match_formatter.h",
     "autocomplete_result_wrapper.h",
     "autocomplete_result_wrapper_delegate.h",
+    "autocomplete_suggestion.h",
+    "autocomplete_suggestion_group_impl.h",
     "omnibox_autocomplete_controller.h",
     "omnibox_autocomplete_controller_debugger_delegate.h",
     "omnibox_autocomplete_controller_delegate.h",
     "omnibox_controller.h",
     "omnibox_image_fetcher.h",
+    "omnibox_pedal.h",
+    "omnibox_pedal_annotator.h",
     "omnibox_text_controller.h",
     "omnibox_text_controller_delegate.h",
   ]
   deps = [
     "//ios/chrome/browser/favicon/model",
+    "//ios/chrome/browser/omnibox/ui_bundled/popup:popup_ui_protocols",
     "//ui/base:types",
   ]
 }
 
 source_set("model") {
   sources = [
+    "autocomplete_match_formatter.mm",
     "autocomplete_result_wrapper.mm",
+    "autocomplete_suggestion_group_impl.mm",
     "omnibox_autocomplete_controller.mm",
     "omnibox_controller.mm",
     "omnibox_image_fetcher.mm",
+    "omnibox_pedal_annotator.mm",
     "omnibox_text_controller.mm",
   ]
   deps = [
@@ -37,18 +46,34 @@
     "//components/image_fetcher/core",
     "//components/omnibox/browser",
     "//components/open_from_clipboard",
+    "//components/password_manager/core/browser/ui",
+    "//ios/chrome/app/strings",
+    "//ios/chrome/browser/default_browser/model",
     "//ios/chrome/browser/favicon/model",
+    "//ios/chrome/browser/net/model:crurl",
+    "//ios/chrome/browser/omnibox/public:features",
     "//ios/chrome/browser/omnibox/ui_bundled:model_interface",
+    "//ios/chrome/browser/omnibox/ui_bundled:omnibox_util",
     "//ios/chrome/browser/omnibox/ui_bundled/popup",
     "//ios/chrome/browser/omnibox/ui_bundled/popup:popup_internal",
+    "//ios/chrome/browser/omnibox/ui_bundled/popup:popup_swift",
     "//ios/chrome/browser/omnibox/ui_bundled/popup:popup_ui_protocols",
     "//ios/chrome/browser/omnibox/ui_bundled/popup/row/actions",
     "//ios/chrome/browser/search_engines/model",
+    "//ios/chrome/browser/settings/ui_bundled/clear_browsing_data:features",
     "//ios/chrome/browser/shared/model/application_context",
     "//ios/chrome/browser/shared/model/prefs",
     "//ios/chrome/browser/shared/model/prefs:pref_names",
+    "//ios/chrome/browser/shared/model/url:constants",
+    "//ios/chrome/browser/shared/public/commands",
+    "//ios/chrome/browser/shared/public/features",
+    "//ios/chrome/browser/shared/ui/symbols",
+    "//ios/chrome/browser/shared/ui/symbols:symbols_views",
     "//ios/chrome/common:string_conversions",
+    "//ios/chrome/common/ui/colors",
     "//ios/chrome/common/ui/favicon",
+    "//ios/chrome/common/ui/util:image_util",
+    "//ui/base",
     "//ui/base:types",
   ]
 
@@ -60,6 +85,7 @@
   sources = [
     "autocomplete_result_wrapper_unittest.mm",
     "omnibox_autocomplete_controller_unittest.mm",
+    "omnibox_pedal_annotator_unittest.mm",
   ]
   deps = [
     ":model",
diff --git a/ios/chrome/browser/omnibox/model/DEPS b/ios/chrome/browser/omnibox/model/DEPS
index 1f9ab2f..e1ecab9 100644
--- a/ios/chrome/browser/omnibox/model/DEPS
+++ b/ios/chrome/browser/omnibox/model/DEPS
@@ -1,5 +1,7 @@
 include_rules = [
   "+third_party/omnibox_proto",
   "+ios/chrome/browser/search_engines/model/search_engine_observer_bridge.h",
-  "+ios/chrome/browser/favicon/model/favicon_loader.h"
+  "+ios/chrome/browser/favicon/model/favicon_loader.h",
+  "+ios/chrome/browser/net/model/crurl.h",
+  "+ios/chrome/browser/settings/ui_bundled/clear_browsing_data/features.h"
 ]
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_match_formatter.h b/ios/chrome/browser/omnibox/model/autocomplete_match_formatter.h
similarity index 80%
rename from ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_match_formatter.h
rename to ios/chrome/browser/omnibox/model/autocomplete_match_formatter.h
index 51d31a6..e14975d 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_match_formatter.h
+++ b/ios/chrome/browser/omnibox/model/autocomplete_match_formatter.h
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_CHROME_BROWSER_OMNIBOX_UI_BUNDLED_POPUP_AUTOCOMPLETE_MATCH_FORMATTER_H_
-#define IOS_CHROME_BROWSER_OMNIBOX_UI_BUNDLED_POPUP_AUTOCOMPLETE_MATCH_FORMATTER_H_
+#ifndef IOS_CHROME_BROWSER_OMNIBOX_MODEL_AUTOCOMPLETE_MATCH_FORMATTER_H_
+#define IOS_CHROME_BROWSER_OMNIBOX_MODEL_AUTOCOMPLETE_MATCH_FORMATTER_H_
 
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_suggestion.h"
+#import "ios/chrome/browser/omnibox/model/autocomplete_suggestion.h"
 
 struct AutocompleteMatch;
 @class OmniboxPedalData;
@@ -42,4 +42,4 @@
 
 @end
 
-#endif  // IOS_CHROME_BROWSER_OMNIBOX_UI_BUNDLED_POPUP_AUTOCOMPLETE_MATCH_FORMATTER_H_
+#endif  // IOS_CHROME_BROWSER_OMNIBOX_MODEL_AUTOCOMPLETE_MATCH_FORMATTER_H_
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_match_formatter.mm b/ios/chrome/browser/omnibox/model/autocomplete_match_formatter.mm
similarity index 99%
rename from ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_match_formatter.mm
rename to ios/chrome/browser/omnibox/model/autocomplete_match_formatter.mm
index d76982c..560010b 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_match_formatter.mm
+++ b/ios/chrome/browser/omnibox/model/autocomplete_match_formatter.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_match_formatter.h"
+#import "ios/chrome/browser/omnibox/model/autocomplete_match_formatter.h"
 
 #import <UIKit/UIKit.h>
 
diff --git a/ios/chrome/browser/omnibox/model/autocomplete_result_wrapper.mm b/ios/chrome/browser/omnibox/model/autocomplete_result_wrapper.mm
index 7114e53..ee1a5ee 100644
--- a/ios/chrome/browser/omnibox/model/autocomplete_result_wrapper.mm
+++ b/ios/chrome/browser/omnibox/model/autocomplete_result_wrapper.mm
@@ -11,11 +11,11 @@
 #import "components/omnibox/browser/autocomplete_match_classification.h"
 #import "components/omnibox/browser/autocomplete_result.h"
 #import "components/omnibox/browser/omnibox_client.h"
+#import "ios/chrome/browser/omnibox/model/autocomplete_match_formatter.h"
 #import "ios/chrome/browser/omnibox/model/autocomplete_result_wrapper_delegate.h"
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_match_formatter.h"
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_suggestion.h"
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_suggestion_group_impl.h"
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_pedal_annotator.h"
+#import "ios/chrome/browser/omnibox/model/autocomplete_suggestion.h"
+#import "ios/chrome/browser/omnibox/model/autocomplete_suggestion_group_impl.h"
+#import "ios/chrome/browser/omnibox/model/omnibox_pedal_annotator.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/pedal_section_extractor.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/row/actions/suggest_action.h"
 #import "ios/chrome/browser/search_engines/model/search_engine_observer_bridge.h"
diff --git a/ios/chrome/browser/omnibox/model/autocomplete_result_wrapper_unittest.mm b/ios/chrome/browser/omnibox/model/autocomplete_result_wrapper_unittest.mm
index f97a3275..eb43574 100644
--- a/ios/chrome/browser/omnibox/model/autocomplete_result_wrapper_unittest.mm
+++ b/ios/chrome/browser/omnibox/model/autocomplete_result_wrapper_unittest.mm
@@ -13,9 +13,9 @@
 #import "components/search_engines/search_engines_test_environment.h"
 #import "components/search_engines/template_url.h"
 #import "components/search_engines/template_url_service.h"
+#import "ios/chrome/browser/omnibox/model/autocomplete_match_formatter.h"
 #import "ios/chrome/browser/omnibox/model/autocomplete_result_wrapper_delegate.h"
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_match_formatter.h"
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_pedal_annotator.h"
+#import "ios/chrome/browser/omnibox/model/omnibox_pedal_annotator.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/pedal_suggestion_wrapper.h"
 #import "ios/chrome/browser/search_engines/model/template_url_service_factory.h"
 #import "ios/chrome/browser/shared/model/profile/test/test_profile_ios.h"
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_suggestion.h b/ios/chrome/browser/omnibox/model/autocomplete_suggestion.h
similarity index 94%
rename from ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_suggestion.h
rename to ios/chrome/browser/omnibox/model/autocomplete_suggestion.h
index b475ee7..9c8a557 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_suggestion.h
+++ b/ios/chrome/browser/omnibox/model/autocomplete_suggestion.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_CHROME_BROWSER_OMNIBOX_UI_BUNDLED_POPUP_AUTOCOMPLETE_SUGGESTION_H_
-#define IOS_CHROME_BROWSER_OMNIBOX_UI_BUNDLED_POPUP_AUTOCOMPLETE_SUGGESTION_H_
+#ifndef IOS_CHROME_BROWSER_OMNIBOX_MODEL_AUTOCOMPLETE_SUGGESTION_H_
+#define IOS_CHROME_BROWSER_OMNIBOX_MODEL_AUTOCOMPLETE_SUGGESTION_H_
 
 #import <UIKit/UIKit.h>
 
@@ -113,4 +113,4 @@
 
 @end
 
-#endif  // IOS_CHROME_BROWSER_OMNIBOX_UI_BUNDLED_POPUP_AUTOCOMPLETE_SUGGESTION_H_
+#endif  // IOS_CHROME_BROWSER_OMNIBOX_MODEL_AUTOCOMPLETE_SUGGESTION_H_
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_suggestion_group_impl.h b/ios/chrome/browser/omnibox/model/autocomplete_suggestion_group_impl.h
similarity index 81%
rename from ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_suggestion_group_impl.h
rename to ios/chrome/browser/omnibox/model/autocomplete_suggestion_group_impl.h
index 55682f9..8242a73 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_suggestion_group_impl.h
+++ b/ios/chrome/browser/omnibox/model/autocomplete_suggestion_group_impl.h
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_CHROME_BROWSER_OMNIBOX_UI_BUNDLED_POPUP_AUTOCOMPLETE_SUGGESTION_GROUP_IMPL_H_
-#define IOS_CHROME_BROWSER_OMNIBOX_UI_BUNDLED_POPUP_AUTOCOMPLETE_SUGGESTION_GROUP_IMPL_H_
+#ifndef IOS_CHROME_BROWSER_OMNIBOX_MODEL_AUTOCOMPLETE_SUGGESTION_GROUP_IMPL_H_
+#define IOS_CHROME_BROWSER_OMNIBOX_MODEL_AUTOCOMPLETE_SUGGESTION_GROUP_IMPL_H_
 
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_suggestion.h"
+#import "ios/chrome/browser/omnibox/model/autocomplete_suggestion.h"
 
 // A basic implementation of AutocompleteSuggestionGroup
 @interface AutocompleteSuggestionGroupImpl
@@ -47,4 +47,4 @@
 
 @end
 
-#endif  // IOS_CHROME_BROWSER_OMNIBOX_UI_BUNDLED_POPUP_AUTOCOMPLETE_SUGGESTION_GROUP_IMPL_H_
+#endif  // IOS_CHROME_BROWSER_OMNIBOX_MODEL_AUTOCOMPLETE_SUGGESTION_GROUP_IMPL_H_
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_suggestion_group_impl.mm b/ios/chrome/browser/omnibox/model/autocomplete_suggestion_group_impl.mm
similarity index 93%
rename from ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_suggestion_group_impl.mm
rename to ios/chrome/browser/omnibox/model/autocomplete_suggestion_group_impl.mm
index 23aad22..ee09c82 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_suggestion_group_impl.mm
+++ b/ios/chrome/browser/omnibox/model/autocomplete_suggestion_group_impl.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_suggestion_group_impl.h"
+#import "ios/chrome/browser/omnibox/model/autocomplete_suggestion_group_impl.h"
 
 @implementation AutocompleteSuggestionGroupImpl
 
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_pedal.h b/ios/chrome/browser/omnibox/model/omnibox_pedal.h
similarity index 70%
rename from ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_pedal.h
rename to ios/chrome/browser/omnibox/model/omnibox_pedal.h
index 6a03894..669d6229 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_pedal.h
+++ b/ios/chrome/browser/omnibox/model/omnibox_pedal.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_CHROME_BROWSER_OMNIBOX_UI_BUNDLED_POPUP_OMNIBOX_PEDAL_H_
-#define IOS_CHROME_BROWSER_OMNIBOX_UI_BUNDLED_POPUP_OMNIBOX_PEDAL_H_
+#ifndef IOS_CHROME_BROWSER_OMNIBOX_MODEL_OMNIBOX_PEDAL_H_
+#define IOS_CHROME_BROWSER_OMNIBOX_MODEL_OMNIBOX_PEDAL_H_
 
 @protocol OmniboxPedal <NSObject>
 
@@ -16,4 +16,4 @@
 
 @end
 
-#endif  // IOS_CHROME_BROWSER_OMNIBOX_UI_BUNDLED_POPUP_OMNIBOX_PEDAL_H_
+#endif  // IOS_CHROME_BROWSER_OMNIBOX_MODEL_OMNIBOX_PEDAL_H_
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_pedal_annotator.h b/ios/chrome/browser/omnibox/model/omnibox_pedal_annotator.h
similarity index 81%
rename from ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_pedal_annotator.h
rename to ios/chrome/browser/omnibox/model/omnibox_pedal_annotator.h
index f2e0a58..1a4a610 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_pedal_annotator.h
+++ b/ios/chrome/browser/omnibox/model/omnibox_pedal_annotator.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef IOS_CHROME_BROWSER_OMNIBOX_UI_BUNDLED_POPUP_OMNIBOX_PEDAL_ANNOTATOR_H_
-#define IOS_CHROME_BROWSER_OMNIBOX_UI_BUNDLED_POPUP_OMNIBOX_PEDAL_ANNOTATOR_H_
+#ifndef IOS_CHROME_BROWSER_OMNIBOX_MODEL_OMNIBOX_PEDAL_ANNOTATOR_H_
+#define IOS_CHROME_BROWSER_OMNIBOX_MODEL_OMNIBOX_PEDAL_ANNOTATOR_H_
 
 #import <UIKit/UIKit.h>
 
@@ -34,4 +34,4 @@
 
 @end
 
-#endif  // IOS_CHROME_BROWSER_OMNIBOX_UI_BUNDLED_POPUP_OMNIBOX_PEDAL_ANNOTATOR_H_
+#endif  // IOS_CHROME_BROWSER_OMNIBOX_MODEL_OMNIBOX_PEDAL_ANNOTATOR_H_
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_pedal_annotator.mm b/ios/chrome/browser/omnibox/model/omnibox_pedal_annotator.mm
similarity index 98%
rename from ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_pedal_annotator.mm
rename to ios/chrome/browser/omnibox/model/omnibox_pedal_annotator.mm
index 3dcce46a..6f68a441 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_pedal_annotator.mm
+++ b/ios/chrome/browser/omnibox/model/omnibox_pedal_annotator.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_pedal_annotator.h"
+#import "ios/chrome/browser/omnibox/model/omnibox_pedal_annotator.h"
 
 #import "base/strings/sys_string_conversions.h"
 #import "components/omnibox/browser/actions/omnibox_action.h"
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_pedal_annotator_unittest.mm b/ios/chrome/browser/omnibox/model/omnibox_pedal_annotator_unittest.mm
similarity index 92%
rename from ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_pedal_annotator_unittest.mm
rename to ios/chrome/browser/omnibox/model/omnibox_pedal_annotator_unittest.mm
index 8ce9842..b45e0f8e 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_pedal_annotator_unittest.mm
+++ b/ios/chrome/browser/omnibox/model/omnibox_pedal_annotator_unittest.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_pedal_annotator.h"
+#import "ios/chrome/browser/omnibox/model/omnibox_pedal_annotator.h"
 
 #import "components/omnibox/browser/actions/omnibox_action.h"
 #import "components/omnibox/browser/actions/omnibox_pedal.h"
diff --git a/ios/chrome/browser/omnibox/model/omnibox_text_controller.mm b/ios/chrome/browser/omnibox/model/omnibox_text_controller.mm
index 1c9ee64..1e858ed 100644
--- a/ios/chrome/browser/omnibox/model/omnibox_text_controller.mm
+++ b/ios/chrome/browser/omnibox/model/omnibox_text_controller.mm
@@ -7,10 +7,10 @@
 #import "base/memory/raw_ptr.h"
 #import "components/omnibox/browser/omnibox_controller.h"
 #import "components/omnibox/browser/omnibox_view.h"
+#import "ios/chrome/browser/omnibox/model/autocomplete_suggestion.h"
 #import "ios/chrome/browser/omnibox/model/omnibox_autocomplete_controller.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/omnibox_text_field_ios.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/omnibox_view_ios.h"
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_suggestion.h"
 #import "ios/chrome/common/NSString+Chromium.h"
 
 @implementation OmniboxTextController {
diff --git a/ios/chrome/browser/omnibox/ui_bundled/omnibox_coordinator.mm b/ios/chrome/browser/omnibox/ui_bundled/omnibox_coordinator.mm
index 534f4fd..2e1f1dd 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/omnibox_coordinator.mm
+++ b/ios/chrome/browser/omnibox/ui_bundled/omnibox_coordinator.mm
@@ -22,6 +22,7 @@
 #import "ios/chrome/browser/location_bar/ui_bundled/location_bar_constants.h"
 #import "ios/chrome/browser/omnibox/model/autocomplete_result_wrapper.h"
 #import "ios/chrome/browser/omnibox/model/omnibox_autocomplete_controller.h"
+#import "ios/chrome/browser/omnibox/model/omnibox_pedal_annotator.h"
 #import "ios/chrome/browser/omnibox/model/omnibox_text_controller.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/keyboard_assist/omnibox_assistive_keyboard_delegate.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/keyboard_assist/omnibox_assistive_keyboard_mediator.h"
@@ -33,7 +34,6 @@
 #import "ios/chrome/browser/omnibox/ui_bundled/omnibox_util.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/omnibox_view_controller.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/omnibox_view_ios.h"
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_pedal_annotator.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_coordinator.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_view_ios.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/pedal_section_extractor.h"
diff --git a/ios/chrome/browser/omnibox/ui_bundled/omnibox_mediator.mm b/ios/chrome/browser/omnibox/ui_bundled/omnibox_mediator.mm
index 4d4b6335..23aa62b 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/omnibox_mediator.mm
+++ b/ios/chrome/browser/omnibox/ui_bundled/omnibox_mediator.mm
@@ -15,13 +15,13 @@
 #import "ios/chrome/browser/favicon/model/favicon_loader.h"
 #import "ios/chrome/browser/lens/ui_bundled/lens_entrypoint.h"
 #import "ios/chrome/browser/net/model/crurl.h"
+#import "ios/chrome/browser/omnibox/model/autocomplete_suggestion.h"
 #import "ios/chrome/browser/omnibox/model/omnibox_text_controller.h"
 #import "ios/chrome/browser/omnibox/public/omnibox_ui_features.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/omnibox_constants.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/omnibox_consumer.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/omnibox_suggestion_icon_util.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/omnibox_util.h"
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_suggestion.h"
 #import "ios/chrome/browser/search_engines/model/search_engine_observer_bridge.h"
 #import "ios/chrome/browser/search_engines/model/search_engines_util.h"
 #import "ios/chrome/browser/shared/public/commands/lens_commands.h"
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/BUILD.gn b/ios/chrome/browser/omnibox/ui_bundled/popup/BUILD.gn
index b69c9ea1..5bf161c1 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/BUILD.gn
+++ b/ios/chrome/browser/omnibox/ui_bundled/popup/BUILD.gn
@@ -14,6 +14,7 @@
     "//ios/chrome/app/strings",
     "//ios/chrome/app/theme",
     "//ios/chrome/browser/net/model:crurl",
+    "//ios/chrome/browser/omnibox/model:ui_bundled_interface",
     "//ios/chrome/common/ui/colors:swift",
     "//ui/base",
   ]
@@ -26,8 +27,6 @@
 
 source_set("popup") {
   sources = [
-    "omnibox_pedal_annotator.h",
-    "omnibox_pedal_annotator.mm",
     "omnibox_popup_coordinator.h",
     "omnibox_popup_coordinator.mm",
     "omnibox_popup_mediator+Testing.h",
@@ -140,6 +139,7 @@
     "//ios/chrome/browser/download/model",
     "//ios/chrome/browser/favicon/ui_bundled",
     "//ios/chrome/browser/net/model:crurl",
+    "//ios/chrome/browser/omnibox/model:ui_bundled_interface",
     "//ios/chrome/browser/omnibox/public:features",
     "//ios/chrome/browser/omnibox/ui_bundled:omnibox_popup_shared",
     "//ios/chrome/browser/omnibox/ui_bundled:omnibox_util",
@@ -185,10 +185,6 @@
 
 source_set("popup_internal") {
   sources = [
-    "autocomplete_match_formatter.h",
-    "autocomplete_match_formatter.mm",
-    "autocomplete_suggestion_group_impl.h",
-    "autocomplete_suggestion_group_impl.mm",
     "omnibox_icon_formatter.h",
     "omnibox_icon_formatter.mm",
   ]
@@ -213,10 +209,8 @@
 source_set("popup_ui_protocols") {
   sources = [
     "autocomplete_result_consumer.h",
-    "autocomplete_suggestion.h",
     "content_providing.h",
     "omnibox_icon.h",
-    "omnibox_pedal.h",
     "popup_match_preview_delegate.h",
   ]
 }
@@ -224,7 +218,6 @@
 source_set("unit_tests") {
   testonly = true
   sources = [
-    "omnibox_pedal_annotator_unittest.mm",
     "omnibox_popup_mediator_unittest.mm",
     "omnibox_popup_view_controller_unittest.mm",
     "pedal_section_extractor_unittest.mm",
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/debugger/BUILD.gn b/ios/chrome/browser/omnibox/ui_bundled/popup/debugger/BUILD.gn
index 23cbfdd..e5a80d8 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/debugger/BUILD.gn
+++ b/ios/chrome/browser/omnibox/ui_bundled/popup/debugger/BUILD.gn
@@ -45,6 +45,7 @@
     "//base",
     "//components/omnibox/browser",
     "//components/variations",
+    "//ios/chrome/browser/omnibox/model:ui_bundled_interface",
     "//ios/chrome/browser/omnibox/ui_bundled/popup:popup_internal",
     "//ios/chrome/browser/shared/ui/elements",
     "//ios/chrome/browser/shared/ui/symbols",
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/debugger/autocomplete_match_cell.h b/ios/chrome/browser/omnibox/ui_bundled/popup/debugger/autocomplete_match_cell.h
index de134bf..dc4350aa 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/debugger/autocomplete_match_cell.h
+++ b/ios/chrome/browser/omnibox/ui_bundled/popup/debugger/autocomplete_match_cell.h
@@ -7,7 +7,7 @@
 
 #import <UIKit/UIKit.h>
 
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_match_formatter.h"
+#import "ios/chrome/browser/omnibox/model/autocomplete_match_formatter.h"
 
 extern NSString* const kAutocompleteMatchCellReuseIdentifier;
 
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/debugger/autocomplete_match_cell.mm b/ios/chrome/browser/omnibox/ui_bundled/popup/debugger/autocomplete_match_cell.mm
index aef4a9c..0375be0 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/debugger/autocomplete_match_cell.mm
+++ b/ios/chrome/browser/omnibox/ui_bundled/popup/debugger/autocomplete_match_cell.mm
@@ -8,7 +8,7 @@
 #import "components/omnibox/browser/autocomplete_match.h"
 #import "components/omnibox/browser/autocomplete_match_type.h"
 #import "components/omnibox/browser/autocomplete_provider.h"
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_match_formatter.h"
+#import "ios/chrome/browser/omnibox/model/autocomplete_match_formatter.h"
 #import "ios/chrome/browser/shared/ui/elements/fade_truncating_label.h"
 #import "ios/chrome/browser/shared/ui/symbols/symbols.h"
 #import "ios/chrome/common/ui/util/constraints_ui_util.h"
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/debugger/autocomplete_match_group.h b/ios/chrome/browser/omnibox/ui_bundled/popup/debugger/autocomplete_match_group.h
index 0cdb349..7431f0da 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/debugger/autocomplete_match_group.h
+++ b/ios/chrome/browser/omnibox/ui_bundled/popup/debugger/autocomplete_match_group.h
@@ -7,7 +7,7 @@
 
 #import <UIKit/UIKit.h>
 
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_match_formatter.h"
+#import "ios/chrome/browser/omnibox/model/autocomplete_match_formatter.h"
 
 /// A class that store a list of autocomplete matches with a title.
 @interface AutocompleteMatchGroup : NSObject
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/debugger/omnibox_autocomplete_event.mm b/ios/chrome/browser/omnibox/ui_bundled/popup/debugger/omnibox_autocomplete_event.mm
index f8c5805..1dba4c66 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/debugger/omnibox_autocomplete_event.mm
+++ b/ios/chrome/browser/omnibox/ui_bundled/popup/debugger/omnibox_autocomplete_event.mm
@@ -7,7 +7,7 @@
 #import "components/omnibox/browser/autocomplete_controller.h"
 #import "components/omnibox/browser/autocomplete_match.h"
 #import "components/omnibox/browser/autocomplete_provider.h"
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_match_formatter.h"
+#import "ios/chrome/browser/omnibox/model/autocomplete_match_formatter.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/debugger/omnibox_event.h"
 
 namespace {
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/debugger/omnibox_autocomplete_event_view_controller.mm b/ios/chrome/browser/omnibox/ui_bundled/popup/debugger/omnibox_autocomplete_event_view_controller.mm
index 98723cb..3fcf4a2 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/debugger/omnibox_autocomplete_event_view_controller.mm
+++ b/ios/chrome/browser/omnibox/ui_bundled/popup/debugger/omnibox_autocomplete_event_view_controller.mm
@@ -4,7 +4,7 @@
 
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/debugger/omnibox_autocomplete_event_view_controller.h"
 
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_match_formatter.h"
+#import "ios/chrome/browser/omnibox/model/autocomplete_match_formatter.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/debugger/autocomplete_match_cell.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/debugger/omnibox_autocomplete_event.h"
 
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/debugger/omnibox_debugger_view_controller.mm b/ios/chrome/browser/omnibox/ui_bundled/popup/debugger/omnibox_debugger_view_controller.mm
index de4b5f6..7ece2f0c 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/debugger/omnibox_debugger_view_controller.mm
+++ b/ios/chrome/browser/omnibox/ui_bundled/popup/debugger/omnibox_debugger_view_controller.mm
@@ -9,7 +9,7 @@
 #import "components/omnibox/browser/autocomplete_match_type.h"
 #import "components/omnibox/browser/autocomplete_provider.h"
 #import "components/variations/variations_switches.h"
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_match_formatter.h"
+#import "ios/chrome/browser/omnibox/model/autocomplete_match_formatter.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/debugger/omnibox_autocomplete_event.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/debugger/omnibox_autocomplete_event_view_controller.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/debugger/omnibox_event.h"
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_coordinator.mm b/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_coordinator.mm
index 86f74ae..1644c72 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_coordinator.mm
+++ b/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_coordinator.mm
@@ -30,7 +30,6 @@
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/content_providing.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/debugger/omnibox_debugger_mediator.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/debugger/omnibox_debugger_view_controller.h"
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_pedal_annotator.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_mediator.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_presenter.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_view_controller.h"
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_mediator.mm b/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_mediator.mm
index a348dd3..bc30d74 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_mediator.mm
+++ b/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_mediator.mm
@@ -30,12 +30,12 @@
 #import "ios/chrome/browser/menu/ui_bundled/browser_action_factory.h"
 #import "ios/chrome/browser/net/model/crurl.h"
 #import "ios/chrome/browser/ntp/model/new_tab_page_util.h"
+#import "ios/chrome/browser/omnibox/model/autocomplete_match_formatter.h"
 #import "ios/chrome/browser/omnibox/model/autocomplete_result_wrapper.h"
 #import "ios/chrome/browser/omnibox/model/autocomplete_result_wrapper_delegate.h"
+#import "ios/chrome/browser/omnibox/model/autocomplete_suggestion_group_impl.h"
 #import "ios/chrome/browser/omnibox/model/omnibox_autocomplete_controller.h"
 #import "ios/chrome/browser/omnibox/model/omnibox_image_fetcher.h"
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_match_formatter.h"
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_suggestion_group_impl.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/carousel/carousel_item.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/carousel/carousel_item_menu_provider.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_mediator+Testing.h"
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_mediator_unittest.mm b/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_mediator_unittest.mm
index f732745..1203622 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_mediator_unittest.mm
+++ b/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_mediator_unittest.mm
@@ -26,15 +26,15 @@
 #import "components/search_engines/search_engines_test_environment.h"
 #import "components/search_engines/template_url_service.h"
 #import "components/search_engines/template_url_service_client.h"
+#import "ios/chrome/browser/omnibox/model/autocomplete_match_formatter.h"
 #import "ios/chrome/browser/omnibox/model/autocomplete_result_wrapper.h"
+#import "ios/chrome/browser/omnibox/model/autocomplete_suggestion.h"
+#import "ios/chrome/browser/omnibox/model/autocomplete_suggestion_group_impl.h"
 #import "ios/chrome/browser/omnibox/model/omnibox_image_fetcher.h"
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_match_formatter.h"
+#import "ios/chrome/browser/omnibox/model/omnibox_pedal.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_result_consumer.h"
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_suggestion.h"
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_suggestion_group_impl.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/favicon_retriever.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/image_retriever.h"
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_pedal.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_mediator+Testing.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/popup_swift.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/row/actions/suggest_action.h"
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_view_controller.mm b/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_view_controller.mm
index a53fd0d..2d42633 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_view_controller.mm
+++ b/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_view_controller.mm
@@ -13,9 +13,9 @@
 #import "ios/chrome/browser/favicon/ui_bundled/favicon_attributes_provider.h"
 #import "ios/chrome/browser/favicon/ui_bundled/favicon_attributes_with_payload.h"
 #import "ios/chrome/browser/net/model/crurl.h"
+#import "ios/chrome/browser/omnibox/model/autocomplete_suggestion.h"
 #import "ios/chrome/browser/omnibox/public/omnibox_ui_features.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/omnibox_constants.h"
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_suggestion.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/carousel/carousel_item.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/carousel/omnibox_popup_carousel_cell.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/content_providing.h"
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_view_controller_unittest.mm b/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_view_controller_unittest.mm
index 0a68629..034ba3b6 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_view_controller_unittest.mm
+++ b/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_view_controller_unittest.mm
@@ -4,7 +4,7 @@
 
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_view_controller.h"
 
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_suggestion_group_impl.h"
+#import "ios/chrome/browser/omnibox/model/autocomplete_suggestion_group_impl.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/popup_match_preview_delegate.h"
 #import "testing/gtest_mac.h"
 #import "testing/platform_test.h"
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/pedal_section_extractor.h b/ios/chrome/browser/omnibox/ui_bundled/popup/pedal_section_extractor.h
index 362fdca..a63e7c8 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/pedal_section_extractor.h
+++ b/ios/chrome/browser/omnibox/ui_bundled/popup/pedal_section_extractor.h
@@ -5,8 +5,8 @@
 #ifndef IOS_CHROME_BROWSER_OMNIBOX_UI_BUNDLED_POPUP_PEDAL_SECTION_EXTRACTOR_H_
 #define IOS_CHROME_BROWSER_OMNIBOX_UI_BUNDLED_POPUP_PEDAL_SECTION_EXTRACTOR_H_
 
+#import "ios/chrome/browser/omnibox/model/autocomplete_suggestion.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_result_consumer.h"
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_suggestion.h"
 
 @protocol PopupMatchPreviewDelegate;
 @class AutocompleteMatchFormatter;
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/pedal_section_extractor.mm b/ios/chrome/browser/omnibox/ui_bundled/popup/pedal_section_extractor.mm
index 3ddaa3c..6e3c6401c 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/pedal_section_extractor.mm
+++ b/ios/chrome/browser/omnibox/ui_bundled/popup/pedal_section_extractor.mm
@@ -7,10 +7,10 @@
 #import "base/check.h"
 #import "base/metrics/histogram_functions.h"
 #import "components/omnibox/browser/actions/omnibox_pedal_concepts.h"
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_match_formatter.h"
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_suggestion.h"
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_suggestion_group_impl.h"
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_pedal.h"
+#import "ios/chrome/browser/omnibox/model/autocomplete_match_formatter.h"
+#import "ios/chrome/browser/omnibox/model/autocomplete_suggestion.h"
+#import "ios/chrome/browser/omnibox/model/autocomplete_suggestion_group_impl.h"
+#import "ios/chrome/browser/omnibox/model/omnibox_pedal.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/pedal_suggestion_wrapper.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/popup_match_preview_delegate.h"
 
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/pedal_section_extractor_unittest.mm b/ios/chrome/browser/omnibox/ui_bundled/popup/pedal_section_extractor_unittest.mm
index dc0f009..ffd568e 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/pedal_section_extractor_unittest.mm
+++ b/ios/chrome/browser/omnibox/ui_bundled/popup/pedal_section_extractor_unittest.mm
@@ -7,9 +7,9 @@
 #import "base/test/ios/wait_util.h"
 #import "components/omnibox/browser/actions/omnibox_pedal_concepts.h"
 #import "components/omnibox/browser/autocomplete_match_test_util.h"
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_match_formatter.h"
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_suggestion_group_impl.h"
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_pedal.h"
+#import "ios/chrome/browser/omnibox/model/autocomplete_match_formatter.h"
+#import "ios/chrome/browser/omnibox/model/autocomplete_suggestion_group_impl.h"
+#import "ios/chrome/browser/omnibox/model/omnibox_pedal.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/popup_match_preview_delegate.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/popup_swift.h"
 #import "testing/gtest_mac.h"
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/pedal_suggestion_wrapper.h b/ios/chrome/browser/omnibox/ui_bundled/popup/pedal_suggestion_wrapper.h
index d94ece49..a5d7918 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/pedal_suggestion_wrapper.h
+++ b/ios/chrome/browser/omnibox/ui_bundled/popup/pedal_suggestion_wrapper.h
@@ -7,8 +7,8 @@
 
 #import <UIKit/UIKit.h>
 
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_suggestion.h"
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_pedal.h"
+#import "ios/chrome/browser/omnibox/model/autocomplete_suggestion.h"
+#import "ios/chrome/browser/omnibox/model/omnibox_pedal.h"
 
 /// A wrapper for an OmniboxPedal that exposes AutocompleteSuggestion-compatible
 /// API. Used to display pedals as suggestions in the popup.
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/popup_swift_bridge.h b/ios/chrome/browser/omnibox/ui_bundled/popup/popup_swift_bridge.h
index 72765626..07a25dd 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/popup_swift_bridge.h
+++ b/ios/chrome/browser/omnibox/ui_bundled/popup/popup_swift_bridge.h
@@ -9,8 +9,8 @@
 // Obj-C and have no C++ in them.
 
 #import "ios/chrome/browser/net/model/crurl.h"
+#import "ios/chrome/browser/omnibox/model/omnibox_pedal.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_icon.h"
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_pedal.h"
 #import "ios/chrome/grit/ios_strings.h"
 #import "ios/chrome/grit/ios_theme_resources.h"
 
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/row/BUILD.gn b/ios/chrome/browser/omnibox/ui_bundled/popup/row/BUILD.gn
index 0e4a427..d05f356 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/row/BUILD.gn
+++ b/ios/chrome/browser/omnibox/ui_bundled/popup/row/BUILD.gn
@@ -17,6 +17,7 @@
     "//components/omnibox/common",
     "//ios/chrome/app/strings",
     "//ios/chrome/app/theme",
+    "//ios/chrome/browser/omnibox/model:ui_bundled_interface",
     "//ios/chrome/browser/omnibox/public:features",
     "//ios/chrome/browser/omnibox/ui_bundled/popup:popup_accessibility_identifier_constants",
     "//ios/chrome/browser/omnibox/ui_bundled/popup:popup_icon",
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/row/actions/BUILD.gn b/ios/chrome/browser/omnibox/ui_bundled/popup/row/actions/BUILD.gn
index a45ecf6..439bda1e 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/row/actions/BUILD.gn
+++ b/ios/chrome/browser/omnibox/ui_bundled/popup/row/actions/BUILD.gn
@@ -17,6 +17,7 @@
   deps = [
     "//components/omnibox/browser",
     "//ios/chrome/app/strings",
+    "//ios/chrome/browser/omnibox/model:ui_bundled_interface",
     "//ios/chrome/browser/omnibox/public:features",
     "//ios/chrome/browser/omnibox/ui_bundled:omnibox_popup_shared",
     "//ios/chrome/browser/omnibox/ui_bundled:omnibox_util",
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/row/actions/omnibox_popup_actions_row_content_configuration.mm b/ios/chrome/browser/omnibox/ui_bundled/popup/row/actions/omnibox_popup_actions_row_content_configuration.mm
index 5977a48..3e502b5 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/row/actions/omnibox_popup_actions_row_content_configuration.mm
+++ b/ios/chrome/browser/omnibox/ui_bundled/popup/row/actions/omnibox_popup_actions_row_content_configuration.mm
@@ -4,7 +4,7 @@
 
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/row/actions/omnibox_popup_actions_row_content_configuration.h"
 
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_suggestion.h"
+#import "ios/chrome/browser/omnibox/model/autocomplete_suggestion.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/row/actions/omnibox_popup_actions_row_content_view.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/row/actions/omnibox_popup_actions_row_delegate.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/row/actions/suggest_action.h"
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/row/omnibox_popup_row_content_configuration.mm b/ios/chrome/browser/omnibox/ui_bundled/popup/row/omnibox_popup_row_content_configuration.mm
index 01d1bcb..2724f4b 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/row/omnibox_popup_row_content_configuration.mm
+++ b/ios/chrome/browser/omnibox/ui_bundled/popup/row/omnibox_popup_row_content_configuration.mm
@@ -7,8 +7,8 @@
 #import "base/check.h"
 #import "base/ios/ios_util.h"
 #import "base/strings/sys_string_conversions.h"
+#import "ios/chrome/browser/omnibox/model/autocomplete_suggestion.h"
 #import "ios/chrome/browser/omnibox/public/omnibox_ui_features.h"
-#import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_suggestion.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_accessibility_identifier_constants.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/row/omnibox_popup_row_content_view.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/row/omnibox_popup_row_delegate.h"
diff --git a/ios/chrome/browser/parcel_tracking/parcel_tracking_prefs.mm b/ios/chrome/browser/parcel_tracking/parcel_tracking_prefs.mm
index 27ebeb0..a07efe5 100644
--- a/ios/chrome/browser/parcel_tracking/parcel_tracking_prefs.mm
+++ b/ios/chrome/browser/parcel_tracking/parcel_tracking_prefs.mm
@@ -16,18 +16,11 @@
 }
 
 bool IsParcelTrackingDisabled(PrefService* prefs) {
-  if (IsHomeCustomizationEnabled()) {
-    return !prefs->GetBoolean(
-        prefs::kHomeCustomizationMagicStackParcelTrackingEnabled);
-  }
-  return prefs->GetBoolean(kParcelTrackingDisabled);
+  return !prefs->GetBoolean(
+      prefs::kHomeCustomizationMagicStackParcelTrackingEnabled);
 }
 
 void DisableParcelTracking(PrefService* prefs) {
-  if (IsHomeCustomizationEnabled()) {
-    prefs->SetBoolean(prefs::kHomeCustomizationMagicStackParcelTrackingEnabled,
-                      false);
-  } else {
-    prefs->SetBoolean(kParcelTrackingDisabled, true);
-  }
+  prefs->SetBoolean(prefs::kHomeCustomizationMagicStackParcelTrackingEnabled,
+                    false);
 }
diff --git a/ios/chrome/browser/policy/model/BUILD.gn b/ios/chrome/browser/policy/model/BUILD.gn
index 6b3821c7..ab90721 100644
--- a/ios/chrome/browser/policy/model/BUILD.gn
+++ b/ios/chrome/browser/policy/model/BUILD.gn
@@ -30,6 +30,8 @@
     "device_management_service_configuration_ios.mm",
     "management_state.h",
     "management_state.mm",
+    "management_status_providers_ios.h",
+    "management_status_providers_ios.mm",
     "new_tab_page_location_policy_handler.cc",
     "new_tab_page_location_policy_handler.h",
     "policy_conversions_client_ios.h",
@@ -95,6 +97,7 @@
     "//ios/chrome/browser/shared/model/paths",
     "//ios/chrome/browser/shared/model/prefs:pref_names",
     "//ios/chrome/browser/shared/model/profile",
+    "//ios/chrome/browser/shared/model/profile:features",
     "//ios/chrome/browser/shared/model/profile:profile_keyed_service_factory",
     "//ios/chrome/browser/shared/public/commands",
     "//ios/chrome/browser/shared/public/features",
diff --git a/ios/chrome/browser/policy/model/cloud/user_policy_signin_service.mm b/ios/chrome/browser/policy/model/cloud/user_policy_signin_service.mm
index 57055db..2098d267 100644
--- a/ios/chrome/browser/policy/model/cloud/user_policy_signin_service.mm
+++ b/ios/chrome/browser/policy/model/cloud/user_policy_signin_service.mm
@@ -16,6 +16,7 @@
 #import "components/signin/public/identity_manager/primary_account_change_event.h"
 #import "google_apis/gaia/core_account_id.h"
 #import "google_apis/gaia/gaia_auth_util.h"
+#import "ios/chrome/browser/shared/model/profile/features.h"
 #import "ios/chrome/browser/shared/model/profile/profile_ios.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
 #import "services/network/public/cpp/shared_url_loader_factory.h"
diff --git a/ios/chrome/browser/policy/model/enterprise_policy_test_helper.cc b/ios/chrome/browser/policy/model/enterprise_policy_test_helper.cc
index 2abf927..a11723b 100644
--- a/ios/chrome/browser/policy/model/enterprise_policy_test_helper.cc
+++ b/ios/chrome/browser/policy/model/enterprise_policy_test_helper.cc
@@ -50,7 +50,8 @@
   profile_policy_connector_ = std::make_unique<ProfilePolicyConnector>();
   profile_policy_connector_->Init(
       browser_policy_connector_->GetSchemaRegistry(),
-      browser_policy_connector_.get(), /*user_policy_provider=*/nullptr);
+      browser_policy_connector_.get(), /*user_policy_provider=*/nullptr,
+      /*policy_store=*/nullptr);
   scoped_refptr<user_prefs::PrefRegistrySyncable> pref_registry(
       new user_prefs::PrefRegistrySyncable);
   RegisterProfilePrefs(pref_registry.get());
diff --git a/ios/chrome/browser/policy/model/management_status_providers_ios.h b/ios/chrome/browser/policy/model/management_status_providers_ios.h
new file mode 100644
index 0000000..694b824e
--- /dev/null
+++ b/ios/chrome/browser/policy/model/management_status_providers_ios.h
@@ -0,0 +1,94 @@
+// 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_POLICY_MODEL_MANAGEMENT_STATUS_PROVIDERS_IOS_H_
+#define IOS_CHROME_BROWSER_POLICY_MODEL_MANAGEMENT_STATUS_PROVIDERS_IOS_H_
+
+#import "base/memory/raw_ptr.h"
+#import "components/policy/core/common/management/management_service.h"
+
+class ProfileIOS;
+
+// TODO (crbug.com/1238355): Add unit tests for this file.
+
+namespace policy {
+
+class BrowserCloudManagementStatusProvider final
+    : public policy::ManagementStatusProvider {
+ public:
+  BrowserCloudManagementStatusProvider();
+  ~BrowserCloudManagementStatusProvider() final;
+
+ protected:
+  // ManagementStatusProvider:
+  policy::EnterpriseManagementAuthority FetchAuthority() final;
+};
+
+class LocalBrowserManagementStatusProvider final
+    : public policy::ManagementStatusProvider {
+ public:
+  LocalBrowserManagementStatusProvider();
+  ~LocalBrowserManagementStatusProvider() final;
+
+ protected:
+  // ManagementStatusProvider:
+  policy::EnterpriseManagementAuthority FetchAuthority() final;
+};
+
+class LocalDomainBrowserManagementStatusProvider final
+    : public policy::ManagementStatusProvider {
+ public:
+  LocalDomainBrowserManagementStatusProvider();
+  ~LocalDomainBrowserManagementStatusProvider() final;
+
+ protected:
+  // ManagementStatusProvider:
+  policy::EnterpriseManagementAuthority FetchAuthority() final;
+};
+
+class ProfileCloudManagementStatusProvider final
+    : public policy::ManagementStatusProvider {
+ public:
+  explicit ProfileCloudManagementStatusProvider(ProfileIOS* profile);
+  ~ProfileCloudManagementStatusProvider() final;
+
+ protected:
+  // ManagementStatusProvider:
+  policy::EnterpriseManagementAuthority FetchAuthority() final;
+
+ private:
+  raw_ptr<ProfileIOS> profile_;
+};
+
+class LocalTestPolicyUserManagementProvider final
+    : public policy::ManagementStatusProvider {
+ public:
+  explicit LocalTestPolicyUserManagementProvider(ProfileIOS* profile);
+  ~LocalTestPolicyUserManagementProvider() final;
+
+ protected:
+  // ManagementStatusProvider:
+  policy::EnterpriseManagementAuthority FetchAuthority() final;
+
+ private:
+  raw_ptr<ProfileIOS> profile_;
+};
+
+class LocalTestPolicyBrowserManagementProvider final
+    : public policy::ManagementStatusProvider {
+ public:
+  explicit LocalTestPolicyBrowserManagementProvider(ProfileIOS* profile);
+  ~LocalTestPolicyBrowserManagementProvider() final;
+
+ protected:
+  // ManagementStatusProvider:
+  policy::EnterpriseManagementAuthority FetchAuthority() final;
+
+ private:
+  raw_ptr<ProfileIOS> profile_;
+};
+
+}  // namespace policy
+
+#endif  // IOS_CHROME_BROWSER_POLICY_MODEL_MANAGEMENT_STATUS_PROVIDERS_IOS_H_
diff --git a/ios/chrome/browser/policy/model/management_status_providers_ios.mm b/ios/chrome/browser/policy/model/management_status_providers_ios.mm
new file mode 100644
index 0000000..d7338c7
--- /dev/null
+++ b/ios/chrome/browser/policy/model/management_status_providers_ios.mm
@@ -0,0 +1,146 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/policy/model/management_status_providers_ios.h"
+
+#import "build/build_config.h"
+#import "components/enterprise/browser/controller/browser_dm_token_storage.h"
+#import "components/policy/core/common/policy_namespace.h"
+#import "components/policy/core/common/policy_service.h"
+#import "ios/chrome/browser/policy/model/browser_policy_connector_ios.h"
+#import "ios/chrome/browser/policy/model/profile_policy_connector.h"
+#import "ios/chrome/browser/shared/model/application_context/application_context.h"
+#import "ios/chrome/browser/shared/model/profile/profile_ios.h"
+
+namespace policy {
+
+namespace {
+
+bool IsProfileManaged(ProfileIOS* profile) {
+  return profile && profile->GetPolicyConnector() &&
+         profile->GetPolicyConnector()->IsManaged();
+}
+
+}  // namespace
+
+BrowserCloudManagementStatusProvider::BrowserCloudManagementStatusProvider() =
+    default;
+
+BrowserCloudManagementStatusProvider::~BrowserCloudManagementStatusProvider() =
+    default;
+
+policy::EnterpriseManagementAuthority
+BrowserCloudManagementStatusProvider::FetchAuthority() {
+  // A machine level user cloud policy manager is only created if the browser is
+  // managed by CBCM.
+  if (GetApplicationContext()
+          ->GetBrowserPolicyConnector()
+          ->machine_level_user_cloud_policy_manager() != nullptr) {
+    return policy::EnterpriseManagementAuthority::CLOUD_DOMAIN;
+  }
+  return policy::EnterpriseManagementAuthority::NONE;
+}
+
+LocalBrowserManagementStatusProvider::LocalBrowserManagementStatusProvider() =
+    default;
+
+LocalBrowserManagementStatusProvider::~LocalBrowserManagementStatusProvider() =
+    default;
+
+policy::EnterpriseManagementAuthority
+LocalBrowserManagementStatusProvider::FetchAuthority() {
+  return GetApplicationContext() &&
+                 GetApplicationContext()->GetBrowserPolicyConnector() &&
+                 GetApplicationContext()
+                     ->GetBrowserPolicyConnector()
+                     ->HasMachineLevelPolicies()
+             ? policy::EnterpriseManagementAuthority::COMPUTER_LOCAL
+             : policy::EnterpriseManagementAuthority::NONE;
+}
+
+LocalDomainBrowserManagementStatusProvider::
+    LocalDomainBrowserManagementStatusProvider() = default;
+
+LocalDomainBrowserManagementStatusProvider::
+    ~LocalDomainBrowserManagementStatusProvider() = default;
+
+policy::EnterpriseManagementAuthority
+LocalDomainBrowserManagementStatusProvider::FetchAuthority() {
+  auto result = policy::EnterpriseManagementAuthority::NONE;
+  if (GetApplicationContext()
+          ->GetBrowserPolicyConnector()
+          ->HasMachineLevelPolicies()) {
+    result = policy::EnterpriseManagementAuthority::COMPUTER_LOCAL;
+  }
+  return result;
+}
+
+ProfileCloudManagementStatusProvider::ProfileCloudManagementStatusProvider(
+    ProfileIOS* profile)
+    : profile_(profile) {}
+
+ProfileCloudManagementStatusProvider::~ProfileCloudManagementStatusProvider() =
+    default;
+
+policy::EnterpriseManagementAuthority
+ProfileCloudManagementStatusProvider::FetchAuthority() {
+  if (IsProfileManaged(profile_)) {
+    return policy::EnterpriseManagementAuthority::CLOUD;
+  }
+  return policy::EnterpriseManagementAuthority::NONE;
+}
+
+LocalTestPolicyUserManagementProvider::LocalTestPolicyUserManagementProvider(
+    ProfileIOS* profile)
+    : profile_(profile) {}
+
+LocalTestPolicyUserManagementProvider::
+    ~LocalTestPolicyUserManagementProvider() = default;
+
+policy::EnterpriseManagementAuthority
+LocalTestPolicyUserManagementProvider::FetchAuthority() {
+  if (!profile_->GetPolicyConnector()->IsUsingLocalTestPolicyProvider()) {
+    return policy::EnterpriseManagementAuthority::NONE;
+  }
+  for (const auto& [_, entry] :
+       profile_->GetPolicyConnector()->GetPolicyService()->GetPolicies(
+           policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME,
+                                   std::string()))) {
+    if (entry.scope == policy::POLICY_SCOPE_USER &&
+        entry.source == policy::POLICY_SOURCE_CLOUD) {
+      return policy::EnterpriseManagementAuthority::CLOUD;
+    }
+  }
+  return policy::EnterpriseManagementAuthority::NONE;
+}
+
+LocalTestPolicyBrowserManagementProvider::
+    LocalTestPolicyBrowserManagementProvider(ProfileIOS* profile)
+    : profile_(profile) {}
+
+LocalTestPolicyBrowserManagementProvider::
+    ~LocalTestPolicyBrowserManagementProvider() = default;
+
+policy::EnterpriseManagementAuthority
+LocalTestPolicyBrowserManagementProvider::FetchAuthority() {
+  if (!profile_->GetPolicyConnector()->IsUsingLocalTestPolicyProvider()) {
+    return policy::EnterpriseManagementAuthority::NONE;
+  }
+  for (const auto& [_, entry] :
+       profile_->GetPolicyConnector()->GetPolicyService()->GetPolicies(
+           policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME,
+                                   std::string()))) {
+    if (entry.scope == policy::POLICY_SCOPE_MACHINE &&
+        entry.source == policy::POLICY_SOURCE_CLOUD) {
+      return policy::EnterpriseManagementAuthority::CLOUD_DOMAIN;
+    }
+    if (entry.scope == policy::POLICY_SCOPE_MACHINE &&
+        entry.source == policy::POLICY_SOURCE_PLATFORM) {
+      return policy::EnterpriseManagementAuthority::DOMAIN_LOCAL;
+    }
+  }
+  return policy::EnterpriseManagementAuthority::NONE;
+}
+
+}  // namespace policy
diff --git a/ios/chrome/browser/policy/model/profile_policy_connector.h b/ios/chrome/browser/policy/model/profile_policy_connector.h
index e36fd69..5addbd9 100644
--- a/ios/chrome/browser/policy/model/profile_policy_connector.h
+++ b/ios/chrome/browser/policy/model/profile_policy_connector.h
@@ -14,6 +14,7 @@
 class BrowserPolicyConnectorIOS;
 
 namespace policy {
+class CloudPolicyStore;
 class ConfigurationPolicyProvider;
 class PolicyService;
 class SchemaRegistry;
@@ -35,7 +36,12 @@
   // Initializes this connector.
   void Init(policy::SchemaRegistry* schema_registry,
             BrowserPolicyConnectorIOS* browser_policy_connector,
-            policy::ConfigurationPolicyProvider* user_policy_provider);
+            policy::ConfigurationPolicyProvider* user_policy_provider,
+            policy::CloudPolicyStore* policy_store);
+
+  // Returns true if this Profile is under any kind of policy management. You
+  // must call this method only when the policies system is fully initialized.
+  bool IsManaged() const;
 
   // Sets the local_test_policy_provider as active and all other policy
   // providers to inactive.
@@ -44,6 +50,9 @@
   // Reverts the effects of UseLocalTestPolicyProvider.
   void RevertUseLocalTestPolicyProvider();
 
+  // Returns true if policies from chrome://policy/test are applied.
+  bool IsUsingLocalTestPolicyProvider() const;
+
   // Shuts this connector down in preparation for destruction.
   void Shutdown();
 
@@ -73,6 +82,8 @@
   raw_ptr<policy::LocalTestPolicyProvider> local_test_policy_provider_ =
       nullptr;
 
+  raw_ptr<const policy::CloudPolicyStore> policy_store_ = nullptr;
+
   // The PolicyService that manages policy for this connector's Profile.
   std::unique_ptr<policy::PolicyService> policy_service_;
 
diff --git a/ios/chrome/browser/policy/model/profile_policy_connector.mm b/ios/chrome/browser/policy/model/profile_policy_connector.mm
index b0a0abde..96b953d3 100644
--- a/ios/chrome/browser/policy/model/profile_policy_connector.mm
+++ b/ios/chrome/browser/policy/model/profile_policy_connector.mm
@@ -4,6 +4,7 @@
 
 #import "ios/chrome/browser/policy/model/profile_policy_connector.h"
 
+#import "components/policy/core/common/cloud/cloud_policy_store.h"
 #import "components/policy/core/common/local_test_policy_provider.h"
 #import "components/policy/core/common/policy_service_impl.h"
 #import "components/policy/core/common/schema_registry.h"
@@ -15,8 +16,10 @@
 void ProfilePolicyConnector::Init(
     policy::SchemaRegistry* schema_registry,
     BrowserPolicyConnectorIOS* browser_policy_connector,
-    policy::ConfigurationPolicyProvider* user_policy_provider) {
+    policy::ConfigurationPolicyProvider* user_policy_provider,
+    policy::CloudPolicyStore* policy_store) {
   schema_registry_ = schema_registry;
+  policy_store_ = policy_store;
 
   // The object returned by GetPlatformConnector() may or may not be in the list
   // returned by GetPolicyProviders().  Explicitly add it to `policy_providers_`
@@ -50,6 +53,13 @@
       policy_providers_, policy::PolicyServiceImpl::ScopeForMetrics::kMachine);
 }
 
+bool ProfilePolicyConnector::IsManaged() const {
+  if (policy_store_) {
+    return policy_store_->is_managed();
+  }
+  return false;
+}
+
 void ProfilePolicyConnector::UseLocalTestPolicyProvider() {
   for (policy::ConfigurationPolicyProvider* provider : policy_providers_) {
     provider->set_active(false);
@@ -75,4 +85,9 @@
                                    policy::PolicyFetchReason::kTest);
 }
 
+bool ProfilePolicyConnector::IsUsingLocalTestPolicyProvider() const {
+  return local_test_policy_provider_ &&
+         local_test_policy_provider_->is_active();
+}
+
 void ProfilePolicyConnector::Shutdown() {}
diff --git a/ios/chrome/browser/policy/model/profile_policy_connector_factory.h b/ios/chrome/browser/policy/model/profile_policy_connector_factory.h
index 8bd9936..ae65ab06 100644
--- a/ios/chrome/browser/policy/model/profile_policy_connector_factory.h
+++ b/ios/chrome/browser/policy/model/profile_policy_connector_factory.h
@@ -11,6 +11,7 @@
 class ProfilePolicyConnector;
 
 namespace policy {
+class CloudPolicyStore;
 class SchemaRegistry;
 class UserCloudPolicyManager;
 }  // namespace policy
@@ -18,6 +19,7 @@
 std::unique_ptr<ProfilePolicyConnector> BuildProfilePolicyConnector(
     policy::SchemaRegistry* schema_registry,
     BrowserPolicyConnectorIOS* browser_policy_connector,
-    policy::UserCloudPolicyManager* user_policy_manager);
+    policy::UserCloudPolicyManager* user_policy_manager,
+    policy::CloudPolicyStore* policy_store);
 
 #endif  // IOS_CHROME_BROWSER_POLICY_MODEL_PROFILE_POLICY_CONNECTOR_FACTORY_H_
diff --git a/ios/chrome/browser/policy/model/profile_policy_connector_factory.mm b/ios/chrome/browser/policy/model/profile_policy_connector_factory.mm
index 35a648a..9f46e0d 100644
--- a/ios/chrome/browser/policy/model/profile_policy_connector_factory.mm
+++ b/ios/chrome/browser/policy/model/profile_policy_connector_factory.mm
@@ -11,7 +11,8 @@
 std::unique_ptr<ProfilePolicyConnector> BuildProfilePolicyConnector(
     policy::SchemaRegistry* schema_registry,
     BrowserPolicyConnectorIOS* browser_policy_connector,
-    policy::UserCloudPolicyManager* user_policy_manager) {
+    policy::UserCloudPolicyManager* user_policy_manager,
+    policy::CloudPolicyStore* policy_store) {
   auto connector = std::make_unique<ProfilePolicyConnector>();
 
   // Since extensions are not supported on iOS, the `schema_registry` here has
@@ -20,6 +21,6 @@
   // levels of registry (owned by ApplicationContext vs owned by BrowserState)
   // are maintained to keep a parallel structure with Desktop.
   connector->Init(schema_registry, browser_policy_connector,
-                  user_policy_manager);
+                  user_policy_manager, policy_store);
   return connector;
 }
diff --git a/ios/chrome/browser/policy/ui_bundled/BUILD.gn b/ios/chrome/browser/policy/ui_bundled/BUILD.gn
index 000f9a91..90205af 100644
--- a/ios/chrome/browser/policy/ui_bundled/BUILD.gn
+++ b/ios/chrome/browser/policy/ui_bundled/BUILD.gn
@@ -72,6 +72,7 @@
     "//ios/chrome/browser/policy/model",
     "//ios/chrome/browser/shared/model/application_context",
     "//ios/chrome/browser/shared/model/profile",
+    "//ios/chrome/browser/shared/model/profile:features",
     "//ios/chrome/browser/shared/public/features",
     "//ios/chrome/browser/signin/model:authentication_service",
     "//ui/base:base",
diff --git a/ios/chrome/browser/policy/ui_bundled/management_util.mm b/ios/chrome/browser/policy/ui_bundled/management_util.mm
index 12927232..1e08258 100644
--- a/ios/chrome/browser/policy/ui_bundled/management_util.mm
+++ b/ios/chrome/browser/policy/ui_bundled/management_util.mm
@@ -18,8 +18,8 @@
 #import "ios/chrome/browser/policy/model/browser_policy_connector_ios.h"
 #import "ios/chrome/browser/policy/ui_bundled/user_policy_util.h"
 #import "ios/chrome/browser/shared/model/application_context/application_context.h"
+#import "ios/chrome/browser/shared/model/profile/features.h"
 #import "ios/chrome/browser/shared/model/profile/profile_ios.h"
-#import "ios/chrome/browser/shared/public/features/features.h"
 #import "ios/chrome/browser/signin/model/authentication_service.h"
 #import "ios/chrome/grit/ios_branded_strings.h"
 #import "ios/chrome/grit/ios_strings.h"
diff --git a/ios/chrome/browser/profile/model/profile_ios_impl.mm b/ios/chrome/browser/profile/model/profile_ios_impl.mm
index 72728ee..94b4c1e 100644
--- a/ios/chrome/browser/profile/model/profile_ios_impl.mm
+++ b/ios/chrome/browser/profile/model/profile_ios_impl.mm
@@ -271,9 +271,12 @@
       base::BindRepeating(&ApplicationContext::GetNetworkConnectionTracker,
                           base::Unretained(GetApplicationContext())));
 
-  policy_connector_ =
-      BuildProfilePolicyConnector(policy_schema_registry_.get(), connector,
-                                  user_cloud_policy_manager_.get());
+  policy_connector_ = BuildProfilePolicyConnector(
+      policy_schema_registry_.get(), connector,
+      user_cloud_policy_manager_.get(),
+      user_cloud_policy_manager_ && user_cloud_policy_manager_->core()
+          ? user_cloud_policy_manager_->core()->store()
+          : nullptr);
 
   // Register Profile preferences.
   RegisterProfilePrefs(pref_registry_.get());
diff --git a/ios/chrome/browser/reader_mode/model/resources/reader_mode.ts b/ios/chrome/browser/reader_mode/model/resources/reader_mode.ts
index 2d651ed..02a6e38 100644
--- a/ios/chrome/browser/reader_mode/model/resources/reader_mode.ts
+++ b/ios/chrome/browser/reader_mode/model/resources/reader_mode.ts
@@ -8,7 +8,7 @@
 // For performance reasons, we remove the visibility check, use
 // getElementsByTagName(), and retrieve only <p> and <pre> elements once.
 
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 import {sendWebKitMessage} from '//ios/web/public/js_messaging/resources/utils.js';
 
 interface Result {
@@ -139,6 +139,6 @@
 
 // Mark: Public API
 
-gCrWeb.readerMode = {
+gCrWebLegacy.readerMode = {
   retrieveDOMFeatures,
 };
diff --git a/ios/chrome/browser/settings/ui_bundled/downloads/save_to_photos/save_to_photos_settings_mediator.mm b/ios/chrome/browser/settings/ui_bundled/downloads/save_to_photos/save_to_photos_settings_mediator.mm
index b81d8059..47548af 100644
--- a/ios/chrome/browser/settings/ui_bundled/downloads/save_to_photos/save_to_photos_settings_mediator.mm
+++ b/ios/chrome/browser/settings/ui_bundled/downloads/save_to_photos/save_to_photos_settings_mediator.mm
@@ -7,6 +7,7 @@
 #import "base/memory/raw_ptr.h"
 #import "base/strings/sys_string_conversions.h"
 #import "components/prefs/ios/pref_observer_bridge.h"
+#import "components/prefs/pref_change_registrar.h"
 #import "components/prefs/pref_service.h"
 #import "components/signin/public/identity_manager/objc/identity_manager_observer_bridge.h"
 #import "ios/chrome/browser/account_picker/ui_bundled/account_picker_selection/account_picker_selection_screen_identity_item_configurator.h"
@@ -17,7 +18,7 @@
 #import "ios/chrome/browser/settings/ui_bundled/downloads/save_to_photos/save_to_photos_settings_mediator_delegate.h"
 #import "ios/chrome/browser/shared/model/prefs/pref_names.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
-#import "ios/chrome/browser/signin/model/chrome_account_manager_service_observer_bridge.h"
+#import "ios/chrome/browser/signin/model/chrome_account_manager_service.h"
 
 @interface SaveToPhotosSettingsMediator () <
     IdentityManagerObserverBridgeDelegate,
diff --git a/ios/chrome/browser/settings/ui_bundled/google_services/BUILD.gn b/ios/chrome/browser/settings/ui_bundled/google_services/BUILD.gn
index 33d06f05..297dd5a 100644
--- a/ios/chrome/browser/settings/ui_bundled/google_services/BUILD.gn
+++ b/ios/chrome/browser/settings/ui_bundled/google_services/BUILD.gn
@@ -87,6 +87,7 @@
     "//ios/chrome/browser/shared/model/prefs",
     "//ios/chrome/browser/shared/model/prefs:pref_names",
     "//ios/chrome/browser/shared/model/profile",
+    "//ios/chrome/browser/shared/model/profile:features",
     "//ios/chrome/browser/shared/model/url:constants",
     "//ios/chrome/browser/shared/model/utils",
     "//ios/chrome/browser/shared/public/commands",
@@ -267,6 +268,7 @@
     "//ios/chrome/browser/shared/model/application_context",
     "//ios/chrome/browser/shared/model/browser/test:test_support",
     "//ios/chrome/browser/shared/model/prefs:pref_names",
+    "//ios/chrome/browser/shared/model/profile:features",
     "//ios/chrome/browser/shared/model/profile/test",
     "//ios/chrome/browser/shared/public/commands",
     "//ios/chrome/browser/shared/public/features",
diff --git a/ios/chrome/browser/settings/ui_bundled/google_services/google_services_settings_coordinator.mm b/ios/chrome/browser/settings/ui_bundled/google_services/google_services_settings_coordinator.mm
index 499bf1a..5be8584 100644
--- a/ios/chrome/browser/settings/ui_bundled/google_services/google_services_settings_coordinator.mm
+++ b/ios/chrome/browser/settings/ui_bundled/google_services/google_services_settings_coordinator.mm
@@ -20,6 +20,7 @@
 #import "ios/chrome/browser/shared/coordinator/alert/action_sheet_coordinator.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/profile/features.h"
 #import "ios/chrome/browser/shared/model/profile/profile_ios.h"
 #import "ios/chrome/browser/shared/model/url/chrome_url_constants.h"
 #import "ios/chrome/browser/shared/public/commands/application_commands.h"
diff --git a/ios/chrome/browser/settings/ui_bundled/google_services/manage_accounts/BUILD.gn b/ios/chrome/browser/settings/ui_bundled/google_services/manage_accounts/BUILD.gn
index 2430dbb..0959aa8 100644
--- a/ios/chrome/browser/settings/ui_bundled/google_services/manage_accounts/BUILD.gn
+++ b/ios/chrome/browser/settings/ui_bundled/google_services/manage_accounts/BUILD.gn
@@ -40,6 +40,7 @@
     "//ios/chrome/browser/shared/model/application_context",
     "//ios/chrome/browser/shared/model/browser",
     "//ios/chrome/browser/shared/model/profile",
+    "//ios/chrome/browser/shared/model/profile:features",
     "//ios/chrome/browser/shared/model/url:constants",
     "//ios/chrome/browser/shared/public/commands",
     "//ios/chrome/browser/shared/public/features",
diff --git a/ios/chrome/browser/settings/ui_bundled/google_services/manage_accounts/manage_accounts_coordinator.mm b/ios/chrome/browser/settings/ui_bundled/google_services/manage_accounts/manage_accounts_coordinator.mm
index 616a8a4..e3a1b66 100644
--- a/ios/chrome/browser/settings/ui_bundled/google_services/manage_accounts/manage_accounts_coordinator.mm
+++ b/ios/chrome/browser/settings/ui_bundled/google_services/manage_accounts/manage_accounts_coordinator.mm
@@ -25,6 +25,7 @@
 #import "ios/chrome/browser/shared/coordinator/scene/scene_state.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/profile/features.h"
 #import "ios/chrome/browser/shared/model/profile/profile_ios.h"
 #import "ios/chrome/browser/shared/public/commands/application_commands.h"
 #import "ios/chrome/browser/shared/public/commands/command_dispatcher.h"
diff --git a/ios/chrome/browser/settings/ui_bundled/google_services/manage_accounts/manage_accounts_mediator.mm b/ios/chrome/browser/settings/ui_bundled/google_services/manage_accounts/manage_accounts_mediator.mm
index 3c8db9a..2b2f4e9 100644
--- a/ios/chrome/browser/settings/ui_bundled/google_services/manage_accounts/manage_accounts_mediator.mm
+++ b/ios/chrome/browser/settings/ui_bundled/google_services/manage_accounts/manage_accounts_mediator.mm
@@ -15,6 +15,7 @@
 #import "ios/chrome/browser/settings/ui_bundled/google_services/manage_accounts/identity_view_item.h"
 #import "ios/chrome/browser/settings/ui_bundled/google_services/manage_accounts/manage_accounts_consumer.h"
 #import "ios/chrome/browser/settings/ui_bundled/google_services/manage_accounts/manage_accounts_table_view_controller_constants.h"
+#import "ios/chrome/browser/shared/model/profile/features.h"
 #import "ios/chrome/browser/shared/model/profile/profile_ios.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
 #import "ios/chrome/browser/shared/ui/symbols/symbols.h"
@@ -26,7 +27,6 @@
 #import "ios/chrome/browser/signin/model/authentication_service.h"
 #import "ios/chrome/browser/signin/model/chrome_account_manager_service.h"
 #import "ios/chrome/browser/signin/model/chrome_account_manager_service_factory.h"
-#import "ios/chrome/browser/signin/model/chrome_account_manager_service_observer_bridge.h"
 #import "ios/chrome/browser/signin/model/constants.h"
 #import "ios/chrome/browser/signin/model/system_identity_manager.h"
 #import "ios/chrome/common/ui/colors/semantic_color_names.h"
@@ -34,16 +34,12 @@
 #import "ios/chrome/grit/ios_strings.h"
 #import "ui/base/l10n/l10n_util_mac.h"
 
-@interface ManageAccountsMediator () <ChromeAccountManagerServiceObserver,
-                                      IdentityManagerObserverBridgeDelegate>
+@interface ManageAccountsMediator () <IdentityManagerObserverBridgeDelegate>
 @end
 
 @implementation ManageAccountsMediator {
   // Account manager service to retrieve Chrome identities.
   raw_ptr<ChromeAccountManagerService> _accountManagerService;
-  // Chrome account manager service observer bridge.
-  std::unique_ptr<ChromeAccountManagerServiceObserverBridge>
-      _accountManagerServiceObserver;
   raw_ptr<AuthenticationService> _authService;
   raw_ptr<signin::IdentityManager> _identityManager;
   std::unique_ptr<signin::IdentityManagerObserverBridge>
@@ -58,9 +54,6 @@
   self = [super init];
   if (self) {
     _accountManagerService = accountManagerService;
-    _accountManagerServiceObserver =
-        std::make_unique<ChromeAccountManagerServiceObserverBridge>(
-            self, _accountManagerService);
     _authService = authService;
     _identityManager = identityManager;
     _identityManagerObserver =
@@ -72,7 +65,6 @@
 
 - (void)disconnect {
   _accountManagerService = nullptr;
-  _accountManagerServiceObserver.reset();
   _authService = nullptr;
   _identityManager = nullptr;
   _identityManagerObserver.reset();
@@ -124,22 +116,12 @@
   [self.delegate signOutWithItemView:itemView];
 }
 
-#pragma mark - ChromeAccountManagerServiceObserver
-
-- (void)onChromeAccountManagerServiceShutdown:
-    (ChromeAccountManagerService*)accountManagerService {
-  // TODO(crbug.com/40067367): This method can be removed once
-  // crbug.com/40067367 is fixed.
-  [self disconnect];
-}
-
 #pragma mark - IdentityManagerObserverBridgeDelegate
 
 - (void)onExtendedAccountInfoUpdated:(const AccountInfo&)info {
   id<SystemIdentity> identity =
       _accountManagerService->GetIdentityOnDeviceWithGaiaID(info.gaia);
-  [self.consumer
-      updateIdentityViewItem:[self identityViewItemForIdentity:identity]];
+  [self handleIdentityUpdated:identity];
 }
 
 - (void)onAccountsOnDeviceChanged {
@@ -158,6 +140,11 @@
 
 #pragma mark - Private
 
+- (void)handleIdentityUpdated:(id<SystemIdentity>)identity {
+  [self.consumer
+      updateIdentityViewItem:[self identityViewItemForIdentity:identity]];
+}
+
 - (IdentityViewItem*)identityViewItemForIdentity:(id<SystemIdentity>)identity {
   IdentityViewItem* identityViewItem = [[IdentityViewItem alloc] init];
   identityViewItem.userEmail = identity.userEmail;
@@ -176,9 +163,9 @@
 // Returns true if `identity` is known to be managed.
 // Returns false if the identity is known not to be managed or if the management
 // status is unknown. If the management status is unknown, it is fetched by
-// calling `FetchManagedStatusForIdentity`. `identityUpdated` will be called
-// asynchronously when the management status if retrieved and the identity is
-// managed.
+// calling `FetchManagedStatusForIdentity`. `handleIdentityUpdated` will be
+// called asynchronously when the management status if retrieved and the
+// identity is managed.
 - (BOOL)isIdentityKnownToBeManaged:(id<SystemIdentity>)identity {
   if (std::optional<BOOL> managed = IsIdentityManaged(identity);
       managed.has_value()) {
@@ -188,7 +175,7 @@
   __weak __typeof(self) weakSelf = self;
   FetchManagedStatusForIdentity(identity, base::BindOnce(^(bool managed) {
                                   if (managed) {
-                                    [weakSelf identityUpdated:identity];
+                                    [weakSelf handleIdentityUpdated:identity];
                                   }
                                 }));
   return NO;
diff --git a/ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_mediator.mm b/ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_mediator.mm
index 419444b..cbda6f6 100644
--- a/ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_mediator.mm
+++ b/ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_mediator.mm
@@ -42,6 +42,7 @@
 #import "ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_constants.h"
 #import "ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_consumer.h"
 #import "ios/chrome/browser/settings/ui_bundled/google_services/sync_error_settings_command_handler.h"
+#import "ios/chrome/browser/shared/model/profile/features.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
 #import "ios/chrome/browser/shared/ui/list_model/list_model.h"
 #import "ios/chrome/browser/shared/ui/symbols/symbols.h"
@@ -54,7 +55,6 @@
 #import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h"
 #import "ios/chrome/browser/signin/model/authentication_service.h"
 #import "ios/chrome/browser/signin/model/chrome_account_manager_service.h"
-#import "ios/chrome/browser/signin/model/chrome_account_manager_service_observer_bridge.h"
 #import "ios/chrome/browser/signin/model/constants.h"
 #import "ios/chrome/browser/sync/model/enterprise_utils.h"
 #import "ios/chrome/browser/sync/model/sync_observer_bridge.h"
@@ -85,8 +85,7 @@
 
 }  // namespace
 
-@interface ManageSyncSettingsMediator () <IdentityManagerObserverBridgeDelegate,
-                                          ChromeAccountManagerServiceObserver>
+@interface ManageSyncSettingsMediator () <IdentityManagerObserverBridgeDelegate>
 
 // Model item for each data types.
 @property(nonatomic, strong) NSArray<TableViewItem*>* syncSwitchItems;
@@ -121,9 +120,6 @@
   raw_ptr<AuthenticationService> _authenticationService;
   // Account manager service to retrieve Chrome identities.
   raw_ptr<ChromeAccountManagerService> _chromeAccountManagerService;
-  // Chrome account manager service observer bridge.
-  std::unique_ptr<ChromeAccountManagerServiceObserverBridge>
-      _accountManagerServiceObserver;
   // The pref service.
   raw_ptr<PrefService> _prefService;
   // Signed-in identity. Note: may be nil while signing out.
@@ -148,9 +144,6 @@
                                                                 self);
     _authenticationService = authenticationService;
     _chromeAccountManagerService = accountManagerService;
-    _accountManagerServiceObserver =
-        std::make_unique<ChromeAccountManagerServiceObserverBridge>(
-            self, _chromeAccountManagerService);
     _signedInIdentity = _authenticationService->GetPrimaryIdentity(
         signin::ConsentLevel::kSignin);
     _prefService = prefService;
@@ -171,7 +164,6 @@
   _identityManagerObserver.reset();
   _authenticationService = nullptr;
   _chromeAccountManagerService = nullptr;
-  _accountManagerServiceObserver.reset();
   _prefService = nullptr;
   _signedInIdentity = nil;
   [[NSNotificationCenter defaultCenter] removeObserver:self];
@@ -969,14 +961,6 @@
   }
 }
 
-#pragma mark - ChromeAccountManagerServiceObserver
-
-- (void)onChromeAccountManagerServiceShutdown:
-    (ChromeAccountManagerService*)accountManagerService {
-  // TODO(crbug.com/40284086): Remove `[self disconnect]`.
-  [self disconnect];
-}
-
 #pragma mark - ManageSyncSettingsServiceDelegate
 
 - (void)toggleSwitchItem:(TableViewItem*)item withValue:(BOOL)value {
diff --git a/ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_mediator_unittest.mm b/ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_mediator_unittest.mm
index 6df3f02..d558af9 100644
--- a/ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_mediator_unittest.mm
+++ b/ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_mediator_unittest.mm
@@ -24,6 +24,7 @@
 #import "ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_table_view_controller.h"
 #import "ios/chrome/browser/shared/model/application_context/application_context.h"
 #import "ios/chrome/browser/shared/model/browser/test/test_browser.h"
+#import "ios/chrome/browser/shared/model/profile/features.h"
 #import "ios/chrome/browser/shared/model/profile/test/test_profile_ios.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
 #import "ios/chrome/browser/shared/ui/table_view/cells/table_view_detail_icon_item.h"
diff --git a/ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_table_view_controller.mm b/ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_table_view_controller.mm
index 3e9c5a4e..5b454f3 100644
--- a/ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_table_view_controller.mm
+++ b/ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_table_view_controller.mm
@@ -14,7 +14,7 @@
 #import "ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_constants.h"
 #import "ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_service_delegate.h"
 #import "ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_table_view_controller_model_delegate.h"
-#import "ios/chrome/browser/shared/public/features/features.h"
+#import "ios/chrome/browser/shared/model/profile/features.h"
 #import "ios/chrome/browser/shared/ui/symbols/symbols.h"
 #import "ios/chrome/browser/shared/ui/table_view/cells/table_view_info_button_cell.h"
 #import "ios/chrome/browser/shared/ui/table_view/cells/table_view_switch_cell.h"
diff --git a/ios/chrome/browser/settings/ui_bundled/password/password_manager_view_controller.mm b/ios/chrome/browser/settings/ui_bundled/password/password_manager_view_controller.mm
index f12cf2c..e548025 100644
--- a/ios/chrome/browser/settings/ui_bundled/password/password_manager_view_controller.mm
+++ b/ios/chrome/browser/settings/ui_bundled/password/password_manager_view_controller.mm
@@ -70,7 +70,6 @@
 #import "ios/chrome/browser/shared/ui/table_view/table_view_navigation_controller_constants.h"
 #import "ios/chrome/browser/shared/ui/table_view/table_view_utils.h"
 #import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h"
-#import "ios/chrome/browser/signin/model/chrome_account_manager_service_observer_bridge.h"
 #import "ios/chrome/common/string_util.h"
 #import "ios/chrome/common/ui/colors/semantic_color_names.h"
 #import "ios/chrome/common/ui/elements/branded_navigation_item_title_view.h"
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 2f66a89..d5353f6 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
@@ -134,7 +134,6 @@
 #import "ios/chrome/browser/signin/model/authentication_service_factory.h"
 #import "ios/chrome/browser/signin/model/chrome_account_manager_service.h"
 #import "ios/chrome/browser/signin/model/chrome_account_manager_service_factory.h"
-#import "ios/chrome/browser/signin/model/chrome_account_manager_service_observer_bridge.h"
 #import "ios/chrome/browser/signin/model/identity_manager_factory.h"
 #import "ios/chrome/browser/signin/model/system_identity.h"
 #import "ios/chrome/browser/sync/model/enterprise_utils.h"
@@ -190,7 +189,6 @@
 
 @interface SettingsTableViewController () <
     BooleanObserver,
-    ChromeAccountManagerServiceObserver,
     DownloadsSettingsCoordinatorDelegate,
     EnhancedSafeBrowsingInlinePromoDelegate,
     GoogleServicesSettingsCoordinatorDelegate,
@@ -263,10 +261,8 @@
   // Presenter for the signin IPH.
   BubbleViewControllerPresenter* _bubblePresenter;
 
-  // Identity object and observer used for Account Item refresh.
+  // Identity object.
   id<SystemIdentity> _identity;
-  std::unique_ptr<ChromeAccountManagerServiceObserverBridge>
-      _accountManagerServiceObserver;
 
   // PrefMember for voice locale code.
   StringPrefMember _voiceLocaleCode;
@@ -365,9 +361,7 @@
     AuthenticationService* authService =
         AuthenticationServiceFactory::GetForProfile(_profile);
     _identity = authService->GetPrimaryIdentity(signin::ConsentLevel::kSignin);
-    _accountManagerServiceObserver.reset(
-        new ChromeAccountManagerServiceObserverBridge(self,
-                                                      _accountManagerService));
+
     _featureEngagementTracker =
         feature_engagement::TrackerFactory::GetForProfile(_profile);
 
@@ -2122,7 +2116,6 @@
   _searchEngineObserverBridge.reset();
   _syncObserverBridge.reset();
   _identityObserverBridge.reset();
-  _accountManagerServiceObserver.reset();
 
   // Remove PrefObserverDelegates.
   _notificationsObserver.delegate = nil;
@@ -2166,16 +2159,6 @@
   }
 }
 
-#pragma mark - ChromeAccountManagerServiceObserver
-
-- (void)onChromeAccountManagerServiceShutdown:
-    (ChromeAccountManagerService*)accountManagerService {
-  // TODO(crbug.com/40926211): settingsWillBeDismissed must be called before the
-  // AccountManagerService is destroyed. Switch to DCHECK if the number of
-  // reports is low.
-  DUMP_WILL_BE_CHECK(!_accountManagerServiceObserver.get());
-}
-
 #pragma mark - BooleanObserver
 
 - (void)booleanDidChange:(id<ObservableBoolean>)observableBoolean {
diff --git a/ios/chrome/browser/shared/model/prefs/browser_prefs.mm b/ios/chrome/browser/shared/model/prefs/browser_prefs.mm
index 1055b7f..c503f4b 100644
--- a/ios/chrome/browser/shared/model/prefs/browser_prefs.mm
+++ b/ios/chrome/browser/shared/model/prefs/browser_prefs.mm
@@ -1061,6 +1061,9 @@
 
   // Added 03/2025.
   prefs->ClearPref(kIosParcelTrackingPolicyEnabled);
+
+  // Added 04/2025.
+  prefs->ClearPref("set_up_list.disabled");
 }
 
 // This method should be periodically pruned of year+ old migrations.
diff --git a/ios/chrome/browser/shared/model/profile/BUILD.gn b/ios/chrome/browser/shared/model/profile/BUILD.gn
index cb4c5ed..4c28f84 100644
--- a/ios/chrome/browser/shared/model/profile/BUILD.gn
+++ b/ios/chrome/browser/shared/model/profile/BUILD.gn
@@ -8,7 +8,13 @@
     "features.mm",
   ]
 
-  deps = [ "//base" ]
+  deps = [
+    ":profile",
+    "//base",
+    "//ios/chrome/browser/ntp/ui_bundled:feature_flags",
+    "//ios/chrome/browser/shared/model/application_context",
+    "//ios/chrome/browser/shared/public/features",
+  ]
 }
 
 source_set("profile") {
diff --git a/ios/chrome/browser/shared/model/profile/DEPS b/ios/chrome/browser/shared/model/profile/DEPS
index 5f9b68d..d29646b 100644
--- a/ios/chrome/browser/shared/model/profile/DEPS
+++ b/ios/chrome/browser/shared/model/profile/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
   "+ios/chrome/browser/net/model",
+  "+ios/chrome/browser/ntp/ui_bundled/new_tab_page_feature.h",
   "+ios/web/webui",
 ]
diff --git a/ios/chrome/browser/shared/model/profile/features.h b/ios/chrome/browser/shared/model/profile/features.h
index 807b515..b0d5ec43 100644
--- a/ios/chrome/browser/shared/model/profile/features.h
+++ b/ios/chrome/browser/shared/model/profile/features.h
@@ -7,8 +7,14 @@
 
 #import "base/feature_list.h"
 
-// TODO(crbug.com/383977223): Move
-// AreSeparateProfilesForManagedAccountsEnabled() here once internal references
-// are updated to include this file.
+// THIS CANNOT BE USED FROM EARLGREY TESTS.
+
+// Returns whether the feature to put each managed account into its own separate
+// profile is enabled. This is the case if `kSeparateProfilesForManagedAccounts`
+// is enabled *and* the iOS version is >= 17 (required for multiprofile).
+bool AreSeparateProfilesForManagedAccountsEnabled();
+
+// YES if the account particle disc on the NTP should open the account menu.
+bool IsIdentityDiscAccountMenuEnabled();
 
 #endif  // IOS_CHROME_BROWSER_SHARED_MODEL_PROFILE_FEATURES_H_
diff --git a/ios/chrome/browser/shared/model/profile/features.mm b/ios/chrome/browser/shared/model/profile/features.mm
index 97ab248..5b91e23f 100644
--- a/ios/chrome/browser/shared/model/profile/features.mm
+++ b/ios/chrome/browser/shared/model/profile/features.mm
@@ -3,3 +3,74 @@
 // found in the LICENSE file.
 
 #import "ios/chrome/browser/shared/model/profile/features.h"
+
+#import "base/check_is_test.h"
+#import "base/feature_list.h"
+#import "ios/chrome/browser/ntp/ui_bundled/new_tab_page_feature.h"
+#import "ios/chrome/browser/shared/model/application_context/application_context.h"
+#import "ios/chrome/browser/shared/model/profile/profile_attributes_ios.h"
+#import "ios/chrome/browser/shared/model/profile/profile_attributes_storage_ios.h"
+#import "ios/chrome/browser/shared/model/profile/profile_manager_ios.h"
+#import "ios/chrome/browser/shared/public/features/features.h"
+
+namespace {
+
+bool DetermineHasMultipleProfiles() {
+  ProfileManagerIOS* profile_manager =
+      GetApplicationContext()->GetProfileManager();
+  ProfileAttributesStorageIOS* attributes =
+      profile_manager ? profile_manager->GetProfileAttributesStorage()
+                      : nullptr;
+  if (!attributes) {
+    // ProfileManagerIOS or ProfileAttributesStorageIOS shouldn't be null,
+    // except in some unit tests.
+    CHECK_IS_TEST();
+    return false;
+  }
+  // If only a single profile has been registered, nothing else to do.
+  if (attributes->GetNumberOfProfiles() <= 1) {
+    return false;
+  }
+  // When more than one profile has been registered, count how many have been
+  // been initialized (i.e. actually created).
+  int fully_initialized_profiles = 0;
+  attributes->IterateOverProfileAttributes(base::BindRepeating(
+      [](int& fully_initialized_profiles, const ProfileAttributesIOS& attr) {
+        if (attr.IsFullyInitialized()) {
+          ++fully_initialized_profiles;
+        }
+      },
+      std::ref(fully_initialized_profiles)));
+  return fully_initialized_profiles > 1;
+}
+
+}  // namespace
+
+bool AreSeparateProfilesForManagedAccountsEnabled() {
+  // The APIs to support multiple profiles are only available in iOS 17+, so
+  // consider this feature as disabled in earlier versions.
+  if (!@available(iOS 17, *)) {
+    return false;
+  }
+  // If the killswitch has been triggered, it's off.
+  if (base::FeatureList::IsEnabled(
+          kSeparateProfilesForManagedAccountsKillSwitch)) {
+    return false;
+  }
+  // Standard case: Check the regular feature flag.
+  if (base::FeatureList::IsEnabled(kSeparateProfilesForManagedAccounts)) {
+    return true;
+  }
+  // If the feature is disabled, but the user already has multiple profiles
+  // (can happen if the feature used to be enabled), leave it on so these
+  // profiles remain accessible.
+  static const bool has_multiple_profiles = DetermineHasMultipleProfiles();
+  return has_multiple_profiles;
+}
+
+bool IsIdentityDiscAccountMenuEnabled() {
+  if (AreSeparateProfilesForManagedAccountsEnabled()) {
+    return true;
+  }
+  return base::FeatureList::IsEnabled(kIdentityDiscAccountMenu);
+}
diff --git a/ios/chrome/browser/shared/public/features/features.h b/ios/chrome/browser/shared/public/features/features.h
index a1cbfa5..89913da 100644
--- a/ios/chrome/browser/shared/public/features/features.h
+++ b/ios/chrome/browser/shared/public/features/features.h
@@ -821,12 +821,6 @@
 // Returns true if the Save to Photos account picker improvement is enabled.
 bool IsSaveToPhotosAccountPickerImprovementEnabled();
 
-// Feature that enables personalization of the Home surface.
-BASE_DECLARE_FEATURE(kHomeCustomization);
-
-// Returns true if Home Customization is enabled.
-bool IsHomeCustomizationEnabled();
-
 // Feature flag to enable app background refresh.
 // Use IsAppBackgroundRefreshEnabled() instead of this constant directly.
 BASE_DECLARE_FEATURE(kEnableAppBackgroundRefresh);
@@ -868,10 +862,10 @@
 // DO NOT CHECK DIRECTLY, use AreSeparateProfilesForManagedAccountsEnabled()!
 BASE_DECLARE_FEATURE(kSeparateProfilesForManagedAccounts);
 
-// Returns whether the feature to put each managed account into its own separate
-// profile is enabled. This is the case if `kSeparateProfilesForManagedAccounts`
-// is enabled *and* the iOS version is >= 17 (required for multiprofile).
-bool AreSeparateProfilesForManagedAccountsEnabled();
+// Kill switch to turn off `kSeparateProfilesForManagedAccounts`, even if
+// multiple profiles already exist.
+// DO NOT CHECK DIRECTLY, use AreSeparateProfilesForManagedAccountsEnabled()!
+BASE_DECLARE_FEATURE(kSeparateProfilesForManagedAccountsKillSwitch);
 
 // Feature to control resyncing the omaha ping timer on foregrounding.
 BASE_DECLARE_FEATURE(kOmahaResyncTimerOnForeground);
diff --git a/ios/chrome/browser/shared/public/features/features.mm b/ios/chrome/browser/shared/public/features/features.mm
index 239c14e..ad3493e 100644
--- a/ios/chrome/browser/shared/public/features/features.mm
+++ b/ios/chrome/browser/shared/public/features/features.mm
@@ -974,17 +974,8 @@
              kSaveToPhotosAccountDefaultChoiceImprovementParam, true);
 }
 
-BASE_FEATURE(kHomeCustomization,
-             "HomeCustomization",
-             base::FEATURE_ENABLED_BY_DEFAULT);
-
-bool IsHomeCustomizationEnabled() {
-  return base::FeatureList::IsEnabled(kHomeCustomization);
-}
-
 bool ShouldDeprecateFeedHeader() {
-  return IsHomeCustomizationEnabled() &&
-         base::FeatureList::IsEnabled(kDeprecateFeedHeader);
+  return base::FeatureList::IsEnabled(kDeprecateFeedHeader);
 }
 
 BASE_FEATURE(kEnableAppBackgroundRefresh,
@@ -1046,14 +1037,9 @@
              "SeparateProfilesForManagedAccounts",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
-bool AreSeparateProfilesForManagedAccountsEnabled() {
-  // The APIs to support multiple profiles are only available in iOS 17+, so
-  // consider this feature as disabled in earlier versions.
-  if (!@available(iOS 17, *)) {
-    return false;
-  }
-  return base::FeatureList::IsEnabled(kSeparateProfilesForManagedAccounts);
-}
+BASE_FEATURE(kSeparateProfilesForManagedAccountsKillSwitch,
+             "SeparateProfilesForManagedAccountsKillSwitch",
+             base::FEATURE_DISABLED_BY_DEFAULT);
 
 BASE_FEATURE(kOmahaResyncTimerOnForeground,
              "OmahaResyncTimerOnForeground",
diff --git a/ios/chrome/browser/signin/model/BUILD.gn b/ios/chrome/browser/signin/model/BUILD.gn
index 0cf2979..3fc6d63 100644
--- a/ios/chrome/browser/signin/model/BUILD.gn
+++ b/ios/chrome/browser/signin/model/BUILD.gn
@@ -87,6 +87,7 @@
     "//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/profile:features",
     "//ios/chrome/browser/shared/model/profile:profile_keyed_service_factory",
     "//ios/chrome/browser/shared/model/web_state_list",
     "//ios/chrome/browser/shared/public/commands",
@@ -152,6 +153,7 @@
     "//ios/chrome/browser/policy/model:policy_util",
     "//ios/chrome/browser/shared/model/application_context",
     "//ios/chrome/browser/shared/model/prefs:pref_names",
+    "//ios/chrome/browser/shared/model/profile:features",
     "//ios/chrome/browser/shared/public/features",
     "//ios/chrome/browser/shared/public/features:system_flags",
     "//ios/chrome/browser/widget_kit/model:features",
@@ -178,6 +180,7 @@
     "//ios/chrome/browser/ntp/ui_bundled:feature_flags",
     "//ios/chrome/browser/shared/model/prefs:pref_names",
     "//ios/chrome/browser/shared/model/profile",
+    "//ios/chrome/browser/shared/model/profile:features",
     "//ios/chrome/browser/shared/model/profile:profile_keyed_service_factory",
     "//ios/chrome/browser/sync/model",
   ]
@@ -489,6 +492,7 @@
     "//ios/chrome/browser/shared/model/prefs:browser_prefs",
     "//ios/chrome/browser/shared/model/prefs:pref_names",
     "//ios/chrome/browser/shared/model/profile",
+    "//ios/chrome/browser/shared/model/profile:features",
     "//ios/chrome/browser/shared/model/profile/test",
     "//ios/chrome/browser/shared/model/web_state_list",
     "//ios/chrome/browser/shared/public/commands",
diff --git a/ios/chrome/browser/signin/model/account_consistency_browser_agent.mm b/ios/chrome/browser/signin/model/account_consistency_browser_agent.mm
index 972640a7..dd090b3 100644
--- a/ios/chrome/browser/signin/model/account_consistency_browser_agent.mm
+++ b/ios/chrome/browser/signin/model/account_consistency_browser_agent.mm
@@ -9,6 +9,7 @@
 #import "components/signin/core/browser/account_reconcilor.h"
 #import "components/signin/ios/browser/account_consistency_service.h"
 #import "ios/chrome/browser/shared/model/application_context/application_context.h"
+#import "ios/chrome/browser/shared/model/profile/features.h"
 #import "ios/chrome/browser/shared/model/profile/profile_attributes_storage_ios.h"
 #import "ios/chrome/browser/shared/model/profile/profile_manager_ios.h"
 #import "ios/chrome/browser/shared/public/commands/application_commands.h"
@@ -16,7 +17,6 @@
 #import "ios/chrome/browser/shared/public/commands/open_new_tab_command.h"
 #import "ios/chrome/browser/shared/public/commands/settings_commands.h"
 #import "ios/chrome/browser/shared/public/commands/show_signin_command.h"
-#import "ios/chrome/browser/shared/public/features/features.h"
 #import "ios/chrome/browser/signin/model/account_consistency_service_factory.h"
 #import "ios/chrome/browser/signin/model/account_reconcilor_factory.h"
 #import "ios/chrome/browser/web/model/web_navigation_browser_agent.h"
diff --git a/ios/chrome/browser/signin/model/account_consistency_browser_agent_unittest.mm b/ios/chrome/browser/signin/model/account_consistency_browser_agent_unittest.mm
index 07209c5..d1a7a75 100644
--- a/ios/chrome/browser/signin/model/account_consistency_browser_agent_unittest.mm
+++ b/ios/chrome/browser/signin/model/account_consistency_browser_agent_unittest.mm
@@ -8,6 +8,7 @@
 #import "base/test/scoped_feature_list.h"
 #import "ios/chrome/browser/lens/model/lens_browser_agent.h"
 #import "ios/chrome/browser/shared/model/browser/test/test_browser.h"
+#import "ios/chrome/browser/shared/model/profile/features.h"
 #import "ios/chrome/browser/shared/model/profile/test/test_profile_ios.h"
 #import "ios/chrome/browser/shared/model/profile/test/test_profile_manager_ios.h"
 #import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h"
diff --git a/ios/chrome/browser/signin/model/account_profile_mapper.mm b/ios/chrome/browser/signin/model/account_profile_mapper.mm
index 2ecdd61..fb0b22d 100644
--- a/ios/chrome/browser/signin/model/account_profile_mapper.mm
+++ b/ios/chrome/browser/signin/model/account_profile_mapper.mm
@@ -16,12 +16,12 @@
 #import "google_apis/gaia/gaia_id.h"
 #import "ios/chrome/app/change_profile_commands.h"
 #import "ios/chrome/browser/policy/model/policy_util.h"
+#import "ios/chrome/browser/shared/model/profile/features.h"
 #import "ios/chrome/browser/shared/model/profile/profile_attributes_ios.h"
 #import "ios/chrome/browser/shared/model/profile/profile_attributes_storage_ios.h"
 #import "ios/chrome/browser/shared/model/profile/profile_attributes_storage_observer_ios.h"
 #import "ios/chrome/browser/shared/model/profile/profile_ios.h"
 #import "ios/chrome/browser/shared/model/profile/profile_manager_ios.h"
-#import "ios/chrome/browser/shared/public/features/features.h"
 #import "ios/chrome/browser/signin/model/system_identity.h"
 #import "ios/chrome/browser/signin/model/system_identity_manager_observer.h"
 #import "net/base/backoff_entry.h"
diff --git a/ios/chrome/browser/signin/model/account_profile_mapper_unittest.mm b/ios/chrome/browser/signin/model/account_profile_mapper_unittest.mm
index ac36e68..c2b7baa 100644
--- a/ios/chrome/browser/signin/model/account_profile_mapper_unittest.mm
+++ b/ios/chrome/browser/signin/model/account_profile_mapper_unittest.mm
@@ -17,6 +17,7 @@
 #import "base/uuid.h"
 #import "ios/chrome/app/change_profile_commands.h"
 #import "ios/chrome/browser/shared/model/application_context/application_context.h"
+#import "ios/chrome/browser/shared/model/profile/features.h"
 #import "ios/chrome/browser/shared/model/profile/mutable_profile_attributes_storage_ios.h"
 #import "ios/chrome/browser/shared/model/profile/profile_attributes_ios.h"
 #import "ios/chrome/browser/shared/model/profile/profile_attributes_storage_observer_ios.h"
diff --git a/ios/chrome/browser/signin/model/authentication_service.mm b/ios/chrome/browser/signin/model/authentication_service.mm
index 779a283..70d9f3be 100644
--- a/ios/chrome/browser/signin/model/authentication_service.mm
+++ b/ios/chrome/browser/signin/model/authentication_service.mm
@@ -33,6 +33,7 @@
 #import "ios/chrome/browser/policy/model/policy_util.h"
 #import "ios/chrome/browser/shared/model/application_context/application_context.h"
 #import "ios/chrome/browser/shared/model/prefs/pref_names.h"
+#import "ios/chrome/browser/shared/model/profile/features.h"
 #import "ios/chrome/browser/shared/model/profile/profile_attributes_ios.h"
 #import "ios/chrome/browser/shared/model/profile/profile_attributes_storage_ios.h"
 #import "ios/chrome/browser/shared/model/profile/profile_manager_ios.h"
diff --git a/ios/chrome/browser/signin/model/authentication_service_delegate_impl.cc b/ios/chrome/browser/signin/model/authentication_service_delegate_impl.cc
index 58c2cde..4acc185 100644
--- a/ios/chrome/browser/signin/model/authentication_service_delegate_impl.cc
+++ b/ios/chrome/browser/signin/model/authentication_service_delegate_impl.cc
@@ -15,6 +15,7 @@
 #include "ios/chrome/browser/browsing_data/model/browsing_data_remover.h"
 #include "ios/chrome/browser/ntp/ui_bundled/new_tab_page_feature.h"
 #include "ios/chrome/browser/shared/model/prefs/pref_names.h"
+#include "ios/chrome/browser/shared/model/profile/features.h"
 
 AuthenticationServiceDelegateImpl::AuthenticationServiceDelegateImpl(
     BrowsingDataRemover* data_remover,
diff --git a/ios/chrome/browser/signin/model/authentication_service_unittest.mm b/ios/chrome/browser/signin/model/authentication_service_unittest.mm
index 8f8d732d..b3753be 100644
--- a/ios/chrome/browser/signin/model/authentication_service_unittest.mm
+++ b/ios/chrome/browser/signin/model/authentication_service_unittest.mm
@@ -35,6 +35,7 @@
 #import "ios/chrome/browser/shared/model/application_context/application_context.h"
 #import "ios/chrome/browser/shared/model/prefs/browser_prefs.h"
 #import "ios/chrome/browser/shared/model/prefs/pref_names.h"
+#import "ios/chrome/browser/shared/model/profile/features.h"
 #import "ios/chrome/browser/shared/model/profile/test/test_profile_ios.h"
 #import "ios/chrome/browser/shared/model/profile/test/test_profile_manager_ios.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
diff --git a/ios/chrome/browser/signin/model/chrome_account_manager_service_observer_bridge.h b/ios/chrome/browser/signin/model/chrome_account_manager_service_observer_bridge.h
index df2944d..a4f4cbd 100644
--- a/ios/chrome/browser/signin/model/chrome_account_manager_service_observer_bridge.h
+++ b/ios/chrome/browser/signin/model/chrome_account_manager_service_observer_bridge.h
@@ -11,10 +11,9 @@
 #import "ios/chrome/browser/signin/model/chrome_account_manager_service.h"
 
 // Objective-C protocol mirroring ChromeAccountManagerService::Observer.
+// TODO(crbug.com/377467350): Remove this protocol.
 @protocol ChromeAccountManagerServiceObserver <NSObject>
 @optional
-- (void)identityListChanged;
-- (void)identityUpdated:(id<SystemIdentity>)identity;
 - (void)onChromeAccountManagerServiceShutdown:
     (ChromeAccountManagerService*)accountManagerService;
 @end
@@ -34,8 +33,6 @@
 
  private:
   // ChromeAccountManagerService::Observer implementation.
-  void OnIdentitiesInProfileChanged() override;
-  void OnIdentityInProfileUpdated(id<SystemIdentity> identity) override;
   void OnChromeAccountManagerServiceShutdown(
       ChromeAccountManagerService* chrome_account_manager_service) override;
 
diff --git a/ios/chrome/browser/signin/model/chrome_account_manager_service_observer_bridge.mm b/ios/chrome/browser/signin/model/chrome_account_manager_service_observer_bridge.mm
index 2c51c3c9..8d9bd5f 100644
--- a/ios/chrome/browser/signin/model/chrome_account_manager_service_observer_bridge.mm
+++ b/ios/chrome/browser/signin/model/chrome_account_manager_service_observer_bridge.mm
@@ -18,20 +18,7 @@
 }
 
 ChromeAccountManagerServiceObserverBridge::
-    ~ChromeAccountManagerServiceObserverBridge() {}
-
-void ChromeAccountManagerServiceObserverBridge::OnIdentitiesInProfileChanged() {
-  if ([observer_ respondsToSelector:@selector(identityListChanged)]) {
-    [observer_ identityListChanged];
-  }
-}
-
-void ChromeAccountManagerServiceObserverBridge::OnIdentityInProfileUpdated(
-    id<SystemIdentity> identity) {
-  if ([observer_ respondsToSelector:@selector(identityUpdated:)]) {
-    [observer_ identityUpdated:identity];
-  }
-}
+    ~ChromeAccountManagerServiceObserverBridge() = default;
 
 void ChromeAccountManagerServiceObserverBridge::
     OnChromeAccountManagerServiceShutdown(
diff --git a/ios/chrome/browser/signin/model/chrome_account_manager_service_observer_bridge_unittest.mm b/ios/chrome/browser/signin/model/chrome_account_manager_service_observer_bridge_unittest.mm
index 6970c0dc..6a5b3ef 100644
--- a/ios/chrome/browser/signin/model/chrome_account_manager_service_observer_bridge_unittest.mm
+++ b/ios/chrome/browser/signin/model/chrome_account_manager_service_observer_bridge_unittest.mm
@@ -43,16 +43,10 @@
   id<ChromeAccountManagerServiceObserver> test_observer_ = nil;
 };
 
-// Tests that `onIdentityListChanged` is forwarded.
-TEST_F(ChromeAccountManagerServiceObserverBridgeTest, onIdentityListChanged) {
-  OCMExpect([test_observer_ identityListChanged]);
-  observer_bridge_->OnIdentitiesInProfileChanged();
-}
-
-// Tests that `onIdentityChanged` is forwarded.
-TEST_F(ChromeAccountManagerServiceObserverBridgeTest, onIdentityUpdated) {
-  id<SystemIdentity> identity = [FakeSystemIdentity fakeIdentity1];
-
-  OCMExpect([test_observer_ identityUpdated:identity]);
-  observer_bridge_->OnIdentityInProfileUpdated(identity);
+// Tests that `OnChromeAccountManagerServiceShutdown` is forwarded.
+TEST_F(ChromeAccountManagerServiceObserverBridgeTest,
+       OnChromeAccountManagerServiceShutdown) {
+  ChromeAccountManagerService* service = nullptr;
+  OCMExpect([test_observer_ onChromeAccountManagerServiceShutdown:service]);
+  observer_bridge_->OnChromeAccountManagerServiceShutdown(service);
 }
diff --git a/ios/chrome/browser/signin/model/signin_util_internal.h b/ios/chrome/browser/signin/model/signin_util_internal.h
index 0ea7337..2b8ce91 100644
--- a/ios/chrome/browser/signin/model/signin_util_internal.h
+++ b/ios/chrome/browser/signin/model/signin_util_internal.h
@@ -8,6 +8,7 @@
 #include <optional>
 
 #include "base/files/file_path.h"
+#include "base/functional/callback_helpers.h"
 #include "base/time/time.h"
 
 namespace signin {
@@ -38,6 +39,8 @@
 // Returns whether Chrome has been started after a device restore. This method
 // needs to be called for the first time before IO is disallowed on UI thread.
 // The value is cached. The result is cached for later calls.
-signin::RestoreData LoadDeviceRestoreDataInternal();
+// `completion` is called once all sentinel files are created.
+signin::RestoreData LoadDeviceRestoreDataInternal(
+    base::OnceClosure completion = base::DoNothing());
 
 #endif  // IOS_CHROME_BROWSER_SIGNIN_MODEL_SIGNIN_UTIL_INTERNAL_H_
diff --git a/ios/chrome/browser/signin/model/signin_util_internal.mm b/ios/chrome/browser/signin/model/signin_util_internal.mm
index 5d82458e3..d781ba4 100644
--- a/ios/chrome/browser/signin/model/signin_util_internal.mm
+++ b/ios/chrome/browser/signin/model/signin_util_internal.mm
@@ -8,10 +8,13 @@
 
 #import "base/files/file.h"
 #import "base/files/file_util.h"
+#import "base/functional/callback_helpers.h"
 #import "base/logging.h"
 #import "base/metrics/histogram_functions.h"
 #import "base/path_service.h"
 #import "base/strings/sys_string_conversions.h"
+#import "base/task/task_traits.h"
+#import "base/task/thread_pool.h"
 #import "base/threading/scoped_blocking_call.h"
 #import "base/time/time.h"
 #import "components/signin/public/identity_manager/tribool.h"
@@ -32,6 +35,12 @@
   kMaxValue = kExcludedFromBackupFlagFailed,
 };
 
+// Represents information about a sentinel file.
+struct SentinelFileInfo {
+  base::FilePath path;
+  bool exclude_from_backup;
+};
+
 // Records Signin.IOSDeviceRestoreSentinelError histogram.
 void RecordSentinelErrorHistogram(SigninIOSDeviceRestoreSentinelError error) {
   base::UmaHistogramEnumeration("Signin.IOSDeviceRestoreSentinelError", error);
@@ -76,6 +85,19 @@
   return false;
 }
 
+// Creates the sentinel files for LoadDeviceRestoreDataInternal(...).
+void CreateSentinelFiles(std::array<SentinelFileInfo, 2> infos) {
+  for (const SentinelFileInfo& info : infos) {
+    if (!base::PathExists(info.path) &&
+        !CreateSentinelFile(info.path, info.exclude_from_backup)) {
+      // If creating any of the sentinel files fail, stop and
+      // do not try to create the other ones. This avoid returning
+      // false positives.
+      return;
+    }
+  }
+}
+
 }  // namespace
 
 // File name for sentinel to backup in iOS backup device.
@@ -95,7 +117,8 @@
   return user_data_path.Append(sentinel_name);
 }
 
-signin::RestoreData LoadDeviceRestoreDataInternal() {
+signin::RestoreData LoadDeviceRestoreDataInternal(
+    base::OnceClosure completion) {
   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                 base::BlockingType::WILL_BLOCK);
   const base::FilePath backed_up_sentinel_path =
@@ -125,21 +148,20 @@
   // fails, the resulting state can be detected and, upon next invocation
   // (which in practice means upon next browser startup), it resumes normally
   // and meanwhile Tribool::kUnknown is returned.
-  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
-    if (does_not_backed_up_sentinel_file_exist ||
-        CreateSentinelFile(not_backed_up_sentinel_path,
-                           /* exclude_from_backup */ true)) {
-      // The not-backed-up file is known to exist, so it is safe to create the
-      // backed-up file. Doing so conditionally avoids returning false positives
-      // in IsFirstSessionAfterDeviceRestoreInternal(), which otherwise could
-      // return true if the first file's creation (the not-backed-up one's)
-      // failed.
-      if (!does_backed_up_sentinel_file_exist) {
-        CreateSentinelFile(backed_up_sentinel_path,
-                           /* exclude_from_backup */ false);
-      }
-    }
-  });
+  base::ThreadPool::PostTaskAndReply(
+      FROM_HERE, {base::MayBlock(), base::TaskPriority::LOWEST},
+      base::BindOnce(&CreateSentinelFiles,
+                     std::array<SentinelFileInfo, 2>{
+                         SentinelFileInfo{
+                             .path = not_backed_up_sentinel_path,
+                             .exclude_from_backup = true,
+                         },
+                         SentinelFileInfo{
+                             .path = backed_up_sentinel_path,
+                             .exclude_from_backup = false,
+                         },
+                     }),
+      std::move(completion));
 
   signin::RestoreData restore_data;
   if (!does_backed_up_sentinel_file_exist) {
diff --git a/ios/chrome/browser/signin/model/signin_util_internal_unittest.mm b/ios/chrome/browser/signin/model/signin_util_internal_unittest.mm
index 2d33ddd..49392767 100644
--- a/ios/chrome/browser/signin/model/signin_util_internal_unittest.mm
+++ b/ios/chrome/browser/signin/model/signin_util_internal_unittest.mm
@@ -8,8 +8,10 @@
 
 #import "base/files/file.h"
 #import "base/files/file_util.h"
+#import "base/run_loop.h"
 #import "base/strings/sys_string_conversions.h"
 #import "base/test/ios/wait_util.h"
+#import "base/test/task_environment.h"
 #import "base/time/time.h"
 #import "components/signin/public/identity_manager/tribool.h"
 #import "testing/gtest_mac.h"
@@ -44,70 +46,64 @@
     return [NSURL fileURLWithPath:path_string];
   }
 
-  void WaitAndExpectSentinelThatIsBackedUp() {
-    NSURL* url = GetSentinelThatIsBackedUpURLPath();
-    ConditionBlock condition = ^() {
-      BOOL sentinel_exist =
-          [[NSFileManager defaultManager] fileExistsAtPath:[url path]];
-      return sentinel_exist;
-    };
-    bool wait_success = base::test::ios::WaitUntilConditionOrTimeout(
-        base::Seconds(5), condition);
-    EXPECT_TRUE(wait_success);
+  void ExpectSentinelFile(NSURL* url, BOOL is_excluded_from_backup) {
+    std::string url_description = base::SysNSStringToUTF8([url description]);
+    EXPECT_TRUE([[NSFileManager defaultManager] fileExistsAtPath:url.path])
+        << url_description;
     NSError* error = nil;
     id resource_value;
     BOOL success = [url getResourceValue:&resource_value
                                   forKey:NSURLIsExcludedFromBackupKey
                                    error:&error];
-    ASSERT_TRUE(success);
-    ASSERT_EQ(nil, error);
-    EXPECT_NE(nil, resource_value);
-    EXPECT_FALSE([resource_value boolValue]);
+    ASSERT_TRUE(success) << url_description;
+    ASSERT_EQ(nil, error) << url_description;
+    EXPECT_NE(nil, resource_value) << url_description;
+    EXPECT_EQ(is_excluded_from_backup, [resource_value boolValue])
+        << url_description;
   }
 
-  void WaitAndExpectSentinelThatIsNotBackedUp() {
-    NSURL* url = GetSentinelThatIsNotBackedUpURLPath();
-    ConditionBlock condition = ^() {
-      BOOL sentinel_exist =
-          [[NSFileManager defaultManager] fileExistsAtPath:[url path]];
-      return sentinel_exist;
-    };
-    bool wait_success = base::test::ios::WaitUntilConditionOrTimeout(
-        base::Seconds(5), condition);
-    EXPECT_TRUE(wait_success);
-    __block id resource_value = nil;
-    __block NSError* error = nil;
-    condition = ^bool() {
-      [url getResourceValue:&resource_value
-                     forKey:NSURLIsExcludedFromBackupKey
-                      error:&error];
-      return resource_value != nil && [resource_value boolValue];
-    };
-    wait_success = base::test::ios::WaitUntilConditionOrTimeout(
-        base::Seconds(5), condition);
-    ASSERT_EQ(nil, error);
-    EXPECT_TRUE(wait_success);
+  void ExpectSentinelThatIsBackedUp() {
+    NSURL* url = GetSentinelThatIsBackedUpURLPath();
+    ExpectSentinelFile(url, /*is_excluded_from_backup=*/NO);
   }
+
+  void ExpectSentinelThatIsNotBackedUp() {
+    NSURL* url = GetSentinelThatIsNotBackedUpURLPath();
+    ExpectSentinelFile(url, /*is_excluded_from_backup=*/YES);
+  }
+
+ protected:
+  base::test::TaskEnvironment task_environment_;
 };
 
 // Tests the result of IsFirstSessionAfterDeviceRestoreInternal(), when no
 // sentinel exists.
 TEST_F(SigninUtilInternalTest,
        IsFirstSessionAfterDeviceRestoreInternalNoSentinelFile) {
-  signin::RestoreData restore_data = LoadDeviceRestoreDataInternal();
-  EXPECT_EQ(signin::Tribool::kUnknown,
-            restore_data.is_first_session_after_device_restore);
-  // Device restore is unknown, so there is no timestamp.
-  EXPECT_FALSE(restore_data.last_restore_timestamp.has_value());
-  WaitAndExpectSentinelThatIsBackedUp();
-  WaitAndExpectSentinelThatIsNotBackedUp();
+  {
+    base::RunLoop run_loop;
+    signin::RestoreData restore_data =
+        LoadDeviceRestoreDataInternal(run_loop.QuitClosure());
+    EXPECT_EQ(signin::Tribool::kUnknown,
+              restore_data.is_first_session_after_device_restore);
+    // Device restore is unknown, so there is no timestamp.
+    EXPECT_FALSE(restore_data.last_restore_timestamp.has_value());
+    run_loop.Run();
+    ExpectSentinelThatIsBackedUp();
+    ExpectSentinelThatIsNotBackedUp();
+  }
   // Simulate the next run.
-  restore_data = LoadDeviceRestoreDataInternal();
-  // After both sentinel files are created, there is still no device restore
-  // detected.
-  EXPECT_EQ(signin::Tribool::kFalse,
-            restore_data.is_first_session_after_device_restore);
-  EXPECT_FALSE(restore_data.last_restore_timestamp.has_value());
+  {
+    base::RunLoop run_loop;
+    signin::RestoreData restore_data =
+        LoadDeviceRestoreDataInternal(run_loop.QuitClosure());
+    run_loop.Run();
+    // After both sentinel files are created, there is still no device restore
+    // detected.
+    EXPECT_EQ(signin::Tribool::kFalse,
+              restore_data.is_first_session_after_device_restore);
+    EXPECT_FALSE(restore_data.last_restore_timestamp.has_value());
+  }
 }
 
 // Tests the result of IsFirstSessionAfterDeviceRestoreInternal(), when only the
@@ -115,24 +111,34 @@
 TEST_F(SigninUtilInternalTest,
        IsFirstSessionAfterDeviceRestoreInternalAfterRestore) {
   NSURL* url = GetSentinelThatIsBackedUpURLPath();
-  [[NSFileManager defaultManager] createFileAtPath:[url path]
+  [[NSFileManager defaultManager] createFileAtPath:url.path
                                           contents:nil
                                         attributes:nil];
-  signin::RestoreData restore_data = LoadDeviceRestoreDataInternal();
-  EXPECT_EQ(signin::Tribool::kTrue,
-            restore_data.is_first_session_after_device_restore);
-  // First run after a device restore, so there is no timestamp.
-  EXPECT_FALSE(restore_data.last_restore_timestamp.has_value());
-  WaitAndExpectSentinelThatIsBackedUp();
-  WaitAndExpectSentinelThatIsNotBackedUp();
+  {
+    base::RunLoop run_loop;
+    signin::RestoreData restore_data =
+        LoadDeviceRestoreDataInternal(run_loop.QuitClosure());
+    EXPECT_EQ(signin::Tribool::kTrue,
+              restore_data.is_first_session_after_device_restore);
+    // First run after a device restore, so there is no timestamp.
+    EXPECT_FALSE(restore_data.last_restore_timestamp.has_value());
+    run_loop.Run();
+    ExpectSentinelThatIsBackedUp();
+    ExpectSentinelThatIsNotBackedUp();
+  }
   // Simulate the next run.
-  restore_data = LoadDeviceRestoreDataInternal();
-  // This is not the first session after the device restore.
-  EXPECT_EQ(signin::Tribool::kFalse,
-            restore_data.is_first_session_after_device_restore);
-  // There is restore timestamp since there was a device restore in a previous
-  // run.
-  EXPECT_TRUE(restore_data.last_restore_timestamp.has_value());
+  {
+    base::RunLoop run_loop;
+    signin::RestoreData restore_data =
+        LoadDeviceRestoreDataInternal(run_loop.QuitClosure());
+    run_loop.Run();
+    // This is not the first session after the device restore.
+    EXPECT_EQ(signin::Tribool::kFalse,
+              restore_data.is_first_session_after_device_restore);
+    // There is restore timestamp since there was a device restore in a previous
+    // run.
+    EXPECT_TRUE(restore_data.last_restore_timestamp.has_value());
+  }
 }
 
 // Tests the result of IsFirstSessionAfterDeviceRestoreInternal(), when only the
@@ -140,22 +146,32 @@
 TEST_F(SigninUtilInternalTest,
        IsFirstSessionAfterDeviceRestoreInternalAfterUnexpectedSentinel) {
   NSURL* url = GetSentinelThatIsNotBackedUpURLPath();
-  [[NSFileManager defaultManager] createFileAtPath:[url path]
+  [[NSFileManager defaultManager] createFileAtPath:url.path
                                           contents:nil
                                         attributes:nil];
-  signin::RestoreData restore_data = LoadDeviceRestoreDataInternal();
-  EXPECT_EQ(signin::Tribool::kUnknown,
-            restore_data.is_first_session_after_device_restore);
-  // Device restore is unknown, so there is no timestamp.
-  EXPECT_FALSE(restore_data.last_restore_timestamp.has_value());
-  WaitAndExpectSentinelThatIsBackedUp();
+  {
+    base::RunLoop run_loop;
+    signin::RestoreData restore_data =
+        LoadDeviceRestoreDataInternal(run_loop.QuitClosure());
+    EXPECT_EQ(signin::Tribool::kUnknown,
+              restore_data.is_first_session_after_device_restore);
+    // Device restore is unknown, so there is no timestamp.
+    EXPECT_FALSE(restore_data.last_restore_timestamp.has_value());
+    run_loop.Run();
+    ExpectSentinelThatIsBackedUp();
+  }
   // Simulate the next run.
-  restore_data = LoadDeviceRestoreDataInternal();
-  // This is not the first session after the device restore.
-  EXPECT_EQ(signin::Tribool::kFalse,
-            restore_data.is_first_session_after_device_restore);
-  // No device restore happened in previous run.
-  EXPECT_FALSE(restore_data.last_restore_timestamp.has_value());
+  {
+    base::RunLoop run_loop;
+    signin::RestoreData restore_data =
+        LoadDeviceRestoreDataInternal(run_loop.QuitClosure());
+    run_loop.Run();
+    // This is not the first session after the device restore.
+    EXPECT_EQ(signin::Tribool::kFalse,
+              restore_data.is_first_session_after_device_restore);
+    // No device restore happened in previous run.
+    EXPECT_FALSE(restore_data.last_restore_timestamp.has_value());
+  }
 }
 
 // Tests the result of IsFirstSessionAfterDeviceRestoreInternal(), when all
@@ -180,22 +196,32 @@
   [[NSFileManager defaultManager] createFileAtPath:not_backed_up_url.path
                                           contents:nil
                                         attributes:not_backed_up_attributes];
-  signin::RestoreData restore_data = LoadDeviceRestoreDataInternal();
-  EXPECT_EQ(signin::Tribool::kFalse,
-            restore_data.is_first_session_after_device_restore);
-  EXPECT_TRUE(restore_data.last_restore_timestamp.has_value());
-  // The device restore happened on the create timestamp of the not backed up
-  // create date.
-  EXPECT_NSEQ(not_backed_up_creation_date,
-              restore_data.last_restore_timestamp->ToNSDate());
+  {
+    base::RunLoop run_loop;
+    signin::RestoreData restore_data =
+        LoadDeviceRestoreDataInternal(run_loop.QuitClosure());
+    EXPECT_EQ(signin::Tribool::kFalse,
+              restore_data.is_first_session_after_device_restore);
+    EXPECT_TRUE(restore_data.last_restore_timestamp.has_value());
+    run_loop.Run();
+    // The device restore happened on the create timestamp of the not backed up
+    // create date.
+    EXPECT_NSEQ(not_backed_up_creation_date,
+                restore_data.last_restore_timestamp->ToNSDate());
+  }
   // Simulate the next run.
-  restore_data = LoadDeviceRestoreDataInternal();
-  // Expect the values to be the same.
-  EXPECT_EQ(signin::Tribool::kFalse,
-            restore_data.is_first_session_after_device_restore);
-  EXPECT_TRUE(restore_data.last_restore_timestamp.has_value());
-  EXPECT_NSEQ(not_backed_up_creation_date,
-              restore_data.last_restore_timestamp->ToNSDate());
+  {
+    base::RunLoop run_loop;
+    signin::RestoreData restore_data =
+        LoadDeviceRestoreDataInternal(run_loop.QuitClosure());
+    run_loop.Run();
+    // Expect the values to be the same.
+    EXPECT_EQ(signin::Tribool::kFalse,
+              restore_data.is_first_session_after_device_restore);
+    EXPECT_TRUE(restore_data.last_restore_timestamp.has_value());
+    EXPECT_NSEQ(not_backed_up_creation_date,
+                restore_data.last_restore_timestamp->ToNSDate());
+  }
 }
 
 // Tests the result of IsFirstSessionAfterDeviceRestoreInternal(), when all
@@ -219,14 +245,24 @@
   [[NSFileManager defaultManager] createFileAtPath:backed_up_url.path
                                           contents:nil
                                         attributes:backed_up_attributes];
-  signin::RestoreData restore_data = LoadDeviceRestoreDataInternal();
-  EXPECT_EQ(signin::Tribool::kFalse,
-            restore_data.is_first_session_after_device_restore);
-  EXPECT_FALSE(restore_data.last_restore_timestamp.has_value());
+  {
+    base::RunLoop run_loop;
+    signin::RestoreData restore_data =
+        LoadDeviceRestoreDataInternal(run_loop.QuitClosure());
+    EXPECT_EQ(signin::Tribool::kFalse,
+              restore_data.is_first_session_after_device_restore);
+    EXPECT_FALSE(restore_data.last_restore_timestamp.has_value());
+    run_loop.Run();
+  }
   // Simulate the next run.
-  restore_data = LoadDeviceRestoreDataInternal();
-  // Expect the values to be the same.
-  EXPECT_EQ(signin::Tribool::kFalse,
-            restore_data.is_first_session_after_device_restore);
-  EXPECT_FALSE(restore_data.last_restore_timestamp.has_value());
+  {
+    base::RunLoop run_loop;
+    signin::RestoreData restore_data =
+        LoadDeviceRestoreDataInternal(run_loop.QuitClosure());
+    run_loop.Run();
+    // Expect the values to be the same.
+    EXPECT_EQ(signin::Tribool::kFalse,
+              restore_data.is_first_session_after_device_restore);
+    EXPECT_FALSE(restore_data.last_restore_timestamp.has_value());
+  }
 }
diff --git a/ios/chrome/browser/ssl/model/ios_captive_portal_blocking_page.mm b/ios/chrome/browser/ssl/model/ios_captive_portal_blocking_page.mm
index 1863fe66..88080fc 100644
--- a/ios/chrome/browser/ssl/model/ios_captive_portal_blocking_page.mm
+++ b/ios/chrome/browser/ssl/model/ios_captive_portal_blocking_page.mm
@@ -77,10 +77,8 @@
   load_time_data.Set("closeDetails", "");
   load_time_data.Set("explanationParagraph", "");
   load_time_data.Set("finalParagraph", "");
-  load_time_data.Set("recurrentErrorParagraph", "");
   load_time_data.Set("optInLink", "");
   load_time_data.Set("enhancedProtectionMessage", "");
-  load_time_data.Set("show_recurrent_error_paragraph", false);
 }
 
 void IOSCaptivePortalBlockingPage::HandleCommand(
diff --git a/ios/chrome/browser/tabs/model/BUILD.gn b/ios/chrome/browser/tabs/model/BUILD.gn
index 5985736d..741a3e73 100644
--- a/ios/chrome/browser/tabs/model/BUILD.gn
+++ b/ios/chrome/browser/tabs/model/BUILD.gn
@@ -177,6 +177,7 @@
     "//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/profile:features",
     "//ios/chrome/browser/shared/model/web_state_list",
     "//ios/chrome/browser/signin/model",
     "//ios/chrome/browser/sync/model/glue",
diff --git a/ios/chrome/browser/tabs/model/ios_chrome_synced_tab_delegate.mm b/ios/chrome/browser/tabs/model/ios_chrome_synced_tab_delegate.mm
index 765f80eb..fc43f5c 100644
--- a/ios/chrome/browser/tabs/model/ios_chrome_synced_tab_delegate.mm
+++ b/ios/chrome/browser/tabs/model/ios_chrome_synced_tab_delegate.mm
@@ -16,6 +16,7 @@
 #import "ios/chrome/browser/sessions/model/ios_chrome_session_tab_helper.h"
 #import "ios/chrome/browser/shared/model/application_context/application_context.h"
 #import "ios/chrome/browser/shared/model/prefs/pref_names.h"
+#import "ios/chrome/browser/shared/model/profile/features.h"
 #import "ios/chrome/browser/shared/model/profile/profile_attributes_storage_ios.h"
 #import "ios/chrome/browser/shared/model/profile/profile_ios.h"
 #import "ios/chrome/browser/shared/model/profile/profile_manager_ios.h"
diff --git a/ios/chrome/browser/web/model/font_size/resources/font_size.ts b/ios/chrome/browser/web/model/font_size/resources/font_size.ts
index 9ad618e7..03aff69 100644
--- a/ios/chrome/browser/web/model/font_size/resources/font_size.ts
+++ b/ios/chrome/browser/web/model/font_size/resources/font_size.ts
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 
 /**
  * @fileoverview Add functionality related to font size adjustment.
@@ -34,4 +34,4 @@
   } catch (error) {}
 }
 
-gCrWeb.font_size = {adjustFontSize};
+gCrWebLegacy.font_size = {adjustFontSize};
diff --git a/ios/chrome/browser/web/model/image_fetch/resources/image_fetch.ts b/ios/chrome/browser/web/model/image_fetch/resources/image_fetch.ts
index 9dbc0fe4..a848840e 100644
--- a/ios/chrome/browser/web/model/image_fetch/resources/image_fetch.ts
+++ b/ios/chrome/browser/web/model/image_fetch/resources/image_fetch.ts
@@ -6,7 +6,7 @@
  * @fileoverview Add functionality related to getting image data.
  */
 
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 import {sendWebKitMessage} from '//ios/web/public/js_messaging/resources/utils.js';
 
 /**
@@ -116,4 +116,4 @@
   xhr.send();
 }
 
-gCrWeb.imageFetch = {getImageData};
+gCrWebLegacy.imageFetch = {getImageData};
diff --git a/ios/chrome/browser/web/model/java_script_console/resources/console.ts b/ios/chrome/browser/web/model/java_script_console/resources/console.ts
index c741f04..c1f8a280 100644
--- a/ios/chrome/browser/web/model/java_script_console/resources/console.ts
+++ b/ios/chrome/browser/web/model/java_script_console/resources/console.ts
@@ -7,7 +7,7 @@
 
 /* eslint-disable no-console */
 
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 import {sendWebKitMessage} from '//ios/web/public/js_messaging/resources/utils.js';
 
 type LogLevel = 'log'|'debug'|'info'|'warn'|'error';
@@ -20,7 +20,7 @@
   } catch (err) {
   }
   sendWebKitMessage('ConsoleMessageHandler', {
-    'sender_frame': gCrWeb.message.getFrameId(),
+    'sender_frame': gCrWebLegacy.message.getFrameId(),
     'log_level': logLevel,
     'message': message,
     'url': document.location.href,
diff --git a/ios/chrome/browser/web_selection/model/resources/web_selection.ts b/ios/chrome/browser/web_selection/model/resources/web_selection.ts
index 6537227..69080e4 100644
--- a/ios/chrome/browser/web_selection/model/resources/web_selection.ts
+++ b/ios/chrome/browser/web_selection/model/resources/web_selection.ts
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 import {sendWebKitMessage} from '//ios/web/public/js_messaging/resources/utils.js';
 
 /**
@@ -58,7 +58,7 @@
   });
 }
 
-gCrWeb.webSelection =  { getSelectedText };
+gCrWebLegacy.webSelection = {getSelectedText};
 
 window.addEventListener('message', function(message) {
   const payload = message.data;
diff --git a/ios/web/annotations/resources/annotations.ts b/ios/web/annotations/resources/annotations.ts
index 73181db5..5f3158e 100644
--- a/ios/web/annotations/resources/annotations.ts
+++ b/ios/web/annotations/resources/annotations.ts
@@ -8,7 +8,7 @@
  */
 
 import {MS_DELAY_BEFORE_TRIGGER, NO_DECORATION_NODE_NAMES, NON_TEXT_NODE_NAMES} from '//ios/web/annotations/resources/annotations_constants.js';
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 import {sendWebKitMessage} from '//ios/web/public/js_messaging/resources/utils.js';
 
 // Mark: Private properties
@@ -734,7 +734,7 @@
   };
 }
 
-gCrWeb.annotations = {
+gCrWebLegacy.annotations = {
   extractText,
   decorateAnnotations,
   removeDecorations,
diff --git a/ios/web/annotations/resources/annotations_test.ts b/ios/web/annotations/resources/annotations_test.ts
index b988011..6510dcf 100644
--- a/ios/web/annotations/resources/annotations_test.ts
+++ b/ios/web/annotations/resources/annotations_test.ts
@@ -6,9 +6,8 @@
  * @fileoverview Test helpers for the annotations manager.
  */
 
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
-import {NON_TEXT_NODE_NAMES}
-    from '//ios/web/annotations/resources/annotations_constants.js';
+import {NON_TEXT_NODE_NAMES} from '//ios/web/annotations/resources/annotations_constants.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 
 // Simpleton tags with no closing tags (only those used in tests).
 const NO_END_TAGS_NODE_NAMES = new Set([
@@ -91,7 +90,7 @@
   return ''.concat(...parts);
 }
 
-gCrWeb.annotationsTest = {
+gCrWebLegacy.annotationsTest = {
   getPageTaggedText,
   countAnnotations,
   clickAnnotation,
diff --git a/ios/web/annotations/resources/text_main.ts b/ios/web/annotations/resources/text_main.ts
index 0107c64..db2ed479 100644
--- a/ios/web/annotations/resources/text_main.ts
+++ b/ios/web/annotations/resources/text_main.ts
@@ -20,7 +20,7 @@
 import {TextIntersectionObserver} from '//ios/web/annotations/resources/text_intersection_observer.js';
 import {TextStyler} from '//ios/web/annotations/resources/text_styler.js';
 import {IdleTaskTracker} from '//ios/web/annotations/resources/text_tasks.js';
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 import {sendWebKitMessage} from '//ios/web/public/js_messaging/resources/utils.js';
 
 // Used to trigger text extraction and decoration when system is idle.
@@ -175,7 +175,7 @@
   decorator?.removeHighlight();
 }
 
-gCrWeb.annotations = {
+gCrWebLegacy.annotations = {
   start,
   stop,
   decorateAnnotations,
diff --git a/ios/web/annotations/resources/text_tests.ts b/ios/web/annotations/resources/text_tests.ts
index b4f89d32..8d181101 100644
--- a/ios/web/annotations/resources/text_tests.ts
+++ b/ios/web/annotations/resources/text_tests.ts
@@ -15,7 +15,7 @@
 import {TestTextExtractor} from '//ios/web/annotations/resources/text_extractor_test.js';
 import {TestTextIntersectionObserver} from '//ios/web/annotations/resources/text_intersection_observer_test.js';
 import {TestTextTasks} from '//ios/web/annotations/resources/text_tasks_test.js';
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 
 function testAll() {
   return [
@@ -31,6 +31,6 @@
   ];
 }
 
-gCrWeb.textTests = {
+gCrWebLegacy.textTests = {
   testAll,
 };
diff --git a/ios/web/find_in_page/resources/find_in_page_event_listeners.ts b/ios/web/find_in_page/resources/find_in_page_event_listeners.ts
index 7b87584..b8f5ef5 100644
--- a/ios/web/find_in_page/resources/find_in_page_event_listeners.ts
+++ b/ios/web/find_in_page/resources/find_in_page_event_listeners.ts
@@ -2,6 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 
-window.addEventListener('pagehide', gCrWeb.findInPage.stop);
+window.addEventListener('pagehide', gCrWebLegacy.findInPage.stop);
diff --git a/ios/web/find_in_page/resources/find_in_page_native_api.ts b/ios/web/find_in_page/resources/find_in_page_native_api.ts
index 4fd3f550..0128136f 100644
--- a/ios/web/find_in_page/resources/find_in_page_native_api.ts
+++ b/ios/web/find_in_page/resources/find_in_page_native_api.ts
@@ -15,7 +15,7 @@
     '//ios/web/find_in_page/resources/find_in_page.js';
 import {createRegex, escapeHTML} from
     '//ios/web/find_in_page/resources/find_in_page_utils.js';
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 // clang-format on
 
 /**
@@ -185,7 +185,7 @@
     previousEnd = partialMatch.end;
 
     // Record the <chrome_find> Node in corresponding Match.
-    gCrWeb.findInPage.matches[partialMatch.matchId].nodes.push(newNode);
+    gCrWebLegacy.findInPage.matches[partialMatch.matchId].nodes.push(newNode);
   }
   // Create the TEXT node for trailing non-matching string piece.
   if (previousEnd !== section.end) {
@@ -208,7 +208,7 @@
   if (selectedMatchIndex_ < 0) {
     return undefined;
   }
-  return gCrWeb.findInPage.matches[selectedMatchIndex_];
+  return gCrWebLegacy.findInPage.matches[selectedMatchIndex_];
 }
 
 /**
@@ -218,7 +218,7 @@
  * @return {Number} of visible matches.
  */
 function countVisibleMatches(timer: Timer|null): number {
-  const max = gCrWeb.findInPage.matches.length;
+  const max = gCrWebLegacy.findInPage.matches.length;
   const maxVisible = MAX_VISIBLE_ELEMENTS;
   let currentlyVisibleMatchCount = 0;
   for (let index = visibleMatchesCountIndexIterator_; index < max; index++) {
@@ -232,7 +232,7 @@
       continue;
     }
 
-    const match = gCrWeb.findInPage.matches[index];
+    const match = gCrWebLegacy.findInPage.matches[index];
     if (match && match.visible()) {
       currentlyVisibleMatchCount++;
     }
@@ -255,7 +255,7 @@
   sections_ = [];
   sectionsIndex_ = 0;
 
-  gCrWeb.findInPage.matches = [];
+  gCrWebLegacy.findInPage.matches = [];
   selectedMatchIndex_ = -1;
   selectedVisibleMatchIndex_ = -1;
   matchId_ = 0;
@@ -342,9 +342,9 @@
  */
 function findString(string: string, timeout: number): number {
   // Enable findInPage module if hasn't been done yet.
-  if (!gCrWeb.findInPage.hasInitialized) {
+  if (!gCrWebLegacy.findInPage.hasInitialized) {
     enable();
-    gCrWeb.findInPage.hasInitialized = true;
+    gCrWebLegacy.findInPage.hasInitialized = true;
   }
 
   if (!searchStateIsClean_) {
@@ -357,7 +357,7 @@
   }
 
   // Holds what nodes we have not processed yet.
-  gCrWeb.findInPage.stack = [document.body];
+  gCrWebLegacy.findInPage.stack = [document.body];
 
   // Number of visible matches found.
   visibleMatchCount_ = 0;
@@ -365,7 +365,7 @@
   // Index tracking variables so search can be broken up into multiple calls.
   visibleMatchesCountIndexIterator_ = 0;
 
-  gCrWeb.findInPage.regex = createRegex(string);
+  gCrWebLegacy.findInPage.regex = createRegex(string);
 
   searchInProgress_ = true;
 
@@ -401,8 +401,8 @@
   const timer = new Timer(timeout);
 
   // Go through every node in DFS fashion.
-  while (gCrWeb.findInPage.stack.length) {
-    const node = gCrWeb.findInPage.stack.pop();
+  while (gCrWebLegacy.findInPage.stack.length) {
+    const node = gCrWebLegacy.findInPage.stack.pop();
     const children = node.childNodes;
     if (children && children.length) {
       // add all (reasonable) children
@@ -410,7 +410,7 @@
         const child = children[i];
         if ((child.nodeType === 1 || child.nodeType === 3) &&
             !IGNORE_NODE_NAMES.has(child.nodeName)) {
-          gCrWeb.findInPage.stack.push(children[i]);
+          gCrWebLegacy.findInPage.stack.push(children[i]);
         }
       }
     }
@@ -430,13 +430,13 @@
   // Do regex match in |allText_|, create |matches| and |replacements|. The
   // regex is set on __gCrWeb, so its state is kept between continuous calls on
   // pumpSearch.
-  const regex = gCrWeb.findInPage.regex;
+  const regex = gCrWebLegacy.findInPage.regex;
   if (regex) {
     for (let res; res = regex.exec(allText_);) {
       // The range of current Match in |allText_| is [begin, end).
       const begin = res.index;
       const end = begin + res[0].length;
-      gCrWeb.findInPage.matches.push(new Match());
+      gCrWebLegacy.findInPage.matches.push(new Match());
 
       // Find the Section where current Match starts.
       const oldSectionIndex = sectionsIndex_;
@@ -475,7 +475,7 @@
     }
     // Process remaining PartialMatches.
     processPartialMatchesInCurrentSection();
-    gCrWeb.findInPage.regex = undefined;
+    gCrWebLegacy.findInPage.regex = undefined;
   }
 
   // Execute replacements to highlight search results.
@@ -542,8 +542,8 @@
   let total_match_index = 0;
   let visible_match_count = index;
   // Select the |index|-th visible match.
-  while (total_match_index < gCrWeb.findInPage.matches.length) {
-    if (gCrWeb.findInPage.matches[total_match_index].visible()) {
+  while (total_match_index < gCrWebLegacy.findInPage.matches.length) {
+    if (gCrWebLegacy.findInPage.matches[total_match_index].visible()) {
       visible_match_count--;
       if (visible_match_count < 0) {
         break;
@@ -606,7 +606,7 @@
     removeStyle();
     cleanUp();
   }
-  gCrWeb.findInPage.hasInitialized = false;
+  gCrWebLegacy.findInPage.hasInitialized = false;
 }
 
 // Mark: Public API
@@ -617,7 +617,7 @@
  */
 const matches: Match[] = [];
 
-gCrWeb.findInPage = {
+gCrWebLegacy.findInPage = {
   findString,
   matches,
   pumpSearch,
diff --git a/ios/web/js_features/context_menu/resources/all_frames_context_menu.ts b/ios/web/js_features/context_menu/resources/all_frames_context_menu.ts
index b0f672a..0eac12b 100644
--- a/ios/web/js_features/context_menu/resources/all_frames_context_menu.ts
+++ b/ios/web/js_features/context_menu/resources/all_frames_context_menu.ts
@@ -7,7 +7,7 @@
  */
 
 import {getSurroundingText} from '//ios/web/js_features/context_menu/resources/surrounding_text.js';
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 import {sendWebKitMessage} from '//ios/web/public/js_messaging/resources/utils.js';
 
 // The minimum opacity for an element to be considered as opaque. Elements
@@ -644,9 +644,9 @@
   }
 });
 
-// Call contextMenuAllFrames on gCrWeb directly to prevent code duplication
-// that using export/import would create.
-gCrWeb.contextMenuAllFrames = {
+// Call contextMenuAllFrames on gCrWebLegacy directly to prevent code
+// duplication that using export/import would create.
+gCrWebLegacy.contextMenuAllFrames = {
   findElementAtPointInPageCoordinates,
   // For testing only:
   getSurroundingText,
diff --git a/ios/web/js_features/context_menu/resources/main_frame_context_menu.ts b/ios/web/js_features/context_menu/resources/main_frame_context_menu.ts
index d8b25c4..0f76396 100644
--- a/ios/web/js_features/context_menu/resources/main_frame_context_menu.ts
+++ b/ios/web/js_features/context_menu/resources/main_frame_context_menu.ts
@@ -6,7 +6,7 @@
  * @fileoverview APIs used by CRWContextMenuController.
  */
 
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 
 /**
  * Finds the url of the image or link under the selected point. Sends the
@@ -22,8 +22,8 @@
  *                 coordinates.
  */
 function findElementAtPoint(requestId: string, x: number, y: number) {
-  gCrWeb.contextMenuAllFrames.findElementAtPointInPageCoordinates(
+  gCrWebLegacy.contextMenuAllFrames.findElementAtPointInPageCoordinates(
       requestId, x, y);
 }
 
-gCrWeb.contextMenu = {findElementAtPoint};
+gCrWebLegacy.contextMenu = {findElementAtPoint};
diff --git a/ios/web/js_features/scroll_helper/resources/scroll_helper.ts b/ios/web/js_features/scroll_helper/resources/scroll_helper.ts
index ac777a4c..22f6bd6 100644
--- a/ios/web/js_features/scroll_helper/resources/scroll_helper.ts
+++ b/ios/web/js_features/scroll_helper/resources/scroll_helper.ts
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 
 /**
  * @fileoverview APIs used for the scroll workaround. See crbug.com/554257.
@@ -14,7 +14,7 @@
  * Tracks whether user is in the middle of scrolling/dragging. If user is
  * scrolling, ignore window.scrollTo() until user stops scrolling.
  */
-gCrWeb.setWebViewScrollViewIsDragging = function(state: boolean) {
+gCrWebLegacy.setWebViewScrollViewIsDragging = function(state: boolean) {
   webViewScrollViewIsDragging = state;
 };
 
diff --git a/ios/web/js_features/window_error/resources/wrap_gcrweb_functions.ts b/ios/web/js_features/window_error/resources/wrap_gcrweb_functions.ts
index 5317182..1852595 100644
--- a/ios/web/js_features/window_error/resources/wrap_gcrweb_functions.ts
+++ b/ios/web/js_features/window_error/resources/wrap_gcrweb_functions.ts
@@ -3,15 +3,15 @@
 // found in the LICENSE file.
 
 import {catchAndReportErrors} from '//ios/web/public/js_messaging/resources/error_reporting.js';
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 
-for (const namespace in gCrWeb) {
-  const namespaceObject = gCrWeb[namespace];
+for (const namespace in gCrWebLegacy) {
+  const namespaceObject = gCrWebLegacy[namespace];
   for (const itemName in namespaceObject) {
     const exposedItem = namespaceObject[itemName];
     if (typeof exposedItem === 'function') {
       const funcName = '__gCrWeb.' + namespace + '.' + itemName;
-      gCrWeb[namespace][itemName] = function(...args: unknown[]) {
+      gCrWebLegacy[namespace][itemName] = function(...args: unknown[]) {
         return catchAndReportErrors.apply(null, [funcName, exposedItem, args]);
       };
     }
diff --git a/ios/web/js_messaging/resources/frame_listeners.ts b/ios/web/js_messaging/resources/frame_listeners.ts
index 34e1ad1..44d1f59 100644
--- a/ios/web/js_messaging/resources/frame_listeners.ts
+++ b/ios/web/js_messaging/resources/frame_listeners.ts
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import {getFrameId} from '//ios/web/public/js_messaging/resources/frame_id.js';
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 import {sendWebKitMessage} from '//ios/web/public/js_messaging/resources/utils.js';
 
 window.addEventListener('unload', function() {
@@ -21,6 +21,6 @@
   }
   if (payload.hasOwnProperty('type') &&
       payload.type === 'org.chromium.registerForFrameMessaging') {
-    gCrWeb.message.getExistingFrames();
+    gCrWebLegacy.message.getExistingFrames();
   }
 });
diff --git a/ios/web/js_messaging/resources/message.ts b/ios/web/js_messaging/resources/message.ts
index d3280df..989d1d4 100644
--- a/ios/web/js_messaging/resources/message.ts
+++ b/ios/web/js_messaging/resources/message.ts
@@ -8,7 +8,7 @@
  */
 
 import {getFrameId, registerFrame} from '//ios/web/public/js_messaging/resources/frame_id.js';
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 
 /**
  * Registers this frame with the native code and forwards the message to any
@@ -35,7 +35,7 @@
   }
 }
 
-gCrWeb.message = {
+gCrWebLegacy.message = {
   getFrameId,
   getExistingFrames,
 };
diff --git a/ios/web/navigation/resources/navigation.ts b/ios/web/navigation/resources/navigation.ts
index 43014a4..d51c332 100644
--- a/ios/web/navigation/resources/navigation.ts
+++ b/ios/web/navigation/resources/navigation.ts
@@ -6,7 +6,7 @@
  * @fileoverview Navigation related APIs.
  */
 
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 import {sendWebKitMessage} from '//ios/web/public/js_messaging/resources/utils.js';
 
 declare interface Message {
@@ -82,7 +82,7 @@
     stateObject: object, pageTitle: string, pageUrl: string|URL): void {
   messageQueue.queueNavigationEventMessage({
     'command': 'willChangeState',
-    'frame_id': gCrWeb.message.getFrameId(),
+    'frame_id': gCrWebLegacy.message.getFrameId(),
   });
 
   // JSONStringify throws an exception when given a cyclical object. This
@@ -104,7 +104,7 @@
     'stateObject': serializedState,
     'baseUrl': document.baseURI,
     'pageUrl': pageUrl.toString(),
-    'frame_id': gCrWeb.message.getFrameId(),
+    'frame_id': gCrWebLegacy.message.getFrameId(),
   });
 };
 
@@ -112,7 +112,7 @@
     stateObject: object, pageTitle: string, pageUrl: string|URL): void {
   messageQueue.queueNavigationEventMessage({
     'command': 'willChangeState',
-    'frame_id': gCrWeb.message.getFrameId(),
+    'frame_id': gCrWebLegacy.message.getFrameId(),
   });
 
   // JSONStringify throws an exception when given a cyclical object. This
@@ -136,6 +136,6 @@
     'stateObject': serializedState,
     'baseUrl': document.baseURI,
     'pageUrl': pageUrl.toString(),
-    'frame_id': gCrWeb.message.getFrameId(),
+    'frame_id': gCrWebLegacy.message.getFrameId(),
   });
 };
diff --git a/ios/web/navigation/resources/navigation_listeners.ts b/ios/web/navigation/resources/navigation_listeners.ts
index 2fbe5633..4eace95 100644
--- a/ios/web/navigation/resources/navigation_listeners.ts
+++ b/ios/web/navigation/resources/navigation_listeners.ts
@@ -6,11 +6,11 @@
  * @fileoverview Navigation listener to report hash change.
  */
 
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 import {sendWebKitMessage} from '//ios/web/public/js_messaging/resources/utils.js';
 
 window.addEventListener('hashchange', () => {
   sendWebKitMessage(
       'NavigationEventMessage',
-      {'command': 'hashchange', 'frame_id': gCrWeb.message.getFrameId()});
+      {'command': 'hashchange', 'frame_id': gCrWebLegacy.message.getFrameId()});
 });
diff --git a/ios/web/public/js_messaging/README.md b/ios/web/public/js_messaging/README.md
index 7582c0f..411781d6 100644
--- a/ios/web/public/js_messaging/README.md
+++ b/ios/web/public/js_messaging/README.md
@@ -194,7 +194,7 @@
 can be split across multiple files. Reference other files using the full path,
 similar to other imports in native code. For example:
 
-    import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+    import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 
 Note that the import uses the ".js" extension, even if the file is written as
 TypeScript with a ".ts" file extension.
diff --git a/ios/web/public/js_messaging/resources/frame_id.ts b/ios/web/public/js_messaging/resources/frame_id.ts
index 41e94f96..68cae48 100644
--- a/ios/web/public/js_messaging/resources/frame_id.ts
+++ b/ios/web/public/js_messaging/resources/frame_id.ts
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 import {generateRandomId, sendWebKitMessage} from '//ios/web/public/js_messaging/resources/utils.js';
 
 /**
@@ -12,10 +12,10 @@
  * when navigating 'back' to this frame.
  */
 export function getFrameId(): string {
-  if (!gCrWeb.hasOwnProperty('frameId')) {
-    gCrWeb.frameId = generateRandomId();
+  if (!gCrWebLegacy.hasOwnProperty('frameId')) {
+    gCrWebLegacy.frameId = generateRandomId();
   }
-  return gCrWeb.frameId;
+  return gCrWebLegacy.frameId;
 }
 
 /**
diff --git a/ios/web/public/js_messaging/resources/gcrweb.ts b/ios/web/public/js_messaging/resources/gcrweb.ts
index a21d3de..83de4fb 100644
--- a/ios/web/public/js_messaging/resources/gcrweb.ts
+++ b/ios/web/public/js_messaging/resources/gcrweb.ts
@@ -22,4 +22,4 @@
   (window as WindowWithGcrWeb).__gCrWeb = {};
 }
 
-export const gCrWeb: any = (window as WindowWithGcrWeb).__gCrWeb;
+export const gCrWebLegacy: any = (window as WindowWithGcrWeb).__gCrWeb;
diff --git a/ios/web/public/js_messaging/resources/utils_test_api.ts b/ios/web/public/js_messaging/resources/utils_test_api.ts
index 0844454..9503e80 100644
--- a/ios/web/public/js_messaging/resources/utils_test_api.ts
+++ b/ios/web/public/js_messaging/resources/utils_test_api.ts
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 import {isTextField, removeQueryAndReferenceFromURL, sendWebKitMessage, trim} from '//ios/web/public/js_messaging/resources/utils.js';
 
-gCrWeb.utils_tests = {
+gCrWebLegacy.utils_tests = {
   removeQueryAndReferenceFromURL,
   sendWebKitMessage,
   trim,
diff --git a/ios/web/test/resources/java_script_feature_test_inject_once.ts b/ios/web/test/resources/java_script_feature_test_inject_once.ts
index 9b8758fb..60e3d28 100644
--- a/ios/web/test/resources/java_script_feature_test_inject_once.ts
+++ b/ios/web/test/resources/java_script_feature_test_inject_once.ts
@@ -7,13 +7,13 @@
  * will be executed once for a given `window` JS object.
  */
 
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 import {sendWebKitMessage} from '//ios/web/public/js_messaging/resources/utils.js';
 
 const errorReceivedCount: number = 0;
 
 function getErrorCount() {
-  return gCrWeb.javaScriptFeatureTest.errorReceivedCount;
+  return gCrWebLegacy.javaScriptFeatureTest.errorReceivedCount;
 }
 
 function replaceDivContents() {
@@ -32,7 +32,7 @@
   body.appendChild(document.createTextNode('injected_script_loaded'));
 }
 
-gCrWeb.javaScriptFeatureTest = {
+gCrWebLegacy.javaScriptFeatureTest = {
   errorReceivedCount,
   getErrorCount,
   replaceDivContents,
diff --git a/ios/web/test/resources/java_script_feature_test_reinject.ts b/ios/web/test/resources/java_script_feature_test_reinject.ts
index cd120867..c61759b 100644
--- a/ios/web/test/resources/java_script_feature_test_reinject.ts
+++ b/ios/web/test/resources/java_script_feature_test_reinject.ts
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 
 /**
  * @fileoverview Setup used in JavaScriptFeature inttests. This file
@@ -10,5 +10,5 @@
  */
 
 window.addEventListener('error', () => {
-  gCrWeb.javaScriptFeatureTest.errorReceivedCount++;
+  gCrWebLegacy.javaScriptFeatureTest.errorReceivedCount++;
 });
diff --git a/ios/web_view/internal/js_messaging/resources/cwv_messaging.ts b/ios/web_view/internal/js_messaging/resources/cwv_messaging.ts
index ac453f4..89ca423 100644
--- a/ios/web_view/internal/js_messaging/resources/cwv_messaging.ts
+++ b/ios/web_view/internal/js_messaging/resources/cwv_messaging.ts
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js';
+import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js';
 import {sendWebKitMessage} from '//ios/web/public/js_messaging/resources/utils.js';
 
 function messageHost(messageName: string, payload: Object): void {
@@ -10,4 +10,4 @@
   sendWebKitMessage('CWVWebViewMessage', message);
 }
 
-gCrWeb.cwvMessaging = {messageHost};
+gCrWebLegacy.cwvMessaging = {messageHost};
diff --git a/ios_internal b/ios_internal
index c399a02..ecc08cc 160000
--- a/ios_internal
+++ b/ios_internal
@@ -1 +1 @@
-Subproject commit c399a02597c037cc2117413c9161f72b57307121
+Subproject commit ecc08cc10ed9e1886e0f3197eb883f648293430b
diff --git a/net/base/hash_value.cc b/net/base/hash_value.cc
index e63a7cb..609fdeb3 100644
--- a/net/base/hash_value.cc
+++ b/net/base/hash_value.cc
@@ -59,7 +59,7 @@
     return false;
   }
   tag_ = HASH_VALUE_SHA256;
-  UNSAFE_TODO(memcpy(data(), decoded->data(), size()));
+  span().copy_from(*decoded);
   return true;
 }
 
diff --git a/net/cert/cert_verify_proc.cc b/net/cert/cert_verify_proc.cc
index 1f1ba7f..966ad198 100644
--- a/net/cert/cert_verify_proc.cc
+++ b/net/cert/cert_verify_proc.cc
@@ -2,11 +2,6 @@
 // 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/390223051): Remove C-library calls to fix the errors.
-#pragma allow_unsafe_libc_calls
-#endif
-
 #include "net/cert/cert_verify_proc.h"
 
 #include <stdint.h>
@@ -512,8 +507,7 @@
     if (hash.tag() != HASH_VALUE_SHA256) {
       continue;
     }
-    if (!crl_set()->IsKnownInterceptionKey(std::string_view(
-            reinterpret_cast<const char*>(hash.data()), hash.size()))) {
+    if (!crl_set()->IsKnownInterceptionKey(hash.span())) {
       continue;
     }
 
diff --git a/net/cert/cert_verify_proc_android.cc b/net/cert/cert_verify_proc_android.cc
index d356d5d..261af23 100644
--- a/net/cert/cert_verify_proc_android.cc
+++ b/net/cert/cert_verify_proc_android.cc
@@ -11,9 +11,11 @@
 
 #include "base/check_op.h"
 #include "base/containers/adapters.h"
+#include "base/containers/span.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/notreached.h"
+#include "crypto/hash.h"
 #include "crypto/sha2.h"
 #include "net/android/cert_verify_result_android.h"
 #include "net/android/network_library.h"
@@ -317,8 +319,7 @@
       continue;
     }
 
-    HashValue sha256(HASH_VALUE_SHA256);
-    crypto::SHA256HashString(spki_bytes, sha256.data(), crypto::kSHA256Length);
+    HashValue sha256(crypto::hash::Sha256(base::as_byte_span(spki_bytes)));
     verify_result->public_key_hashes.push_back(sha256);
 
     if (!verify_result->is_issued_by_known_root) {
diff --git a/net/cert/cert_verify_proc_builtin.cc b/net/cert/cert_verify_proc_builtin.cc
index ecfda1a..d2f4d60 100644
--- a/net/cert/cert_verify_proc_builtin.cc
+++ b/net/cert/cert_verify_proc_builtin.cc
@@ -10,6 +10,7 @@
 #include <string_view>
 #include <vector>
 
+#include "base/containers/span.h"
 #include "base/feature_list.h"
 #include "base/logging.h"
 #include "base/memory/raw_ptr.h"
@@ -19,7 +20,6 @@
 #include "base/values.h"
 #include "components/network_time/time_tracker/time_tracker.h"
 #include "crypto/hash.h"
-#include "crypto/sha2.h"
 #include "net/base/features.h"
 #include "net/base/ip_address.h"
 #include "net/base/net_errors.h"
@@ -1033,10 +1033,7 @@
 //               in the delegate's PathInfo).
 void AppendPublicKeyHashes(const bssl::der::Input& spki_bytes,
                            HashValueVector* hashes) {
-  HashValue sha256(HASH_VALUE_SHA256);
-  crypto::SHA256HashString(spki_bytes.AsStringView(), sha256.data(),
-                           crypto::kSHA256Length);
-  hashes->push_back(sha256);
+  hashes->emplace_back(crypto::hash::Sha256(spki_bytes));
 }
 
 // Appends the SubjectPublicKeyInfo hashes for all certificates in
diff --git a/net/cert/cert_verify_proc_ios.cc b/net/cert/cert_verify_proc_ios.cc
index d7cc94c..a9fac08 100644
--- a/net/cert/cert_verify_proc_ios.cc
+++ b/net/cert/cert_verify_proc_ios.cc
@@ -261,7 +261,7 @@
     }
 
     HashValue sha256(HASH_VALUE_SHA256);
-    CC_SHA256(spki_bytes.data(), spki_bytes.size(), sha256.data());
+    CC_SHA256(spki_bytes.data(), spki_bytes.size(), sha256.span().data());
     verify_result->public_key_hashes.push_back(sha256);
   }
   if (!verified_cert.get()) {
diff --git a/net/cert/crl_set.cc b/net/cert/crl_set.cc
index 8f4ead2..a1174cf 100644
--- a/net/cert/crl_set.cc
+++ b/net/cert/crl_set.cc
@@ -13,6 +13,7 @@
 #include <string_view>
 
 #include "base/base64.h"
+#include "base/containers/span.h"
 #include "base/json/json_reader.h"
 #include "base/time/time.h"
 #include "base/values.h"
@@ -351,9 +352,10 @@
   return GOOD;
 }
 
-bool CRLSet::IsKnownInterceptionKey(std::string_view spki_hash) const {
+bool CRLSet::IsKnownInterceptionKey(base::span<const uint8_t> spki_hash) const {
   return std::binary_search(known_interception_spkis_.begin(),
-                            known_interception_spkis_.end(), spki_hash);
+                            known_interception_spkis_.end(),
+                            base::as_string_view(spki_hash));
 }
 
 bool CRLSet::IsExpired() const {
diff --git a/net/cert/crl_set.h b/net/cert/crl_set.h
index 40c4b3e..71734243 100644
--- a/net/cert/crl_set.h
+++ b/net/cert/crl_set.h
@@ -14,6 +14,7 @@
 #include <utility>
 #include <vector>
 
+#include "base/containers/span.h"
 #include "base/memory/ref_counted.h"
 #include "net/base/hash_value.h"
 #include "net/base/net_export.h"
@@ -57,7 +58,7 @@
   // Returns true if |spki_hash|, the SHA256 of the SubjectPublicKeyInfo,
   // is known to be used for interception by a party other than the device
   // or machine owner.
-  bool IsKnownInterceptionKey(std::string_view spki_hash) const;
+  bool IsKnownInterceptionKey(base::span<const uint8_t> spki_hash) const;
 
   // IsExpired returns true iff the current time is past the NotAfter time
   // specified in the CRLSet.
diff --git a/net/cert/known_roots.cc b/net/cert/known_roots.cc
index 1c0b56b0f..cbae1a6 100644
--- a/net/cert/known_roots.cc
+++ b/net/cert/known_roots.cc
@@ -2,11 +2,6 @@
 // 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/390223051): Remove C-library calls to fix the errors.
-#pragma allow_unsafe_libc_calls
-#endif
-
 #include "net/cert/known_roots.h"
 
 #include <string.h>
@@ -26,12 +21,12 @@
 struct HashValueToRootCertDataComp {
   bool operator()(const HashValue& hash, const RootCertData& root_cert) {
     DCHECK_EQ(HASH_VALUE_SHA256, hash.tag());
-    return memcmp(hash.data(), root_cert.sha256_spki_hash, 32) < 0;
+    return hash.span() < root_cert.sha256_spki_hash;
   }
 
   bool operator()(const RootCertData& root_cert, const HashValue& hash) {
     DCHECK_EQ(HASH_VALUE_SHA256, hash.tag());
-    return memcmp(root_cert.sha256_spki_hash, hash.data(), 32) < 0;
+    return root_cert.sha256_spki_hash < hash.span();
   }
 };
 
diff --git a/net/cert/x509_util.cc b/net/cert/x509_util.cc
index 5fc73e1..f386f6bd 100644
--- a/net/cert/x509_util.cc
+++ b/net/cert/x509_util.cc
@@ -10,6 +10,7 @@
 #include <memory>
 #include <string_view>
 
+#include "base/containers/span.h"
 #include "base/logging.h"
 #include "base/memory/raw_ptr.h"
 #include "base/notreached.h"
@@ -17,9 +18,9 @@
 #include "base/strings/string_util.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "crypto/hash.h"
 #include "crypto/openssl_util.h"
 #include "crypto/rsa_private_key.h"
-#include "crypto/sha2.h"
 #include "net/base/hash_value.h"
 #include "net/cert/asn1_util.h"
 #include "net/cert/time_conversions.h"
@@ -513,8 +514,7 @@
   if (!asn1::ExtractSPKIFromDERCert(CryptoBufferAsStringPiece(buffer), &spki)) {
     return false;
   }
-  *hash = HashValue(HASH_VALUE_SHA256);
-  crypto::SHA256HashString(spki, hash->data(), hash->size());
+  *hash = HashValue(crypto::hash::Sha256(base::as_byte_span(spki)));
   return true;
 }
 
diff --git a/net/http/transport_security_state_static.pins b/net/http/transport_security_state_static.pins
index c6c482d..9f309a2 100644
--- a/net/http/transport_security_state_static.pins
+++ b/net/http/transport_security_state_static.pins
@@ -43,9 +43,9 @@
 #   hash function for preloaded entries again (we have already done so once).
 #
 
-# Last updated: 2025-03-20 12:58 UTC
+# Last updated: 2025-04-03 12:57 UTC
 PinsListTimestamp
-1742475533
+1743685029
 
 TestSPKI
 sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/net/http/transport_security_state_static_pins.json b/net/http/transport_security_state_static_pins.json
index 57f8bd3..8be25331 100644
--- a/net/http/transport_security_state_static_pins.json
+++ b/net/http/transport_security_state_static_pins.json
@@ -31,7 +31,7 @@
 // the 'static_spki_hashes' and 'bad_static_spki_hashes' fields in 'pinsets'
 // refer to, and the timestamp at which the pins list was last updated.
 //
-// Last updated: 2025-03-20 12:58 UTC
+// Last updated: 2025-04-03 12:57 UTC
 //
 {
   "pinsets": [
diff --git a/net/test/scoped_disable_exit_on_dfatal.cc b/net/test/scoped_disable_exit_on_dfatal.cc
index e65b126..70130456 100644
--- a/net/test/scoped_disable_exit_on_dfatal.cc
+++ b/net/test/scoped_disable_exit_on_dfatal.cc
@@ -17,11 +17,10 @@
 ScopedDisableExitOnDFatal::~ScopedDisableExitOnDFatal() = default;
 
 // static
-void ScopedDisableExitOnDFatal::LogAssertHandler(
-    std::string_view file,
-    int line,
-    const std::string_view message,
-    const std::string_view stack_trace) {
+void ScopedDisableExitOnDFatal::LogAssertHandler(const char* file,
+                                                 int line,
+                                                 std::string_view message,
+                                                 std::string_view stack_trace) {
   // Simply swallow the assert.
 }
 
diff --git a/net/test/scoped_disable_exit_on_dfatal.h b/net/test/scoped_disable_exit_on_dfatal.h
index 0a3e300..adc65be11 100644
--- a/net/test/scoped_disable_exit_on_dfatal.h
+++ b/net/test/scoped_disable_exit_on_dfatal.h
@@ -30,7 +30,7 @@
  private:
   // Static function which is set as the logging assert handler.
   // Called when there is a check failure.
-  static void LogAssertHandler(std::string_view file,
+  static void LogAssertHandler(const char* file,
                                int line,
                                std::string_view message,
                                std::string_view stack_trace);
diff --git a/net/tools/stress_cache/stress_cache.cc b/net/tools/stress_cache/stress_cache.cc
index d6e158a..f4845d2 100644
--- a/net/tools/stress_cache/stress_cache.cc
+++ b/net/tools/stress_cache/stress_cache.cc
@@ -386,7 +386,7 @@
   return true;
 }
 
-void CrashHandler(std::string_view file,
+void CrashHandler(const char* file,
                   int line,
                   std::string_view str,
                   std::string_view stack_trace) {
diff --git a/remoting/host/native_messaging/log_message_handler.cc b/remoting/host/native_messaging/log_message_handler.cc
index 821207f4..1f60708 100644
--- a/remoting/host/native_messaging/log_message_handler.cc
+++ b/remoting/host/native_messaging/log_message_handler.cc
@@ -4,8 +4,6 @@
 
 #include "remoting/host/native_messaging/log_message_handler.h"
 
-#include <string_view>
-
 #include "base/functional/bind.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
@@ -57,7 +55,7 @@
 
 // static
 bool LogMessageHandler::OnLogMessage(logging::LogSeverity severity,
-                                     std::string_view file,
+                                     const char* file,
                                      int line,
                                      size_t message_start,
                                      const std::string& str) {
@@ -71,7 +69,7 @@
 
 void LogMessageHandler::PostLogMessageToCorrectThread(
     logging::LogSeverity severity,
-    std::string_view file,
+    const char* file,
     int line,
     size_t message_start,
     const std::string& str) {
@@ -103,7 +101,7 @@
 }
 
 void LogMessageHandler::SendLogMessageToClient(logging::LogSeverity severity,
-                                               std::string_view file,
+                                               const char* file,
                                                int line,
                                                size_t message_start,
                                                const std::string& str) {
diff --git a/remoting/host/native_messaging/log_message_handler.h b/remoting/host/native_messaging/log_message_handler.h
index 09174e9..43df5c40 100644
--- a/remoting/host/native_messaging/log_message_handler.h
+++ b/remoting/host/native_messaging/log_message_handler.h
@@ -45,17 +45,17 @@
   // TODO(yuweih): Reimplement this class using using a message queue which is
   // protected by |g_log_message_handler_lock|.
   static bool OnLogMessage(int severity,
-                           std::string_view file,
+                           const char* file,
                            int line,
                            size_t message_start,
                            const std::string& str);
   void PostLogMessageToCorrectThread(int severity,
-                                     std::string_view file,
+                                     const char* file,
                                      int line,
                                      size_t message_start,
                                      const std::string& str);
   void SendLogMessageToClient(int severity,
-                              std::string_view file,
+                              const char* file,
                               int line,
                               size_t message_start,
                               const std::string& str);
diff --git a/sandbox/linux/tests/main.cc b/sandbox/linux/tests/main.cc
index deb7ae6..e4a9114 100644
--- a/sandbox/linux/tests/main.cc
+++ b/sandbox/linux/tests/main.cc
@@ -41,7 +41,7 @@
 }  // namespace sandbox
 
 #if !defined(SANDBOX_USES_BASE_TEST_SUITE)
-void UnitTestAssertHandler(std::string_view file,
+void UnitTestAssertHandler(const char* file,
                            int line,
                            std::string_view message,
                            std::string_view stack_trace) {
diff --git a/services/audio/audio_sandbox_hook_linux.cc b/services/audio/audio_sandbox_hook_linux.cc
index b8088c2..458dde14 100644
--- a/services/audio/audio_sandbox_hook_linux.cc
+++ b/services/audio/audio_sandbox_hook_linux.cc
@@ -6,6 +6,8 @@
 
 #include <dlfcn.h>
 #include <unistd.h>
+
+#include <optional>
 #include <string>
 #include <string_view>
 #include <vector>
@@ -62,11 +64,12 @@
     bool recursive_only) {
   std::unique_ptr<base::Environment> env(base::Environment::Create());
 
-  std::string path_value;
-  if (!env->GetVar(variable_name, &path_value))
+  std::optional<std::string> path_value = env->GetVar(variable_name);
+  if (!path_value.has_value()) {
     return;
+  }
 
-  const base::FilePath pa_config_path(path_value);
+  const base::FilePath pa_config_path(*path_value);
   if (pa_config_path.empty())
     return;
 
diff --git a/services/viz/public/mojom/BUILD.gn b/services/viz/public/mojom/BUILD.gn
index a6a2ec37..4ae0475a 100644
--- a/services/viz/public/mojom/BUILD.gn
+++ b/services/viz/public/mojom/BUILD.gn
@@ -48,6 +48,7 @@
     "compositing/vertical_scroll_direction.mojom",
     "compositing/video_detector_observer.mojom",
     "compositing/view_transition_element_resource_id.mojom",
+    "compositing/view_transition_request.mojom",
     "gpu.mojom",
     "hit_test/aggregated_hit_test_region.mojom",
     "hit_test/hit_test_region_list.mojom",
diff --git a/services/viz/public/mojom/compositing/layer_context.mojom b/services/viz/public/mojom/compositing/layer_context.mojom
index c57ce08..d1e27543 100644
--- a/services/viz/public/mojom/compositing/layer_context.mojom
+++ b/services/viz/public/mojom/compositing/layer_context.mojom
@@ -10,8 +10,10 @@
 import "services/viz/public/mojom/compositing/local_surface_id.mojom";
 import "services/viz/public/mojom/compositing/tiling.mojom";
 import "services/viz/public/mojom/compositing/surface_range.mojom";
+import "services/viz/public/mojom/compositing/view_transition_request.mojom";
 import "skia/public/mojom/skcolor4f.mojom";
 import "ui/gfx/geometry/mojom/geometry.mojom";
+import "ui/gfx/mojom/display_color_spaces.mojom";
 
 // Metadata and contents of a service-side display tree to be updated each time
 // the corresponding client layer tree activates.
@@ -52,6 +54,9 @@
   float device_scale_factor;
   float painted_device_scale_factor;
 
+  // Display color spaces that the compositor expects, set by the tree's client.
+  gfx.mojom.DisplayColorSpaces display_color_spaces;
+
   // If a new LocalSurfaceId is assigned by the parent, it's included here.
   LocalSurfaceId? local_surface_id_from_parent;
 
@@ -105,6 +110,10 @@
   // If nullopt, there are no added or removed surfaces in this frame.
   array<SurfaceRange>? surface_ranges;
 
+  // Document transition requests to be transferred to Viz.
+  // If nullopt, there are no requests in this frame.
+  array<ViewTransitionRequest>? view_transition_requests;
+
   // New or updated animation timelines.
   array<AnimationTimeline>? animation_timelines;
 
diff --git a/services/viz/public/mojom/compositing/view_transition_request.mojom b/services/viz/public/mojom/compositing/view_transition_request.mojom
new file mode 100644
index 0000000..ffec485
--- /dev/null
+++ b/services/viz/public/mojom/compositing/view_transition_request.mojom
@@ -0,0 +1,28 @@
+// 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.
+
+module viz.mojom;
+
+import "services/viz/public/mojom/compositing/compositor_frame_transition_directive.mojom";
+import "services/viz/public/mojom/compositing/view_transition_element_resource_id.mojom";
+import "third_party/blink/public/mojom/tokens/tokens.mojom";
+
+struct ViewTransitionRequest {
+  // The type of this view transition request.
+  CompositorFrameTransitionDirectiveType type;
+
+  // It is an identifier that uniquely identifies each
+  // transition.
+  blink.mojom.ViewTransitionToken transition_token;
+
+  // Indicate if this transition can start and animate on different
+  // CompositorFrameSink instances (i.e. cross-document navigations).
+  bool maybe_cross_frame_sink;
+
+  // The sequence id for this request.
+  uint32 sequence_id;
+
+  // The snapshot resource ids.
+  array<ViewTransitionElementResourceId> capture_resource_ids;
+};
\ No newline at end of file
diff --git a/styleguide/java/nullaway.md b/styleguide/java/nullaway.md
index 0ef92e9a..2760c86 100644
--- a/styleguide/java/nullaway.md
+++ b/styleguide/java/nullaway.md
@@ -238,17 +238,33 @@
   for the parameters.
 * As a bonus, the constructor may also allow you to mark fields as `final`.
 
-### Rarely-Nullable Return Types
+### Effectively Non-Null Return Types
 
-In order to reduce excessive use of `assumeNonNull()`, here are two options
-for what to do with a method that rarely returns `null`:
+Some methods are technically `@Nullable`, but effectively `@NonNull`. That is,
+they are marked as having `@NonNull` return types despite sometimes returning
+`null`. Examples:
+   * [`Activity.findViewById()`]
+   * `Context.getSystemService()`
+   * `PreferenceManager.findPreference()` (this one via [`ChromeNullAwayLibraryModel`])
 
-1) Mark it as: `@NullUnmarked // Do not force assumeNonNull() at call sites`
-   * This is what [`Activity.findViewById()`] does.
-   * Non-null parameters must be marked as `@NonNull` to not also be considered
-     to have unknown nullness (so that nullness of parameters is still checked).
-2) Add sibling `*Checked()` methods that assert their return value is non-null.
-   * The nullable `TabModel.getTabById()` has a non-nullable `TabModel.getTabByIdChecked()`
+Enforcing null checks for these would be detrimental to readability.
+
+For Chromium-authored code that falls into this bucket, prefer to add
+companion "Checked" methods over mis-annotating nullability.
+
+Example:
+
+```java
+// When you're not sure if the tab exists:
+public @Nullable Tab getTabById(String tabId) {
+    ...
+}
+
+// When you know the tab exists:
+public Tab getTabByIdChecked(String tabId) {
+    return assertNonNull(getTabById(key));
+}
+```
 
 [`Activity.findViewById()`]: https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/core/java/android/app/Activity.java?q=symbol%3A%5Cbandroid.app.Activity.findViewById%5Cb%20case%3Ayes
 
diff --git a/testing/buildbot/filters/ios.compositor_unittests.filter b/testing/buildbot/filters/ios.compositor_unittests.filter
index 328e414..6fbb9fe 100644
--- a/testing/buildbot/filters/ios.compositor_unittests.filter
+++ b/testing/buildbot/filters/ios.compositor_unittests.filter
@@ -25,24 +25,56 @@
 -LayerDelegateTest.OnLayerTransformedNotCalledWhenUnchanged
 -LayerDelegateTest.OnLayerTransformedThreadedAnimation
 -LayerStandaloneTest.ReleaseMailboxOnDestruction
--LayerWithDelegateTest.AddRemoveLayerUpdatesAnimatorsFromSubtree
--LayerWithDelegateTest.CloneDamagedRegion
--LayerWithDelegateTest.Cloning
--LayerWithDelegateTest.ConvertPointToLayer_Medium
--LayerWithDelegateTest.ConvertPointToLayer_Simple
--LayerWithDelegateTest.DestroyingLayerRemovesTheAnimatorFromCollection
--LayerWithDelegateTest.ExternalContent
--LayerWithDelegateTest.ExternalContentMirroring
--LayerWithDelegateTest.GradientMask
--LayerWithDelegateTest.LayerFiltersSurvival
--LayerWithDelegateTest.Mirroring
--LayerWithDelegateTest.NonAnimatingAnimatorsAreRemovedFromCollection
--LayerWithDelegateTest.RootLayerAnimatorsInCompositor
--LayerWithDelegateTest.RoundedCorner
--LayerWithDelegateTest.SchedulePaintFromOnPaintLayer
--LayerWithDelegateTest.SetBoundsWhenInvisible
--LayerWithDelegateTest.SurfaceLayerCloneAndMirror
--LayerWithDelegateTest.TransferableResourceMirroring
+-All/LayerWithDelegateTest.ConvertPointToLayer_Medium/layer_lists_disabled
+-All/LayerWithDelegateTest.ConvertPointToLayer_Medium/layer_lists_enabled
+-All/LayerWithDelegateTest.ConvertPointToLayer_Simple/layer_lists_disabled
+-All/LayerWithDelegateTest.ConvertPointToLayer_Simple/layer_lists_enabled
+-All/LayerWithDelegateTest.GradientMask/layer_lists_disabled
+-All/LayerWithDelegateTest.GradientMask/layer_lists_enabled
+-All/LayerWithDelegateTest.Mirroring/layer_lists_disabled
+-All/LayerWithDelegateTest.Mirroring/layer_lists_enabled
+-All/LayerWithDelegateTest.RoundedCorner/layer_lists_disabled
+-All/LayerWithDelegateTest.RoundedCorner/layer_lists_enabled
+-All/LayerWithDelegateTest.SchedulePaintFromOnPaintLayer/layer_lists_disabled
+-All/LayerWithDelegateTest.SchedulePaintFromOnPaintLayer/layer_lists_enabled
+-All/LayerWithDelegateTest.SetBoundsWhenInvisible/layer_lists_disabled
+-All/LayerWithDelegateTest.SetBoundsWhenInvisible/layer_lists_enabled
+-All/LayerWithNullDelegateTest.AlwaysSendsMaskDamagedRects/layer_lists_disabled
+-All/LayerWithNullDelegateTest.AlwaysSendsMaskDamagedRects/layer_lists_enabled
+-All/LayerWithNullDelegateTest.EmptyDamagedRect/layer_lists_disabled
+-All/LayerWithNullDelegateTest.EmptyDamagedRect/layer_lists_enabled
+-All/LayerWithNullDelegateTest.MirroringVisibility/layer_lists_disabled
+-All/LayerWithNullDelegateTest.MirroringVisibility/layer_lists_enabled
+-All/LayerWithNullDelegateTest.SetBoundsSchedulesPaint/layer_lists_disabled
+-All/LayerWithNullDelegateTest.SetBoundsSchedulesPaint/layer_lists_enabled
+-All/LayerWithNullDelegateTest.UpdateDamageInDeferredPaint/layer_lists_disabled
+-All/LayerWithNullDelegateTest.UpdateDamageInDeferredPaint/layer_lists_enabled
+-All/LayerWithNullDelegateTest.Visibility/layer_lists_disabled
+-All/LayerWithNullDelegateTest.Visibility/layer_lists_enabled
+-All/LayerWithRealCompositorTest.CompositorAnimationObserverTest/layer_lists_disabled
+-All/LayerWithRealCompositorTest.CompositorAnimationObserverTest/layer_lists_enabled
+-All/LayerWithRealCompositorTest.CompositorObservers/layer_lists_disabled
+-All/LayerWithRealCompositorTest.CompositorObservers/layer_lists_enabled
+-All/LayerWithRealCompositorTest.Delegate/layer_lists_disabled
+-All/LayerWithRealCompositorTest.Delegate/layer_lists_enabled
+-All/LayerWithRealCompositorTest.Draw/layer_lists_disabled
+-All/LayerWithRealCompositorTest.Draw/layer_lists_enabled
+-All/LayerWithRealCompositorTest.DrawAlphaBlendedPixels/layer_lists_disabled
+-All/LayerWithRealCompositorTest.DrawAlphaBlendedPixels/layer_lists_enabled
+-All/LayerWithRealCompositorTest.DrawAlphaThresholdFilterPixels/layer_lists_disabled
+-All/LayerWithRealCompositorTest.DrawAlphaThresholdFilterPixels/layer_lists_enabled
+-All/LayerWithRealCompositorTest.DrawPixels/layer_lists_disabled
+-All/LayerWithRealCompositorTest.DrawPixels/layer_lists_enabled
+-All/LayerWithRealCompositorTest.DrawTree/layer_lists_disabled
+-All/LayerWithRealCompositorTest.DrawTree/layer_lists_enabled
+-All/LayerWithRealCompositorTest.Hierarchy/layer_lists_disabled
+-All/LayerWithRealCompositorTest.Hierarchy/layer_lists_enabled
+-All/LayerWithRealCompositorTest.HierarchyNoTexture/layer_lists_disabled
+-All/LayerWithRealCompositorTest.HierarchyNoTexture/layer_lists_enabled
+-All/LayerWithRealCompositorTest.NoContentNoDraw/layer_lists_disabled
+-All/LayerWithRealCompositorTest.NoContentNoDraw/layer_lists_enabled
+-All/LayerWithRealCompositorTest.SchedulePaintUpdatesMask/layer_lists_disabled
+-All/LayerWithRealCompositorTest.SchedulePaintUpdatesMask/layer_lists_enabled
 -LayerWithNullDelegateTest.AlwaysSendsMaskDamagedRects
 -LayerWithNullDelegateTest.EmptyDamagedRect
 -LayerWithNullDelegateTest.MirroringVisibility
diff --git a/testing/buildbot/filters/layer_list_mode.cc_unittests.filter b/testing/buildbot/filters/layer_list_mode.cc_unittests.filter
index 50b2ccd..6c420d6 100644
--- a/testing/buildbot/filters/layer_list_mode.cc_unittests.filter
+++ b/testing/buildbot/filters/layer_list_mode.cc_unittests.filter
@@ -40,6 +40,14 @@
 -All/LayerTreeHostFiltersPixelTest.BackdropFilterInvalid/SkiaGL
 -All/LayerTreeHostFiltersPixelTest.BackdropFilterInvalid/SkiaGraphiteDawn
 -All/LayerTreeHostFiltersPixelTest.BackdropFilterInvalid/Software
+-All/LayerTreeHostFiltersPixelTest.BackdropFilterQuality_0_33/SkiaGL
+-All/LayerTreeHostFiltersPixelTest.BackdropFilterQuality_0_33/SkiaGraphiteDawn
+-All/LayerTreeHostFiltersPixelTest.BackdropFilterQuality_0_33/SkiaVulkan
+-All/LayerTreeHostFiltersPixelTest.BackdropFilterQuality_0_33/Software
+-All/LayerTreeHostFiltersPixelTest.BackdropFilterQuality_1_0/SkiaGL
+-All/LayerTreeHostFiltersPixelTest.BackdropFilterQuality_1_0/SkiaGraphiteDawn
+-All/LayerTreeHostFiltersPixelTest.BackdropFilterQuality_1_0/SkiaVulkan
+-All/LayerTreeHostFiltersPixelTest.BackdropFilterQuality_1_0/Software
 -All/LayerTreeHostFiltersPixelTest.BackdropFilterRotated/SkiaGL
 -All/LayerTreeHostFiltersPixelTest.BackdropFilterRotated/SkiaGraphiteDawn
 -All/LayerTreeHostFiltersPixelTest.BackdropFilterRotated/Software
diff --git a/testing/buildbot/filters/trees_in_viz.blink_unittests.filter b/testing/buildbot/filters/trees_in_viz.blink_unittests.filter
index 630e713..e69de29 100644
--- a/testing/buildbot/filters/trees_in_viz.blink_unittests.filter
+++ b/testing/buildbot/filters/trees_in_viz.blink_unittests.filter
@@ -1,17 +0,0 @@
-# TODO(crbug.com/389147356): Implement single-threaded mode, which all of these
-# tests operate in.
--EventHandlingWebFrameWidgetSimTest.NonRafAlignedEventWithUpdate
--EventHandlingWebFrameWidgetSimTest.NonRafAlignedEventWithoutUpdateAfterUpdate
--EventHandlingWebFrameWidgetSimTest.RafAlignedEventWithUpdate
--EventHandlingWebFrameWidgetSimTest.RafAlignedEventWithoutUpdate
--NotifySwapTimesWebFrameWidgetTest.NotifyOnSuccessfulPresentation
--NotifySwapTimesWebFrameWidgetTest.ReportPresentationOnlyOnSuccessfulCommit
--ScrollSnapTest.ResizeDuringGesture
--ScrollSnapTest.ScrollSnapOnBoth
--ScrollSnapTest.ScrollSnapOnX
--ScrollSnapTest.ScrollSnapOnY
--ScrollSnapTest.SnapWhenBodyOverflowHtmlViewportDefining
--ScrollSnapTest.SnapWhenBodyViewportDefining
--ScrollSnapTest.SnapWhenHtmlViewportDefining
--ScrollingSimTest.CompositedStickyTracksMainRepaintScroll
--ScrollingSimTest.ScrollTimelineActiveAtBoundary
diff --git a/testing/buildbot/filters/trees_in_viz.cc_unittests.filter b/testing/buildbot/filters/trees_in_viz.cc_unittests.filter
index fc296b5..689d474 100644
--- a/testing/buildbot/filters/trees_in_viz.cc_unittests.filter
+++ b/testing/buildbot/filters/trees_in_viz.cc_unittests.filter
@@ -65,10 +65,6 @@
 # TODO(crbug.com/404940699) Fix missing frame submit to Viz after commit request
 -LayerTreeHostTestBeginFrameAcks.RunMultiThread_DelegatingRenderer
 
-# TODO(crbug.com/404941217) Fix submitted frame.metadata.transition_directives
--LayerTreeHostTestViewTransitionsPropagatedToMetadata.RunMultiThread_DelegatingRenderer
--LayerTreeHostTestViewTransitionsPropagatedToMetadata.RunSingleThread_DelegatingRenderer
-
 # TODO (crbug.com/404940328) Fix LayerTreeHostTestInvisibleLayersSkipRenderPass
 -LayerTreeHostTestInvisibleLayersSkipRenderPass.RunSingleThread_DelegatingRenderer
 -LayerTreeHostTestInvisibleLayersSkipRenderPass.RunMultiThread_DelegatingRenderer
@@ -153,11 +149,13 @@
 -LayerTreeHostTestCompositeImmediatelyStateTransitions.RunSingleThread_DelegatingRenderer
 -LayerTreeHostTestSynchronousCompositeSwapPromise.RunSingleThread_DelegatingRenderer
 
-# TODO(crbug.com/406273351) Update tests to use DisplayReceivedCompositorFrameOnThread for introspection
--LayerTreeHostTestContinuousDrawWhenCreatingVisibleTiles.RunMultiThread_DelegatingRenderer
--LayerTreeHostTestCrispUpAfterPinchEnds.RunMultiThread_DelegatingRenderer
+# TODO(crbug.com/406010462) View transition requests are lost between cc and viz
 -LayerTreeHostTestDamagePropagatesFromViewTransitionSurface.RunMultiThread_DelegatingRenderer
 
+# TODO(crbug.com/408053394) Implement Tile based damage tracking in TileDisplayLayerImpl
+# TODO(crbug.com/408053792) Implement Tiling removal in TileDisplayLayerImpl
+-LayerTreeHostTestCrispUpAfterPinchEnds.RunMultiThread_DelegatingRenderer
+
 # TODO(crbug.com/404813701) Triage cc_unittests failures using non layer list mode
 -All/LayerTreeHostCopyRequestTestDeleteSharedImage.Test/SkiaGL_MultiThreaded
 -All/LayerTreeHostCopyRequestTestDeleteSharedImage.Test/SkiaGL_SingleThreaded
@@ -173,12 +171,6 @@
 -All/LayerTreeHostCopyRequestTestMultipleDrawsHiddenCopyRequest.Test/SkiaVulkan_SingleThreaded
 
 # TODO(crbug.com/383016428) Readback of layers outside of the viewport stopped
-# working for Readback since crrev.com/c/6383158.
--All/LayerTreeHostReadbackPixelTest.ReadbackNonRootLayerOutsideViewport/SkiaGL_Bitmap
--All/LayerTreeHostReadbackPixelTest.ReadbackNonRootLayerOutsideViewport/SkiaGL_Texture
--All/LayerTreeHostReadbackPixelTest.ReadbackNonRootLayerOutsideViewport/SkiaGraphiteDawn_Bitmap
--All/LayerTreeHostReadbackPixelTest.ReadbackNonRootLayerOutsideViewport/Software_Bitmap
--All/LayerTreeHostReadbackPixelTest.ReadbackOutsideViewportWhenNoDamage/SkiaGL_Bitmap
--All/LayerTreeHostReadbackPixelTest.ReadbackOutsideViewportWhenNoDamage/SkiaGL_Texture
--All/LayerTreeHostReadbackPixelTest.ReadbackOutsideViewportWhenNoDamage/SkiaGraphiteDawn_Bitmap
--All/LayerTreeHostReadbackPixelTest.ReadbackOutsideViewportWhenNoDamage/Software_Bitmap
+# working since crrev.com/c/6383158.
+-All/LayerTreeHostReadbackPixelTest.ReadbackNonRootLayerOutsideViewport/*
+-All/LayerTreeHostReadbackPixelTest.ReadbackOutsideViewportWhenNoDamage/*
diff --git a/testing/buildbot/filters/trees_in_viz.content_browsertests.filter b/testing/buildbot/filters/trees_in_viz.content_browsertests.filter
index b7956f8..c9c7322 100644
--- a/testing/buildbot/filters/trees_in_viz.content_browsertests.filter
+++ b/testing/buildbot/filters/trees_in_viz.content_browsertests.filter
@@ -10,20 +10,11 @@
 -All/NavigationBrowserTestPaintHoldingSubframe.BasicInProcessIframe/0
 -All/NavigationBrowserTestPaintHoldingSubframe.BasicInProcessIframe/1
 -All/RenderWidgetHostItemSequenceNumberInRenderFrameMetadataTest.ItemSequenceNumberExpectedNoContentChange/SameDoc
--All/SitePerProcessBrowserTest.ScrollByRAF/0
--All/SitePerProcessBrowserTest.ScrollByRAF/1
 -All/SitePerProcessBrowserTest.ScrollOopifInPinchZoomedPage/0
 -CaptureScreenshotTest.TransparentScreenshotsBeyondViewport
 -CaptureScreenshotTest.TransparentScreenshotsFull
--P/ViewTransitionBrowserTestTraverse.TransitionOnSessionRestoreTraversal/0
--P/ViewTransitionCaptureTest.ViewTransitionNoArtifactDuringCapture/0
--P/ViewTransitionCaptureTest.ViewTransitionNoArtifactDuringCapture/1
 -PrerenderBrowserDeathTest.PrerenderCannotHaveInnerContents
--RenderFrameHostImplBrowserTestWithBFCacheAndViewTransition.NewContentTimeoutIsSetWhenLeavingBFCacheWithViewTransition
 -RenderFrameHostImplDeathTest.ReloadInPendingDeletionOrBFCache
--RenderWidgetHostDelegatedInkMetadataTest.DuplicateMetadata
--ScrollBehaviorBrowserTest.SmoothWheelScrollCompletesWithScriptedMirror
--ScrollLatencyBrowserTest.ScrollingEventLatencyTrace
 -SecurityExploitBrowserTest.AllowBindingsForNonWebUIProcess
 -SitePerProcessHighDPIHitTestBrowserTest.HitTestLayerSquashing
 -SitePerProcessHighDPIHitTestBrowserTest.HitTestWatermark
@@ -38,8 +29,4 @@
 -SitePerProcessHitTestDataGenerationBrowserTest.OccludedOOPIF
 -SitePerProcessHitTestDataGenerationBrowserTest.OverlappedOOPIF
 -SnapshotBrowserTest.SingleWindowTest
--SnapshotBrowserTest.SyncMultiWindowTest
--TouchActionBrowserTestEnableCursorControl.NoCursorControlForHorizontalScrollable
--ViewTransitionBrowserTest.NavigationCancelledAfterScreenshot
--ViewTransitionBrowserTest.NavigationCancelledBeforeScreenshot
--ViewTransitionBrowserTest.OwnershipTransferredToNewRenderer
\ No newline at end of file
+-SnapshotBrowserTest.SyncMultiWindowTest
\ No newline at end of file
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 516b895..653d0eb 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -1610,21 +1610,6 @@
             ]
         }
     ],
-    "AutofillAddressFieldSwapping": [
-        {
-            "platforms": [
-                "ios"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "AutofillAddressFieldSwapping"
-                    ]
-                }
-            ]
-        }
-    ],
     "AutofillAddressSuggestionsOnTyping": [
         {
             "platforms": [
@@ -9860,6 +9845,7 @@
         {
             "platforms": [
                 "android",
+                "android_webview",
                 "chromeos",
                 "fuchsia",
                 "ios",
diff --git a/third_party/angle b/third_party/angle
index f276df6..6631db1 160000
--- a/third_party/angle
+++ b/third_party/angle
@@ -1 +1 @@
-Subproject commit f276df669062b83b6a33f58b764706e582a9151b
+Subproject commit 6631db11d0363b524414c41ac73eacc075d3db19
diff --git a/third_party/blink/common/switches.cc b/third_party/blink/common/switches.cc
index 12df60d..8436d74b8 100644
--- a/third_party/blink/common/switches.cc
+++ b/third_party/blink/common/switches.cc
@@ -128,12 +128,6 @@
 // Sets the min tile height for GPU raster.
 const char kMinHeightForGpuRasterTile[] = "min-height-for-gpu-raster-tile";
 
-// Used to communicate managed policy for MutationEvents feature. This feature
-// is typically controlled by a RuntimeEnabledFeature, but requires an
-// enterprise policy override.
-extern const char kMutationEventsEnabled[] =
-    "deprecated-mutation-events-enabled";
-
 // Used to communicate managed policy for CSSCustomStateDeprecatedSyntax. This
 // feature is typically controlled by a RuntimeEnabledFeature, but requires an
 // enterprise policy override.
diff --git a/third_party/blink/public/common/switches.h b/third_party/blink/public/common/switches.h
index caeaa3ee..e284eba 100644
--- a/third_party/blink/public/common/switches.h
+++ b/third_party/blink/public/common/switches.h
@@ -47,7 +47,6 @@
 BLINK_COMMON_EXPORT extern const char kJavaScriptFlags[];
 BLINK_COMMON_EXPORT extern const char kMaxUntiledLayerHeight[];
 BLINK_COMMON_EXPORT extern const char kMaxUntiledLayerWidth[];
-BLINK_COMMON_EXPORT extern const char kMutationEventsEnabled[];
 BLINK_COMMON_EXPORT extern const char kDisableBlobUrlPartitioning[];
 BLINK_COMMON_EXPORT extern const char kCSSCustomStateDeprecatedSyntaxEnabled[];
 BLINK_COMMON_EXPORT extern const char kDisableSelectParserRelaxation[];
diff --git a/third_party/blink/renderer/core/scroll/scroll_into_view_util.cc b/third_party/blink/renderer/core/scroll/scroll_into_view_util.cc
index 9325d02..7334ce2 100644
--- a/third_party/blink/renderer/core/scroll/scroll_into_view_util.cc
+++ b/third_party/blink/renderer/core/scroll/scroll_into_view_util.cc
@@ -196,9 +196,10 @@
   HeapHashSet<Member<const LayoutBox>> stop_at;
   if (const LayoutObject* halt_object =
           container ? current_box->CommonAncestor(*container) : nullptr) {
-    for (const LayoutBox* halt_box = halt_object->EnclosingBox(); halt_box;
-         halt_box = halt_box->ParentBox()) {
-      stop_at.insert(halt_box);
+    for (; halt_object; halt_object = halt_object->Parent()) {
+      if (const LayoutBox* halt_box = DynamicTo<LayoutBox>(halt_object)) {
+        stop_at.insert(halt_box);
+      }
     }
   }
   while (current_box) {
diff --git a/third_party/blink/renderer/modules/BUILD.gn b/third_party/blink/renderer/modules/BUILD.gn
index 7e18f85..26d941af 100644
--- a/third_party/blink/renderer/modules/BUILD.gn
+++ b/third_party/blink/renderer/modules/BUILD.gn
@@ -731,6 +731,7 @@
     "//third_party/blink/renderer/platform/wtf",
     "//third_party/googletest:gmock",
     "//third_party/opus",
+    "//third_party/webrtc_overrides:logging_test",
     "//third_party/webrtc_overrides:webrtc_component",
     "//ui/strings:ax_strings_grit",
     "//v8",
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 7862e26..cba6c03 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1750,7 +1750,9 @@
     // IncludeJSCallStacksInCrashReports. https://chromestatus.com/feature/4731248572628992
     {
       name: "DocumentPolicyIncludeJSCallStacksInCrashReports",
-      status: "stable",
+      status: "experimental",
+      base_feature_status: "enabled",
+      copied_from_base_feature_if: "overridden",
     },
     {
       name: "DocumentPolicyNegotiation",
@@ -2909,11 +2911,10 @@
     //  - Events disabled for the open web: M127 (July 23, 2024)
     //  - Reminder email sent to all Origin trial registrants: December 12, 2024
     //  - Origin trial disabled: M135 (April 1, 2025)
-    //  - Enterprise policy disabled: {not yet}
-    //  - Flag/code can be removed: {2 milestones after EP removal}
+    //  - Enterprise policy disabled: M137 (May 20, 2025)
+    //  - Flag/code can be removed: M139
     {
       name: "MutationEvents",
-      public: true,
     },
     {
       name: "NavigateEventCanTransition",
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 3fa07ef9..e07cfec8 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -2606,6 +2606,7 @@
 [ Linux ] external/wpt/webdriver/tests/bidi/network/continue_response/cookies.py [ Pass Timeout ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/408039461 [ Win11-arm64 ] external/wpt/css/css-text/white-space/control-chars-01D.html [ Failure ]
 crbug.com/408034113 [ Win11-arm64 ] external/wpt/service-workers/service-worker/fetch-mixed-content-to-inscope.https.html [ Crash ]
 crbug.com/408039452 [ Win11-arm64 ] external/wpt/webaudio/the-audio-api/the-audioworklet-interface/audioworkletnode-constructor-options.https.html [ Timeout ]
 crbug.com/408039416 [ Mac12 ] external/wpt/speech-api/SpeechRecognition-onerror.https.html [ Timeout ]
@@ -7591,13 +7592,13 @@
 
 # Gardener 2024-02-08
 crbug.com/324436866 [ Debug ] external/wpt/webdriver/tests/bidi/browsing_context/context_destroyed/context_destroyed.py [ Failure Timeout ]
-crbug.com/324436866 [ Debug ] external/wpt/webdriver/tests/bidi/browsing_context/get_tree/frames.py [ Failure Timeout ]
+crbug.com/324436866 external/wpt/webdriver/tests/bidi/browsing_context/get_tree/frames.py [ Failure Timeout ]
 crbug.com/324436866 [ Debug ] external/wpt/webdriver/tests/bidi/browsing_context/user_prompt_closed/user_prompt_closed.py [ Failure Timeout ]
-crbug.com/324436866 [ Debug ] external/wpt/webdriver/tests/bidi/script/evaluate/remote_values.py [ Failure Timeout ]
-crbug.com/324436866 [ Debug ] external/wpt/webdriver/tests/bidi/script/get_realms/get_realms.py [ Failure Timeout ]
-crbug.com/324436866 [ Debug ] external/wpt/webdriver/tests/bidi/script/realm_created/realm_created.py [ Failure Timeout ]
-crbug.com/324436866 [ Debug ] external/wpt/webdriver/tests/bidi/script/realm_destroyed/realm_destroyed.py [ Failure Timeout ]
-crbug.com/324436866 [ Debug ] external/wpt/webdriver/tests/bidi/storage/set_cookie/partition.py [ Failure Timeout ]
+crbug.com/324436866 external/wpt/webdriver/tests/bidi/script/evaluate/remote_values.py [ Failure Timeout ]
+crbug.com/324436866 external/wpt/webdriver/tests/bidi/script/get_realms/get_realms.py [ Failure Timeout ]
+crbug.com/324436866 external/wpt/webdriver/tests/bidi/script/realm_created/realm_created.py [ Failure Timeout ]
+crbug.com/324436866 external/wpt/webdriver/tests/bidi/script/realm_destroyed/realm_destroyed.py [ Failure Timeout ]
+crbug.com/324436866 external/wpt/webdriver/tests/bidi/storage/set_cookie/partition.py [ Failure Timeout ]
 
 crbug.com/1467464 http/tests/devtools/a11y-axe-core/sources/event-listener-breakpoints-a11y-test.js [ Failure Pass ]
 
@@ -8608,7 +8609,7 @@
 crbug.com/358437652 [ Linux ] external/wpt/dom/events/scrolling/wheel-event-transactions-multiple-action-chains.html [ Failure ]
 crbug.com/358437652 [ Mac ] external/wpt/dom/events/scrolling/wheel-event-transactions-multiple-action-chains.html [ Failure ]
 crbug.com/358437652 [ Win11-arm64 ] external/wpt/dom/events/scrolling/wheel-event-transactions-multiple-action-chains.html [ Failure ]
-crbug.com/359519774 [ Debug Linux ] external/wpt/webdriver/tests/bidi/input/perform_actions/pointer_touch.py [ Failure Pass ]
+crbug.com/359519774 [ Linux ] external/wpt/webdriver/tests/bidi/input/perform_actions/pointer_touch.py [ Failure Pass ]
 
 # TODO(crbug.com/360166067) This test timeout on headless shell and Chrome
 crbug.com/360166067 [ Release ] external/wpt/longtask-timing/longtask-in-raf.html [ Timeout ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
index f11587c8..e5220af1 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -85665,7 +85665,7 @@
         ]
        ],
        "corner-shape-notch.html": [
-        "79f64070bd8389e5cdcf01566bb0da117d1f313a",
+        "30acefe527f81eec1b807d1f3fa4a16ff0bcb549",
         [
          null,
          [
@@ -85694,12 +85694,12 @@
         ]
        ],
        "corner-shape-render-fuzzy.html": [
-        "afd590461801bf82c73f6e79f73008e22777c5f9",
+        "dd1a32a15ae8c22a881c27217ed10c3d6c07dfd5",
         [
-         "css/css-borders/tentative/corner-shape/corner-shape-render-fuzzy.html?border-radius=30%&corner-shape=superellipse(0.4)&box-shadow=10px%2010px%200%2010px%20black",
+         "css/css-borders/tentative/corner-shape/corner-shape-render-fuzzy.html?border-radius=30%&corner-shape=superellipse(-1.5)&box-shadow=10px%2010px%200%2010px%20black",
          [
           [
-           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?border-radius=30%&corner-shape=superellipse(0.4)&box-shadow=10px%2010px%200%2010px%20black",
+           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?border-radius=30%&corner-shape=superellipse(-1.5)&box-shadow=10px%2010px%200%2010px%20black",
            "=="
           ]
          ],
@@ -85878,10 +85878,10 @@
          }
         ],
         [
-         "css/css-borders/tentative/corner-shape/corner-shape-render-fuzzy.html?corner-shape=superellipse(0.05)&border-radius=20%&border-width=20px",
+         "css/css-borders/tentative/corner-shape/corner-shape-render-fuzzy.html?corner-shape=superellipse(-2)&border-radius=20%&border-width=20px",
          [
           [
-           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-shape=superellipse(0.05)&border-radius=20%&border-width=20px",
+           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-shape=superellipse(-2)&border-radius=20%&border-width=20px",
            "=="
           ]
          ],
@@ -85904,10 +85904,10 @@
          }
         ],
         [
-         "css/css-borders/tentative/corner-shape/corner-shape-render-fuzzy.html?corner-shape=superellipse(0.25)&border-radius=20%&border-width=20px",
+         "css/css-borders/tentative/corner-shape/corner-shape-render-fuzzy.html?corner-shape=superellipse(-7)&border-radius=20%&border-width=20px",
          [
           [
-           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-shape=superellipse(0.25)&border-radius=20%&border-width=20px",
+           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-shape=superellipse(-7)&border-radius=20%&border-width=20px",
            "=="
           ]
          ],
@@ -85930,10 +85930,10 @@
          }
         ],
         [
-         "css/css-borders/tentative/corner-shape/corner-shape-render-fuzzy.html?corner-shape=superellipse(1.8)&border-radius=40px&border-width=10px&border-left-color=purple",
+         "css/css-borders/tentative/corner-shape/corner-shape-render-fuzzy.html?corner-shape=superellipse(0.8)&border-radius=40px&border-width=10px&border-left-color=purple",
          [
           [
-           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-shape=superellipse(1.8)&border-radius=40px&border-width=10px&border-left-color=purple",
+           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-shape=superellipse(0.8)&border-radius=40px&border-width=10px&border-left-color=purple",
            "=="
           ]
          ],
@@ -85956,10 +85956,10 @@
          }
         ],
         [
-         "css/css-borders/tentative/corner-shape/corner-shape-render-fuzzy.html?corner-shape=superellipse(40)&border-radius=20%&border-width=20px",
+         "css/css-borders/tentative/corner-shape/corner-shape-render-fuzzy.html?corner-shape=superellipse(3)&border-radius=40px&box-shadow=10px 10px 0 10px black",
          [
           [
-           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-shape=superellipse(40)&border-radius=20%&border-width=20px",
+           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-shape=superellipse(3)&border-radius=40px&box-shadow=10px 10px 0 10px black",
            "=="
           ]
          ],
@@ -85982,10 +85982,10 @@
          }
         ],
         [
-         "css/css-borders/tentative/corner-shape/corner-shape-render-fuzzy.html?corner-shape=superellipse(8)&border-radius=40px&box-shadow=10px 10px 0 10px black",
+         "css/css-borders/tentative/corner-shape/corner-shape-render-fuzzy.html?corner-shape=superellipse(5)&border-radius=20%&border-width=20px",
          [
           [
-           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-shape=superellipse(8)&border-radius=40px&box-shadow=10px 10px 0 10px black",
+           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-shape=superellipse(5)&border-radius=20%&border-width=20px",
            "=="
           ]
          ],
@@ -86112,10 +86112,10 @@
          }
         ],
         [
-         "css/css-borders/tentative/corner-shape/corner-shape-render-fuzzy.html?corner-top-left-shape=superellipse(0.3)&border-radius=40%",
+         "css/css-borders/tentative/corner-shape/corner-shape-render-fuzzy.html?corner-top-left-shape=superellipse(-4)&border-radius=40%",
          [
           [
-           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-top-left-shape=superellipse(0.3)&border-radius=40%",
+           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-top-left-shape=superellipse(-4)&border-radius=40%",
            "=="
           ]
          ],
@@ -86138,10 +86138,10 @@
          }
         ],
         [
-         "css/css-borders/tentative/corner-shape/corner-shape-render-fuzzy.html?corner-top-left-shape=superellipse(6)&border-radius=20%&border-width=10px",
+         "css/css-borders/tentative/corner-shape/corner-shape-render-fuzzy.html?corner-top-left-shape=superellipse(2.5)&border-radius=20%&border-width=10px",
          [
           [
-           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-top-left-shape=superellipse(6)&border-radius=20%&border-width=10px",
+           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-top-left-shape=superellipse(2.5)&border-radius=20%&border-width=10px",
            "=="
           ]
          ],
@@ -86191,7 +86191,7 @@
         ]
        ],
        "corner-shape-render-precise.html": [
-        "b9092fb32123ddc416ee2f9e43e99cfd74da594f",
+        "07aa70d070d8e55eb17450a3f030d2c38f7aa7bc",
         [
          "css/css-borders/tentative/corner-shape/corner-shape-render-precise.html?border-radius=50%&corner-shape=bevel&box-shadow=10px%2010px%200%2010px%20black",
          [
@@ -86219,10 +86219,10 @@
          }
         ],
         [
-         "css/css-borders/tentative/corner-shape/corner-shape-render-precise.html?border-top-left-radius=50%&corner-shape=superellipse(1.4)&border-left-width=30px&border-top-width=30px",
+         "css/css-borders/tentative/corner-shape/corner-shape-render-precise.html?border-top-left-radius=50%&corner-shape=superellipse(0.7)&border-left-width=30px&border-top-width=30px",
          [
           [
-           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?border-top-left-radius=50%&corner-shape=superellipse(1.4)&border-left-width=30px&border-top-width=30px",
+           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?border-top-left-radius=50%&corner-shape=superellipse(0.7)&border-left-width=30px&border-top-width=30px",
            "=="
           ]
          ],
@@ -86349,10 +86349,10 @@
          }
         ],
         [
-         "css/css-borders/tentative/corner-shape/corner-shape-render-precise.html?corner-bottom-right-shape=superellipse(1.9)&border-bottom-right-radius=50%",
+         "css/css-borders/tentative/corner-shape/corner-shape-render-precise.html?corner-bottom-right-shape=superellipse(0.8)&border-bottom-right-radius=50%",
          [
           [
-           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-bottom-right-shape=superellipse(1.9)&border-bottom-right-radius=50%",
+           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-bottom-right-shape=superellipse(0.8)&border-bottom-right-radius=50%",
            "=="
           ]
          ],
@@ -86479,10 +86479,10 @@
          }
         ],
         [
-         "css/css-borders/tentative/corner-shape/corner-shape-render-precise.html?corner-shape=superellipse(5.2)&border-radius=40%",
+         "css/css-borders/tentative/corner-shape/corner-shape-render-precise.html?corner-shape=superellipse(2.3)&border-radius=40%",
          [
           [
-           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-shape=superellipse(5.2)&border-radius=40%",
+           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-shape=superellipse(2.3)&border-radius=40%",
            "=="
           ]
          ],
@@ -86505,10 +86505,10 @@
          }
         ],
         [
-         "css/css-borders/tentative/corner-shape/corner-shape-render-precise.html?corner-shape=superellipse(8)&border-top-right-radius=33px",
+         "css/css-borders/tentative/corner-shape/corner-shape-render-precise.html?corner-shape=superellipse(3)&border-top-right-radius=33px",
          [
           [
-           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-shape=superellipse(8)&border-top-right-radius=33px",
+           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-shape=superellipse(3)&border-top-right-radius=33px",
            "=="
           ]
          ],
@@ -86609,10 +86609,10 @@
          }
         ],
         [
-         "css/css-borders/tentative/corner-shape/corner-shape-render-precise.html?corner-top-left-shape=superellipse(0.2)&border-radius=40px",
+         "css/css-borders/tentative/corner-shape/corner-shape-render-precise.html?corner-top-left-shape=superellipse(-0.5)&border-radius=40px",
          [
           [
-           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-top-left-shape=superellipse(0.2)&border-radius=40px",
+           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-top-left-shape=superellipse(-0.5)&border-radius=40px",
            "=="
           ]
          ],
@@ -86635,10 +86635,10 @@
          }
         ],
         [
-         "css/css-borders/tentative/corner-shape/corner-shape-render-precise.html?corner-top-left-shape=superellipse(0.8)&border-radius=40px",
+         "css/css-borders/tentative/corner-shape/corner-shape-render-precise.html?corner-top-left-shape=superellipse(-4)&border-radius=40px",
          [
           [
-           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-top-left-shape=superellipse(0.8)&border-radius=40px",
+           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-top-left-shape=superellipse(-4)&border-radius=40px",
            "=="
           ]
          ],
@@ -86661,10 +86661,10 @@
          }
         ],
         [
-         "css/css-borders/tentative/corner-shape/corner-shape-render-precise.html?corner-top-left-shape=superellipse(1.2)&border-radius=40px",
+         "css/css-borders/tentative/corner-shape/corner-shape-render-precise.html?corner-top-left-shape=superellipse(0.5)&border-radius=40px",
          [
           [
-           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-top-left-shape=superellipse(1.2)&border-radius=40px",
+           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-top-left-shape=superellipse(0.5)&border-radius=40px",
            "=="
           ]
          ],
@@ -86713,10 +86713,10 @@
          }
         ],
         [
-         "css/css-borders/tentative/corner-shape/corner-shape-render-precise.html?corner-top-right-shape=superellipse(0.1)&border-top-right-radius=50px",
+         "css/css-borders/tentative/corner-shape/corner-shape-render-precise.html?corner-top-right-shape=superellipse(-4)&border-top-right-radius=50px",
          [
           [
-           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-top-right-shape=superellipse(0.1)&border-top-right-radius=50px",
+           "/css/css-borders/tentative/corner-shape/corner-shape-any-ref.html?corner-top-right-shape=superellipse(-4)&border-top-right-radius=50px",
            "=="
           ]
          ],
@@ -86740,7 +86740,7 @@
         ]
        ],
        "corner-shape-square.html": [
-        "3f86603bd669ff3d3212758cdbc0ba3cfd421d18",
+        "13ab05cc7f677bab47f1fd5d3aa610897a0ccefe",
         [
          null,
          [
@@ -86756,11 +86756,11 @@
             [
              [
               0,
-              32
+              60
              ],
              [
               0,
-              32
+              80
              ]
             ]
            ]
@@ -185405,7 +185405,7 @@
       ]
      ],
      "has-slotted-001.html": [
-      "e750d97a180b5daa6eb0ac18e7178372eeaf96b6",
+      "4e3de3f6adbdfc20fa6a441d23b90d3e9f28c7ea",
       [
        null,
        [
@@ -185431,7 +185431,7 @@
       ]
      ],
      "has-slotted-003.html": [
-      "7578413ff3977094a5ffbcb151498a92ddc4c36d",
+      "d13911e96b76f524e9d934a3a3d13e24360111b7",
       [
        null,
        [
@@ -186380,7 +186380,7 @@
       ]
      ],
      "slotted-has-001.html": [
-      "f70bac7eca386d9060530c2c7b7048cc3c5c2f57",
+      "dcb11ec32eaea0b9982f8d5bc6b4a6cad7c41fad",
       [
        null,
        [
@@ -186393,7 +186393,7 @@
       ]
      ],
      "slotted-has-002.html": [
-      "9ecbea5d413f9244e346e90b25c678471dfc9b53",
+      "5e709a969619b3b48f62231c4ac30209388dc8a5",
       [
        null,
        [
@@ -186406,7 +186406,7 @@
       ]
      ],
      "slotted-has-003.html": [
-      "1ea412492c567e82fe8e911a90cfd5e54f704907",
+      "548f2c5d421d673367abc89c9289d756cf463016",
       [
        null,
        [
@@ -186419,7 +186419,7 @@
       ]
      ],
      "slotted-has-004.html": [
-      "adf50da13a95a5e95e681cb726ac0c1991394d3d",
+      "7e76b1b6de62920eb863a7fb114de6ba6c160b78",
       [
        null,
        [
@@ -296894,7 +296894,7 @@
       ],
       "the-select-element": {
        "option-add-label-quirks.html": [
-        "2c3c8093e253250f11a7e84a7ba89f3535d2eb20",
+        "f91609afc506b7530c6106bd047eab93b8645aa7",
         [
          null,
          [
@@ -332591,7 +332591,7 @@
          []
         ],
         "resolve-corner-style.js": [
-         "e30dde244205abf809ae765d21ddbbee2809408c",
+         "26f18a02a338a26383de502027612c7811ff2298",
          []
         ]
        }
@@ -358455,6 +358455,10 @@
       "53463b38f4154029f9fadf7c337119f9828f57b4",
       []
      ],
+     "WEB_FEATURES.yml": [
+      "88e56feb543f5c84cc630e6dabc72694c7caba60",
+      []
+     ],
      "font-face-001-expected.txt": [
       "0ccc20dfb3a8a07be48e528279d05f1c944ce5df",
       []
@@ -376807,7 +376811,7 @@
      },
      "parsing": {
       "WEB_FEATURES.yml": [
-       "f3453b29162aab65363b2caf0ba076c8ccb58de1",
+       "ab1fe19e4d1e36f06166e76477d0bcf907d34db6",
        []
       ],
       "invalid-pseudos-expected.txt": [
@@ -384630,7 +384634,7 @@
       []
      ],
      "http-cache.js": [
-      "19f1ca9b2bcce2dbe1120ceeb4c5283103d5d105",
+      "0ca5fcc2bc0812f116c483a3dd24ae08fb0545c6",
       []
      ],
      "resources": {
@@ -397838,15 +397842,15 @@
       ],
       "resources": {
        "beforematch-scroll-to-text-fragment-basic.html": [
-        "884e9a67faeae5b3c8236f9843bb2b0ae0c5e803",
+        "4166f9b15aba7792971b8f6411b75833926cc39d",
         []
        ],
        "beforematch-scroll-to-text-fragment-bubble.html": [
-        "abfe8ddd54407c4eb12e5430e72f140e2bad9e24",
+        "d9cae3c74e88e20f04dcf7a67f179e132179b054",
         []
        ],
        "beforematch-scroll-to-text-fragment-with-anchor.html": [
-        "3506c6e60caa4df1093af49c1008e44df13aaec7",
+        "efad439aa003fd8dcb05380e99a91b4e2d13e6db",
         []
        ],
        "container-ref.html": [
@@ -397854,7 +397858,7 @@
         []
        ],
        "hidden-until-found-text-fragment.html": [
-        "fe89b407e654a7b7abbb98dcf4edf1a3d8f64721",
+        "b765c07f27728c9d786eea9616cf3e71a681b7a2",
         []
        ],
        "spacer-and-container-ref.html": [
@@ -399470,7 +399474,7 @@
       ],
       "resources": {
        "auto-expand-details-text-fragment.html": [
-        "b95459fe5c03a91e0baa2ab8f4b1b0503a059e46",
+        "102e4aebd958c3bc8e9669551329054170d4aa2a",
         []
        ]
       },
@@ -409446,7 +409450,7 @@
     ]
    },
    "lint.ignore": [
-    "c8b98fb5890027a93dc73bf94023e26bdc4a7211",
+    "955e5df49077cab63e762988714e1319d551089d",
     []
    ],
    "loading": {
@@ -492722,7 +492726,7 @@
         ]
        ],
        "corner-shape-computed.html": [
-        "0f009f349bf55d289ab3a7549ea80ca164fa7a94",
+        "e1b458fd06eb512ccd12912ed96c464f8a29bf82",
         [
          null,
          {}
@@ -492736,7 +492740,7 @@
         ]
        ],
        "corner-shape-valid.html": [
-        "bf5de38af10ce5e2b91b2a2af1f1e78a366c9e31",
+        "0ad14c81a74425ce905ea5f1b560e737fbff6d08",
         [
          null,
          {}
@@ -573345,7 +573349,7 @@
       ]
      ],
      "heuristic.any.js": [
-      "d846131888288cb863308081eee9271caa108a09",
+      "2bec1aa4c6434513140ee6c342b3685f7be276c1",
       [
        "fetch/http-cache/heuristic.any.html",
        {
@@ -573869,7 +573873,7 @@
       ]
      ],
      "split-cache.html": [
-      "fe93d2e3400e9cba5390d0a3a0cae7ff64f4907f",
+      "c822abba3acee8db1079ad08dd7fbcbf38d9e3b9",
       [
        null,
        {}
@@ -594673,6 +594677,24 @@
        "testdriver": true
       }
      ]
+    ],
+    "watchposition-timeout.https.window.js": [
+     "fc1edd6ea95e9cbdfb20a20cb13fa05063d7c643",
+     [
+      "geolocation/watchposition-timeout.https.window.html",
+      {
+       "script_metadata": [
+        [
+         "script",
+         "/resources/testdriver.js"
+        ],
+        [
+         "script",
+         "/resources/testdriver-vendor.js"
+        ]
+       ]
+      }
+     ]
     ]
    },
    "geolocation-sensor": {
@@ -633582,7 +633604,7 @@
        ]
       ],
       "beforematch-scroll-to-text-fragment.html": [
-       "618493addeac829e672c4da5844ae03521704562",
+       "4ed4431464f79b7be3c354623efe031c6f2d657e",
        [
         null,
         {
@@ -633598,14 +633620,14 @@
        ]
       ],
       "hidden-ua-stylesheet.html": [
-       "913ecc037cfcd3ff4d0b1f41f210808f009d9ca4",
+       "0fde9ea753f14fd039082d4a28da67e6e8abb1f1",
        [
         null,
         {}
        ]
       ],
       "hidden-until-found-002.html": [
-       "e947274bedb89ad4cb162082f5e42c10e5365dad",
+       "0f3dcb1ffb2f3e5d48a5e3b6e0ca5923190e54ba",
        [
         null,
         {
@@ -636881,7 +636903,7 @@
      },
      "the-details-element": {
       "auto-expand-details-text-fragment.html": [
-       "7cc3cc22964a07a3448464bcc9ffaae8086397c8",
+       "b2416c942b633d04c84283aacb23adeca6da634b",
        [
         null,
         {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overflow/scroll-marker-activation-crash.html b/third_party/blink/web_tests/external/wpt/css/css-overflow/scroll-marker-activation-crash.html
new file mode 100644
index 0000000..1f2360a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-overflow/scroll-marker-activation-crash.html
@@ -0,0 +1,77 @@
+<!doctype html>
+<html class=test-wait>
+<meta charset="utf-8">
+<title>CSS Test: ::scroll-marker crash regression test</title>
+<link rel="help" href="https://drafts.csswg.org/css-overflow-5/#scroll-marker-activation">
+<script src="/dom/events/scrolling/scroll_support.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<style>
+  body {
+    margin: 0;
+  }
+
+  #marker-scroller {
+    height: 300px;
+    overflow: auto;
+    scroll-snap-type: x mandatory;
+    position: relative;
+    scroll-marker-group: before;
+    white-space: nowrap;
+  }
+
+  #marker-scroller div {
+    scroll-snap-align: start;
+    box-sizing: border-box;
+    border-radius: 5px;
+    background: lightgray;
+    border: 1px solid black;
+    display: inline-block;
+    width: 500px;
+    height: 100%;
+  }
+
+  #marker-scroller::scroll-marker-group {
+    display: flex;
+    height: 100px;
+  }
+
+  #marker-scroller div::scroll-marker {
+    content: "";
+    width: 100px;
+    height: 100px;
+    box-sizing: border-box;
+    border-radius: 5px;
+    border: 1px solid black;
+    display: inline-block;
+  }
+  #marker-scroller div::scroll-marker:target-current {
+    background: blue;
+  }
+</style>
+<fakeelement>
+  <div id="marker-scroller">
+    <div>1</div>
+    <div id="target">2</div>
+    <div>3</div>
+  </div>
+</fakeelement>
+<script>
+  async function crash() {
+    const target = document.querySelector('#target');
+    const scroller = document.querySelector('#marker-scroller');
+    const scrollEndPromise = waitForScrollEndFallbackToDelayWithoutScrollEvent(scroller);
+    /* Crash regression test for https://issues.chromium.org/407958134 */
+    actions_promise = new test_driver.Actions()
+      .pointerMove(150, 50)
+      .pointerDown()
+      .pointerUp()
+      .send();
+    await actions_promise;
+    await scrollEndPromise;
+    document.documentElement.classList.remove('test-wait');
+  };
+  crash();
+</script>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scoping/WEB_FEATURES.yml b/third_party/blink/web_tests/external/wpt/css/css-scoping/WEB_FEATURES.yml
new file mode 100644
index 0000000..88e56fe
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-scoping/WEB_FEATURES.yml
@@ -0,0 +1,4 @@
+features:
+- name: has-slotted
+  files:
+  - has-slotted-*
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scoping/has-slotted-001.html b/third_party/blink/web_tests/external/wpt/css/css-scoping/has-slotted-001.html
index e750d97a..4e3de3f 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-scoping/has-slotted-001.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-scoping/has-slotted-001.html
@@ -1,6 +1,5 @@
 <!doctype html>
 <meta charset="utf-8">
-<title>:has-slotted</title>
 <link rel="help" href="https://github.com/w3c/csswg-drafts/pull/10586">
 <link rel="match" href="/css/reference/ref-filled-green-100px-square-only.html">
 <p>Test passes if there is a filled green square.</p>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scoping/has-slotted-003.html b/third_party/blink/web_tests/external/wpt/css/css-scoping/has-slotted-003.html
index 7578413f..d13911e 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-scoping/has-slotted-003.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-scoping/has-slotted-003.html
@@ -1,6 +1,5 @@
 <!doctype html>
 <meta charset="utf-8">
-<title>:has-slotted</title>
 <link rel="help" href="https://github.com/w3c/csswg-drafts/pull/10586">
 <link rel="match" href="/css/reference/ref-filled-green-100px-square-only.html">
 <p>Test passes if there is a filled green square.</p>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scoping/slotted-has-001.html b/third_party/blink/web_tests/external/wpt/css/css-scoping/slotted-has-001.html
index f70bac7..dcb11ec3 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-scoping/slotted-has-001.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-scoping/slotted-has-001.html
@@ -1,6 +1,5 @@
 <!doctype html>
 <meta charset="utf-8">
-<title>:has-slotted</title>
 <link rel="help" href="https://github.com/w3c/csswg-drafts/pull/10586">
 <link rel="match" href="/css/reference/ref-filled-green-100px-square-only.html">
 <p>Test passes if there is a filled green square.</p>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scoping/slotted-has-002.html b/third_party/blink/web_tests/external/wpt/css/css-scoping/slotted-has-002.html
index 9ecbea5..5e709a9 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-scoping/slotted-has-002.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-scoping/slotted-has-002.html
@@ -1,6 +1,5 @@
 <!doctype html>
 <meta charset="utf-8">
-<title>:has-slotted</title>
 <link rel="help" href="https://github.com/w3c/csswg-drafts/pull/10586">
 <link rel="match" href="/css/reference/ref-filled-green-100px-square-only.html">
 <p>Test passes if there is a filled green square.</p>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scoping/slotted-has-003.html b/third_party/blink/web_tests/external/wpt/css/css-scoping/slotted-has-003.html
index 1ea41249..548f2c5d 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-scoping/slotted-has-003.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-scoping/slotted-has-003.html
@@ -1,6 +1,5 @@
 <!doctype html>
 <meta charset="utf-8">
-<title>:has-slotted</title>
 <link rel="help" href="https://github.com/w3c/csswg-drafts/pull/10586">
 <link rel="match" href="/css/reference/ref-filled-green-100px-square-only.html">
 <p>Test passes if there is a filled green square.</p>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scoping/slotted-has-004.html b/third_party/blink/web_tests/external/wpt/css/css-scoping/slotted-has-004.html
index adf50da..7e76b1b 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-scoping/slotted-has-004.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-scoping/slotted-has-004.html
@@ -1,6 +1,5 @@
 <!doctype html>
 <meta charset="utf-8">
-<title>:has-slotted</title>
 <link rel="help" href="https://github.com/w3c/csswg-drafts/pull/10586">
 <link rel="match" href="/css/reference/ref-filled-green-100px-square-only.html">
 <p>Test passes if there is a filled green square.</p>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/capture-with-offscreen-child-translated.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/capture-with-offscreen-child-translated.html
index 925bb8db..d7f4f2b1 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/capture-with-offscreen-child-translated.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/capture-with-offscreen-child-translated.html
@@ -30,6 +30,17 @@
   visibility: hidden;
   animation-duration: 500s;
 }
+
+::view-transtion-old(*) {
+  animation: unset;
+  opacity: 1;
+}
+
+::view-transtion-new(*) {
+  animation: unset;
+  opacity: 0;
+}
+
 ::view-transition {
   background: pink;
 }
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/capture-with-offscreen-child.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/capture-with-offscreen-child.html
index 7f8085ca..576c1a0 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/capture-with-offscreen-child.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/capture-with-offscreen-child.html
@@ -26,6 +26,22 @@
   visibility: hidden;
   animation-duration: 500s;
 }
+
+::view-transtion-group(*),
+::view-transtion-image-pair(*) {
+  animation-play-state: paused;
+}
+
+::view-transition-old(*) {
+  animation: unset;
+  opacity: 1;
+}
+
+::view-transition-new(*) {
+  animation: unset;
+  opacity: 0;
+}
+
 ::view-transition {
   background: pink;
 }
@@ -44,4 +60,5 @@
 }
 
 onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/capture-with-opacity-zero-child.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/capture-with-opacity-zero-child.html
index 2b0563e..78bd49f 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/capture-with-opacity-zero-child.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/capture-with-opacity-zero-child.html
@@ -24,6 +24,22 @@
   visibility: hidden;
   animation-duration: 500s;
 }
+
+::view-transtion-group(*),
+::view-transtion-image-pair(*) {
+  animation-play-state: paused;
+}
+
+::view-transition-old(*) {
+  animation: unset;
+  opacity: 1;
+}
+
+::view-transition-new(*) {
+  animation: unset;
+  opacity: 0;
+}
+
 ::view-transition {
   background: pink;
 }
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/capture-with-visibility-hidden-child.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/capture-with-visibility-hidden-child.html
index 2d17612..ba49933 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/capture-with-visibility-hidden-child.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/capture-with-visibility-hidden-child.html
@@ -23,6 +23,23 @@
   visibility: hidden;
   animation-duration: 500s;
 }
+
+::view-transtion-group(*),
+::view-transtion-image-pair(*) {
+  animation-play-state: paused;
+}
+
+::view-transition-old(*) {
+  animation: unset;
+  opacity: 1;
+}
+
+::view-transition-new(*) {
+  animation: unset;
+  opacity: 0;
+}
+
+
 ::view-transition {
   background: pink;
 }
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/capture-with-visibility-mixed-descendants.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/capture-with-visibility-mixed-descendants.html
index 3a4811ad..4577605 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/capture-with-visibility-mixed-descendants.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/capture-with-visibility-mixed-descendants.html
@@ -34,6 +34,22 @@
   visibility: hidden;
   animation-duration: 500s;
 }
+
+::view-transtion-group(*),
+::view-transtion-image-pair(*) {
+  animation-play-state: paused;
+}
+
+::view-transition-old(*) {
+  animation: unset;
+  opacity: 1;
+}
+
+::view-transition-new(*) {
+  animation: unset;
+  opacity: 0;
+}
+
 ::view-transition {
   background: pink;
 }
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-match-wildcard-no-star.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-match-wildcard-no-star.html
index 96186cd8..1231683 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-match-wildcard-no-star.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-match-wildcard-no-star.html
@@ -28,6 +28,17 @@
   ::view-transition-old(.cls) {
     left: 100px;
   }
+
+::view-transition-old(*) {
+  animation: unset;
+  opacity: 1;
+}
+
+::view-transition-new(*) {
+  animation: unset;
+  opacity: 0;
+}
+
 </style>
 <div id=target></div>
 
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-view-transition-image-pair.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-view-transition-image-pair.html
index 047374226..5cc971b9 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-view-transition-image-pair.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/pseudo-with-classes-view-transition-image-pair.html
@@ -23,8 +23,20 @@
 
 ::view-transition-image-pair(target.cls) {
   transform: translateX(100px);
+  animation-play-state: paused;
 }
 
+::view-transition-old(*) {
+  animation: unset;
+  opacity: 1;
+}
+
+::view-transition-new(*) {
+  animation: unset;
+  opacity: 0;
+}
+
+
 </style>
 <div id=target></div>
 
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/rotated-cat-off-top-edge.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/rotated-cat-off-top-edge.html
index f61b916c..3497936 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/rotated-cat-off-top-edge.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/rotated-cat-off-top-edge.html
@@ -16,7 +16,19 @@
 }
 ::view-transition-group(root) {
   animation-duration: 500s;
+  animation-play-state: paused;
 }
+
+::view-transition-old(*) {
+  animation: unset;
+  opacity: 1;
+}
+
+::view-transition-new(*) {
+  animation: unset;
+  opacity: 0;
+}
+
 </style>
 <body>
 <img class="target" src="support/cat.png">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/snapshot-containing-block-absolute.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/snapshot-containing-block-absolute.html
index 91b71f7..a8a03b62 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/snapshot-containing-block-absolute.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/snapshot-containing-block-absolute.html
@@ -35,6 +35,7 @@
 
 ::view-transition-group(target) {
   animation-duration: 50s;
+  animation-play-state: paused;
   top: unset;
   left: unset;
   right: 0px;
@@ -50,6 +51,16 @@
   background-color: limegreen;
 }
 
+::view-transition-old(*) {
+  animation: unset;
+  opacity: 1;
+}
+
+::view-transition-new(*) {
+  animation: unset;
+  opacity: 0;
+}
+
 </style>
 
 <div id="target">TARGET</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/update-callback-called-once.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/update-callback-called-once.html
index c84368c9..cd27df6 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/update-callback-called-once.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/update-callback-called-once.html
@@ -11,6 +11,13 @@
         height: 100px;
         background-color: red;
     }
+
+    ::view-transition-group(*),
+    ::view-transition-image-pair(*),
+    ::view-transition-old(*),
+    ::view-transition-new(*) {
+      animation-play-state: paused;
+    }
 </style>
 <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
 <div id="target"></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/parsing/WEB_FEATURES.yml b/third_party/blink/web_tests/external/wpt/css/selectors/parsing/WEB_FEATURES.yml
index f3453b2..ab1fe19 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/parsing/WEB_FEATURES.yml
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/parsing/WEB_FEATURES.yml
@@ -9,3 +9,6 @@
 - name: state
   files:
   - parse-state.html
+- name: has-slotted
+  files:
+  - parse-has-slotted.tentative.html
diff --git a/third_party/blink/web_tests/external/wpt/fetch/http-cache/heuristic.any.js b/third_party/blink/web_tests/external/wpt/fetch/http-cache/heuristic.any.js
index d846131..2bec1aa 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/http-cache/heuristic.any.js
+++ b/third_party/blink/web_tests/external/wpt/fetch/http-cache/heuristic.any.js
@@ -32,10 +32,33 @@
         ],
       },
       {
-        expected_type: "not_cached"
+        expected_type: "not_cached",
       }
     ]
-  }
+  },
+  {
+    name: "HTTP cache does not reuse a redirected response with no max-age and no Last-Modified header",
+    requests: [
+      {
+        response_status: [301, "Moved Permanently"],
+        response_headers: [
+          ["Cache-Control", "private"],
+          ["Location", "redirect_target"]
+        ],
+      },
+      { skip: true}, // Response to first redirect
+      {
+        response_status: [301, "Moved Permanently"],
+        response_headers: [
+          ["Cache-Control", "private"],
+          ["Location", "redirect_target"]
+        ],
+        expected_type: "not_cached",
+      },
+      { skip: true}, // response to second redirect
+    ],
+    check_count: true,
+  },
 ];
 
 function check_status(status) {
diff --git a/third_party/blink/web_tests/external/wpt/fetch/http-cache/http-cache.js b/third_party/blink/web_tests/external/wpt/fetch/http-cache/http-cache.js
index 19f1ca9..0ca5fcc 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/http-cache/http-cache.js
+++ b/third_party/blink/web_tests/external/wpt/fetch/http-cache/http-cache.js
@@ -43,17 +43,25 @@
     var uuid = token()
     var requests = expandTemplates(test)
     var fetchFunctions = makeFetchFunctions(requests, uuid)
-    return runTest(fetchFunctions, requests, uuid)
+    return runTest(fetchFunctions, test, requests, uuid)
   }
 }
 
 function makeFetchFunctions(requests, uuid) {
     var fetchFunctions = []
     for (let i = 0; i < requests.length; ++i) {
+      var config = requests[i];
+      if (config.skip) {
+        // Skip request are ones that we expect the browser to make in
+        // response to a redirect. We don't fetch them again, but
+        // the server needs them in the config to be able to respond to
+        // them.
+        continue;
+      }
       fetchFunctions.push({
         code: function (idx) {
           var config = requests[idx]
-          var url = makeTestUrl(uuid, config)
+          var url = makeTestUrl(uuid, config);
           var init = fetchInit(requests, config)
           return fetch(url, init)
             .then(makeCheckResponse(idx, config))
@@ -71,7 +79,7 @@
     return fetchFunctions
 }
 
-function runTest(fetchFunctions, requests, uuid) {
+function runTest(fetchFunctions, test, requests, uuid) {
     var idx = 0
     function runNextStep () {
       if (fetchFunctions.length) {
@@ -93,7 +101,7 @@
       .then(function () {
         return getServerState(uuid)
       }).then(function (testState) {
-        checkRequests(requests, testState)
+        checkRequests(test, requests, testState)
         return Promise.resolve()
       })
 }
@@ -153,7 +161,7 @@
     if ('expected_status' in config) {
       assert_equals(response.status, config.expected_status,
         `Response ${reqNum} status is ${response.status}, not ${config.expected_status}`)
-    } else if ('response_status' in config) {
+    } else if ('response_status' in config && config.response_status[0] != 301) {
       assert_equals(response.status, config.response_status[0],
         `Response ${reqNum} status is ${response.status}, not ${config.response_status[0]}`)
     } else {
@@ -197,7 +205,7 @@
   }
 }
 
-function checkRequests (requests, testState) {
+function checkRequests (test, requests, testState) {
   var testIdx = 0
   for (let i = 0; i < requests.length; ++i) {
     var expectedValidatingHeaders = []
@@ -225,6 +233,9 @@
       })
     }
   }
+  if (test?.check_count && testState) {
+    assert_equals(requests.length, testState.length);
+  }
 }
 
 function pause () {
diff --git a/third_party/blink/web_tests/external/wpt/fetch/http-cache/split-cache.html b/third_party/blink/web_tests/external/wpt/fetch/http-cache/split-cache.html
index fe93d2e..c822abba 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/http-cache/split-cache.html
+++ b/third_party/blink/web_tests/external/wpt/fetch/http-cache/split-cache.html
@@ -128,7 +128,7 @@
   function check_server_info() {
     return getServerState(uuid)
       .then(function (testState) {
-        checkRequests(local_requests, testState)
+        checkRequests(undefined, local_requests, testState)
         return Promise.resolve()
       })
   }
diff --git a/third_party/blink/web_tests/external/wpt/geolocation/watchposition-timeout.https.window.js b/third_party/blink/web_tests/external/wpt/geolocation/watchposition-timeout.https.window.js
new file mode 100644
index 0000000..fc1edd6e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/geolocation/watchposition-timeout.https.window.js
@@ -0,0 +1,22 @@
+// META: script=/resources/testdriver.js
+// META: script=/resources/testdriver-vendor.js
+
+promise_setup(async () => {
+  await test_driver.set_permission({ name: "geolocation" }, "granted");
+});
+
+promise_test(async (t) => {
+  let timeoutCount = 0;
+
+  // This may still succeed without timeout in case there's a cache.
+  const watchId = navigator.geolocation.watchPosition(() => {}, (error) => {
+    if (error.code === GeolocationPositionError.TIMEOUT) {
+      ++timeoutCount;
+    }
+  }, { timeout: 1 });
+  t.add_cleanup(() => navigator.geolocation.clearWatch(watchId));
+
+  await new Promise(r => setTimeout(r, 100));
+
+  assert_true(timeoutCount < 2, "At most one timeout should have been seen");
+}, "Passing timeout=1 should not cause multiple timeout errors");
diff --git a/third_party/blink/web_tests/external/wpt/html/editing/the-hidden-attribute/beforematch-scroll-to-text-fragment.html b/third_party/blink/web_tests/external/wpt/html/editing/the-hidden-attribute/beforematch-scroll-to-text-fragment.html
index 618493add..4ed4431 100644
--- a/third_party/blink/web_tests/external/wpt/html/editing/the-hidden-attribute/beforematch-scroll-to-text-fragment.html
+++ b/third_party/blink/web_tests/external/wpt/html/editing/the-hidden-attribute/beforematch-scroll-to-text-fragment.html
@@ -36,7 +36,7 @@
   const key = token();
   test_driver.bless('Open a scroll to text fragment URL', () => {
     window.open(
-      `resources/beforematch-scroll-to-text-fragment-with-anchor.html?key=${key}#:~:text=foo`,
+      `resources/beforematch-scroll-to-text-fragment-with-anchor.html?key=${key}#bar:~:text=foo`,
       '_blank',
       'noopener');
   });
diff --git a/third_party/blink/web_tests/external/wpt/html/editing/the-hidden-attribute/hidden-ua-stylesheet.html b/third_party/blink/web_tests/external/wpt/html/editing/the-hidden-attribute/hidden-ua-stylesheet.html
index 913ecc0..0fde9ea7 100644
--- a/third_party/blink/web_tests/external/wpt/html/editing/the-hidden-attribute/hidden-ua-stylesheet.html
+++ b/third_party/blink/web_tests/external/wpt/html/editing/the-hidden-attribute/hidden-ua-stylesheet.html
@@ -28,7 +28,10 @@
         `${description} should not affect the div's display property.`);
     assert_equals(getComputedStyle(div).contentVisibility, 'hidden',
         `${description} should make the div content-visibility:hidden.`);
+    assert_equals(div.hidden, "until-found",
+      `${description} should make the div hidden=until-found.`);
   }, description);
+
 }
 
 function testNormal(description) {
diff --git a/third_party/blink/web_tests/external/wpt/html/editing/the-hidden-attribute/hidden-until-found-002.html b/third_party/blink/web_tests/external/wpt/html/editing/the-hidden-attribute/hidden-until-found-002.html
index e947274..0f3dcb1 100644
--- a/third_party/blink/web_tests/external/wpt/html/editing/the-hidden-attribute/hidden-until-found-002.html
+++ b/third_party/blink/web_tests/external/wpt/html/editing/the-hidden-attribute/hidden-until-found-002.html
@@ -21,7 +21,7 @@
 
 <script>
 async_test((t) => {
-  const tab = "\t";
+  const tab = "\ue004";
   async function step1() {
     await test_driver.send_keys(document.body, tab);
     t.step(() => {
diff --git a/third_party/blink/web_tests/external/wpt/html/editing/the-hidden-attribute/resources/beforematch-scroll-to-text-fragment-basic.html b/third_party/blink/web_tests/external/wpt/html/editing/the-hidden-attribute/resources/beforematch-scroll-to-text-fragment-basic.html
index 884e9a6..4166f9b1 100644
--- a/third_party/blink/web_tests/external/wpt/html/editing/the-hidden-attribute/resources/beforematch-scroll-to-text-fragment-basic.html
+++ b/third_party/blink/web_tests/external/wpt/html/editing/the-hidden-attribute/resources/beforematch-scroll-to-text-fragment-basic.html
@@ -7,41 +7,47 @@
   <div style="height: 4000px;">spacer</div>
   <script>
     const results = {};
+    results.beforematchFiredOnFoo = false;
+    results.beforematchFiredOnBar = false;
 
+    params = new URLSearchParams(window.location.search);
+
+    // This test adds the elements from JS
+    // (unlike beforematch-scroll-to-text-fragment-with-anchor.html,
+    // which uses parser-created elements)
     const foo = document.createElement('div');
     foo.textContent = 'foo';
     foo.hidden = 'until-found';
     document.body.appendChild(foo);
-    window.beforematchFiredOnFoo = false;
-    foo.addEventListener('beforematch', () => {
-      // This should be zero. Scrolling should happen after beforematch is
-      // fired.
-      results.pageYOffsetDuringBeforematch = window.pageYOffset;
-      window.beforematchFiredOnFoo = true;
-    });
-
     const bar = document.createElement('div');
     bar.textContent = 'bar';
     document.body.appendChild(bar);
-    window.beforematchFiredOnBar = false;
+
     bar.addEventListener('beforematch', () => {
-      window.beforematchFiredOnBar = true;
+      // this handler should never run. If it does,
+      // send back the message immediately to make the test fail.
+      results.beforematchFiredOnBar = true;
+      params = new URLSearchParams(window.location.search);
+      stashResultsThenClose(params.get('key'), results);
     });
 
-    requestAnimationFrame(() => {
-      requestAnimationFrame(async () => {
-        // This should be true. Foo was searched for, so it should get a
-        // beforematch event.
-        results.beforematchFiredOnFoo = window.beforematchFiredOnFoo;
-        // This should be false. Bar was not searched for, so it should not get
-        // a beforematch event.
-        results.beforematchFiredOnBar = window.beforematchFiredOnBar;
-        // This should be greater than zero. The page should be scrolled down
-        // to foo.
-        results.pageYOffsetAfterRaf = window.pageYOffset;
+    foo.addEventListener('beforematch', () => {
+      if (results.beforematchFiredOnBar) {
+        return;
+      }
+      // This should be zero. Scrolling should happen after beforematch is
+      // fired.
+      results.pageYOffsetDuringBeforematch = window.pageYOffset;
+      results.beforematchFiredOnFoo = true;
 
-        params = new URLSearchParams(window.location.search);
-        stashResultsThenClose(params.get('key'), results);
+      requestAnimationFrame(() => {
+        requestAnimationFrame(() => {
+          // This should be greater than zero. The page should be scrolled down
+          // to foo.
+          results.pageYOffsetAfterRaf = window.pageYOffset;
+
+          stashResultsThenClose(params.get('key'), results);
+        });
       });
     });
   </script>
diff --git a/third_party/blink/web_tests/external/wpt/html/editing/the-hidden-attribute/resources/beforematch-scroll-to-text-fragment-bubble.html b/third_party/blink/web_tests/external/wpt/html/editing/the-hidden-attribute/resources/beforematch-scroll-to-text-fragment-bubble.html
index abfe8ddd..d9cae3c 100644
--- a/third_party/blink/web_tests/external/wpt/html/editing/the-hidden-attribute/resources/beforematch-scroll-to-text-fragment-bubble.html
+++ b/third_party/blink/web_tests/external/wpt/html/editing/the-hidden-attribute/resources/beforematch-scroll-to-text-fragment-bubble.html
@@ -19,12 +19,12 @@
 
   parentid.addEventListener('beforematch', () => {
     results.beforematchFiredOnParent = true;
-  });
-
-  requestAnimationFrame(() => {
     requestAnimationFrame(() => {
-      const params = new URLSearchParams(window.location.search);
-      stashResultsThenClose(params.get('key'), results);
+      requestAnimationFrame(() => {
+        const params = new URLSearchParams(window.location.search);
+        stashResultsThenClose(params.get('key'), results);
+      });
     });
   });
+
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/html/editing/the-hidden-attribute/resources/beforematch-scroll-to-text-fragment-with-anchor.html b/third_party/blink/web_tests/external/wpt/html/editing/the-hidden-attribute/resources/beforematch-scroll-to-text-fragment-with-anchor.html
index 3506c6e..efad439 100644
--- a/third_party/blink/web_tests/external/wpt/html/editing/the-hidden-attribute/resources/beforematch-scroll-to-text-fragment-with-anchor.html
+++ b/third_party/blink/web_tests/external/wpt/html/editing/the-hidden-attribute/resources/beforematch-scroll-to-text-fragment-with-anchor.html
@@ -4,32 +4,42 @@
 <!-- This test is navigated to with the fragment #bar:~:text=foo -->
 
 <body>
+  <!--This test uses parser-created elements,
+  unlike beforematch-scroll-to-text-fragment-basic.html, which adds them from JS -->
   <div id=foo hidden=until-found>foo</div>
   <div id=bar hidden=until-found>bar</div>
   <script>
-    window.beforematchFiredOnFoo = false;
-    foo.addEventListener('beforematch', () => {
-      window.beforematchFiredOnFoo = true;
-    });
+    const results = {};
+    results.beforematchFiredOnFoo = false;
+    results.beforematchFiredOnBar = false;
 
-    window.beforematchFiredOnBar = false;
+    params = new URLSearchParams(window.location.search);
+
     bar.addEventListener('beforematch', () => {
-      window.beforematchFiredOnBar = true;
+      // this handler should never run. If it does,
+      // send back the message immediately to make the test fail.
+      results.beforematchFiredOnBar = true;
+      params = new URLSearchParams(window.location.search);
+      stashResultsThenClose(params.get('key'), results);
     });
 
-    requestAnimationFrame(() => {
-      requestAnimationFrame(() => {
-        const results = {};
-        // This should be true. Foo was searched for, so it should get the
-        // beforematch event.
-        results.beforematchFiredOnFoo = window.beforematchFiredOnFoo;
-        // This should be false. Bar should not get the beforematch event
-        // despite being the target of an element fragment due to the text
-        // fragment.
-        results.beforematchFiredOnBar = window.beforematchFiredOnBar;
+    foo.addEventListener('beforematch', () => {
+      if (results.beforematchFiredOnBar) {
+        return;
+      }
+      // This should be zero. Scrolling should happen after beforematch is
+      // fired.
+      results.pageYOffsetDuringBeforematch = window.pageYOffset;
+      results.beforematchFiredOnFoo = true;
 
-        params = new URLSearchParams(window.location.search);
-        stashResultsThenClose(params.get('key'), results);
+      requestAnimationFrame(() => {
+        requestAnimationFrame(() => {
+          // This should be greater than zero. The page should be scrolled down
+          // to foo.
+          results.pageYOffsetAfterRaf = window.pageYOffset;
+
+          stashResultsThenClose(params.get('key'), results);
+        });
       });
     });
   </script>
diff --git a/third_party/blink/web_tests/external/wpt/html/editing/the-hidden-attribute/resources/hidden-until-found-text-fragment.html b/third_party/blink/web_tests/external/wpt/html/editing/the-hidden-attribute/resources/hidden-until-found-text-fragment.html
index fe89b40..b765c07 100644
--- a/third_party/blink/web_tests/external/wpt/html/editing/the-hidden-attribute/resources/hidden-until-found-text-fragment.html
+++ b/third_party/blink/web_tests/external/wpt/html/editing/the-hidden-attribute/resources/hidden-until-found-text-fragment.html
@@ -7,19 +7,28 @@
   <div style="height: 4000px;">spacer</div>
   <div id=target hidden=until-found>foo</div>
   <script>
-    requestAnimationFrame(() => {
+    // scroll-to-text-fragment may delay scrolling for an
+    // arbitrary amount of time for security reasons.
+    // This test would time out if beforematch is not fired, but since the
+    // test file only has one test, this is not shadowing other test results.
+    target.onbeforematch = () => {
+      // Adding two additional requestAnimationFrames ensures
+      // that scrolling has happened after beforematch has fired.
       requestAnimationFrame(() => {
-        const results = {};
-        // This should be false. The hidden=until-found attribute should be
-        // removed in response to ScrollToTextFragment.
-        results.targetHasHiddenAttribute = document.getElementById('target').hasAttribute('hidden');
-        // This should be greater than zero. The page should be scrolled down
-        // to foo.
-        results.pageYOffsetAfterRaf = window.pageYOffset;
+        requestAnimationFrame(() => {
+          const results = {};
+          // This should be false. The hidden=until-found attribute should be
+          // removed in response to ScrollToTextFragment.
+          results.targetHasHiddenAttribute = document.getElementById('target').hasAttribute('hidden');
+          // This should be greater than zero. The page should be scrolled down
+          // to foo.
+          results.pageYOffsetAfterRaf = window.pageYOffset;
 
-        params = new URLSearchParams(window.location.search);
-        stashResultsThenClose(params.get('key'), results);
+          params = new URLSearchParams(window.location.search);
+          stashResultsThenClose(params.get('key'), results);
+
+        });
       });
-    });
+    };
   </script>
 </body>
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/the-details-element/auto-expand-details-text-fragment.html b/third_party/blink/web_tests/external/wpt/html/rendering/the-details-element/auto-expand-details-text-fragment.html
index 7cc3cc2..b2416c9 100644
--- a/third_party/blink/web_tests/external/wpt/html/rendering/the-details-element/auto-expand-details-text-fragment.html
+++ b/third_party/blink/web_tests/external/wpt/html/rendering/the-details-element/auto-expand-details-text-fragment.html
@@ -26,5 +26,5 @@
     'The matching closed details element should be open.');
   assert_true(results.pageYOffsetAfterRaf > 0,
     'The page should be scrolled down to the match.');
-}), 'Verifies that the beforematch event is fired on the matching element of a ScrollToTextFragment navigation.');
+}), 'Verifies that the target page has scrolled as a result of a ScrollToTextFragment navigation.');
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/the-details-element/resources/auto-expand-details-text-fragment.html b/third_party/blink/web_tests/external/wpt/html/rendering/the-details-element/resources/auto-expand-details-text-fragment.html
index b95459f..102e4ae 100644
--- a/third_party/blink/web_tests/external/wpt/html/rendering/the-details-element/resources/auto-expand-details-text-fragment.html
+++ b/third_party/blink/web_tests/external/wpt/html/rendering/the-details-element/resources/auto-expand-details-text-fragment.html
@@ -9,19 +9,18 @@
     <div>foo</div>
   </details>
   <script>
-    requestAnimationFrame(() => {
-      requestAnimationFrame(() => {
-        const results = {};
-        // This should be true. The details element should be opened by
-        // ScrollToTextFragment because it has matching text.
-        results.detailsHasOpenAttribute = document.querySelector('details').hasAttribute('open');
-        // This should be greater than zero. The page should be scrolled down
-        // to the matching target.
-        results.pageYOffsetAfterRaf = window.pageYOffset;
+    const details = document.querySelector("details");
+    details.ontoggle = () => {
+      const results = {};
+      // This should be true. The details element should be opened by
+      // ScrollToTextFragment because it has matching text.
+      results.detailsHasOpenAttribute = document.querySelector('details').hasAttribute('open');
+      // This should be greater than zero. The page should be scrolled down
+      // to the matching target.
+      results.pageYOffsetAfterRaf = window.pageYOffset;
 
-        params = new URLSearchParams(window.location.search);
-        stashResultsThenClose(params.get('key'), results);
-      });
-    });
+      params = new URLSearchParams(window.location.search);
+      stashResultsThenClose(params.get('key'), results);
+    };
   </script>
 </body>
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/widgets/the-select-element/option-add-label-quirks.html b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/the-select-element/option-add-label-quirks.html
index 2c3c809..f91609a 100644
--- a/third_party/blink/web_tests/external/wpt/html/rendering/widgets/the-select-element/option-add-label-quirks.html
+++ b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/the-select-element/option-add-label-quirks.html
@@ -2,7 +2,7 @@
 <title>OPTION's label attribute in SELECT -- Adding a label (quirks)</title>
 <link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#the-select-element-2">
 <link rel="match" href="option-label-ref.html">
-<meta name="assert" content="An option element is expected to be rendered by displaying the element's label.">
+<meta name="assert" content="An option element is expected to be rendered by displaying the element's label when the document is in quirks mode">
 
 <select>
   <option>Element Text</option>
diff --git a/third_party/blink/web_tests/external/wpt/lint.ignore b/third_party/blink/web_tests/external/wpt/lint.ignore
index c8b98fb..955e5df 100644
--- a/third_party/blink/web_tests/external/wpt/lint.ignore
+++ b/third_party/blink/web_tests/external/wpt/lint.ignore
@@ -393,6 +393,7 @@
 SET TIMEOUT: css/css-view-transitions/no-painting-while-render-blocked.html
 SET TIMEOUT: document-policy/font-display/override-to-optional.tentative.html
 SET TIMEOUT: feature-policy/experimental-features/resources/focus-without-user-activation-iframe-tentative.html
+SET TIMEOUT: geolocation/watchposition-timeout.https.window.js
 SET TIMEOUT: permissions-policy/experimental-features/resources/focus-without-user-activation-iframe-tentative.html
 SET TIMEOUT: html/browsers/windows/auxiliary-browsing-contexts/resources/close-opener.html
 SET TIMEOUT: html/cross-origin-embedder-policy/resources/reporting-worker.js
diff --git a/third_party/blink/web_tests/http/tests/devtools/sxg/sxg-cert-not-found-expected.txt b/third_party/blink/web_tests/http/tests/devtools/sxg/sxg-cert-not-found-expected.txt
index 08090cd..72c8517 100644
--- a/third_party/blink/web_tests/http/tests/devtools/sxg/sxg-cert-not-found-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/sxg/sxg-cert-not-found-expected.txt
@@ -1,7 +1,7 @@
 Tests the signed exchange information are available when the certificate file is not available.
 
-inspected-page.html:1 Invalid reponse code: 404
-inspected-page.html:1 Failed to fetch the certificate.
+about:blank:1 Invalid reponse code: 404
+about:blank:1 Failed to fetch the certificate.
 * http://127.0.0.1:8000/loading/sxg/resources/sxg-cert-not-found.sxg
   failed: false
   statusCode: 200
diff --git a/third_party/blink/web_tests/http/tests/devtools/sxg/sxg-navigation-fail-expected.txt b/third_party/blink/web_tests/http/tests/devtools/sxg/sxg-navigation-fail-expected.txt
index 3b091f5b..6f0cf825 100644
--- a/third_party/blink/web_tests/http/tests/devtools/sxg/sxg-navigation-fail-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/sxg/sxg-navigation-fail-expected.txt
@@ -1,7 +1,7 @@
 Tests the signed exchange information are available when the navigation failed.
 
-inspected-page.html:1 Validity URL must be same-origin with request URL.
-inspected-page.html:1 Failed to parse SignedExchange header.
+about:blank:1 Validity URL must be same-origin with request URL.
+about:blank:1 Failed to parse SignedExchange header.
 * http://127.0.0.1:8000/loading/sxg/resources/sxg-invalid-validity-url.sxg
   failed: false
   statusCode: 200
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/target/hidden-target-create-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/target/hidden-target-create-expected.txt
index 6093efe..4d3e860c 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/target/hidden-target-create-expected.txt
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/target/hidden-target-create-expected.txt
@@ -35,6 +35,12 @@
         targetId : <string 0>
     }
 }
+TargetDestroyed{
+    method : Target.targetDestroyed
+    params : {
+        targetId : <string 0>
+    }
+}
 Expected error response: {
     code : -32001
     message : Session with given id not found.
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/target/hidden-target-create.js b/third_party/blink/web_tests/http/tests/inspector-protocol/target/hidden-target-create.js
index 11c5c84..6691f7020 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/target/hidden-target-create.js
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/target/hidden-target-create.js
@@ -21,6 +21,9 @@
   testRunner.browserP().Target.onDetachedFromTarget((event) => {
     testRunnerLog(event, 'DetachedFromTarget');
   });
+  testRunner.browserP().Target.onTargetDestroyed((event) => {
+    testRunnerLog(event, 'TargetDestroyed');
+  });
   /**
    * Filter out the targets that are already present in the existing targets set
    * keeping only the new targets. If the result is an error, return the error.
@@ -68,7 +71,9 @@
       `Filtered targets via browser session: `);
 
   testRunnerLog('Disconnect the parent session');
-  await newBrowserSession.disconnect();
+  newBrowserSession.disconnect();
+
+  await testRunner.browserP().Target.onceTargetDestroyed();
 
   // Verify the hidden target's session is closed.
   testRunnerLog(
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/inspector-protocol/layout-fonts/languages-emoji-rare-glyphs-expected.txt b/third_party/blink/web_tests/platform/mac-mac15-arm64/inspector-protocol/layout-fonts/languages-emoji-rare-glyphs-expected.txt
new file mode 100644
index 0000000..dbc7b9a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac15-arm64/inspector-protocol/layout-fonts/languages-emoji-rare-glyphs-expected.txt
@@ -0,0 +1,60 @@
+百家姓 趙錢孫李 周吳鄭王 馮陳褚衛 蔣沈韓楊 朱秦尤許 何呂施張 孔曹嚴華 金魏陶薑 戚謝鄒喻 柏水竇章 雲蘇潘葛 奚範彭郎 魯韋昌馬 苗鳳花方 俞任袁柳 酆鮑史唐 費廉岑薛 雷賀倪湯 滕殷羅畢 郝鄔安常 樂於時傅 皮卞齊康 伍餘元蔔 顧孟平黃 和穆蕭尹 姚邵堪汪 祁毛禹狄 米貝明臧 計伏成戴 談宋茅龐 熊紀舒屈 項祝董梁 杜阮藍閔 席季麻強 賈路婁危 江童顏郭 梅盛林刁 鍾徐邱駱 高夏蔡田 樊胡淩霍 虞萬支柯 昝管盧莫 經房裘繆 幹解應宗 丁宣賁鄧 鬱單杭洪 包諸左石 崔吉鈕龔 程嵇邢滑 裴陸榮翁 荀羊於惠 甄曲家封 芮羿儲靳 汲邴糜松 井段富巫 烏焦巴弓 牧隗山穀 車侯宓蓬 全郗班仰 秋仲伊宮 寧仇欒暴 甘鈄厲戎 祖武符劉 景詹束龍 葉幸司韶 郜黎薊薄 印宿白懷 蒲台從鄂 索鹹籍賴 卓藺屠蒙 池喬陰鬱 胥能蒼雙 聞莘黨翟 譚貢勞逄 姬申扶堵 冉宰酈雍 卻璩桑桂 濮牛壽通 邊扈燕冀 郟浦尚農 溫別莊晏 柴瞿閻充 慕連茹習 宦艾魚容 向古易慎 戈廖庚終 暨居衡步 都耿滿弘 匡國文寇 廣祿闕東 毆殳沃利 蔚越夔隆 師鞏厙聶 晁勾敖融 冷訾辛闞 那簡饒空 曾毋沙乜 養鞠須豐 巢關蒯相 查後荊紅 遊竺權逯 蓋益桓公 萬俟司馬 上官歐陽 夏侯諸葛 聞人東方 赫連皇甫 尉遲公羊 澹台公冶 宗政濮陽 淳於單於 太叔申屠 公孫仲孫 軒轅令狐 鐘離宇文 長孫慕容 鮮於閭丘 司徒司空 亓官司寇 仉督子車 顓孫端木 巫馬公西 漆雕樂正 壤駟公良 拓拔夾穀 宰父穀粱 晉楚閆法 汝鄢塗欽 段幹百里 東郭南門 呼延歸海 羊舌微生 嶽帥緱亢 況後有琴 梁丘左丘 東門西門 商牟佘佴 伯賞南宮 墨哈譙笪 年愛陽佟
+#hundred_chinese_surnames:
+"Songti SC" : 563,
+"Times" : 140
+
+いろはにほへと ちりぬるを わかよたれそ つねならむ うゐのおくやま けふこえて あさき ゆめみし ゑひもせす(ん)色は匂へど 散りぬるを 我が世誰ぞ 常ならむ 有為の奥山 今日越えて 浅き夢見じ 酔ひもせず(ん)
+#japanese_iroha:
+"Songti SC" : 92,
+"Times" : 15
+
+키스의 고유조건은 입술끼리 만나야 하고 특별한 기술은 필요치 않다.
+#korean_pangram:
+"AppleMyungjo" : 28,
+"Times" : 9
+
+ऋषियों को सताने वाले दुष्ट राक्षसों के राजा रावण का सर्वनाश करने वाले विष्णुवतार भगवान श्रीराम, अयोध्या के महाराज दशरथ के बड़े सपुत्र थे।
+#hindi_pangram:
+"ITF Devanagari" : 97,
+"Times" : 24
+
+نصٌّ حكيمٌ لهُ سِرٌّ قاطِعٌ وَذُو شَأنٍ عَظيمٍ مكتوبٌ على ثوبٍ أخضرَ ومُغلفٌ بجلدٍ أزرق
+#arabic_pangram:
+"Geeza Pro" : 71,
+"Times" : 14
+
+🌱🌲🌳🌴🌵🌷🌸🌹🌺🌻🌼💐🌾🌿🍀🍁🍂🍃🍄🌰☺️😀👪♐☔☃️™️
+#emoji_emoji:
+"Apple Color Emoji" : 27
+
+☔︎♐︎☺☺︎☃☃︎☯︎☯™™︎00︎
+#text_emoji:
+"Times" : 4,
+"Apple Symbols" : 2,
+"AppleMyungjo" : 2,
+"Hiragino Mincho ProN" : 2,
+"Times New Roman" : 2
+
+𓀀𓀁𓀂𓀃𓀄𓀅𓀆𓀇𓀈𓀉𓀊𓀋𓀌𓀍𓀎𓀏
+#egyptian_hieroglyphs:
+"Noto Sans EgyptHiero" : 16
+
+ខ្ញុំអាចញុំកញ្ចក់បាន ដោយគ្មានបញ្ហារ
+#khmer:
+"Khmer MN" : 26,
+"Times" : 1
+
+𐌲𐌿𐍄𐌹𐍃𐌺
+#gothic:
+"Noto Sans Gothic" : 6
+
+ܐܬܘܪܝܐ
+#syriac:
+"Noto Sans Syriac" : 6
+
+⇦⇧⇨⇩←↑→↓⟀
+#text_presentation_arrows_maths:
+"Apple Symbols" : 5,
+"Hiragino Mincho ProN" : 4
+
+
diff --git a/third_party/boringssl/src b/third_party/boringssl/src
index f0ab911..a553a9d 160000
--- a/third_party/boringssl/src
+++ b/third_party/boringssl/src
@@ -1 +1 @@
-Subproject commit f0ab91129d1a234dc127335765b794d62dc9ed4d
+Subproject commit a553a9d65aa4e4f28a6c3007db14e9605e7c3bde
diff --git a/third_party/catapult b/third_party/catapult
index 7236fd6..6e0dcdc 160000
--- a/third_party/catapult
+++ b/third_party/catapult
@@ -1 +1 @@
-Subproject commit 7236fd6c03b5c8f0e31e37207419cfdbe7bfee98
+Subproject commit 6e0dcdccb316673a6a9d498d32e6b9a61e8672d5
diff --git a/third_party/crashpad/README.chromium b/third_party/crashpad/README.chromium
index 29637a44..fb0eb49 100644
--- a/third_party/crashpad/README.chromium
+++ b/third_party/crashpad/README.chromium
@@ -59,5 +59,3 @@
    "base/allocator/partition_allocator/src/partition_alloc/partition_alloc_buildflags.h",
    https://crbug.com/1467773
  - CPEPrefix for third_party/zlib is added to README.chromium
- - logging::LogMessageHandler signature updated to use std::string_view in
-   crashpad/util/thread/thread_log_messages.cc
diff --git a/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader_fuzzer.cc b/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader_fuzzer.cc
index 1d80b6b..3a5b16c 100644
--- a/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader_fuzzer.cc
+++ b/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader_fuzzer.cc
@@ -12,8 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include <string_view>
-
 #include <inttypes.h>
 
 #include "base/logging.h"
@@ -47,11 +45,10 @@
 
 extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
   // Swallow all logs to avoid spam.
-  logging::SetLogMessageHandler([](logging::LogSeverity,
-                                   std::string_view,
-                                   int,
-                                   size_t,
-                                   const std::string&) { return true; });
+  logging::SetLogMessageHandler(
+      [](logging::LogSeverity, const char*, int, size_t, const std::string&) {
+        return true;
+      });
   return 0;
 }
 
diff --git a/third_party/crashpad/crashpad/util/thread/thread_log_messages.cc b/third_party/crashpad/crashpad/util/thread/thread_log_messages.cc
index 4581c9aa..efc6e2e 100644
--- a/third_party/crashpad/crashpad/util/thread/thread_log_messages.cc
+++ b/third_party/crashpad/crashpad/util/thread/thread_log_messages.cc
@@ -16,8 +16,6 @@
 
 #include <sys/types.h>
 
-#include <string_view>
-
 #include "base/check_op.h"
 #include "base/logging.h"
 
@@ -28,7 +26,7 @@
 thread_local std::vector<std::string>* thread_local_log_messages;
 
 bool LogMessageHandler(logging::LogSeverity severity,
-                       std::string_view file_path,
+                       const char* file_path,
                        int line,
                        size_t message_start,
                        const std::string& string) {
diff --git a/third_party/dawn b/third_party/dawn
index 5e44eb5..39a35b8 160000
--- a/third_party/dawn
+++ b/third_party/dawn
@@ -1 +1 @@
-Subproject commit 5e44eb524fb6b341029180bb21de431de5717f98
+Subproject commit 39a35b8b9dc4b135e30a31f596c5f5d42a4ede30
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src
index 51544a7..488f39a 160000
--- a/third_party/devtools-frontend/src
+++ b/third_party/devtools-frontend/src
@@ -1 +1 @@
-Subproject commit 51544a715444d283fd99d4eb4dc1137a1939ee16
+Subproject commit 488f39ac7c36ee7f982335b16807a0c4472cc0bc
diff --git a/third_party/ipcz/.gn b/third_party/ipcz/.gn
index a231c16..87c2998 100644
--- a/third_party/ipcz/.gn
+++ b/third_party/ipcz/.gn
@@ -7,7 +7,7 @@
 # for python3.exe and python3.bat.
 script_executable = "python3"
 
-exec_script_whitelist = build_dotfile_settings.exec_script_whitelist
+exec_script_allowlist = build_dotfile_settings.exec_script_allowlist
 
 default_args = {
   clang_use_chrome_plugins = false
diff --git a/third_party/perfetto b/third_party/perfetto
index 29152c0..ca27004 160000
--- a/third_party/perfetto
+++ b/third_party/perfetto
@@ -1 +1 @@
-Subproject commit 29152c058571b61ef71d266c422cd5f5eb4bf83f
+Subproject commit ca270042d1485933a6a7246c874b3c4ef561ad0d
diff --git a/third_party/rust/OWNERS b/third_party/rust/OWNERS
index 930998c4..bf183d4d 100644
--- a/third_party/rust/OWNERS
+++ b/third_party/rust/OWNERS
@@ -1,7 +1,26 @@
-collinbaker@chromium.org
-dcheng@chromium.org
-djmitche@chromium.org
-liza@chromium.org
-lukasza@chromium.org
-palmer@chromium.org
-phao@chromium.org
+# How to assign reviews
+# =====================
+#
+# Consider assigning reviews to chrome-third-party-rust-reviews@google.com,
+# rather than to a specific reviewer. This helps distribute review load and
+# knowledge more evenly amongst the team. Automation will select a random
+# reviewer and reassign the review within ~5 minutes. Googlers can read more
+# about this at go/gwsq-gerrit.
+chrome-third-party-rust-reviews@google.com
+
+# Actual list of reviewers
+# ========================
+#
+# The find-owners plugin does not support groups, so the actual `unsafe` Rust
+# reviewers are listed below but tagged with {LAST_RESORT_SUGGESTION} so that
+# Gerrit will preferentially suggest the gwsq review alias above.
+#
+# Please keep this list alphabetized and in sync with the gwsq config (see
+# `chromium_gwsq/third-party-rust/config.gwsq`).
+collinbaker@chromium.org     #{LAST_RESORT_SUGGESTION}
+dcheng@chromium.org          #{LAST_RESORT_SUGGESTION}
+djmitche@chromium.org        #{LAST_RESORT_SUGGESTION}
+liza@chromium.org            #{LAST_RESORT_SUGGESTION}
+lukasza@chromium.org         #{LAST_RESORT_SUGGESTION}
+palmer@chromium.org          #{LAST_RESORT_SUGGESTION}
+phao@chromium.org            #{LAST_RESORT_SUGGESTION}
diff --git a/third_party/skia b/third_party/skia
index f91412f5..05f7251 160000
--- a/third_party/skia
+++ b/third_party/skia
@@ -1 +1 @@
-Subproject commit f91412f5d89d85fe2ea6b9e5ea30d04f112d2d53
+Subproject commit 05f7251290b1d43eb5c89370a80846b87e9de916
diff --git a/third_party/spirv-tools/src b/third_party/spirv-tools/src
index 6add4e4..4bd1536 160000
--- a/third_party/spirv-tools/src
+++ b/third_party/spirv-tools/src
@@ -1 +1 @@
-Subproject commit 6add4e478f8802d3bbd100120e5ffc6f725ec9fe
+Subproject commit 4bd1536ed79003a5194a4bd8c9aa2fa17a84c15b
diff --git a/third_party/vulkan-deps b/third_party/vulkan-deps
index 897477b..75036a1 160000
--- a/third_party/vulkan-deps
+++ b/third_party/vulkan-deps
@@ -1 +1 @@
-Subproject commit 897477bba57341592bfd3d6ba0c6901c31c44f27
+Subproject commit 75036a1b874d6269a50daba6146fbd020feadcaf
diff --git a/third_party/vulkan-validation-layers/src b/third_party/vulkan-validation-layers/src
index 1ec32dc..2cfc63f 160000
--- a/third_party/vulkan-validation-layers/src
+++ b/third_party/vulkan-validation-layers/src
@@ -1 +1 @@
-Subproject commit 1ec32dc68665bcaad2e933696f6d9bccd52173a7
+Subproject commit 2cfc63fcf5670a284c73fe91fe4de42d4c0e20a9
diff --git a/third_party/webrtc_overrides/BUILD.gn b/third_party/webrtc_overrides/BUILD.gn
index 139cd623..2be0bcb 100644
--- a/third_party/webrtc_overrides/BUILD.gn
+++ b/third_party/webrtc_overrides/BUILD.gn
@@ -304,6 +304,16 @@
   ]
 }
 
+source_set("logging_test") {
+  testonly = true
+  sources = [ "test/logging_test.cc" ]
+  deps = [
+    ":webrtc_component",
+    "//base/test:test_support",
+    "//testing/gtest:gtest",
+  ]
+}
+
 source_set("metronome_like_task_queue_test") {
   configs += webrtc_configs
   public_configs = webrtc_public_configs
diff --git a/third_party/webrtc_overrides/rtc_base/diagnostic_logging.h b/third_party/webrtc_overrides/rtc_base/diagnostic_logging.h
index a9d2c31..4bbe562 100644
--- a/third_party/webrtc_overrides/rtc_base/diagnostic_logging.h
+++ b/third_party/webrtc_overrides/rtc_base/diagnostic_logging.h
@@ -67,10 +67,10 @@
  public:
   template <typename T>
   ABSL_ATTRIBUTE_NOINLINE DiagnosticLogMessage& operator<<(const T& v) {
-    if constexpr (absl::HasOstreamOperator<T>::value) {
-      print_stream_ << v;
-    } else if constexpr (absl::HasAbslStringify<T>::value) {
+    if constexpr (absl::HasAbslStringify<T>::value) {
       print_stream_ << absl::StrCat(v);
+    } else if constexpr (absl::HasOstreamOperator<T>::value) {
+      print_stream_ << v;
     } else {
       static_assert(false, "Unsupported type to log");
     }
diff --git a/third_party/webrtc_overrides/rtc_base/logging.cc b/third_party/webrtc_overrides/rtc_base/logging.cc
index 264778f..4907b1e 100644
--- a/third_party/webrtc_overrides/rtc_base/logging.cc
+++ b/third_party/webrtc_overrides/rtc_base/logging.cc
@@ -20,7 +20,6 @@
 #endif  // OS_MACOSX
 
 #include <iomanip>
-#include <string_view>
 
 #include "base/logging.h"
 #include "base/notreached.h"
@@ -238,7 +237,7 @@
                          const char* file,
                          size_t N) {
   return WebRtcVerbosityLevel(severity) <=
-         ::logging::GetVlogLevelHelper(std::string_view(file, N - 1));
+         ::logging::GetVlogLevelHelper(file, N);
 }
 
 }  // namespace webrtc
diff --git a/third_party/webrtc_overrides/test/logging_test.cc b/third_party/webrtc_overrides/test/logging_test.cc
new file mode 100644
index 0000000..6ead798a
--- /dev/null
+++ b/third_party/webrtc_overrides/test/logging_test.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 "third_party/webrtc_overrides/rtc_base/logging.h"
+
+#include <cstdint>
+#include <ostream>
+
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/webrtc_overrides/rtc_base/diagnostic_logging.h"
+
+namespace webrtc {
+namespace {
+
+std::optional<std::string> g_last_log_message;
+
+void DoLog(const std::string& message) {
+  g_last_log_message = message;
+}
+
+class LoggingTest : public ::testing::Test {
+ public:
+  void SetUp() override {
+    g_last_log_message.reset();
+    InitDiagnosticLoggingDelegateFunction(&DoLog);
+  }
+};
+
+TEST_F(LoggingTest, LogMessage) {
+  RTC_LOG(LS_INFO) << "Hello World";
+  EXPECT_EQ(g_last_log_message, "Hello World");
+}
+
+struct TestStructWithOstream {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-function"
+  friend std::ostream& operator<<(std::ostream& os, TestStructWithOstream) {
+    os << "TestStructWithOstream";
+    return os;
+  }
+#pragma clang diagnostic pop
+};
+
+TEST_F(LoggingTest, LogMessageUsesOstreamOperator) {
+  TestStructWithOstream s;
+  RTC_LOG(LS_INFO) << s;
+  EXPECT_EQ(g_last_log_message, "TestStructWithOstream");
+}
+
+struct TestStruct {
+  template <typename Sink>
+  friend void AbslStringify(Sink& sink, const TestStruct& s) {
+    sink.Append("TestStruct");
+  }
+};
+
+TEST_F(LoggingTest, LogMessageUsesAbslStringify) {
+  TestStruct s;
+  RTC_LOG(LS_INFO) << s;
+  EXPECT_EQ(g_last_log_message, "TestStruct");
+}
+
+enum class TestEnum : uint8_t {
+  kFoo = 1,
+};
+
+template <typename Sink>
+void AbslStringify(Sink& sink, TestEnum e) {
+  sink.Append("Foo");
+}
+
+TEST_F(LoggingTest, UsesAbslStringifyOnTrivialConvertibleEnums) {
+  RTC_LOG(LS_INFO) << TestEnum::kFoo;
+  EXPECT_EQ(g_last_log_message, "Foo");
+}
+
+}  // namespace
+}  // namespace webrtc
diff --git a/tools/accessibility/inspect/ax_dump_events.cc b/tools/accessibility/inspect/ax_dump_events.cc
index e7b90644..89c92a35 100644
--- a/tools/accessibility/inspect/ax_dump_events.cc
+++ b/tools/accessibility/inspect/ax_dump_events.cc
@@ -5,7 +5,6 @@
 #include <iostream>
 #include <memory>
 #include <string>
-#include <string_view>
 
 #include "base/at_exit.h"
 #include "base/command_line.h"
@@ -25,7 +24,7 @@
 constexpr char kHelpSwitch[] = "help";
 
 bool AXDumpEventsLogMessageHandler(int severity,
-                                   std::string_view file,
+                                   const char* file,
                                    int line,
                                    size_t message_start,
                                    const std::string& str) {
diff --git a/tools/accessibility/inspect/ax_dump_tree.cc b/tools/accessibility/inspect/ax_dump_tree.cc
index 103e30a..c0d9d655 100644
--- a/tools/accessibility/inspect/ax_dump_tree.cc
+++ b/tools/accessibility/inspect/ax_dump_tree.cc
@@ -6,7 +6,6 @@
 #include <iostream>
 #include <numeric>
 #include <string>
-#include <string_view>
 
 #include "base/at_exit.h"
 #include "base/command_line.h"
@@ -23,7 +22,7 @@
 constexpr char kHelpSwitch[] = "help";
 
 bool AXDumpTreeLogMessageHandler(int severity,
-                                 std::string_view file,
+                                 const char* file,
                                  int line,
                                  size_t message_start,
                                  const std::string& str) {
diff --git a/tools/crates/gnrt/lib/deps.rs b/tools/crates/gnrt/lib/deps.rs
index 45126aa0..3aee182 100644
--- a/tools/crates/gnrt/lib/deps.rs
+++ b/tools/crates/gnrt/lib/deps.rs
@@ -9,6 +9,7 @@
     crates,
     gn::{target_spec_to_condition, Condition},
     group::Group,
+    inherit::find_inherited_privilege_group,
 };
 
 use anyhow::{bail, Context, Result};
@@ -259,6 +260,13 @@
         .collect::<HashSet<_>>();
     let feature_set = cargo_set.target_features().union(cargo_set.host_features());
     let package_set = feature_set.to_package_set();
+    let root_id = cargo_set
+        .initials()
+        .to_package_set()
+        .root_ids(DependencyDirection::Forward)
+        .exactly_one()
+        .map_err(|_| ())
+        .expect("`resolve_root_package_set` should have verified `exactly_one` root");
 
     // Translate the packages into an internal `gnrt` representation.
     let is_toplevel_dep = |package: &PackageMetadata| -> bool {
@@ -291,8 +299,7 @@
 
             let BuildTargets { lib_target, bin_targets, build_script } =
                 get_build_targets(&package, extra_config).with_context(err_context)?;
-            let group = get_privilege_group(&package, extra_config, is_toplevel_dep)
-                .with_context(err_context)?;
+            let group = find_inherited_privilege_group(package.id(), root_id, graph, extra_config);
 
             Ok(Package {
                 package_name: package.name().to_string(),
@@ -563,110 +570,6 @@
     }
 }
 
-fn get_privilege_group(
-    package: &PackageMetadata,
-    extra_config: &BuildConfig,
-    is_toplevel_dep: impl Fn(&PackageMetadata) -> bool,
-) -> Result<Group> {
-    // If the dependency is a top-level dep of Chromium, then it defaults to this
-    // privilege level.
-    // TODO: Default should be sandbox??
-    const DEFAULT_FOR_TOPLEVEL: Group = Group::Safe;
-
-    let package_name = package.name();
-    let get_group_from_config = |package: &PackageMetadata| -> Option<Group> {
-        extra_config.per_crate_config.get(package.name())?.group
-    };
-
-    // If `package` transitively depends on `Test` `descendant1` and `Safe`
-    // `descendant2`, then it is okay if `package` is just `Test` (but it can't
-    // be higher).  So `**max**_from_descendants = ...descendant-groups...
-    // **min**_by_key`.
-    //
-    // TODO(lukasza): Performance improvement opportunity.  Recomputing
-    // descendants / ancestors information for every `package` is simple and
-    // works, but is also inefficient.  If needed we should try caching this
-    // information somehow.
-    let max_from_descendants = package
-        .graph()
-        .query_forward([package.id()])?
-        .resolve()
-        .packages(DependencyDirection::Forward)
-        .filter_map(|p| get_group_from_config(&p).map(|group| (p.name(), group)))
-        .min_by_key(|(_package_name, group)| *group);
-
-    // If `Test` `ancestor1` and `Safe` `ancestor2` transitively depend on
-    // `package`, then package needs to be `Safe` or better (max of `Test` and
-    // `Safe`).  So `**min**_from_ancestors = ...ancestor-groups...
-    // **max**_by_key`.
-    let min_from_ancestors =
-        package
-            .graph()
-            .query_reverse([package.id()])?
-            .resolve()
-            .packages(DependencyDirection::Reverse)
-            .filter_map(|package| {
-                get_group_from_config(&package)
-                    .or_else(|| {
-                        if is_toplevel_dep(&package) {
-                            Some(DEFAULT_FOR_TOPLEVEL)
-                        } else {
-                            None
-                        }
-                    })
-                    .map(|group| (package.name(), group))
-            })
-            .max_by_key(|(_package_name, group)| *group);
-
-    let configured_group = get_group_from_config(package);
-    match configured_group {
-        None => match (min_from_ancestors, max_from_descendants) {
-            (None, None) => {
-                assert!(is_toplevel_dep(package));
-                Ok(DEFAULT_FOR_TOPLEVEL)
-            }
-            (Some((_, min_from_ancestors)), None) => Ok(min_from_ancestors),
-            (None, Some((_, max_from_descendants))) => Ok(max_from_descendants),
-            (
-                Some((ancestor_example, min_from_ancestors)),
-                Some((descendant_example, max_from_descendants)),
-            ) => {
-                if min_from_ancestors > max_from_descendants {
-                    bail!(
-                        "`{descendant_example}` is configured as `{max_from_descendants}`; \
-                         `{ancestor_example}` is configured as `{min_from_ancestors}`; \
-                         `{min_from_ancestors}` cannot transitively \
-                         depend on `max_from_descendants`."
-                    );
-                }
-                Ok(min_from_ancestors)
-            }
-        },
-        Some(configured_group) => {
-            if let Some((ancestor_example, min_from_ancestors)) = min_from_ancestors {
-                if min_from_ancestors > configured_group {
-                    bail!(
-                        "`{package_name}` is configured as `{configured_group}`; \
-                         `{ancestor_example}` is configured as `{min_from_ancestors}`; \
-                         `{min_from_ancestors}` cannot transitively depend on `configured`."
-                    );
-                }
-            }
-            if let Some((descendant_example, max_from_descendants)) = max_from_descendants {
-                if max_from_descendants < configured_group {
-                    bail!(
-                        "`{package_name}` is configured as `{configured_group}`; \
-                         `{descendant_example}` is configured as `{max_from_descendants}`; \
-                         `{configured_group}` cannot transitively \
-                         depend on `max_from_descendants`."
-                    );
-                }
-            }
-            Ok(configured_group)
-        }
-    }
-}
-
 #[cfg(test)]
 mod tests {
     use crate::config::CrateConfig;
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 5747311..43e97eeb 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -24254,6 +24254,15 @@
   <description>User pressed 'New Window' in the app menu.</description>
 </action>
 
+<action name="MobileMenuNtpCustomization">
+  <owner>hanxi@chromium.org</owner>
+  <owner>yanlinghu@google.com</owner>
+  <owner>clank-start@google.com</owner>
+  <description>
+    User pressed 'Customize new tab page' in the app menu.
+  </description>
+</action>
+
 <action name="MobileMenuOpenTabs">
   <obsolete>This action was renamed to MobileMenuRecentTabs.</obsolete>
   <owner>aurimas@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/new_tab_page/enums.xml b/tools/metrics/histograms/metadata/new_tab_page/enums.xml
index 04ecac30..94cd4ad 100644
--- a/tools/metrics/histograms/metadata/new_tab_page/enums.xml
+++ b/tools/metrics/histograms/metadata/new_tab_page/enums.xml
@@ -31,6 +31,19 @@
   <int value="1" label="HTTP cache hit"/>
 </enum>
 
+<enum name="BottomSheetType">
+  <summary/>
+  <int value="0" label="Main Bottom Sheet"/>
+  <int value="1" label="New Tab Page Cards Bottom Sheet"/>
+  <int value="2" label="Discover Feed Bottom Sheet"/>
+</enum>
+
+<enum name="Entry">
+  <summary/>
+  <int value="0" label="App Menu"/>
+  <int value="1" label="Customization button in toolbar"/>
+</enum>
+
 <enum name="FailToShowHomeSurfaceReason">
   <int value="0" label="Fail to create a NTP Tab"/>
   <int value="1" label="Fail to find a NTP Tab"/>
diff --git a/tools/metrics/histograms/metadata/new_tab_page/histograms.xml b/tools/metrics/histograms/metadata/new_tab_page/histograms.xml
index cfdd1faf..4e20b46c 100644
--- a/tools/metrics/histograms/metadata/new_tab_page/histograms.xml
+++ b/tools/metrics/histograms/metadata/new_tab_page/histograms.xml
@@ -34,6 +34,11 @@
   <variant name=".RecentTabs" summary="Recent (offline) tabs"/>
 </variants>
 
+<variants name="ModuleToggleState">
+  <variant name="TurnOffModule"/>
+  <variant name="TurnOnModule"/>
+</variants>
+
 <variants name="NewTabPage_BackgroundService_RequestLatency">
   <variant name=".Failure"
       summary="Failed to fetch data from background service"/>
@@ -318,6 +323,48 @@
   </token>
 </histogram>
 
+<histogram name="NewTabPage.Customization.BottomSheet.Shown"
+    enum="BottomSheetType" expires_after="2025-08-31">
+  <owner>hanxi@chromium.org</owner>
+  <owner>yanlinghu@google.com</owner>
+  <owner>clank-start@google.com</owner>
+  <summary>
+    Android: Records the type of bottom sheet each time the customization bottom
+    sheet is shown. The histogram is logged when the user opens a NTP
+    customization bottom sheet, regardless of whether the bottom sheet has been
+    opened before.
+  </summary>
+</histogram>
+
+<histogram name="NewTabPage.Customization.OpenBottomSheetEntry" enum="Entry"
+    expires_after="2025-08-31">
+  <owner>hanxi@chromium.org</owner>
+  <owner>xinyiji@chromium.org</owner>
+  <owner>yanlinghu@google.com</owner>
+  <owner>clank-start@google.com</owner>
+  <summary>
+    Android: Records the number of times the initial NTP customization bottom
+    sheet is opened by the user, categorized by the specific source of the
+    opening action. This initial bottom sheet is the entry point to the NTP
+    customization flow. The histogram is logged in response to user clicking on
+    the main menu or on the toolbar to open the initial NTP customization bottom
+    sheet.
+  </summary>
+</histogram>
+
+<histogram name="NewTabPage.Customization.{ModuleToggleState}"
+    enum="ModuleType" expires_after="2025-08-31">
+  <owner>hanxi@chromium.org</owner>
+  <owner>yanlinghu@google.com</owner>
+  <owner>clank-start@google.com</owner>
+  <summary>
+    Android: Records when a module is activated or deactivated in the NTP Cards
+    bottom sheet. The histogram is logged in response to a user clicking on the
+    toggle switch on the NTP Cards bottom sheet. Each press of the toggle switch
+    is counted as a separate count.
+  </summary>
+</histogram>
+
 <histogram name="NewTabPage.CustomizeChromeBackgroundAction"
     enum="NTPCustomizeChromeBackgroundAction" expires_after="2025-05-31">
   <owner>pauladedeji@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/page/histograms.xml b/tools/metrics/histograms/metadata/page/histograms.xml
index 82ba172..f2a74b9 100644
--- a/tools/metrics/histograms/metadata/page/histograms.xml
+++ b/tools/metrics/histograms/metadata/page/histograms.xml
@@ -2081,7 +2081,7 @@
 
 <histogram
     name="PageLoad.Clients.PerformanceManager.LCPToLoadedIdle{LoadedIdleVisibility}"
-    units="ms" expires_after="2025-08-24">
+    units="ms" expires_after="2025-09-28">
   <owner>joenotcharles@google.com</owner>
   <owner>catan-team@chromium.org</owner>
   <summary>
@@ -2130,6 +2130,39 @@
 </histogram>
 
 <histogram
+    name="PageLoad.Clients.PerformanceManager.NavigationToLoadedIdle{LoadedIdleVisibility}"
+    units="ms" expires_after="2025-09-28">
+  <owner>joenotcharles@google.com</owner>
+  <owner>catan-team@chromium.org</owner>
+  <summary>
+    Recorded for each navigation when its PerformanceManager loading state
+    reaches PageNode::LoadingState::kLoadedIdle, with the time since navigation
+    start. If a navigation is abandoned without ever reaching kLoadedIdle,
+    PageLoad.Clients.PerformanceManager.NavigationWithoutLoadedIdle is recorded
+    instead. This version of the metric is recorded for navigations in
+    {LoadedIdleVisibility}.
+  </summary>
+  <token key="LoadedIdleVisibility" variants="LoadedIdleVisibility"/>
+</histogram>
+
+<histogram
+    name="PageLoad.Clients.PerformanceManager.NavigationWithoutLoadedIdle{LoadedIdleVisibility}"
+    units="ms" expires_after="2025-09-28">
+  <owner>joenotcharles@google.com</owner>
+  <owner>catan-team@chromium.org</owner>
+  <summary>
+    Recorded for each navigation that's abandoned without its PerformanceManager
+    loading state reaching PageNode::LoadingState::kLoadedIdle, such as by the
+    page closing or a new navigation starting. The value is the time from
+    navigation start to the time it's abandoned. If the navigation reaches
+    kLoadedIdle, PageLoad.Clients.PerformanceManager.NavigateToLoadedIdle is
+    recorded instead. This version of the metric is recorded for navigations in
+    {LoadedIdleVisibility}.
+  </summary>
+  <token key="LoadedIdleVisibility" variants="LoadedIdleVisibility"/>
+</histogram>
+
+<histogram
     name="PageLoad.Clients.Prerender.InteractiveTiming.FirstInputDelay4{PreloadingTriggerType}"
     units="ms" expires_after="2025-09-14">
   <owner>nhiroki@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/permissions/histograms.xml b/tools/metrics/histograms/metadata/permissions/histograms.xml
index a9ca0b4..9a3b3bc 100644
--- a/tools/metrics/histograms/metadata/permissions/histograms.xml
+++ b/tools/metrics/histograms/metadata/permissions/histograms.xml
@@ -219,7 +219,7 @@
 </variants>
 
 <histogram name="BrowserDialogs.ExternalProtocol.BlockState"
-    enum="BlockStateMetric" expires_after="2025-04-27">
+    enum="BlockStateMetric" expires_after="2026-04-27">
   <owner>rsesek@chromium.org</owner>
   <owner>src/components/permissions/PERMISSIONS_OWNERS</owner>
   <summary>
@@ -522,7 +522,7 @@
 </histogram>
 
 <histogram name="Permissions.AutoBlocker.EmbargoStatus"
-    enum="PermissionEmbargoStatus" expires_after="2025-04-27">
+    enum="PermissionEmbargoStatus" expires_after="2026-04-27">
   <owner>engedy@chromium.org</owner>
   <owner>src/components/permissions/PERMISSIONS_OWNERS</owner>
   <summary>
@@ -1593,7 +1593,7 @@
 </histogram>
 
 <histogram name="Permissions.Request.CrossOrigin" enum="PermissionType"
-    expires_after="2025-04-13">
+    expires_after="2026-04-13">
   <owner>elklm@chromium.org</owner>
   <owner>src/components/permissions/PERMISSIONS_OWNERS</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/privacy/histograms.xml b/tools/metrics/histograms/metadata/privacy/histograms.xml
index fc93b53..ba10426 100644
--- a/tools/metrics/histograms/metadata/privacy/histograms.xml
+++ b/tools/metrics/histograms/metadata/privacy/histograms.xml
@@ -1560,6 +1560,26 @@
   <token key="PSNoticeAction" variants="PSNoticeAction"/>
 </histogram>
 
+<histogram name="PrivacySandbox.Notice.NotHoldingHandle.InQueue" units="counts"
+    expires_after="2026-03-28">
+  <owner>aashnas@google.com</owner>
+  <owner>koilos@google.com</owner>
+  <summary>
+    Records the number of times a notice that tries to show is not holding the
+    handle, because it is waiting in the queue.
+  </summary>
+</histogram>
+
+<histogram name="PrivacySandbox.Notice.NotHoldingHandle.NotInQueue"
+    units="counts" expires_after="2026-03-28">
+  <owner>aashnas@google.com</owner>
+  <owner>koilos@google.com</owner>
+  <summary>
+    Records the number of times a notice that tries to show is not holding the
+    handle, because it is not queued.
+  </summary>
+</histogram>
+
 <!-- DO NOT USE. To be deprecated soon, use PrivacySandbox.Notice.NoticeEvent.{PSNotice} instead. -->
 
 <histogram name="PrivacySandbox.Notice.NoticeAction.{PSNotice}"
diff --git a/tools/metrics/histograms/metadata/signin/enums.xml b/tools/metrics/histograms/metadata/signin/enums.xml
index 5aa9b14..b0f55df7 100644
--- a/tools/metrics/histograms/metadata/signin/enums.xml
+++ b/tools/metrics/histograms/metadata/signin/enums.xml
@@ -690,6 +690,7 @@
   <int value="74" label="Glic launch button"/>
   <int value="75" label="History page (Android only)"/>
   <int value="76" label="Join collaboration tab group authentication"/>
+  <int value="77" label="History Sync Opt-in Expanded Pill"/>
 </enum>
 
 <enum name="SigninAccountReconcilorState">
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index 8cfe87de..3841f1241 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -16458,6 +16458,18 @@
       Bucketed into exponential intervals with a standard bucket_spacing of 2.0.
     </summary>
   </metric>
+  <metric name="ZeroPrefixSearchShown" enum="Boolean">
+    <summary>
+      Whether at least one zero-prefix Search suggestion was shown in the
+      Omnibox session.
+    </summary>
+  </metric>
+  <metric name="ZeroPrefixUrlShown" enum="Boolean">
+    <summary>
+      Whether at least one zero-prefix URL suggestion was shown in the Omnibox
+      session.
+    </summary>
+  </metric>
 </event>
 
 <event name="OmniboxSecurityIndicator.FormSubmission">
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml
index 4f9dcf52..31a93cf5 100644
--- a/tools/traffic_annotation/summary/annotations.xml
+++ b/tools/traffic_annotation/summary/annotations.xml
@@ -131,7 +131,7 @@
  <item id="omaha_client_android_uc" added_in_milestone="99" content_hash_code="0757ca45" os_list="android" file_path="chrome/android/java/src/org/chromium/chrome/browser/omaha/OmahaBase.java" />
  <item id="omnibox_documentsuggest" added_in_milestone="69" content_hash_code="07917541" os_list="linux,windows,chromeos,android" file_path="components/omnibox/browser/document_suggestions_service.cc" />
  <item id="omnibox_navigation_observer" added_in_milestone="62" content_hash_code="043a7a2f" os_list="linux,windows,chromeos" file_path="chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer.cc" />
- <item id="omnibox_result_change" added_in_milestone="62" content_hash_code="017a7557" os_list="linux,windows,chromeos,android" file_path="chrome/browser/bitmap_fetcher/bitmap_fetcher_service.cc" />
+ <item id="omnibox_result_change" added_in_milestone="62" content_hash_code="00bbc4fe" os_list="linux,windows,chromeos,android" file_path="chrome/browser/bitmap_fetcher/bitmap_fetcher_service.cc" />
  <item id="omnibox_suggest" added_in_milestone="62" content_hash_code="0524cc7e" os_list="linux,windows,chromeos,android" file_path="components/omnibox/browser/remote_suggestions_service.cc" />
  <item id="omnibox_suggest_deletion" added_in_milestone="62" content_hash_code="017d302e" os_list="linux,windows,chromeos,android" file_path="components/omnibox/browser/remote_suggestions_service.cc" />
  <item id="omnibox_zerosuggest" added_in_milestone="62" content_hash_code="071e32e9" os_list="linux,windows,chromeos,android" file_path="components/omnibox/browser/remote_suggestions_service.cc" />
diff --git a/ui/android/BUILD.gn b/ui/android/BUILD.gn
index f54426bd..27aace1e 100644
--- a/ui/android/BUILD.gn
+++ b/ui/android/BUILD.gn
@@ -834,6 +834,7 @@
   resources_package = "org.chromium.ui"
 
   sources = [
+    "java/src/org/chromium/ui/UiUtilsTest.java",
     "java/src/org/chromium/ui/listmenu/ListMenuButtonTest.java",
     "java/src/org/chromium/ui/widget/TextViewWithTightWrapTest.java",
     "javatests/src/org/chromium/ui/animation/RenderTestAnimationUtils.java",
diff --git a/ui/android/java/src/org/chromium/ui/UiUtils.java b/ui/android/java/src/org/chromium/ui/UiUtils.java
index 9c82d75..014e0d8 100644
--- a/ui/android/java/src/org/chromium/ui/UiUtils.java
+++ b/ui/android/java/src/org/chromium/ui/UiUtils.java
@@ -20,7 +20,10 @@
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.StrictMode;
+import android.text.Spanned;
 import android.text.TextUtils;
+import android.text.method.LinkMovementMethod;
+import android.text.style.ClickableSpan;
 import android.view.SurfaceView;
 import android.view.View;
 import android.view.View.MeasureSpec;
@@ -33,11 +36,13 @@
 import android.view.inputmethod.InputMethodSubtype;
 import android.widget.AbsListView;
 import android.widget.ListAdapter;
+import android.widget.TextView;
 
 import androidx.annotation.ColorInt;
 import androidx.annotation.ColorRes;
 import androidx.annotation.DimenRes;
 import androidx.annotation.DrawableRes;
+import androidx.annotation.NonNull;
 import androidx.annotation.StyleableRes;
 import androidx.appcompat.content.res.AppCompatResources;
 import androidx.core.graphics.Insets;
@@ -506,4 +511,23 @@
 
         return new BitmapDrawable(context.getResources(), bitmap);
     }
+
+    /**
+     * Set a link movement method if the {@code textView} text contains at least one {@link
+     * ClickableSpan}.
+     *
+     * @param textView The TextView which might set a link movement method.
+     */
+    public static void maybeSetLinkMovementMethod(@NonNull TextView textView) {
+        CharSequence text = textView.getText();
+        if (TextUtils.isEmpty(text)) return;
+        if (text instanceof Spanned spanned) {
+            for (Object o : spanned.getSpans(0, text.length(), Object.class)) {
+                if (o instanceof ClickableSpan) {
+                    textView.setMovementMethod(LinkMovementMethod.getInstance());
+                    return;
+                }
+            }
+        }
+    }
 }
diff --git a/ui/android/java/src/org/chromium/ui/UiUtilsTest.java b/ui/android/java/src/org/chromium/ui/UiUtilsTest.java
new file mode 100644
index 0000000..d47350b
--- /dev/null
+++ b/ui/android/java/src/org/chromium/ui/UiUtilsTest.java
@@ -0,0 +1,66 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.ui;
+
+import android.content.Context;
+import android.widget.TextView;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.test.BaseActivityTestRule;
+import org.chromium.base.test.BaseJUnit4ClassRunner;
+import org.chromium.base.test.util.Batch;
+import org.chromium.ui.test.util.BlankUiTestActivity;
+import org.chromium.ui.text.ChromeClickableSpan;
+import org.chromium.ui.text.SpanApplier;
+
+/** Unit tests for {@link UiUtils}. */
+@RunWith(BaseJUnit4ClassRunner.class)
+@Batch(Batch.UNIT_TESTS)
+public class UiUtilsTest {
+    @ClassRule
+    public static BaseActivityTestRule<BlankUiTestActivity> activityTestRule =
+            new BaseActivityTestRule<>(BlankUiTestActivity.class);
+
+    private Context mContext;
+
+    @Before
+    public void setUp() {
+        mContext = ApplicationProvider.getApplicationContext();
+    }
+
+    /** Test the method {@link UiUtils#maybeSetLinkMovementMethod(TextView)}. */
+    @Test
+    @SmallTest
+    public void testMaybeSetLinkMovementMethod() {
+        TextView textView = new TextView(mContext);
+
+        UiUtils.maybeSetLinkMovementMethod(textView);
+        Assert.assertNull("No movement method if no text", textView.getMovementMethod());
+
+        textView.setText("test");
+        UiUtils.maybeSetLinkMovementMethod(textView);
+        Assert.assertNull("No movement method if no clickable span", textView.getMovementMethod());
+
+        textView.setText(
+                SpanApplier.applySpans(
+                        "test <link> link </link>",
+                        new SpanApplier.SpanInfo(
+                                "<link>",
+                                "</link>",
+                                new ChromeClickableSpan(mContext, (v) -> {}))));
+        UiUtils.maybeSetLinkMovementMethod(textView);
+        Assert.assertNotNull(
+                "Set movement method if a clickable span is included",
+                textView.getMovementMethod());
+    }
+}
diff --git a/ui/base/clipboard/BUILD.gn b/ui/base/clipboard/BUILD.gn
index 9d28e68..0bbbe28 100644
--- a/ui/base/clipboard/BUILD.gn
+++ b/ui/base/clipboard/BUILD.gn
@@ -15,7 +15,6 @@
   output_name = "ui_base_clipboard_types"
   sources = [
     "clipboard_buffer.h",
-    "clipboard_constants.cc",
     "clipboard_constants.h",
   ]
 
diff --git a/ui/base/clipboard/clipboard_android.cc b/ui/base/clipboard/clipboard_android.cc
index 7ced7adaa..4b292d1 100644
--- a/ui/base/clipboard/clipboard_android.cc
+++ b/ui/base/clipboard/clipboard_android.cc
@@ -544,26 +544,31 @@
   std::vector<std::u16string> types;
   // would be nice to ask the ClipboardMap to enumerate the types it supports,
   // rather than hardcode the list here.
-  if (IsFormatAvailable(ClipboardFormatType::PlainTextType(), buffer, data_dst))
-    types.push_back(base::UTF8ToUTF16(kMimeTypePlainText));
-  if (IsFormatAvailable(ClipboardFormatType::HtmlType(), buffer, data_dst))
-    types.push_back(base::UTF8ToUTF16(kMimeTypeHtml));
-  if (IsFormatAvailable(ClipboardFormatType::SvgType(), buffer, data_dst))
-    types.push_back(base::UTF8ToUTF16(kMimeTypeSvg));
+  if (IsFormatAvailable(ClipboardFormatType::PlainTextType(), buffer,
+                        data_dst)) {
+    types.push_back(kMimeTypePlainText16);
+  }
+  if (IsFormatAvailable(ClipboardFormatType::HtmlType(), buffer, data_dst)) {
+    types.push_back(kMimeTypeHtml16);
+  }
+  if (IsFormatAvailable(ClipboardFormatType::SvgType(), buffer, data_dst)) {
+    types.push_back(kMimeTypeSvg16);
+  }
   // We can read images from either the Android clipboard or the local map.
   if (IsFormatAvailable(ClipboardFormatType::BitmapType(), buffer, data_dst) ||
       IsFormatAvailable(ClipboardFormatType::PngType(), buffer, data_dst)) {
-    types.push_back(base::UTF8ToUTF16(kMimeTypeImageUri));
-    types.push_back(base::UTF8ToUTF16(kMimeTypePng));
+    types.push_back(kMimeTypeImageUri16);
+    types.push_back(kMimeTypePng16);
   }
   if (IsFormatAvailable(ClipboardFormatType::FilenamesType(), buffer,
                         data_dst)) {
-    types.push_back(base::UTF8ToUTF16(kMimeTypeUriList));
+    types.push_back(kMimeTypeUriList16);
   }
   // these formats aren't supported by the ClipboardMap currently, but might
   // be one day?
-  if (IsFormatAvailable(ClipboardFormatType::RtfType(), buffer, data_dst))
-    types.push_back(base::UTF8ToUTF16(kMimeTypeRtf));
+  if (IsFormatAvailable(ClipboardFormatType::RtfType(), buffer, data_dst)) {
+    types.push_back(kMimeTypeRtf16);
+  }
   return types;
 }
 
diff --git a/ui/base/clipboard/clipboard_constants.cc b/ui/base/clipboard/clipboard_constants.cc
deleted file mode 100644
index a877103..0000000
--- a/ui/base/clipboard/clipboard_constants.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2013 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/clipboard/clipboard_constants.h"
-
-#include "build/build_config.h"
-
-namespace ui {
-
-const char kMimeTypePlainText[] = "text/plain";
-const char kMimeTypeUtf8PlainText[] = "text/plain;charset=utf-8";
-// Used for file:// URLs.
-const char kMimeTypeUriList[] = "text/uri-list";
-// Used for site URL bookmarks.
-const char kMimeTypeMozillaUrl[] = "text/x-moz-url";
-const char kMimeTypeDownloadUrl[] = "downloadurl";
-const char kMimeTypeHtml[] = "text/html";
-const char kMimeTypeUtf8Html[] = "text/html;charset=utf-8";
-const char kMimeTypeSvg[] = "image/svg+xml";
-const char kMimeTypeRtf[] = "text/rtf";
-const char kMimeTypePng[] = "image/png";
-// Used for image drag & drop on X11 and Wayland.
-const char kMimeTypeOctetStream[] = "application/octet-stream";
-// Used for window dragging on some platforms.
-const char kMimeTypeWindowDrag[] = "chromium/x-window-drag";
-
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_FUCHSIA)
-const char kMimeTypeLinuxUtf8String[] = "UTF8_STRING";
-const char kMimeTypeLinuxString[] = "STRING";
-const char kMimeTypeLinuxText[] = "TEXT";
-#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
-        // BUILDFLAG(IS_FUCHSIA)
-
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_FUCHSIA) || \
-    BUILDFLAG(IS_ANDROID)
-const char kMimeTypeSourceUrl[] = "chromium/x-source-url";
-#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
-        // BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_ANDROID)
-
-#if !BUILDFLAG(IS_APPLE)
-const char kMimeTypeDataTransferCustomData[] = "chromium/x-web-custom-data";
-const char kMimeTypeWebkitSmartPaste[] = "chromium/x-webkit-paste";
-#endif  // BUILDFLAG(IS_APPLE)
-
-#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
-const char kMimeTypeImageUri[] = "image-uri";
-#endif  // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
-
-const int kMaxRegisteredClipboardFormats = 100;
-const char kWebClipboardFormatPrefix[] = "web ";
-
-}  // namespace ui
diff --git a/ui/base/clipboard/clipboard_constants.h b/ui/base/clipboard/clipboard_constants.h
index 68ad6293..11c0e47 100644
--- a/ui/base/clipboard/clipboard_constants.h
+++ b/ui/base/clipboard/clipboard_constants.h
@@ -11,8 +11,6 @@
 #if BUILDFLAG(IS_APPLE)
 #ifdef __OBJC__
 @class NSString;
-#else
-class NSString;
 #endif
 #endif  // BUILDFLAG(IS_APPLE)
 
@@ -20,63 +18,67 @@
 
 // ----- PLATFORM NEUTRAL MIME TYPES -----
 
-COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES)
-extern const char kMimeTypePlainText[];
-COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES)
-extern const char kMimeTypeUtf8PlainText[];
-COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES) extern const char kMimeTypeUriList[];
+inline constexpr char kMimeTypePlainText[] = "text/plain";
+inline constexpr char16_t kMimeTypePlainText16[] = u"text/plain";
+inline constexpr char kMimeTypeUtf8PlainText[] = "text/plain;charset=utf-8";
+inline constexpr char kMimeTypeUriList[] = "text/uri-list";
+inline constexpr char16_t kMimeTypeUriList16[] = u"text/uri-list";
 // Non-standard type for downloading files after drop events. Only works on
-// Windows. See https://crbug.com/860557 and https://crbug.com/425170.
-COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES)
-extern const char kMimeTypeDownloadUrl[];
-COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES)
-extern const char kMimeTypeMozillaUrl[];
-COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES) extern const char kMimeTypeHtml[];
-COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES) extern const char kMimeTypeUtf8Html[];
-COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES) extern const char kMimeTypeSvg[];
-COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES) extern const char kMimeTypeRtf[];
-COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES) extern const char kMimeTypePng[];
-COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES)
-extern const char kMimeTypeOctetStream[];
-COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES)
-extern const char kMimeTypeWindowDrag[];
+// Windows. See https://crbug.com/41399675 and https://crbug.com/40390016.
+inline constexpr char kMimeTypeDownloadUrl[] = "downloadurl";
+inline constexpr char kMimeTypeMozillaUrl[] = "text/x-moz-url";
+inline constexpr char16_t kMimeTypeMozillaUrl16[] = u"text/x-moz-url";
+inline constexpr char kMimeTypeHtml[] = "text/html";
+inline constexpr char16_t kMimeTypeHtml16[] = u"text/html";
+inline constexpr char kMimeTypeUtf8Html[] = "text/html;charset=utf-8";
+inline constexpr char kMimeTypeSvg[] = "image/svg+xml";
+inline constexpr char16_t kMimeTypeSvg16[] = u"image/svg+xml";
+inline constexpr char kMimeTypeRtf[] = "text/rtf";
+inline constexpr char16_t kMimeTypeRtf16[] = u"text/rtf";
+inline constexpr char kMimeTypePng[] = "image/png";
+inline constexpr char16_t kMimeTypePng16[] = u"image/png";
+// Used for image drag & drop on X11 and Wayland.
+inline constexpr char kMimeTypeOctetStream[] = "application/octet-stream";
+// Used for window dragging on some platforms.
+inline constexpr char kMimeTypeWindowDrag[] = "chromium/x-window-drag";
 
 // ----- LINUX & CHROMEOS & FUCHSIA MIME TYPES -----
 
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_FUCHSIA)
-COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES)
-extern const char kMimeTypeLinuxUtf8String[];
-COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES)
-extern const char kMimeTypeLinuxString[];
-COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES)
-extern const char kMimeTypeLinuxText[];
-COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES)
+inline constexpr char kMimeTypeLinuxUtf8String[] = "UTF8_STRING";
+inline constexpr char kMimeTypeLinuxString[] = "STRING";
+inline constexpr char kMimeTypeLinuxText[] = "TEXT";
 #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
         // BUILDFLAG(IS_FUCHSIA)
 
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_FUCHSIA) || \
     BUILDFLAG(IS_ANDROID)
-extern const char kMimeTypeSourceUrl[];
+inline constexpr char kMimeTypeSourceUrl[] = "chromium/x-source-url";
 #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
         // BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_ANDROID)
 
 // ----- EVERYTHING EXCEPT FOR APPLE MIME TYPES -----
 
 #if !BUILDFLAG(IS_APPLE)
-// TODO(dcheng): This name is temporary. See crbug.com/106449.
-COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES)
-extern const char kMimeTypeDataTransferCustomData[];
-COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES)
-extern const char kMimeTypeWebkitSmartPaste[];
+
+// TODO(dcheng): This name is temporary. See https://crbug.com/40123727.
+inline constexpr char kMimeTypeDataTransferCustomData[] =
+    "chromium/x-web-custom-data";
+inline constexpr char16_t kMimeTypeDataTransferCustomData16[] =
+    u"chromium/x-web-custom-data";
+inline constexpr char kMimeTypeWebkitSmartPaste[] = "chromium/x-webkit-paste";
+
 #else
 
 // ----- APPLE UNIFORM TYPES -----
 
+#ifdef __OBJC__
+
 // Mail.app and TextEdit accept drags that have both HTML and image types on
-// them, but don't process them correctly <http://crbug.com/55879>. Therefore,
-// if there is an image type, don't put the HTML data on as HTML, but rather
-// put it on as this Chrome-only type. External apps won't see HTML but
-// Chrome will know enough to read it as HTML. <http://crbug.com/55879>
+// them, but don't process them correctly <https://crbug.com/40445637>.
+// Therefore, if there is an image type, don't put the HTML data on as HTML, but
+// rather put it on as this Chrome-only type. External apps won't see HTML but
+// Chrome will know enough to read it as HTML.
 COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES)
 extern NSString* const kUTTypeChromiumImageAndHtml;
 
@@ -133,13 +135,15 @@
 COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES)
 extern NSString* const kUTTypeChromiumSourceUrl;
 
+#endif  //  __OBJC__
+
 #endif  // BUILDFLAG(IS_APPLE)
 
 // ----- ANDROID MIME TYPES -----
 
 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
-COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES)
-extern const char kMimeTypeImageUri[];
+inline constexpr char kMimeTypeImageUri[] = "image-uri";
+inline constexpr char16_t kMimeTypeImageUri16[] = u"image-uri";
 #endif  // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
 
 // ----- OTHER RELATED CONSTANTS -----
@@ -149,12 +153,11 @@
 // some amount of unique formats, and there's no way to un-register these
 // formats. For these clipboards, we use a conservative limit to avoid
 // registering too many formats.
-COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES)
-extern const int kMaxRegisteredClipboardFormats;
+inline constexpr int kMaxRegisteredClipboardFormats = 100;
 
 // Web prefix for web custom format types.
-COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES)
-extern const char kWebClipboardFormatPrefix[];
+inline constexpr char kWebClipboardFormatPrefix[] = "web ";
+inline constexpr char16_t kWebClipboardFormatPrefix16[] = u"web ";
 
 }  // namespace ui
 
diff --git a/ui/base/clipboard/clipboard_ios.mm b/ui/base/clipboard/clipboard_ios.mm
index 2c685d74..b15304cf 100644
--- a/ui/base/clipboard/clipboard_ios.mm
+++ b/ui/base/clipboard/clipboard_ios.mm
@@ -89,20 +89,20 @@
   std::vector<std::u16string> types;
   if (IsFormatAvailable(ClipboardFormatType::PlainTextType(), buffer,
                         data_dst)) {
-    types.push_back(base::UTF8ToUTF16(kMimeTypePlainText));
+    types.push_back(kMimeTypePlainText16);
   }
   if (IsFormatAvailable(ClipboardFormatType::HtmlType(), buffer, data_dst)) {
-    types.push_back(base::UTF8ToUTF16(kMimeTypeHtml));
+    types.push_back(kMimeTypeHtml16);
   }
   if (IsFormatAvailable(ClipboardFormatType::SvgType(), buffer, data_dst)) {
-    types.push_back(base::UTF8ToUTF16(kMimeTypeSvg));
+    types.push_back(kMimeTypeSvg16);
   }
   if (IsFormatAvailable(ClipboardFormatType::RtfType(), buffer, data_dst)) {
-    types.push_back(base::UTF8ToUTF16(kMimeTypeRtf));
+    types.push_back(kMimeTypeRtf16);
   }
   if (IsFormatAvailable(ClipboardFormatType::FilenamesType(), buffer,
                         data_dst)) {
-    types.push_back(base::UTF8ToUTF16(kMimeTypeUriList));
+    types.push_back(kMimeTypeUriList16);
   }
   return types;
 }
diff --git a/ui/base/clipboard/clipboard_mac.mm b/ui/base/clipboard/clipboard_mac.mm
index bdb655a..903328e 100644
--- a/ui/base/clipboard/clipboard_mac.mm
+++ b/ui/base/clipboard/clipboard_mac.mm
@@ -217,23 +217,28 @@
     const DataTransferEndpoint* data_dst) const {
   std::vector<std::u16string> types;
   NSPasteboard* pb = GetPasteboard();
-  if (IsFormatAvailable(ClipboardFormatType::PlainTextType(), buffer, data_dst))
-    types.push_back(base::UTF8ToUTF16(kMimeTypePlainText));
-  if (IsFormatAvailable(ClipboardFormatType::HtmlType(), buffer, data_dst))
-    types.push_back(base::UTF8ToUTF16(kMimeTypeHtml));
-  if (IsFormatAvailable(ClipboardFormatType::SvgType(), buffer, data_dst))
-    types.push_back(base::UTF8ToUTF16(kMimeTypeSvg));
-  if (IsFormatAvailable(ClipboardFormatType::RtfType(), buffer, data_dst))
-    types.push_back(base::UTF8ToUTF16(kMimeTypeRtf));
+  if (IsFormatAvailable(ClipboardFormatType::PlainTextType(), buffer,
+                        data_dst)) {
+    types.push_back(kMimeTypePlainText16);
+  }
+  if (IsFormatAvailable(ClipboardFormatType::HtmlType(), buffer, data_dst)) {
+    types.push_back(kMimeTypeHtml16);
+  }
+  if (IsFormatAvailable(ClipboardFormatType::SvgType(), buffer, data_dst)) {
+    types.push_back(kMimeTypeSvg16);
+  }
+  if (IsFormatAvailable(ClipboardFormatType::RtfType(), buffer, data_dst)) {
+    types.push_back(kMimeTypeRtf16);
+  }
   if (IsFormatAvailable(ClipboardFormatType::FilenamesType(), buffer,
                         data_dst)) {
-    types.push_back(base::UTF8ToUTF16(kMimeTypeUriList));
+    types.push_back(kMimeTypeUriList16);
   } else if (pb && [NSImage canInitWithPasteboard:pb]) {
     // Finder Cmd+C places both file and icon onto the clipboard
     // (http://crbug.com/553686), so ignore images if we have detected files.
     // This means that if an image is present with file content, we will always
     // ignore the image, but this matches observable Safari behavior.
-    types.push_back(base::UTF8ToUTF16(kMimeTypePng));
+    types.push_back(kMimeTypePng16);
   }
   return types;
 }
diff --git a/ui/base/clipboard/clipboard_non_backed.cc b/ui/base/clipboard/clipboard_non_backed.cc
index 30f3dcd..c759176 100644
--- a/ui/base/clipboard/clipboard_non_backed.cc
+++ b/ui/base/clipboard/clipboard_non_backed.cc
@@ -591,23 +591,23 @@
   std::vector<std::u16string> types;
   if (IsFormatAvailable(ClipboardFormatType::PlainTextType(), buffer,
                         data_dst)) {
-    types.push_back(base::UTF8ToUTF16(kMimeTypePlainText));
+    types.push_back(kMimeTypePlainText16);
   }
   if (IsFormatAvailable(ClipboardFormatType::HtmlType(), buffer, data_dst)) {
-    types.push_back(base::UTF8ToUTF16(kMimeTypeHtml));
+    types.push_back(kMimeTypeHtml16);
   }
   if (IsFormatAvailable(ClipboardFormatType::SvgType(), buffer, data_dst)) {
-    types.push_back(base::UTF8ToUTF16(kMimeTypeSvg));
+    types.push_back(kMimeTypeSvg16);
   }
   if (IsFormatAvailable(ClipboardFormatType::RtfType(), buffer, data_dst)) {
-    types.push_back(base::UTF8ToUTF16(kMimeTypeRtf));
+    types.push_back(kMimeTypeRtf16);
   }
   if (IsFormatAvailable(ClipboardFormatType::BitmapType(), buffer, data_dst)) {
-    types.push_back(base::UTF8ToUTF16(kMimeTypePng));
+    types.push_back(kMimeTypePng16);
   }
   if (IsFormatAvailable(ClipboardFormatType::FilenamesType(), buffer,
                         data_dst)) {
-    types.push_back(base::UTF8ToUTF16(kMimeTypeUriList));
+    types.push_back(kMimeTypeUriList16);
   }
   return types;
 }
diff --git a/ui/base/clipboard/clipboard_ozone.cc b/ui/base/clipboard/clipboard_ozone.cc
index 6b97a3f..d2194f3 100644
--- a/ui/base/clipboard/clipboard_ozone.cc
+++ b/ui/base/clipboard/clipboard_ozone.cc
@@ -425,8 +425,8 @@
          mime_type == kMimeTypeLinuxText || mime_type == kMimeTypeLinuxString ||
          mime_type == kMimeTypeUtf8PlainText ||
          mime_type == kMimeTypeLinuxUtf8String) &&
-        !base::Contains(types, base::UTF8ToUTF16(kMimeTypePlainText))) {
-      types.push_back(base::UTF8ToUTF16(kMimeTypePlainText));
+        !base::Contains(types, kMimeTypePlainText16)) {
+      types.push_back(kMimeTypePlainText16);
       continue;
     }
   }
diff --git a/ui/base/clipboard/clipboard_test_template.h b/ui/base/clipboard/clipboard_test_template.h
index 33bd657b..02aef78 100644
--- a/ui/base/clipboard/clipboard_test_template.h
+++ b/ui/base/clipboard/clipboard_test_template.h
@@ -177,7 +177,7 @@
   }
 
   EXPECT_THAT(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste),
-              Contains(ASCIIToUTF16(kMimeTypePlainText)));
+              Contains(kMimeTypePlainText16));
   EXPECT_TRUE(this->clipboard().IsFormatAvailable(
       ClipboardFormatType::PlainTextType(), ClipboardBuffer::kCopyPaste,
       /* data_dst = */ nullptr));
@@ -208,7 +208,7 @@
   }
 
   EXPECT_THAT(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste),
-              Contains(ASCIIToUTF16(kMimeTypeHtml)));
+              Contains(kMimeTypeHtml16));
   EXPECT_TRUE(this->clipboard().IsFormatAvailable(
       ClipboardFormatType::HtmlType(), ClipboardBuffer::kCopyPaste,
       /* data_dst = */ nullptr));
@@ -236,7 +236,7 @@
   }
 
   EXPECT_THAT(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste),
-              Contains(ASCIIToUTF16(kMimeTypeSvg)));
+              Contains(kMimeTypeSvg16));
   EXPECT_TRUE(this->clipboard().IsFormatAvailable(
       ClipboardFormatType::SvgType(), ClipboardBuffer::kCopyPaste,
       /* data_dst = */ nullptr));
@@ -275,7 +275,7 @@
   }
 
   EXPECT_THAT(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste),
-              Contains(ASCIIToUTF16(kMimeTypeRtf)));
+              Contains(kMimeTypeRtf16));
   EXPECT_TRUE(this->clipboard().IsFormatAvailable(
       ClipboardFormatType::RtfType(), ClipboardBuffer::kCopyPaste,
       /* data_dst = */ nullptr));
@@ -310,9 +310,9 @@
   }
 
   EXPECT_THAT(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste),
-              Contains(ASCIIToUTF16(kMimeTypePlainText)));
+              Contains(kMimeTypePlainText16));
   EXPECT_THAT(this->GetAvailableTypes(ClipboardBuffer::kSelection),
-              Contains(ASCIIToUTF16(kMimeTypeHtml)));
+              Contains(kMimeTypeHtml16));
 
   EXPECT_TRUE(this->clipboard().IsFormatAvailable(
       ClipboardFormatType::PlainTextType(), ClipboardBuffer::kCopyPaste,
@@ -356,7 +356,7 @@
   }
 
   EXPECT_THAT(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste),
-              Contains(ASCIIToUTF16(kMimeTypeHtml)));
+              Contains(kMimeTypeHtml16));
   EXPECT_TRUE(this->clipboard().IsFormatAvailable(
       ClipboardFormatType::HtmlType(), ClipboardBuffer::kCopyPaste,
       /* data_dst = */ nullptr));
@@ -391,7 +391,7 @@
   }
 
   EXPECT_THAT(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste),
-              Contains(ASCIIToUTF16(kMimeTypeHtml)));
+              Contains(kMimeTypeHtml16));
   EXPECT_TRUE(this->clipboard().IsFormatAvailable(
       ClipboardFormatType::HtmlType(), ClipboardBuffer::kCopyPaste,
       /* data_dst = */ nullptr));
@@ -477,9 +477,9 @@
   }
 
   EXPECT_THAT(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste),
-              Contains(ASCIIToUTF16(kMimeTypeHtml)));
+              Contains(kMimeTypeHtml16));
   EXPECT_THAT(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste),
-              Contains(ASCIIToUTF16(kMimeTypePlainText)));
+              Contains(kMimeTypePlainText16));
   EXPECT_TRUE(this->clipboard().IsFormatAvailable(
       ClipboardFormatType::HtmlType(), ClipboardBuffer::kCopyPaste,
       /* data_dst = */ nullptr));
@@ -521,7 +521,7 @@
   }
 
   EXPECT_THAT(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste),
-              Contains(ASCIIToUTF16(kMimeTypePlainText)));
+              Contains(kMimeTypePlainText16));
   EXPECT_TRUE(this->clipboard().IsFormatAvailable(
       ClipboardFormatType::PlainTextType(), ClipboardBuffer::kCopyPaste,
       /* data_dst = */ nullptr));
@@ -564,23 +564,22 @@
   }
 
   EXPECT_THAT(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste),
-              Contains(ASCIIToUTF16(kMimeTypeHtml)));
-  EXPECT_THAT(
-      this->GetAvailableTypes(ClipboardBuffer::kCopyPaste),
-      testing::Not(Contains(ASCIIToUTF16(kMimeTypeDataTransferCustomData))));
+              Contains(kMimeTypeHtml16));
+  EXPECT_THAT(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste),
+              testing::Not(Contains(kMimeTypeDataTransferCustomData16)));
   {
     ScopedClipboardWriter clipboard_writer(ClipboardBuffer::kCopyPaste);
     base::flat_map<std::u16string, std::u16string> custom_data;
-    custom_data[ASCIIToUTF16(kMimeTypeDataTransferCustomData)] = u"data";
+    custom_data[kMimeTypeDataTransferCustomData16] = u"data";
     base::Pickle pickle;
     WriteCustomDataToPickle(custom_data, &pickle);
     clipboard_writer.WritePickledData(
         pickle, ClipboardFormatType::DataTransferCustomType());
   }
   EXPECT_THAT(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste),
-              testing::Not(Contains(ASCIIToUTF16(kMimeTypeHtml))));
+              testing::Not(Contains(kMimeTypeHtml16)));
   EXPECT_THAT(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste),
-              Contains(ASCIIToUTF16(kMimeTypeDataTransferCustomData)));
+              Contains(kMimeTypeDataTransferCustomData16));
 }
 #endif  // BUILDFLAG(IS_WIN)
 
diff --git a/ui/base/clipboard/clipboard_win.cc b/ui/base/clipboard/clipboard_win.cc
index d50b190..0f3ef217 100644
--- a/ui/base/clipboard/clipboard_win.cc
+++ b/ui/base/clipboard/clipboard_win.cc
@@ -343,21 +343,27 @@
     const DataTransferEndpoint* data_dst) const {
   std::vector<std::u16string> types;
   if (::IsClipboardFormatAvailable(
-          ClipboardFormatType::PlainTextAType().ToFormatEtc().cfFormat))
-    types.push_back(base::UTF8ToUTF16(kMimeTypePlainText));
+          ClipboardFormatType::PlainTextAType().ToFormatEtc().cfFormat)) {
+    types.push_back(kMimeTypePlainText16);
+  }
   if (::IsClipboardFormatAvailable(
-          ClipboardFormatType::HtmlType().ToFormatEtc().cfFormat))
-    types.push_back(base::UTF8ToUTF16(kMimeTypeHtml));
+          ClipboardFormatType::HtmlType().ToFormatEtc().cfFormat)) {
+    types.push_back(kMimeTypeHtml16);
+  }
   if (::IsClipboardFormatAvailable(
-          ClipboardFormatType::SvgType().ToFormatEtc().cfFormat))
-    types.push_back(base::UTF8ToUTF16(kMimeTypeSvg));
+          ClipboardFormatType::SvgType().ToFormatEtc().cfFormat)) {
+    types.push_back(kMimeTypeSvg16);
+  }
   if (::IsClipboardFormatAvailable(
-          ClipboardFormatType::RtfType().ToFormatEtc().cfFormat))
-    types.push_back(base::UTF8ToUTF16(kMimeTypeRtf));
-  if (::IsClipboardFormatAvailable(CF_DIB))
-    types.push_back(base::UTF8ToUTF16(kMimeTypePng));
-  if (ReadFilenamesAvailable())
-    types.push_back(base::UTF8ToUTF16(kMimeTypeUriList));
+          ClipboardFormatType::RtfType().ToFormatEtc().cfFormat)) {
+    types.push_back(kMimeTypeRtf16);
+  }
+  if (::IsClipboardFormatAvailable(CF_DIB)) {
+    types.push_back(kMimeTypePng16);
+  }
+  if (ReadFilenamesAvailable()) {
+    types.push_back(kMimeTypeUriList16);
+  }
   return types;
 }
 
diff --git a/ui/base/clipboard/test/test_clipboard.cc b/ui/base/clipboard/test/test_clipboard.cc
index 8766119..d65d32c 100644
--- a/ui/base/clipboard/test/test_clipboard.cc
+++ b/ui/base/clipboard/test/test_clipboard.cc
@@ -113,19 +113,19 @@
 
   if (IsFormatAvailable(ClipboardFormatType::PlainTextType(), buffer,
                         data_dst)) {
-    types.push_back(base::UTF8ToUTF16(kMimeTypePlainText));
+    types.push_back(kMimeTypePlainText16);
   }
   if (IsFormatAvailable(ClipboardFormatType::HtmlType(), buffer, data_dst))
-    types.push_back(base::UTF8ToUTF16(kMimeTypeHtml));
+    types.push_back(kMimeTypeHtml16);
   if (IsFormatAvailable(ClipboardFormatType::SvgType(), buffer, data_dst))
-    types.push_back(base::UTF8ToUTF16(kMimeTypeSvg));
+    types.push_back(kMimeTypeSvg16);
   if (IsFormatAvailable(ClipboardFormatType::RtfType(), buffer, data_dst))
-    types.push_back(base::UTF8ToUTF16(kMimeTypeRtf));
+    types.push_back(kMimeTypeRtf16);
   if (IsFormatAvailable(ClipboardFormatType::PngType(), buffer, data_dst) ||
       IsFormatAvailable(ClipboardFormatType::BitmapType(), buffer, data_dst))
-    types.push_back(base::UTF8ToUTF16(kMimeTypePng));
+    types.push_back(kMimeTypePng16);
   if (IsFormatAvailable(ClipboardFormatType::FilenamesType(), buffer, data_dst))
-    types.push_back(base::UTF8ToUTF16(kMimeTypeUriList));
+    types.push_back(kMimeTypeUriList16);
 
   auto it = store.data.find(ClipboardFormatType::DataTransferCustomType());
   if (it != store.data.end())
diff --git a/ui/display/ios/screen_ios.mm b/ui/display/ios/screen_ios.mm
index 5add085..2447f9e 100644
--- a/ui/display/ios/screen_ios.mm
+++ b/ui/display/ios/screen_ios.mm
@@ -91,6 +91,8 @@
       scale = Display::GetForcedDeviceScaleFactor();
     }
     display.set_device_scale_factor(scale);
+
+#if !BUILDFLAG(IS_IOS_TVOS)
     Display::Rotation rotation = Display::ROTATE_0;
     switch (UIDevice.currentDevice.orientation) {
       case UIDeviceOrientationPortrait:
@@ -113,6 +115,8 @@
     display.set_touch_support(Display::TouchSupport::AVAILABLE);
     display.set_accelerometer_support(Display::AccelerometerSupport::AVAILABLE);
     AddInternalDisplayId(display_id);
+#endif
+
     ProcessDisplayChanged(display, true /* is_primary */);
   }
 
diff --git a/ui/events/BUILD.gn b/ui/events/BUILD.gn
index 446cd35..6204836 100644
--- a/ui/events/BUILD.gn
+++ b/ui/events/BUILD.gn
@@ -14,6 +14,7 @@
 }
 
 if (is_ios) {
+  import("//build/config/apple/mobile_config.gni")
   import("//ios/build/config.gni")
 }
 
@@ -160,10 +161,12 @@
   }
 
   if (is_ios && use_blink) {
-    sources += [
-      "keycodes/keyboard_code_conversion_ios.h",
-      "keycodes/keyboard_code_conversion_ios.mm",
-    ]
+    if (target_platform == "iphoneos") {
+      sources += [
+        "keycodes/keyboard_code_conversion_ios.h",
+        "keycodes/keyboard_code_conversion_ios.mm",
+      ]
+    }
   }
 
   if (is_fuchsia) {
diff --git a/ui/webui/resources/js/focus_without_ink.ts b/ui/webui/resources/js/focus_without_ink.ts
index 74e6177..6a4e28ba 100644
--- a/ui/webui/resources/js/focus_without_ink.ts
+++ b/ui/webui/resources/js/focus_without_ink.ts
@@ -2,15 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// clang-format off
 import {assert} from './assert.js';
-import {isIOS} from './platform.js';
-// clang-format on
 
 
-let hideInk = false;
-
-assert(!isIOS, 'pointerdown doesn\'t work on iOS');
+let hideInk: boolean = false;
 
 document.addEventListener('pointerdown', function() {
   hideInk = true;
diff --git a/v8 b/v8
index cfe1476..82b4f3c 160000
--- a/v8
+++ b/v8
@@ -1 +1 @@
-Subproject commit cfe14766c19eb555caa2bd36dba729646eaca469
+Subproject commit 82b4f3cde5bc74ed21aeeae257301550b620277b