diff --git a/DEPS b/DEPS
index 0682a558..dcb99a8 100644
--- a/DEPS
+++ b/DEPS
@@ -300,15 +300,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': '6a57876d0e4425855753003fc1990c881e139139',
+  'skia_revision': '3ded22186598442901bd4c30f14016dd94ba3c7c',
   # 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': '6f542f16016d45b1961fc689197a7f574f929e0a',
+  'v8_revision': '0c4044b7336787781646e48b2f98f0c7d1b400a5',
   # 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': '3f633521356d65679acaba2918c014fcbd8c0a5e',
+  'angle_revision': '98d6dd38ecb22219aedaaa45e3e4e2df1f32143b',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -387,7 +387,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': '487ee0ca44a9b411a72f8726eac47052f4229b34',
+  'devtools_frontend_revision': '1e46dc25d1a4f8e55d4f2d31a7a290c7c34a25c1',
   # 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.
@@ -427,7 +427,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': 'bfa1d3a870ec0fef5b6a87c481913055aace608c',
+  'dawn_revision': '40bf2a0110d7cbcb85c89e9e09df207d20654f18',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -803,7 +803,7 @@
 
   'src/clank': {
     'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' +
-    '68d7621ebf07cdf357a304c7421ec819cbf8244a',
+    '014ca730f54fb8dc94ad55d70939b6771deeec84',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
@@ -1233,7 +1233,7 @@
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
 
   'src/third_party/devtools-frontend-internal': {
-      'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '55caae7b3537b671566e63636f3cc02521002ac6',
+      'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '1c30f355bc88bf4e4c80effde851a34c6aa95b81',
     'condition': 'checkout_src_internal',
   },
 
@@ -1460,7 +1460,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/kotlin_stdlib',
-              'version': '5vxa94PP6aaNePK9IF8ZwAYbDA-08mk4nkPED5CMbFoC',
+              'version': 'z4_AYYz2Tw5GKikuiDLTuxxf0NJVGLkC3CVcyiIpc-gC',
           },
       ],
       'condition': 'checkout_android',
@@ -1845,7 +1845,7 @@
       'dep_type': 'cipd',
   },
 
-  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@e2fe2393abb4b5cf344d1731306b47ab576980ee',
+  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@87de63d83503c799d972a7e6b11d61de854720dc',
 
   'src/third_party/vulkan_memory_allocator':
     Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'ebe84bec02c041d28f902da0214bf442743fc907',
@@ -1885,7 +1885,7 @@
     Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '062e548df1d873fb6b98459eb3d3391b8c3c9702',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '3fea51aa2015543a9fddfa7e029227be565d5d75',
+    Var('webrtc_git') + '/src.git' + '@' + '85632b81912d8ff7ead99531dfc082c3578aa586',
 
   # Wuffs' canonical repository is at github.com/google/wuffs, but we use
   # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file.
@@ -1994,7 +1994,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/eche_app/app',
-        'version': 'sLWeOjL4G-D4A_bChDSoLuxlIJNgcolXupAbfnnWS64C',
+        'version': 'X_-AEe7yM_cIfjl8vvM3tB4fV0hSLraWg9TJUd_efL8C',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/ash/components/arc/arc_util.cc b/ash/components/arc/arc_util.cc
index 3b528d6..24b29f2 100644
--- a/ash/components/arc/arc_util.cc
+++ b/ash/components/arc/arc_util.cc
@@ -536,7 +536,8 @@
 }
 
 uint64_t GetRequiredFreeDiskSpaceForArcVmDataMigrationInBytes(
-    uint64_t android_data_size_in_bytes,
+    uint64_t android_data_size_src_in_bytes,
+    uint64_t android_data_size_dest_in_bytes,
     uint64_t free_disk_space_in_bytes) {
   // Mask to make the required free disk space a multiple of 512 MB.
   constexpr uint64_t kRequiredFreeDiskSpaceMaskInBytes = ~((512ULL << 20) - 1);
@@ -546,13 +547,22 @@
 
   const uint64_t required_disk_image_size_in_bytes =
       GetRequiredDiskImageSizeForArcVmDataMigrationInBytes(
-          android_data_size_in_bytes);
+          android_data_size_dest_in_bytes);
 
   const uint64_t maximum_disk_space_overhead_in_bytes =
-      required_disk_image_size_in_bytes - android_data_size_in_bytes;
+      required_disk_image_size_in_bytes - android_data_size_dest_in_bytes;
+
+  // Amount of additional disk space required after the migration due to
+  // expanded sparse files in Android /data.
+  uint64_t android_data_expansion_size_in_bytes = 0;
+  if (android_data_size_dest_in_bytes > android_data_size_src_in_bytes) {
+    android_data_expansion_size_in_bytes =
+        android_data_size_dest_in_bytes - android_data_size_src_in_bytes;
+  }
 
   return (kMinimumRequiredFreeDiskSpaceInBytes +
-          maximum_disk_space_overhead_in_bytes) &
+          maximum_disk_space_overhead_in_bytes +
+          android_data_expansion_size_in_bytes) &
          kRequiredFreeDiskSpaceMaskInBytes;
 }
 
diff --git a/ash/components/arc/arc_util.h b/ash/components/arc/arc_util.h
index f89c22c..d0caf7a 100644
--- a/ash/components/arc/arc_util.h
+++ b/ash/components/arc/arc_util.h
@@ -258,15 +258,17 @@
 // ARCVM /data migration based on the size of the source (existing Android
 // /data) and free disk space.
 uint64_t GetDesiredDiskImageSizeForArcVmDataMigrationInBytes(
-    uint64_t android_data_size,
-    uint64_t free_disk_space);
+    uint64_t android_data_size_in_bytes,
+    uint64_t free_disk_space_in_bytes);
 
 // Calculates and returns how much free disk space should be there to start
-// ARCVM /data migration based on the size of existing Android /data and free
+// ARCVM /data migration based on the disk space allocated for pre-migration
+// Android /data, estimated disk space allocated for migrated /data, and free
 // disk space.
 uint64_t GetRequiredFreeDiskSpaceForArcVmDataMigrationInBytes(
-    uint64_t android_data_size,
-    uint64_t free_disk_space);
+    uint64_t android_data_size_src_in_bytes,
+    uint64_t android_data_size_dest_in_bytes,
+    uint64_t free_disk_space_in_bytes);
 
 // Returns true if ARC app permissions should be shown as read-only in the App
 // Management page.
diff --git a/ash/components/arc/arc_util_unittest.cc b/ash/components/arc/arc_util_unittest.cc
index 9d313f2..751f8d2 100644
--- a/ash/components/arc/arc_util_unittest.cc
+++ b/ash/components/arc/arc_util_unittest.cc
@@ -772,18 +772,32 @@
 }
 
 TEST_F(ArcUtilTest, GetRequiredFreeDiskSpaceForArcVmDataMigrationInBytes) {
-  EXPECT_EQ(GetRequiredFreeDiskSpaceForArcVmDataMigrationInBytes(0, 0),
+  EXPECT_EQ(GetRequiredFreeDiskSpaceForArcVmDataMigrationInBytes(0, 0, 0),
             1ULL << 30 /* kMinimumRequiredFreeDiskSpaceInBytes = 1 GB */);
 
   EXPECT_EQ(GetRequiredFreeDiskSpaceForArcVmDataMigrationInBytes(
-                4ULL << 30 /* android_data_size_in_bytes = 4 GB */,
+                4ULL << 30 /* android_data_size_src_in_bytes = 4 GB */,
+                4ULL << 30 /* android_data_size_dest_in_bytes = 4 GB */,
                 32ULL << 30 /* free_disk_space_in_bytes = 32 GB */),
             3ULL * (512ULL << 20) /* 1.5 GB */);
 
   EXPECT_EQ(GetRequiredFreeDiskSpaceForArcVmDataMigrationInBytes(
-                32ULL << 30 /* android_data_size_in_bytes = 32 GB */,
+                32ULL << 30 /* android_data_size_src_in_bytes = 32 GB */,
+                32ULL << 30 /* android_data_size_dest_in_bytes = 32 GB */,
                 4ULL << 30 /* free_disk_space_in_bytes = 4 GB */),
             4ULL << 30 /* 4 GB */);
+
+  EXPECT_EQ(GetRequiredFreeDiskSpaceForArcVmDataMigrationInBytes(
+                33ULL << 30 /* android_data_size_src_in_bytes = 33 GB */,
+                32ULL << 30 /* android_data_size_dest_in_bytes = 32 GB */,
+                4ULL << 30 /* free_disk_space_in_bytes = 4 GB */),
+            4ULL << 30 /* 4 GB */);
+
+  EXPECT_EQ(GetRequiredFreeDiskSpaceForArcVmDataMigrationInBytes(
+                16ULL << 30 /* android_data_size_src_in_bytes = 16 GB */,
+                32ULL << 30 /* android_data_size_dest_in_bytes = 32 GB */,
+                4ULL << 30 /* free_disk_space_in_bytes = 4 GB */),
+            20ULL << 30 /* 20 GB */);
 }
 
 }  // namespace
diff --git a/ash/components/arc/net/arc_net_host_impl.cc b/ash/components/arc/net/arc_net_host_impl.cc
index 558a3662..2c7d9734 100644
--- a/ash/components/arc/net/arc_net_host_impl.cc
+++ b/ash/components/arc/net/arc_net_host_impl.cc
@@ -6,6 +6,7 @@
 
 #include <net/if.h>
 
+#include <queue>
 #include <utility>
 
 #include "ash/components/arc/arc_browser_context_keyed_service_factory_base.h"
@@ -17,6 +18,7 @@
 #include "ash/components/arc/session/arc_bridge_service.h"
 #include "ash/constants/ash_features.h"
 #include "ash/public/cpp/window_properties.h"
+#include "ash/shell.h"
 #include "base/containers/cxx20_erase.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback_helpers.h"
@@ -42,11 +44,11 @@
 #include "chromeos/ash/components/network/onc/network_onc_utils.h"
 #include "chromeos/ash/components/network/technology_state_controller.h"
 #include "components/device_event_log/device_event_log.h"
-#include "components/exo/wm_helper.h"
 #include "components/prefs/pref_service.h"
 #include "components/user_manager/user_manager.h"
 #include "dbus/object_path.h"
 #include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
+#include "ui/aura/window.h"
 
 namespace {
 
@@ -224,15 +226,6 @@
                  << ", message: " << error_message;
 }
 
-aura::Window* GetActiveWindow() {
-  const exo::WMHelper* wm_helper =
-      exo::WMHelper::HasInstance() ? exo::WMHelper::GetInstance() : nullptr;
-  if (!wm_helper) {
-    return nullptr;
-  }
-  return wm_helper->GetActiveWindow();
-}
-
 }  // namespace
 
 namespace arc {
@@ -1109,6 +1102,33 @@
                      weak_factory_.GetWeakPtr()));
 }
 
+aura::Window* ArcNetHostImpl::GetAppWindow(const std::string& package_name) {
+  std::queue<aura::Window*> windows = {};
+  for (auto* window : ash::Shell::GetAllRootWindows()) {
+    windows.push(window);
+  }
+  while (!windows.empty()) {
+    auto* window = windows.front();
+    windows.pop();
+    if (!window) {
+      continue;
+    }
+    for (auto* child_window : window->children()) {
+      windows.push(child_window);
+    }
+    const std::string* app_id = window->GetProperty(ash::kAppIDKey);
+    if (!app_id || app_id->empty()) {
+      continue;
+    }
+    const std::string window_package_name =
+        app_metadata_provider_->GetAppPackageName(*app_id);
+    if (window_package_name == package_name) {
+      return window;
+    }
+  }
+  return nullptr;
+}
+
 void ArcNetHostImpl::RequestPasspointAppApproval(
     mojom::PasspointApprovalRequestPtr request,
     RequestPasspointAppApprovalCallback callback) {
@@ -1117,30 +1137,18 @@
         mojom::PasspointApprovalResponse::New(/*allow=*/false));
     return;
   }
-  aura::Window* window = GetActiveWindow();
+
+  aura::Window* window = GetAppWindow(request->package_name);
   if (!window) {
-    NET_LOG(ERROR) << __func__ << ": Failed to get active window";
+    NET_LOG(ERROR) << __func__ << ": Failed to get app window";
     std::move(callback).Run(
         mojom::PasspointApprovalResponse::New(/*allow=*/false));
     return;
   }
-  const std::string* app_id = window->GetProperty(ash::kAppIDKey);
-  if (!app_id || app_id->empty()) {
-    NET_LOG(ERROR) << __func__ << ": Failed to get app info";
-    std::move(callback).Run(
-        mojom::PasspointApprovalResponse::New(/*allow=*/false));
-    return;
-  }
-  const std::string package_name =
-      app_metadata_provider_->GetAppPackageName(*app_id);
-  if (request->package_name != package_name) {
-    NET_LOG(ERROR) << __func__
-                   << ": Unexpected app package name of the active window: "
-                   << package_name;
-    std::move(callback).Run(
-        mojom::PasspointApprovalResponse::New(/*allow=*/false));
-    return;
-  }
+  // Prior to starting the dialog, the app is already expected to be on
+  // foreground, this is only necessary for edge cases (b/283739295).
+  window->Focus();
+
   PasspointDialogView::Show(window, std::move(request), std::move(callback));
 }
 
diff --git a/ash/components/arc/net/arc_net_host_impl.h b/ash/components/arc/net/arc_net_host_impl.h
index 17bb314..15ac0d94 100644
--- a/ash/components/arc/net/arc_net_host_impl.h
+++ b/ash/components/arc/net/arc_net_host_impl.h
@@ -27,6 +27,7 @@
 #include "chromeos/ash/components/network/network_profile_handler.h"
 #include "chromeos/ash/components/network/network_state_handler_observer.h"
 #include "components/keyed_service/core/keyed_service.h"
+#include "ui/aura/window.h"
 
 namespace content {
 class BrowserContext;
@@ -226,6 +227,11 @@
   // the properties values translated taken from mojo.
   void AddPasspointCredentialsWithProperties(base::Value::Dict properties);
 
+  // Get the app window with |package_name|. This is necessary to start the
+  // user approval Passpoint dialog above the app. The app window is fetched by
+  // doing BFS over the device's root windows and its children.
+  aura::Window* GetAppWindow(const std::string& package_name);
+
   // Pass any Chrome flags into ARC.
   void SetUpFlags();
 
diff --git a/ash/components/arc/session/arc_vm_client_adapter.cc b/ash/components/arc/session/arc_vm_client_adapter.cc
index ea57812..c761ed7 100644
--- a/ash/components/arc/session/arc_vm_client_adapter.cc
+++ b/ash/components/arc/session/arc_vm_client_adapter.cc
@@ -375,8 +375,6 @@
     request.set_mglru_reclaim_swappiness(0);
   }
 
-  request.set_enable_consumer_auto_update_toggle(base::FeatureList::IsEnabled(
-      ash::features::kConsumerAutoUpdateToggleAllowed));
   if (base::FeatureList::IsEnabled(kVmMemoryPSIReports))
     request.set_vm_memory_psi_period(kVmMemoryPSIReportsPeriod.Get());
   else
diff --git a/ash/components/arc/session/arc_vm_client_adapter_unittest.cc b/ash/components/arc/session/arc_vm_client_adapter_unittest.cc
index 52ef027d..f19587b 100644
--- a/ash/components/arc/session/arc_vm_client_adapter_unittest.cc
+++ b/ash/components/arc/session/arc_vm_client_adapter_unittest.cc
@@ -118,8 +118,9 @@
 bool HasDiskImage(const vm_tools::concierge::StartArcVmRequest& request,
                   const std::string& disk_path) {
   for (const auto& disk : request.disks()) {
-    if (disk.path() == disk_path)
+    if (disk.path() == disk_path) {
       return true;
+    }
   }
   return false;
 }
@@ -170,8 +171,9 @@
     ++stop_vm_call_count_;
     stop_vm_request_ = request;
     ash::FakeConciergeClient::StopVm(request, std::move(callback));
-    if (on_stop_vm_callback_ && (stop_vm_call_count_ == callback_count_))
+    if (on_stop_vm_callback_ && (stop_vm_call_count_ == callback_count_)) {
       std::move(on_stop_vm_callback_).Run();
+    }
   }
 
   void StartArcVm(
@@ -292,8 +294,9 @@
     char buf[256];
     while (true) {
       ssize_t len = HANDLE_EINTR(read(client_fd.get(), buf, sizeof(buf)));
-      if (len <= 0)
+      if (len <= 0) {
         break;
+      }
       out.append(buf, len);
     }
     received_.append(out);
@@ -498,15 +501,17 @@
   void SendVmStartedSignal() {
     vm_tools::concierge::VmStartedSignal signal;
     signal.set_name(kArcVmName);
-    for (auto& observer : GetTestConciergeClient()->vm_observer_list())
+    for (auto& observer : GetTestConciergeClient()->vm_observer_list()) {
       observer.OnVmStarted(signal);
+    }
   }
 
   void SendVmStartedSignalNotForArcVm() {
     vm_tools::concierge::VmStartedSignal signal;
     signal.set_name("penguin");
-    for (auto& observer : GetTestConciergeClient()->vm_observer_list())
+    for (auto& observer : GetTestConciergeClient()->vm_observer_list()) {
       observer.OnVmStarted(signal);
+    }
   }
 
   void SendVmStoppedSignalForCid(vm_tools::concierge::VmStopReason reason,
@@ -515,8 +520,9 @@
     signal.set_name(kArcVmName);
     signal.set_cid(cid);
     signal.set_reason(reason);
-    for (auto& observer : GetTestConciergeClient()->vm_observer_list())
+    for (auto& observer : GetTestConciergeClient()->vm_observer_list()) {
       observer.OnVmStopped(signal);
+    }
   }
 
   void SendVmStoppedSignal(vm_tools::concierge::VmStopReason reason) {
@@ -529,13 +535,15 @@
     signal.set_name("penguin");
     signal.set_cid(kCid);
     signal.set_reason(reason);
-    for (auto& observer : GetTestConciergeClient()->vm_observer_list())
+    for (auto& observer : GetTestConciergeClient()->vm_observer_list()) {
       observer.OnVmStopped(signal);
+    }
   }
 
   void SendNameOwnerChangedSignal() {
-    for (auto& observer : GetTestConciergeClient()->observer_list())
+    for (auto& observer : GetTestConciergeClient()->observer_list()) {
       observer.ConciergeServiceStopped();
+    }
   }
 
   void InjectUpstartStartJobFailure(const std::string& job_name_to_fail) {
@@ -871,8 +879,9 @@
     Observer& operator=(const Observer&) = delete;
 
     ~Observer() override {
-      if (child_observer_ && nested_adapter_)
+      if (child_observer_ && nested_adapter_) {
         nested_adapter_->RemoveObserver(child_observer_);
+      }
     }
 
     bool stopped_called() const { return stopped_called_; }
@@ -1055,11 +1064,10 @@
   StartMiniArcWithParams(true, std::move(start_params));
 
   const auto& ops = upstart_operations();
-  const auto it =
-      base::ranges::find_if(ops, [](const UpstartOperation& op) {
-        return op.type == UpstartOperationType::START &&
-               kArcVmPreLoginServicesJobName == op.name;
-      });
+  const auto it = base::ranges::find_if(ops, [](const UpstartOperation& op) {
+    return op.type == UpstartOperationType::START &&
+           kArcVmPreLoginServicesJobName == op.name;
+  });
   ASSERT_NE(ops.end(), it);
   EXPECT_TRUE(it->env.empty());
 }
@@ -1073,11 +1081,10 @@
   StartMiniArcWithParams(true, std::move(start_params));
 
   const auto& ops = upstart_operations();
-  const auto it =
-      base::ranges::find_if(ops, [](const UpstartOperation& op) {
-        return op.type == UpstartOperationType::START &&
-               kArcVmPreLoginServicesJobName == op.name;
-      });
+  const auto it = base::ranges::find_if(ops, [](const UpstartOperation& op) {
+    return op.type == UpstartOperationType::START &&
+           kArcVmPreLoginServicesJobName == op.name;
+  });
   ASSERT_NE(ops.end(), it);
   const auto it_ureadahead =
       base::ranges::find(it->env, "DISABLE_UREADAHEAD=1");
@@ -2300,18 +2307,19 @@
   EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
   EXPECT_FALSE(is_system_shutdown().has_value());
   const auto& request = GetTestConciergeClient()->start_arc_vm_request();
-  EXPECT_TRUE(request.enable_consumer_auto_update_toggle());
+  EXPECT_TRUE(
+      request.mini_instance_request().enable_consumer_auto_update_toggle());
 }
 
 TEST_F(ArcVmClientAdapterTest,
        StartArc_EnableConsumerAutoUpdateToggle_Enabled) {
   base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndEnableFeature(ash::features::kConsumerAutoUpdateToggleAllowed);
+  feature_list.InitAndEnableFeature(
+      ash::features::kConsumerAutoUpdateToggleAllowed);
   StartMiniArc();
   EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
   EXPECT_FALSE(is_system_shutdown().has_value());
   const auto& request = GetTestConciergeClient()->start_arc_vm_request();
-  EXPECT_TRUE(request.enable_consumer_auto_update_toggle());
   EXPECT_TRUE(
       request.mini_instance_request().enable_consumer_auto_update_toggle());
 }
@@ -2319,12 +2327,12 @@
 TEST_F(ArcVmClientAdapterTest,
        StartArc_EnableConsumerAutoUpdateToggle_Disabled) {
   base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndDisableFeature(ash::features::kConsumerAutoUpdateToggleAllowed);
+  feature_list.InitAndDisableFeature(
+      ash::features::kConsumerAutoUpdateToggleAllowed);
   StartMiniArc();
   EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
   EXPECT_FALSE(is_system_shutdown().has_value());
   const auto& request = GetTestConciergeClient()->start_arc_vm_request();
-  EXPECT_FALSE(request.enable_consumer_auto_update_toggle());
   EXPECT_FALSE(
       request.mini_instance_request().enable_consumer_auto_update_toggle());
 }
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc
index 059c2c6..544909a 100644
--- a/ash/constants/ash_features.cc
+++ b/ash/constants/ash_features.cc
@@ -577,7 +577,7 @@
 // Enables access to Chrome's Network Service for DriveFS.
 BASE_FEATURE(kDriveFsChromeNetworking,
              "DriveFsChromeNetworking",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+             base::FEATURE_ENABLED_BY_DEFAULT);
 
 // Enables DriveFS' bulk pinning functionality.
 BASE_FEATURE(kDriveFsBulkPinning,
@@ -1061,7 +1061,7 @@
 // move, ZIP on MS Office files call on the Drive to resync the files.
 BASE_FEATURE(kForceReSyncDrive,
              "ForceReSyncDrive",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+             base::FEATURE_ENABLED_BY_DEFAULT);
 
 // Controls whether to allow keeping full screen mode after unlock.
 BASE_FEATURE(kFullscreenAfterUnlockAllowed,
@@ -1486,7 +1486,7 @@
 // Enables PDF signature saving and a selection tool in the media app.
 BASE_FEATURE(kMediaAppPdfSignature,
              "MediaAppPdfSignature",
-             base::FEATURE_ENABLED_BY_DEFAULT);
+             base::FEATURE_DISABLED_BY_DEFAULT);
 
 // Enables notification of when a microphone-using app is launched while the
 // microphone is muted.
diff --git a/ash/constants/ash_pref_names.cc b/ash/constants/ash_pref_names.cc
index b1acce0..bf6e2d4 100644
--- a/ash/constants/ash_pref_names.cc
+++ b/ash/constants/ash_pref_names.cc
@@ -1014,14 +1014,6 @@
 // detection.
 const char kUserSpeakOnMuteDetectionEnabled[] =
     "ash.user.speak_on_mute_detection_enabled";
-// A boolean pref indicating whether a speak-on-mute detection opt-in nudge
-// should be displayed to the user.
-const char kShouldShowSpeakOnMuteOptInNudge[] =
-    "ash.user.should_show_speak_on_mute_opt_in_nudge";
-// An integer pref counting the number of times speak-on-mute detection opt-in
-// nudge has been displayed to the user.
-const char kSpeakOnMuteOptInNudgeShownCount[] =
-    "ash.user.speak_on_mute_opt_in_nudge_shown_count";
 
 // A boolean pref indicating whether the geolocation is allowed for the user.
 const char kUserGeolocationAllowed[] = "ash.user.geolocation_allowed";
diff --git a/ash/constants/ash_pref_names.h b/ash/constants/ash_pref_names.h
index 438f36b9..75029bb4 100644
--- a/ash/constants/ash_pref_names.h
+++ b/ash/constants/ash_pref_names.h
@@ -469,10 +469,6 @@
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kUserMicrophoneAllowed[];
 COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const char kUserSpeakOnMuteDetectionEnabled[];
-COMPONENT_EXPORT(ASH_CONSTANTS)
-extern const char kShouldShowSpeakOnMuteOptInNudge[];
-COMPONENT_EXPORT(ASH_CONSTANTS)
-extern const char kSpeakOnMuteOptInNudgeShownCount[];
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kUserGeolocationAllowed[];
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kDeviceGeolocationAllowed[];
 COMPONENT_EXPORT(ASH_CONSTANTS)
diff --git a/ash/style/color_palette_controller.cc b/ash/style/color_palette_controller.cc
index 768315d..46215c6 100644
--- a/ash/style/color_palette_controller.cc
+++ b/ash/style/color_palette_controller.cc
@@ -90,14 +90,21 @@
 
   std::unique_ptr<ui::Palette> palette =
       ui::GeneratePalette(seed_color, ToVariant(scheme));
-  // These match the tone values for cros.ref.primary-80,
-  // cros.ref.primary-60, and cros.ref.tertiary-70.
   SampleColorScheme sample;
   sample.scheme = scheme;
-  sample.primary = palette->primary().get(80.f);    // primary 80
-  sample.secondary = palette->primary().get(60.f);  // primary 60
+  // Tertiary is cros.ref.teratiary-70 for all color schemes.
   sample.tertiary = palette->tertiary().get(70.f);  // tertiary 70
 
+  if (scheme == ColorScheme::kVibrant) {
+    // Vibrant uses cros.ref.primary-70 and cros.ref.primary-50.
+    sample.primary = palette->primary().get(70.f);    // primary 70
+    sample.secondary = palette->primary().get(50.f);  // primary 50
+  } else {
+    // All other schemes use cros.ref.primary-80 and cros.ref.primary-60.
+    sample.primary = palette->primary().get(80.f);    // primary 80
+    sample.secondary = palette->primary().get(60.f);  // primary 60
+  }
+
   return sample;
 }
 
diff --git a/ash/style/color_palette_controller_unittest.cc b/ash/style/color_palette_controller_unittest.cc
index e84bc15..c5217b5 100644
--- a/ash/style/color_palette_controller_unittest.cc
+++ b/ash/style/color_palette_controller_unittest.cc
@@ -361,8 +361,8 @@
   auto& result = results.front();
   EXPECT_THAT(result, testing::Eq(SampleColorScheme{
                           .scheme = ColorScheme::kVibrant,
-                          .primary = SkColorSetRGB(0x00, 0xe2, 0x97),
-                          .secondary = SkColorSetRGB(0x00, 0xa5, 0x6d),
+                          .primary = SkColorSetRGB(0x00, 0xc3, 0x82),
+                          .secondary = SkColorSetRGB(0x00, 0x88, 0x59),
                           .tertiary = SkColorSetRGB(0x70, 0xb7, 0xb7)}));
 }
 
diff --git a/ash/system/audio/mic_gain_slider_controller_unittest.cc b/ash/system/audio/mic_gain_slider_controller_unittest.cc
index 0a7011c..ec875d5 100644
--- a/ash/system/audio/mic_gain_slider_controller_unittest.cc
+++ b/ash/system/audio/mic_gain_slider_controller_unittest.cc
@@ -123,11 +123,8 @@
 TEST_P(MicGainSliderControllerTest, CreateMuteToastView) {
   auto toast_view = GetMuteToastView();
   if (IsQsRevampEnabled()) {
-    // Hide the slider icon and show the mic button in the mute toast view.
-    EXPECT_FALSE(toast_view->children()[0]->GetVisible());
-    EXPECT_EQ(
-        u"Toggle Mic. Mic is on, toggling will mute input.",
-        static_cast<IconButton*>(toast_view->children()[1])->GetTooltipText());
+    // `MicGainSliderView` is the first child in the toast view and is visible.
+    EXPECT_TRUE(toast_view->children()[0]->GetVisible());
   } else {
     EXPECT_EQ(
         u"Toggle Mic. Mic is on, toggling will mute input.",
@@ -137,6 +134,10 @@
 
 // Verify pressing the mute button is recorded to metrics.
 TEST_P(MicGainSliderControllerTest, RecordInputGainMuteSource) {
+  // For QsRevamp: `slider_view_` doesn't have a `button()`.
+  if (IsQsRevampEnabled()) {
+    return;
+  }
   PressSliderButton();
   histogram_tester_.ExpectBucketCount(
       CrasAudioHandler::kInputGainMuteSourceHistogramName,
diff --git a/ash/system/audio/mic_gain_slider_view.cc b/ash/system/audio/mic_gain_slider_view.cc
index 95baaeb..cff1bc7 100644
--- a/ash/system/audio/mic_gain_slider_view.cc
+++ b/ash/system/audio/mic_gain_slider_view.cc
@@ -7,11 +7,15 @@
 #include "ash/constants/ash_features.h"
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/strings/grit/ash_strings.h"
+#include "ash/style/ash_color_provider.h"
+#include "ash/style/typography.h"
 #include "ash/system/audio/mic_gain_slider_controller.h"
 #include "ash/system/tray/tray_constants.h"
+#include "ash/system/tray/tray_popup_utils.h"
 #include "ash/system/unified/quick_settings_slider.h"
 #include "chromeos/ash/components/audio/audio_device.h"
 #include "chromeos/ash/components/audio/cras_audio_handler.h"
+#include "chromeos/constants/chromeos_features.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/chromeos/styles/cros_tokens_color_mappings.h"
@@ -52,12 +56,25 @@
       internal_(false) {
   CrasAudioHandler::Get()->AddAudioObserver(this);
 
-  CreateToastLabel();
-  slider()->SetVisible(false);
-  announcement_view_ = AddChildView(std::make_unique<views::View>());
+  // Only adds the `toast_label_` for pre-revamped mic toast.
+  if (!features::IsQsRevampEnabled()) {
+    slider()->SetVisible(false);
+    toast_label_ = AddChildView(std::make_unique<views::Label>());
+    if (chromeos::features::IsJellyEnabled()) {
+      toast_label_->SetEnabledColorId(cros_tokens::kCrosSysOnSurface);
+      TypographyProvider::Get()->StyleLabel(TypographyToken::kCrosBody2,
+                                            *toast_label_);
+    } else {
+      toast_label_->SetEnabledColorId(cros_tokens::kTextColorPrimary);
+      TrayPopupUtils::SetLabelFontList(
+          toast_label_, TrayPopupUtils::FontStyle::kPodMenuHeader);
+    }
+    announcement_view_ = AddChildView(std::make_unique<views::View>());
+    announcement_view_->GetViewAccessibility().AnnounceText(
+        toast_label_->GetText());
+  }
+
   Update(/*by_user=*/false);
-  announcement_view_->GetViewAccessibility().AnnounceText(
-      toast_label()->GetText());
 }
 
 MicGainSliderView::MicGainSliderView(MicGainSliderController* controller,
@@ -141,11 +158,35 @@
   const bool is_muted_by_mute_switch =
       audio_handler->input_muted_by_microphone_mute_switch();
 
+  if (toast_label_) {
+    toast_label_->SetText(
+        l10n_util::GetStringUTF16(is_muted ? IDS_ASH_STATUS_AREA_TOAST_MIC_OFF
+                                           : IDS_ASH_STATUS_AREA_TOAST_MIC_ON));
+  }
+
+  if (button()) {
+    // The button should be gray when muted and colored otherwise.
+    button()->SetToggled(!is_muted);
+    button()->SetEnabled(!is_muted_by_mute_switch);
+    button()->SetVectorIcon(is_muted ? kMutedMicrophoneIcon
+                                     : kImeMenuMicrophoneIcon);
+    std::u16string state_tooltip_text = l10n_util::GetStringUTF16(
+        GetMuteStateTooltipTextResourceId(is_muted, is_muted_by_mute_switch));
+    button()->SetTooltipText(l10n_util::GetStringFUTF16(
+        IDS_ASH_STATUS_TRAY_MIC_GAIN, state_tooltip_text));
+  }
+
   float level = audio_handler->GetInputGainPercent() / 100.f;
 
-  // Gets the input gain for each device to draw each slider in
-  // `AudioDetailedView`.
-  if (features::IsQsRevampEnabled()) {
+  if (!features::IsQsRevampEnabled()) {
+    // To indicate that the volume is muted, set the volume slider to the
+    // minimal visual style.
+    slider()->SetRenderingStyle(
+        is_muted ? views::Slider::RenderingStyle::kMinimalStyle
+                 : views::Slider::RenderingStyle::kDefaultStyle);
+  } else {
+    // Gets the input gain for each device to draw each slider in
+    // `AudioDetailedView`.
     uint64_t device_id;
     if (audio_handler->GetDeviceFromId(device_id_)) {
       // If the device can be found by its id, this slider must not be one of
@@ -169,40 +210,24 @@
     // Still needs to check if `level` is 0 because toggling the mic mute by
     // keyboard will not set the input to be muted in `MicGainSliderController`.
     is_muted = audio_handler->IsInputMutedForDevice(device_id) || level == 0;
-  }
-
-  if (toast_label()) {
-    toast_label()->SetText(
-        l10n_util::GetStringUTF16(is_muted ? IDS_ASH_STATUS_AREA_TOAST_MIC_OFF
-                                           : IDS_ASH_STATUS_AREA_TOAST_MIC_ON));
-  }
-
-  if (button()) {
-    // The button should be gray when muted and colored otherwise.
-    button()->SetToggled(!is_muted);
-    button()->SetEnabled(!is_muted_by_mute_switch);
-    button()->SetVectorIcon(is_muted ? kMutedMicrophoneIcon
-                                     : kImeMenuMicrophoneIcon);
-    std::u16string state_tooltip_text = l10n_util::GetStringUTF16(
-        GetMuteStateTooltipTextResourceId(is_muted, is_muted_by_mute_switch));
-    button()->SetTooltipText(l10n_util::GetStringFUTF16(
-        IDS_ASH_STATUS_TRAY_MIC_GAIN, state_tooltip_text));
-  }
-
-  if (!features::IsQsRevampEnabled()) {
-    // To indicate that the volume is muted, set the volume slider to the
-    // minimal visual style.
-    slider()->SetRenderingStyle(
-        is_muted ? views::Slider::RenderingStyle::kMinimalStyle
-                 : views::Slider::RenderingStyle::kDefaultStyle);
-  } else {
     // For active internal mic stub, `show_internal_stub` indicates whether it's
     // showing and `device_id_` doesn't match with `active_device_id`.
     const bool is_active = show_internal_stub || active_device_id == device_id_;
-    static_cast<QuickSettingsSlider*>(slider())->SetSliderStyle(
-        is_active ? (is_muted ? Style::kRadioActiveMuted : Style::kRadioActive)
-                  : Style::kRadioInactive);
+    auto* qs_slider = static_cast<QuickSettingsSlider*>(slider());
+    const Style slider_style = qs_slider->slider_style();
+    // The default style is for the slider in the toast, and the radio style is
+    // for all other mic gain sliders in the audio subpage.
+    const bool is_default_style = (slider_style == Style::kDefault ||
+                                   slider_style == Style::kDefaultMuted);
 
+    if (is_default_style) {
+      qs_slider->SetSliderStyle(is_muted ? Style::kDefaultMuted
+                                         : Style::kDefault);
+    } else {
+      qs_slider->SetSliderStyle(is_active ? (is_muted ? Style::kRadioActiveMuted
+                                                      : Style::kRadioActive)
+                                          : Style::kRadioInactive);
+    }
     slider_button()->SetVectorIcon(is_muted ? kMutedMicrophoneIcon
                                             : kImeMenuMicrophoneIcon);
     slider_button()->SetIconColorId(
@@ -232,9 +257,11 @@
     bool mute_on,
     CrasAudioHandler::InputMuteChangeMethod method) {
   Update(/*by_user=*/true);
-  announcement_view_->GetViewAccessibility().AnnounceText(
-      l10n_util::GetStringUTF16(mute_on ? IDS_ASH_STATUS_AREA_TOAST_MIC_OFF
-                                        : IDS_ASH_STATUS_AREA_TOAST_MIC_ON));
+  if (!features::IsQsRevampEnabled()) {
+    announcement_view_->GetViewAccessibility().AnnounceText(
+        l10n_util::GetStringUTF16(mute_on ? IDS_ASH_STATUS_AREA_TOAST_MIC_OFF
+                                          : IDS_ASH_STATUS_AREA_TOAST_MIC_ON));
+  }
 }
 
 void MicGainSliderView::OnInputMutedByMicrophoneMuteSwitchChanged(bool muted) {
diff --git a/ash/system/audio/mic_gain_slider_view.h b/ash/system/audio/mic_gain_slider_view.h
index 5842afa..266978a0a 100644
--- a/ash/system/audio/mic_gain_slider_view.h
+++ b/ash/system/audio/mic_gain_slider_view.h
@@ -10,6 +10,10 @@
 #include "chromeos/ash/components/audio/cras_audio_handler.h"
 #include "ui/base/metadata/metadata_header_macros.h"
 
+namespace views {
+class Label;
+}  // namespace views
+
 namespace ash {
 
 class MicGainSliderController;
@@ -47,6 +51,8 @@
   // True if the audio device this slider represents is internal.
   const bool internal_;
 
+  // Owned by views hierarchy.
+  raw_ptr<views::Label, ExperimentalAsh> toast_label_ = nullptr;
   // View used for a11y alert when mute state changes.
   raw_ptr<views::View, ExperimentalAsh> announcement_view_ = nullptr;
 };
diff --git a/ash/system/bluetooth/bluetooth_detailed_view.h b/ash/system/bluetooth/bluetooth_detailed_view.h
index 07aaef3..a00f10e 100644
--- a/ash/system/bluetooth/bluetooth_detailed_view.h
+++ b/ash/system/bluetooth/bluetooth_detailed_view.h
@@ -85,7 +85,9 @@
   // Notifies that the device list has changed and the layout is invalid.
   virtual void NotifyDeviceListChanged() = 0;
 
-  // Returns the device list.
+  // Returns the main content view which contains a list of child views that
+  // make up the list of connected and previously connected bluetooth devices,
+  // including their headers and any separators.
   virtual views::View* device_list() = 0;
 
  protected:
diff --git a/ash/system/bluetooth/bluetooth_device_list_controller_unittest.cc b/ash/system/bluetooth/bluetooth_device_list_controller_unittest.cc
index 7a319a5d..304fe86 100644
--- a/ash/system/bluetooth/bluetooth_device_list_controller_unittest.cc
+++ b/ash/system/bluetooth/bluetooth_device_list_controller_unittest.cc
@@ -8,12 +8,14 @@
 #include <string>
 #include <vector>
 
+#include "ash/constants/ash_features.h"
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/system/bluetooth/bluetooth_detailed_view.h"
 #include "ash/system/bluetooth/bluetooth_device_list_item_view.h"
 #include "ash/system/bluetooth/fake_bluetooth_detailed_view.h"
 #include "ash/system/tray/tri_view.h"
 #include "ash/test/ash_test_base.h"
+#include "base/test/scoped_feature_list.h"
 #include "chromeos/ash/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/views/controls/label.h"
@@ -33,9 +35,13 @@
 
 }  // namespace
 
-class BluetoothDeviceListControllerTest : public AshTestBase {
+class BluetoothDeviceListControllerTest
+    : public AshTestBase,
+      public testing::WithParamInterface<bool> {
  public:
   void SetUp() override {
+    scoped_feature_list_.InitWithFeatureState(features::kQsRevamp,
+                                              IsQsRevampEnabled());
     AshTestBase::SetUp();
 
     fake_bluetooth_detailed_view_ =
@@ -103,22 +109,27 @@
       const TriView* connected_sub_header = FindConnectedSubHeader();
       const TriView* previously_connected_sub_header =
           FindPreviouslyConnectedSubHeader();
-      const views::Separator* device_list_separator = FindSeparator();
 
       EXPECT_TRUE(connected_sub_header);
       EXPECT_TRUE(previously_connected_sub_header);
-      EXPECT_TRUE(device_list_separator);
 
       const size_t connected_index =
           device_list()->GetIndexOf(connected_sub_header).value();
-      const size_t previously_connected_index =
-          device_list()->GetIndexOf(previously_connected_sub_header).value();
-      const size_t separator_index =
-          device_list()->GetIndexOf(device_list_separator).value();
-
       EXPECT_EQ(0u, connected_index);
-      EXPECT_EQ(connected_device_count + 1, separator_index);
-      EXPECT_EQ(separator_index + 1, previously_connected_index);
+
+      // QsRevamp does not use a separator.
+      if (!features::IsQsRevampEnabled()) {
+        const views::Separator* device_list_separator = FindSeparator();
+        EXPECT_TRUE(device_list_separator);
+
+        const size_t previously_connected_index =
+            device_list()->GetIndexOf(previously_connected_sub_header).value();
+        const size_t separator_index =
+            device_list()->GetIndexOf(device_list_separator).value();
+        EXPECT_EQ(connected_device_count + 1, separator_index);
+        EXPECT_EQ(separator_index + 1, previously_connected_index);
+      }
+
       return;
     }
 
@@ -152,6 +163,8 @@
                               ->notify_device_list_changed_call_count());
   }
 
+  bool IsQsRevampEnabled() { return GetParam(); }
+
   views::View* device_list() {
     return static_cast<BluetoothDetailedView*>(
                fake_bluetooth_detailed_view_.get())
@@ -184,9 +197,16 @@
   std::unique_ptr<FakeBluetoothDetailedView> fake_bluetooth_detailed_view_;
   std::unique_ptr<BluetoothDeviceListControllerImpl>
       bluetooth_device_list_controller_impl_;
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
-TEST_F(BluetoothDeviceListControllerTest,
+INSTANTIATE_TEST_SUITE_P(All,
+                         BluetoothDeviceListControllerTest,
+                         testing::Bool());
+
+TEST_P(BluetoothDeviceListControllerTest,
        HasCorrectSubHeaderWithNoPairedDevices) {
   CheckNotifyDeviceListChangedCount(/*call_count=*/0u);
 
@@ -203,8 +223,8 @@
   EXPECT_TRUE(no_device_connected_sub_header);
 }
 
-TEST_F(BluetoothDeviceListControllerTest,
-       HasCorrectDeviceListOrderWithPairedDevices) {
+TEST_P(BluetoothDeviceListControllerTest,
+       HasCorrectDeviceListOrderWithPairedAndPreviouslyPairedDevices) {
   CheckNotifyDeviceListChangedCount(/*call_count=*/0u);
 
   bluetooth_device_list_controller()->UpdateBluetoothEnabledState(true);
@@ -256,14 +276,31 @@
 
   CheckNotifyDeviceListChangedCount(/*call_count=*/4u);
 
-  EXPECT_EQ(5u, device_list()->children().size());
+  // This is confusing but `device_list()` is actually the scroll contents of
+  // the bluetooth detailed view, rather than a list of devices. So the count
+  // here is a combination of the following views (all are optional):
+  // *  Connected device header
+  // *  Connected device list
+  // *  Separator
+  // *  Previously connected device header
+  // *  Previously connected device list
+  const int connected_header_count = FindConnectedSubHeader() ? 1 : 0;
+  const int previously_connected_header_count =
+      FindPreviouslyConnectedSubHeader() ? 1 : 0;
+  const int separator_count = FindSeparator() ? 1 : 0;
+  const size_t device_count =
+      connected_list.size() + previously_connected_list.size();
+  const auto expected_device_list_size = connected_header_count +
+                                         previously_connected_header_count +
+                                         separator_count + device_count;
+  EXPECT_EQ(expected_device_list_size, device_list()->children().size());
 
   CheckDeviceListOrdering(
       /*connected_device_count=*/connected_list.size(),
       /*previously_connected_device_count=*/previously_connected_list.size());
 }
 
-TEST_F(BluetoothDeviceListControllerTest, ExistingDeviceViewsAreUpdated) {
+TEST_P(BluetoothDeviceListControllerTest, ExistingDeviceViewsAreUpdated) {
   CheckNotifyDeviceListChangedCount(/*call_count=*/0u);
 
   bluetooth_device_list_controller()->UpdateBluetoothEnabledState(true);
@@ -296,7 +333,7 @@
                first_item->device_properties()->nickname.value().c_str());
 }
 
-TEST_F(BluetoothDeviceListControllerTest,
+TEST_P(BluetoothDeviceListControllerTest,
        DeviceListIsClearedWhenBluetoothBecomesDisabled) {
   CheckNotifyDeviceListChangedCount(/*call_count=*/0u);
 
diff --git a/ash/system/eche/eche_tray.cc b/ash/system/eche/eche_tray.cc
index 8296b0c7..4f19b00 100644
--- a/ash/system/eche/eche_tray.cc
+++ b/ash/system/eche/eche_tray.cc
@@ -443,33 +443,39 @@
       break;
 
     case eche_app::mojom::ConnectionStatus::kConnectionStatusConnected:
+      PA_LOG(INFO) << "Connection successful, updating UI to connected.";
       eche_connection_status_handler_->SetConnectionStatusForUi(
           connection_status);
       has_reported_initializer_result_ = true;
       base::UmaHistogramBoolean("Eche.NetworkCheck.Result", true);
+      StartGracefulCloseInitializer();
       break;
     case eche_app::mojom::ConnectionStatus::kConnectionStatusFailed:
+      PA_LOG(WARNING) << "Connection failed, updating UI to error state.";
       eche_connection_status_handler_->SetConnectionStatusForUi(
           connection_status);
       base::UmaHistogramBoolean("Eche.NetworkCheck.Result", false);
       has_reported_initializer_result_ = true;
+      StartGracefulCloseInitializer();
       break;
     case eche_app::mojom::ConnectionStatus::kConnectionStatusDisconnected:
-      if (!has_reported_initializer_result_) {
-        // If we've timedout or been disconnected before a success/failure has
-        // come in, report failure.
+      // If we've timed out or been disconnected before a success/failure has
+      // come in, report failure, unless we intentionally disconnected in
+      // preparation for an app stream launch.
+      if (!has_reported_initializer_result_ && !on_initializer_closed_) {
+        PA_LOG(WARNING)
+            << "Disconnected without result, updating UI to error state.";
         base::UmaHistogramBoolean("Eche.NetworkCheck.Result", false);
         eche_connection_status_handler_->SetConnectionStatusForUi(
             eche_app::mojom::ConnectionStatus::kConnectionStatusFailed);
       }
-
-      StartGracefulCloseInitializer();
+      initializer_webview_.reset();
       break;
   }
 }
 
 void EcheTray::OnRequestBackgroundConnectionAttempt() {
-  if (!features::IsEcheNetworkConnectionStateEnabled() || IsInitialized()) {
+  if (!features::IsEcheNetworkConnectionStateEnabled() || web_view_) {
     return;
   }
   has_reported_initializer_result_ = false;
@@ -477,13 +483,30 @@
   initializer_webview_->Navigate(GURL(kEchePrewarmConnectionUrl));
   initializer_timeout_ = std::make_unique<base::DelayTimer>(
       FROM_HERE, kInitializerTimeout, this,
-      &EcheTray::StartGracefulCloseInitializer);
+      &EcheTray::OnBackgroundConnectionTimeout);
   initializer_timeout_->Reset();  // Starts the timer.
   SetIconVisibility(false);
 }
 
 void EcheTray::CloseInitializer() {
   initializer_webview_.reset();
+  if (on_initializer_closed_) {
+    std::move(on_initializer_closed_).Run();
+  }
+}
+
+void EcheTray::OnBackgroundConnectionTimeout() {
+  if (!initializer_webview_ || web_view_) {
+    return;
+  }
+
+  // Notify that the connection attempt failed reset the connection status for
+  // timeouts, this happens automatically for other failures.
+  eche_connection_status_handler_->SetConnectionStatusForUi(
+      eche_app::mojom::ConnectionStatus::kConnectionStatusFailed);
+  eche_connection_status_handler_->OnConnectionStatusChanged(
+      eche_app::mojom::ConnectionStatus::kConnectionStatusDisconnected);
+  StartGracefulCloseInitializer();
 }
 
 void EcheTray::StartGracefulCloseInitializer() {
@@ -611,6 +634,22 @@
     const std::u16string& phone_name,
     eche_app::mojom::ConnectionStatus last_connection_status,
     eche_app::mojom::AppStreamLaunchEntryPoint entry_point) {
+  // We only support a single connection between the phone and chromebook, if
+  // there's an existing background connection it must first be disconnected
+  // before we can continue with the app stream initialization.
+  // TODO(b/283880725) re-use the existing connection instead of terminating it
+  // and starting a new one.
+  if (initializer_webview_) {
+    PA_LOG(INFO)
+        << "Active background connection must be terminated prior to launching "
+           "app.  Saving launch details and will retry once ready.";
+    on_initializer_closed_ =
+        base::BindOnce(&EcheTray::InitBubble, base::Unretained(this),
+                       phone_name, last_connection_status, entry_point);
+    StartGracefulCloseInitializer();
+    return;
+  }
+
   if (features::IsEcheNetworkConnectionStateEnabled() &&
       last_connection_status !=
           eche_app::mojom::ConnectionStatus::kConnectionStatusConnected &&
@@ -675,11 +714,6 @@
   static_cast<views::BoxLayout*>(bubble_view->GetLayoutManager())
       ->set_inside_border_insets(kBubblePadding);
 
-  // Stop any in-progress prewearm channel operation.
-  if (initializer_webview_) {
-    initializer_webview_.reset();
-  }
-
   // TODO(b/271478560): Re-use initializer_webview_ when available, once support
   // launching apps on prewarmed connection is available.
   auto web_view = CreateWebview();
diff --git a/ash/system/eche/eche_tray.h b/ash/system/eche/eche_tray.h
index 5376f8e8..7e89e79 100644
--- a/ash/system/eche/eche_tray.h
+++ b/ash/system/eche/eche_tray.h
@@ -233,6 +233,8 @@
   // the window is closed.
   void StartGracefulClose();
 
+  void OnBackgroundConnectionTimeout();
+
   void SetEcheConnectionStatusHandler(
       eche_app::EcheConnectionStatusHandler* eche_connection_status_handler);
 
@@ -347,7 +349,9 @@
   // attach to.
   std::unique_ptr<AshWebView> initializer_webview_{};
   std::unique_ptr<base::DelayTimer> initializer_timeout_{};
+  base::OnceClosure on_initializer_closed_;
   bool has_reported_initializer_result_ = false;
+  bool has_retried_initializer_ = false;
 
   raw_ptr<eche_app::EcheConnectionStatusHandler, ExperimentalAsh>
       eche_connection_status_handler_ = nullptr;
diff --git a/ash/system/privacy_hub/privacy_hub_controller.cc b/ash/system/privacy_hub/privacy_hub_controller.cc
index 47404ac..3d94ef5b 100644
--- a/ash/system/privacy_hub/privacy_hub_controller.cc
+++ b/ash/system/privacy_hub/privacy_hub_controller.cc
@@ -25,6 +25,7 @@
 void PrivacyHubController::RegisterProfilePrefs(PrefRegistrySimple* registry) {
   registry->RegisterBooleanPref(prefs::kUserCameraAllowed, true);
   registry->RegisterBooleanPref(prefs::kUserMicrophoneAllowed, true);
+  registry->RegisterBooleanPref(prefs::kUserSpeakOnMuteDetectionEnabled, false);
   registry->RegisterBooleanPref(prefs::kUserGeolocationAllowed, true);
 }
 
diff --git a/ash/system/unified/unified_slider_bubble_controller.cc b/ash/system/unified/unified_slider_bubble_controller.cc
index 9a7390b..0c9d3c4 100644
--- a/ash/system/unified/unified_slider_bubble_controller.cc
+++ b/ash/system/unified/unified_slider_bubble_controller.cc
@@ -57,7 +57,6 @@
     // Toggle toast has only a button and label. Slider toast has a slider, a
     // button on the slider body, and possible trailing buttons.
     const bool is_toggle_toast =
-        slider_type == SliderType::SLIDER_TYPE_MIC ||
         slider_type == SliderType::SLIDER_TYPE_KEYBOARD_BACKLIGHT_TOGGLE;
     auto* layout =
         slider_view->SetLayoutManager(std::make_unique<views::BoxLayout>(
diff --git a/ash/system/unified/unified_slider_view.cc b/ash/system/unified/unified_slider_view.cc
index 761671a..a366cc9 100644
--- a/ash/system/unified/unified_slider_view.cc
+++ b/ash/system/unified/unified_slider_view.cc
@@ -8,14 +8,10 @@
 
 #include "ash/constants/ash_features.h"
 #include "ash/constants/quick_settings_catalogs.h"
-#include "ash/style/ash_color_provider.h"
-#include "ash/style/typography.h"
 #include "ash/system/tray/tray_constants.h"
-#include "ash/system/tray/tray_popup_utils.h"
 #include "ash/system/unified/quick_settings_metrics_util.h"
 #include "ash/system/unified/quick_settings_slider.h"
 #include "base/check_op.h"
-#include "chromeos/constants/chromeos_features.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/base/models/image_model.h"
@@ -34,8 +30,6 @@
 
 namespace ash {
 
-using ContentLayerType = AshColorProvider::ContentLayerType;
-
 namespace {
 
 constexpr auto kQsSliderRowPadding = gfx::Insets::TLBR(0, 12, 4, 16);
@@ -70,9 +64,7 @@
                                      int accessible_name_id,
                                      bool read_only,
                                      QuickSettingsSlider::Style slider_style)
-    : icon_(&icon),
-      accessible_name_id_(accessible_name_id),
-      callback_(callback) {
+    : icon_(&icon), callback_(callback) {
   if (!features::IsQsRevampEnabled()) {
     button_ = AddChildView(std::make_unique<IconButton>(
         std::move(callback), IconButton::Type::kMedium, &icon,
@@ -167,34 +159,6 @@
 
 UnifiedSliderView::~UnifiedSliderView() = default;
 
-void UnifiedSliderView::CreateToastLabel() {
-  if (features::IsQsRevampEnabled()) {
-    button_ = AddChildView(std::make_unique<IconButton>(
-        std::move(callback_), IconButton::Type::kMedium, icon_,
-        accessible_name_id_,
-        /*is_togglable=*/true,
-        /*has_border=*/true));
-    slider_->SetVisible(false);
-  }
-  toast_label_ = AddChildView(std::make_unique<views::Label>());
-  if (chromeos::features::IsJellyEnabled()) {
-    toast_label_->SetEnabledColorId(cros_tokens::kCrosSysOnSurface);
-    TypographyProvider::Get()->StyleLabel(TypographyToken::kCrosBody2,
-                                          *toast_label_);
-    return;
-  }
-  TrayPopupUtils::SetLabelFontList(toast_label_,
-                                   TrayPopupUtils::FontStyle::kPodMenuHeader);
-}
-
-void UnifiedSliderView::OnThemeChanged() {
-  views::View::OnThemeChanged();
-  if (toast_label_ && !chromeos::features::IsJellyEnabled()) {
-    toast_label_->SetEnabledColor(AshColorProvider::Get()->GetContentLayerColor(
-        AshColorProvider::ContentLayerType::kTextColorPrimary));
-  }
-}
-
 void UnifiedSliderView::OnEvent(ui::Event* event) {
   if (!event->IsKeyEvent()) {
     views::View::OnEvent(event);
diff --git a/ash/system/unified/unified_slider_view.h b/ash/system/unified/unified_slider_view.h
index 6a77ab3..a9cf786 100644
--- a/ash/system/unified/unified_slider_view.h
+++ b/ash/system/unified/unified_slider_view.h
@@ -18,7 +18,6 @@
 }  // namespace gfx
 
 namespace views {
-class Label;
 class Slider;
 class View;
 }  // namespace views
@@ -73,7 +72,6 @@
 
   IconButton* button() { return button_; }
   views::Slider* slider() { return slider_; }
-  views::Label* toast_label() { return toast_label_; }
   IconButton* slider_button() { return slider_button_; }
 
   // Sets a slider value. If `by_user` is false, accessibility events will not
@@ -81,21 +79,15 @@
   void SetSliderValue(float value, bool by_user);
 
   // views::View:
-  void OnThemeChanged() override;
   void OnEvent(ui::Event* event) override;
 
- protected:
-  void CreateToastLabel();
-
  private:
   raw_ptr<const gfx::VectorIcon, ExperimentalAsh> icon_;
-  int accessible_name_id_;
   views::Button::PressedCallback callback_;
 
   // Unowned. Owned by views hierarchy.
   raw_ptr<IconButton, ExperimentalAsh> button_ = nullptr;
   raw_ptr<views::Slider, ExperimentalAsh> slider_ = nullptr;
-  raw_ptr<views::Label, ExperimentalAsh> toast_label_ = nullptr;
   raw_ptr<IconButton, ExperimentalAsh> slider_button_ = nullptr;
   raw_ptr<views::View, ExperimentalAsh> container_ = nullptr;
 };
diff --git a/ash/webui/BUILD.gn b/ash/webui/BUILD.gn
index 2e10d95..67a273b 100644
--- a/ash/webui/BUILD.gn
+++ b/ash/webui/BUILD.gn
@@ -48,11 +48,6 @@
     "//ui/gl:test_support",
   ]
 
-  # Tests for Camera App only work on Chrome OS device but not linux-chromeos.
-  if (is_chromeos_device) {
-    deps += [ "//ash/webui/camera_app_ui:unit_tests" ]
-  }
-
   data_deps = [
     "//chromeos/strings:chromeos_test_strings",
     "//ui/resources:ui_test_pak_data",
diff --git a/ash/webui/camera_app_ui/BUILD.gn b/ash/webui/camera_app_ui/BUILD.gn
index 02ea08d..0e0238f 100644
--- a/ash/webui/camera_app_ui/BUILD.gn
+++ b/ash/webui/camera_app_ui/BUILD.gn
@@ -55,8 +55,6 @@
 
 source_set("window_managemet") {
   sources = [
-    "camera_app_window_manager.cc",
-    "camera_app_window_manager.h",
     "camera_app_window_state_controller.cc",
     "camera_app_window_state_controller.h",
   ]
@@ -94,23 +92,6 @@
   ]
 }
 
-source_set("unit_tests") {
-  testonly = true
-
-  sources = [ "camera_app_window_manager_unittest.cc" ]
-
-  deps = [
-    ":window_managemet",
-    "//base",
-    "//base/test:test_support",
-    "//content/test:test_support",
-    "//testing/gmock",
-    "//testing/gtest",
-    "//ui/views",
-    "//ui/views:test_support",
-  ]
-}
-
 mojom("mojo_bindings") {
   sources = [ "camera_app_helper.mojom" ]
 
diff --git a/ash/webui/camera_app_ui/camera_app_helper.mojom b/ash/webui/camera_app_ui/camera_app_helper.mojom
index 5515907..79d56f6 100644
--- a/ash/webui/camera_app_ui/camera_app_helper.mojom
+++ b/ash/webui/camera_app_ui/camera_app_helper.mojom
@@ -69,6 +69,9 @@
 interface WindowStateMonitor {
   // Updates when any of the window states are changed.
   OnWindowStateChanged(array<WindowStateType> states);
+
+  // Updates when the window focus state is changed.
+  OnWindowFocusChanged(bool is_focus);
 };
 
 // The possible result of the file deletion monitor.
@@ -199,12 +202,6 @@
   // Opens the given URL in the browser.
   OpenUrlInBrowser(url.mojom.Url url);
 
-  // Sets the monitor to monitor the camera usage ownership changed. If the
-  // window operation is not supported for current instance, return false.
-  SetCameraUsageMonitor(
-      pending_remote<CameraUsageOwnershipMonitor> usage_monitor)
-          => (bool is_success);
-
   // Gets the controller to control and monitor the window state of app.
   GetWindowStateController()
       => (pending_remote<WindowStateController> controller);
diff --git a/ash/webui/camera_app_ui/camera_app_helper_impl.cc b/ash/webui/camera_app_ui/camera_app_helper_impl.cc
index ae32c2f..67f78f7 100644
--- a/ash/webui/camera_app_ui/camera_app_helper_impl.cc
+++ b/ash/webui/camera_app_ui/camera_app_helper_impl.cc
@@ -267,13 +267,6 @@
       NewWindowDelegate::Disposition::kNewForegroundTab);
 }
 
-void CameraAppHelperImpl::SetCameraUsageMonitor(
-    mojo::PendingRemote<CameraUsageOwnershipMonitor> usage_monitor,
-    SetCameraUsageMonitorCallback callback) {
-  camera_app_ui_->app_window_manager()->SetCameraUsageMonitor(
-      window_, std::move(usage_monitor), std::move(callback));
-}
-
 void CameraAppHelperImpl::GetWindowStateController(
     GetWindowStateControllerCallback callback) {
   if (!window_state_controller_) {
diff --git a/ash/webui/camera_app_ui/camera_app_helper_impl.h b/ash/webui/camera_app_ui/camera_app_helper_impl.h
index f89cf1e5..e7777d8 100644
--- a/ash/webui/camera_app_ui/camera_app_helper_impl.h
+++ b/ash/webui/camera_app_ui/camera_app_helper_impl.h
@@ -76,9 +76,6 @@
   void OpenFileInGallery(const std::string& name) override;
   void OpenFeedbackDialog(const std::string& placeholder) override;
   void OpenUrlInBrowser(const GURL& url) override;
-  void SetCameraUsageMonitor(
-      mojo::PendingRemote<CameraUsageOwnershipMonitor> usage_monitor,
-      SetCameraUsageMonitorCallback callback) override;
   void GetWindowStateController(
       GetWindowStateControllerCallback callback) override;
   void SendNewCaptureBroadcast(bool is_video, const std::string& name) override;
diff --git a/ash/webui/camera_app_ui/camera_app_ui.cc b/ash/webui/camera_app_ui/camera_app_ui.cc
index 2660ecc..5102b08 100644
--- a/ash/webui/camera_app_ui/camera_app_ui.cc
+++ b/ash/webui/camera_app_ui/camera_app_ui.cc
@@ -292,10 +292,6 @@
   return web_ui()->GetWebContents()->GetTopLevelNativeWindow();
 }
 
-CameraAppWindowManager* CameraAppUI::app_window_manager() {
-  return CameraAppWindowManager::GetInstance();
-}
-
 const GURL& CameraAppUI::url() {
   return web_ui()->GetWebContents()->GetLastCommittedURL();
 }
diff --git a/ash/webui/camera_app_ui/camera_app_ui.h b/ash/webui/camera_app_ui/camera_app_ui.h
index 85a2031..16a9d14 100644
--- a/ash/webui/camera_app_ui/camera_app_ui.h
+++ b/ash/webui/camera_app_ui/camera_app_ui.h
@@ -7,7 +7,6 @@
 
 #include "ash/webui/camera_app_ui/camera_app_helper.mojom.h"
 #include "ash/webui/camera_app_ui/camera_app_ui_delegate.h"
-#include "ash/webui/camera_app_ui/camera_app_window_manager.h"
 #include "ash/webui/camera_app_ui/url_constants.h"
 #include "ash/webui/system_apps/public/system_web_app_ui_config.h"
 #include "content/public/browser/devtools_agent_host_observer.h"
@@ -70,8 +69,6 @@
 
   aura::Window* window();
 
-  CameraAppWindowManager* app_window_manager();
-
   const GURL& url();
 
   // content::DevToolsAgentHostObserver overrides.
diff --git a/ash/webui/camera_app_ui/camera_app_window_manager.cc b/ash/webui/camera_app_ui/camera_app_window_manager.cc
deleted file mode 100644
index f2e4af0..0000000
--- a/ash/webui/camera_app_ui/camera_app_window_manager.cc
+++ /dev/null
@@ -1,215 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ash/webui/camera_app_ui/camera_app_window_manager.h"
-
-#include "content/public/browser/browser_thread.h"
-#include "ui/aura/window.h"
-#include "ui/views/widget/widget.h"
-
-namespace ash {
-
-CameraAppWindowManager::~CameraAppWindowManager() = default;
-
-// static
-CameraAppWindowManager* CameraAppWindowManager::GetInstance() {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  return base::Singleton<CameraAppWindowManager>::get();
-}
-
-void CameraAppWindowManager::SetCameraUsageMonitor(
-    aura::Window* window,
-    mojo::PendingRemote<camera_app::mojom::CameraUsageOwnershipMonitor>
-        usage_monitor,
-    base::OnceCallback<void(bool)> callback) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  auto* widget = views::Widget::GetWidgetForNativeWindow(window);
-  if (widget == nullptr) {
-    // For some rare use cases (e.g. Launch CCA via devtool inspector), the
-    // widget will be null. Therefore, returns here to let CCA know that
-    // window-retaled operations is not supported.
-    std::move(callback).Run(false);
-    return;
-  }
-
-  mojo::Remote<camera_app::mojom::CameraUsageOwnershipMonitor> remote(
-      std::move(usage_monitor));
-  remote.set_disconnect_handler(
-      base::BindOnce(&CameraAppWindowManager::OnMonitorMojoConnectionError,
-                     base::Unretained(this), widget));
-  camera_usage_monitors_.emplace(widget, std::move(remote));
-
-  if (!widget->HasObserver(this)) {
-    widget->AddObserver(this);
-  }
-  std::move(callback).Run(true);
-
-  if (widget->IsVisible()) {
-    OnWidgetActivationChanged(widget, true);
-  }
-}
-
-void CameraAppWindowManager::OnWidgetVisibilityChanged(views::Widget* widget,
-                                                       bool visible) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  // This event will be triggered and the |visible| will be set to:
-  // * True:
-  //     1. When the window is restored from minimized.
-  // * False:
-  //     1. When the window is minimized.
-  //     2. When the launcher is opened in tablet mode.
-  if (visible ||
-      camera_usage_monitors_.find(widget) == camera_usage_monitors_.end()) {
-    return;
-  }
-
-  if (pending_transfer_.has_value() && widget == *pending_transfer_) {
-    pending_transfer_ = absl::nullopt;
-    // It is possible that |*pending_transfer_| == |owner_|. For example: when a
-    // widget is activated while it is suspending. Therefore, we cannot return
-    // here.
-  }
-
-  if (widget != owner_) {
-    return;
-  }
-
-  switch (transfer_state_) {
-    case TransferState::kIdle:
-      SuspendCameraUsage();
-      break;
-    case TransferState::kSuspending:
-      break;
-    case TransferState::kResuming:
-      pending_transfer_ = nullptr;
-      break;
-  }
-}
-
-void CameraAppWindowManager::OnWidgetActivationChanged(views::Widget* widget,
-                                                       bool active) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  // This event will be triggered and the |active| will be set to:
-  // * True:
-  //     1. When the window is restored from minimized.
-  // * False:
-  //     1. When the window is minimized.
-  //     2. When the launcher is opened (half/fully).
-  //     3. When the window lost focus by clicking other windows.
-  //     4. When the screen is locked.
-  //     5. When entering the overview mode.
-  if (!active ||
-      camera_usage_monitors_.find(widget) == camera_usage_monitors_.end()) {
-    return;
-  }
-
-  switch (transfer_state_) {
-    case TransferState::kIdle:
-      if (owner_ == nullptr) {
-        owner_ = widget;
-        ResumeCameraUsage();
-      } else if (owner_ != widget) {
-        pending_transfer_ = widget;
-        SuspendCameraUsage();
-      }
-      break;
-    case TransferState::kSuspending:
-      pending_transfer_ = widget;
-      break;
-    case TransferState::kResuming:
-      if (owner_ == widget) {
-        pending_transfer_ = absl::nullopt;
-      } else {
-        pending_transfer_ = widget;
-      }
-      break;
-  }
-}
-
-void CameraAppWindowManager::OnWidgetDestroying(views::Widget* widget) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  widget->RemoveObserver(this);
-}
-
-CameraAppWindowManager::CameraAppWindowManager() = default;
-
-void CameraAppWindowManager::OnMonitorMojoConnectionError(
-    views::Widget* widget) {
-  camera_usage_monitors_.erase(widget);
-
-  if (pending_transfer_.has_value() && widget == *pending_transfer_) {
-    pending_transfer_ = absl::nullopt;
-  }
-  if (widget == owner_) {
-    ResumeNextOrIdle();
-  }
-}
-
-void CameraAppWindowManager::SuspendCameraUsage() {
-  DCHECK_NE(owner_, nullptr);
-  auto it = camera_usage_monitors_.find(owner_);
-  DCHECK(it != camera_usage_monitors_.end());
-
-  transfer_state_ = TransferState::kSuspending;
-  it->second->OnCameraUsageOwnershipChanged(
-      false,
-      base::BindRepeating(&CameraAppWindowManager::OnSuspendedCameraUsage,
-                          base::Unretained(this), owner_));
-}
-
-void CameraAppWindowManager::OnSuspendedCameraUsage(views::Widget* prev_owner) {
-  // TODO(crbug.com/1143535): Avoid logging here when we either have test
-  // coverage to simulate the scenario which can hit this or we are confident
-  // enough the case won't happen.
-  if (prev_owner != owner_) {
-    LOG(ERROR) << "The suspension has been interrupted.";
-    return;
-  }
-  ResumeNextOrIdle();
-}
-
-void CameraAppWindowManager::ResumeCameraUsage() {
-  DCHECK_NE(owner_, nullptr);
-  auto it = camera_usage_monitors_.find(owner_);
-  DCHECK(it != camera_usage_monitors_.end());
-
-  transfer_state_ = TransferState::kResuming;
-  it->second->OnCameraUsageOwnershipChanged(
-      true, base::BindRepeating(&CameraAppWindowManager::OnResumedCameraUsage,
-                                base::Unretained(this), owner_));
-}
-
-void CameraAppWindowManager::OnResumedCameraUsage(views::Widget* prev_owner) {
-  // TODO(crbug.com/1143535): Avoid logging here when we either have test
-  // coverage to simulate the scenario which can hit this or we are confident
-  // enough the case won't happen.
-  if (prev_owner != owner_) {
-    LOG(ERROR) << "The resume has been interrupted.";
-    return;
-  }
-
-  if (pending_transfer_.has_value()) {
-    SuspendCameraUsage();
-  } else {
-    transfer_state_ = TransferState::kIdle;
-  }
-}
-
-void CameraAppWindowManager::ResumeNextOrIdle() {
-  auto next_owner(pending_transfer_);
-  pending_transfer_ = absl::nullopt;
-  if (next_owner.has_value()) {
-    owner_ = *next_owner;
-  } else {
-    owner_ = nullptr;
-  }
-
-  if (owner_ != nullptr) {
-    ResumeCameraUsage();
-  } else {
-    transfer_state_ = TransferState::kIdle;
-  }
-}
-
-}  // namespace ash
diff --git a/ash/webui/camera_app_ui/camera_app_window_manager.h b/ash/webui/camera_app_ui/camera_app_window_manager.h
deleted file mode 100644
index e15eef6c..0000000
--- a/ash/webui/camera_app_ui/camera_app_window_manager.h
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_WEBUI_CAMERA_APP_UI_CAMERA_APP_WINDOW_MANAGER_H_
-#define ASH_WEBUI_CAMERA_APP_UI_CAMERA_APP_WINDOW_MANAGER_H_
-
-#include "ash/webui/camera_app_ui/camera_app_helper.mojom.h"
-#include "base/containers/flat_map.h"
-#include "base/memory/raw_ptr.h"
-#include "base/memory/singleton.h"
-#include "mojo/public/cpp/bindings/remote.h"
-#include "ui/views/widget/widget_observer.h"
-
-namespace aura {
-class Window;
-}  // namespace aura
-
-namespace views {
-class Widget;
-}  // namespace views
-
-namespace ash {
-
-// A manager to manage the camera usage ownership between multiple camera app
-// windows. The clients should only use this object as a singleton instance and
-// should only access it on the UI thread.
-class CameraAppWindowManager : public views::WidgetObserver {
- public:
-  CameraAppWindowManager(const CameraAppWindowManager&) = delete;
-  CameraAppWindowManager& operator=(const CameraAppWindowManager&) = delete;
-  ~CameraAppWindowManager() override;
-
-  static CameraAppWindowManager* GetInstance();
-
-  void SetCameraUsageMonitor(
-      aura::Window* window,
-      mojo::PendingRemote<camera_app::mojom::CameraUsageOwnershipMonitor>
-          usage_monitor,
-      base::OnceCallback<void(bool)> callback);
-
-  // views::WidgetObserver:
-  void OnWidgetVisibilityChanged(views::Widget* widget, bool visible) override;
-  void OnWidgetActivationChanged(views::Widget* widget, bool active) override;
-  void OnWidgetDestroying(views::Widget* widget) override;
-
- private:
-  friend class CameraAppWindowManagerTest;
-
-  CameraAppWindowManager();
-
-  friend struct base::DefaultSingletonTraits<CameraAppWindowManager>;
-  enum class TransferState {
-    kIdle,
-    kSuspending,
-    kResuming,
-  };
-  void OnMonitorMojoConnectionError(views::Widget* widget);
-  void SuspendCameraUsage();
-  void OnSuspendedCameraUsage(views::Widget* prev_owner);
-  void ResumeCameraUsage();
-  void OnResumedCameraUsage(views::Widget* prev_owner);
-  void ResumeNextOrIdle();
-
-  base::flat_map<views::Widget*,
-                 mojo::Remote<camera_app::mojom::CameraUsageOwnershipMonitor>>
-      camera_usage_monitors_;
-
-  // Whether the |owner_| is transferring the camera usage.
-  TransferState transfer_state_ = TransferState::kIdle;
-
-  // The widget which has the camera usage ownership currently.
-  raw_ptr<views::Widget, ExperimentalAsh> owner_ = nullptr;
-
-  // For the pending camera usage owner, there are three possible values:
-  // 1. absl::nullopt: When there is no pending owner. Transfer can stop.
-  // 2. nullptr:       When there should be no active window after the transfer
-  //                   is stopped.
-  // 3. non-null:      When there is another window which should own camera
-  //                   usage.
-  absl::optional<views::Widget*> pending_transfer_;
-};
-
-}  // namespace ash
-
-#endif  // ASH_WEBUI_CAMERA_APP_UI_CAMERA_APP_WINDOW_MANAGER_H_
diff --git a/ash/webui/camera_app_ui/camera_app_window_manager_unittest.cc b/ash/webui/camera_app_ui/camera_app_window_manager_unittest.cc
deleted file mode 100644
index 77d3f6d..0000000
--- a/ash/webui/camera_app_ui/camera_app_window_manager_unittest.cc
+++ /dev/null
@@ -1,248 +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.
-
-#include "ash/webui/camera_app_ui/camera_app_window_manager.h"
-
-#include <queue>
-
-#include "base/test/task_environment.h"
-#include "content/public/test/browser_task_environment.h"
-#include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "mojo/public/cpp/bindings/pending_remote.h"
-#include "mojo/public/cpp/bindings/receiver.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/views/test/views_test_base.h"
-#include "ui/views/widget/widget.h"
-
-namespace ash {
-
-namespace {
-
-using testing::_;
-using testing::Invoke;
-using CameraUsageOwnershipMonitor =
-    camera_app::mojom::CameraUsageOwnershipMonitor;
-using OnCameraUsageOwnershipChangedCallback = camera_app::mojom::
-    CameraUsageOwnershipMonitor::OnCameraUsageOwnershipChangedCallback;
-
-class MockCameraUsageOwnershipMonitor
-    : public camera_app::mojom::CameraUsageOwnershipMonitor {
- public:
-  MockCameraUsageOwnershipMonitor() : receiver_(this) {}
-
-  void Bind(mojo::PendingReceiver<CameraUsageOwnershipMonitor> receiver) {
-    receiver_.Bind(std::move(receiver));
-  }
-
-  void Reset() { receiver_.reset(); }
-
-  void OnCameraUsageOwnershipChanged(
-      bool has_usage,
-      OnCameraUsageOwnershipChangedCallback callback) override {
-    DoOnCameraUsageOwnershipChanged(has_usage, std::move(callback));
-  }
-  MOCK_METHOD(void,
-              DoOnCameraUsageOwnershipChanged,
-              (bool has_usage, OnCameraUsageOwnershipChangedCallback callback));
-
- private:
-  mojo::Receiver<camera_app::mojom::CameraUsageOwnershipMonitor> receiver_;
-};
-
-}  // namespace
-
-class CameraAppWindowManagerTest : public views::ViewsTestBase {
- public:
-  struct MockApp {
-    std::unique_ptr<views::Widget> widget;
-    testing::StrictMock<MockCameraUsageOwnershipMonitor> ownership_monitor;
-  };
-
-  CameraAppWindowManagerTest()
-      : views::ViewsTestBase(std::unique_ptr<base::test::TaskEnvironment>(
-            std::make_unique<content::BrowserTaskEnvironment>(
-                content::BrowserTaskEnvironment::MainThreadType::UI,
-                content::BrowserTaskEnvironment::TimeSource::MOCK_TIME))) {}
-  CameraAppWindowManagerTest(const CameraAppWindowManagerTest&) = delete;
-  CameraAppWindowManagerTest& operator=(const CameraAppWindowManagerTest&) =
-      delete;
-  ~CameraAppWindowManagerTest() override = default;
-
-  void BindMonitor(MockApp* mock_app) {
-    mojo::PendingRemote<CameraUsageOwnershipMonitor> monitor_remote;
-    mock_app->ownership_monitor.Bind(
-        monitor_remote.InitWithNewPipeAndPassReceiver());
-    app_window_manager.SetCameraUsageMonitor(
-        mock_app->widget->GetNativeWindow(), std::move(monitor_remote),
-        base::DoNothing());
-  }
-
-  // The activation observer will not be triggered if the focus hasn't been
-  // moved to other widget. It should not happen in the real scenario so for
-  // testing, we simply focus on some random target and then focus back.
-  void FocusOnOtherWidget() {
-    auto some_other_widget = CreateTestWidget();
-    some_other_widget->Activate();
-  }
-
-  void Ack(bool has_usage, OnCameraUsageOwnershipChangedCallback callback) {
-    std::move(callback).Run();
-  }
-
-  void Drop(bool has_usage, OnCameraUsageOwnershipChangedCallback callback) {
-    dropped_callbacks_.push(std::move(callback));
-  }
-
-  void PutCallbackPending(bool has_usage,
-                          OnCameraUsageOwnershipChangedCallback callback) {
-    pending_callbacks_.push(std::move(callback));
-  }
-
-  void ConsumePendingCallbacks() {
-    while (!pending_callbacks_.empty()) {
-      std::move(pending_callbacks_.front()).Run();
-      pending_callbacks_.pop();
-    }
-  }
-
- protected:
-  CameraAppWindowManager app_window_manager;
-
- private:
-  std::queue<OnCameraUsageOwnershipChangedCallback> pending_callbacks_;
-
-  // Put the callbacks to be dropped in a queue to avoid check failure.
-  std::queue<OnCameraUsageOwnershipChangedCallback> dropped_callbacks_;
-};
-
-// Test that when a window lost visibility / activated, the camera usage is
-// suspended/resumed.
-TEST_F(CameraAppWindowManagerTest, LostVisibilityAndActivated) {
-  MockApp mock_app = {CreateTestWidget()};
-  auto* widget = mock_app.widget.get();
-  auto& monitor = mock_app.ownership_monitor;
-
-  EXPECT_CALL(monitor, DoOnCameraUsageOwnershipChanged(true, _))
-      .WillOnce(Invoke(this, &CameraAppWindowManagerTest::Ack));
-  widget->Show();
-  BindMonitor(&mock_app);
-  base::RunLoop().RunUntilIdle();
-
-  EXPECT_CALL(monitor, DoOnCameraUsageOwnershipChanged(false, _))
-      .WillOnce(Invoke(this, &CameraAppWindowManagerTest::Ack));
-  widget->Hide();
-  base::RunLoop().RunUntilIdle();
-
-  FocusOnOtherWidget();
-
-  EXPECT_CALL(monitor, DoOnCameraUsageOwnershipChanged(true, _))
-      .WillOnce(Invoke(this, &CameraAppWindowManagerTest::Ack));
-  widget->Show();
-  base::RunLoop().RunUntilIdle();
-}
-
-// Test that when a window lost visibility when the camera usage is resuming,
-// the camera usage should be suspended in the end.
-TEST_F(CameraAppWindowManagerTest, LostVisibilityWhenResuming) {
-  MockApp mock_app = {CreateTestWidget()};
-  auto* widget = mock_app.widget.get();
-  auto& monitor = mock_app.ownership_monitor;
-
-  EXPECT_CALL(monitor, DoOnCameraUsageOwnershipChanged(true, _))
-      .WillOnce(Invoke(this, &CameraAppWindowManagerTest::PutCallbackPending));
-  widget->Show();
-  BindMonitor(&mock_app);
-  base::RunLoop().RunUntilIdle();
-
-  EXPECT_CALL(monitor, DoOnCameraUsageOwnershipChanged(false, _))
-      .WillOnce(Invoke(this, &CameraAppWindowManagerTest::Ack));
-  widget->Hide();
-  ConsumePendingCallbacks();
-  base::RunLoop().RunUntilIdle();
-}
-
-// Test that when a window is activated when the camera usage is suspending, the
-// camera usage should be resumed in the end.
-TEST_F(CameraAppWindowManagerTest, ActivateWhenSuspending) {
-  MockApp mock_app = {CreateTestWidget()};
-  auto* widget = mock_app.widget.get();
-  auto& monitor = mock_app.ownership_monitor;
-
-  EXPECT_CALL(monitor, DoOnCameraUsageOwnershipChanged(true, _))
-      .WillOnce(Invoke(this, &CameraAppWindowManagerTest::Ack));
-  widget->Show();
-  BindMonitor(&mock_app);
-  base::RunLoop().RunUntilIdle();
-
-  EXPECT_CALL(monitor, DoOnCameraUsageOwnershipChanged(false, _))
-      .WillOnce(Invoke(this, &CameraAppWindowManagerTest::PutCallbackPending));
-  widget->Hide();
-  base::RunLoop().RunUntilIdle();
-
-  FocusOnOtherWidget();
-
-  EXPECT_CALL(monitor, DoOnCameraUsageOwnershipChanged(true, _))
-      .WillOnce(Invoke(this, &CameraAppWindowManagerTest::Ack));
-  widget->Show();
-  ConsumePendingCallbacks();
-  base::RunLoop().RunUntilIdle();
-}
-
-// Test that when a new window is launched, it can get the camera usage.
-TEST_F(CameraAppWindowManagerTest, MultipleWindows) {
-  MockApp mock_app1 = {CreateTestWidget()};
-  auto* widget = mock_app1.widget.get();
-  auto& monitor = mock_app1.ownership_monitor;
-
-  EXPECT_CALL(monitor, DoOnCameraUsageOwnershipChanged(true, _))
-      .WillOnce(Invoke(this, &CameraAppWindowManagerTest::Ack));
-  widget->Show();
-  BindMonitor(&mock_app1);
-  base::RunLoop().RunUntilIdle();
-
-  // The original owner should suspend first.
-  EXPECT_CALL(monitor, DoOnCameraUsageOwnershipChanged(false, _))
-      .WillOnce(Invoke(this, &CameraAppWindowManagerTest::PutCallbackPending));
-  MockApp mock_app2 = {CreateTestWidget()};
-  mock_app2.widget->Show();
-  BindMonitor(&mock_app2);
-  base::RunLoop().RunUntilIdle();
-
-  // And the new owner should get the ownership afterwards.
-  EXPECT_CALL(mock_app2.ownership_monitor,
-              DoOnCameraUsageOwnershipChanged(true, _))
-      .WillOnce(Invoke(this, &CameraAppWindowManagerTest::Ack));
-  ConsumePendingCallbacks();
-  base::RunLoop().RunUntilIdle();
-}
-
-// Test that when a window is unexpectedly closed during transferring camera
-// usage, the next window is still able to grant the camera usage.
-TEST_F(CameraAppWindowManagerTest, UnexpectedlyClosed) {
-  MockApp mock_app1 = {CreateTestWidget()};
-  auto* widget = mock_app1.widget.get();
-  auto& monitor = mock_app1.ownership_monitor;
-
-  EXPECT_CALL(monitor, DoOnCameraUsageOwnershipChanged(true, _))
-      .WillOnce(Invoke(this, &CameraAppWindowManagerTest::Drop));
-  widget->Show();
-  BindMonitor(&mock_app1);
-  base::RunLoop().RunUntilIdle();
-
-  // Close the app without sending ack that the camera usage is resumed.
-  monitor.Reset();
-
-  // Check that newly instantiated app is still able to get the camera
-  // ownership although the previous one is unexpectedly closed.
-  MockApp mock_app2 = {CreateTestWidget()};
-  EXPECT_CALL(mock_app2.ownership_monitor,
-              DoOnCameraUsageOwnershipChanged(true, _))
-      .WillOnce(Invoke(this, &CameraAppWindowManagerTest::Ack));
-  mock_app2.widget->Show();
-  BindMonitor(&mock_app2);
-  base::RunLoop().RunUntilIdle();
-}
-
-}  // namespace ash
diff --git a/ash/webui/camera_app_ui/camera_app_window_state_controller.cc b/ash/webui/camera_app_ui/camera_app_window_state_controller.cc
index 5051d4f..e66c74d4 100644
--- a/ash/webui/camera_app_ui/camera_app_window_state_controller.cc
+++ b/ash/webui/camera_app_ui/camera_app_window_state_controller.cc
@@ -113,6 +113,7 @@
     std::move(focus_callbacks_.front()).Run();
     focus_callbacks_.pop();
   }
+  OnWindowFocusChanged(active);
 }
 
 void CameraAppWindowStateController::OnWidgetBoundsChanged(
@@ -151,6 +152,12 @@
   }
 }
 
+void CameraAppWindowStateController::OnWindowFocusChanged(bool is_focus) {
+  for (const auto& monitor : monitors_) {
+    monitor->OnWindowFocusChanged(is_focus);
+  }
+}
+
 base::flat_set<CameraAppWindowStateController::WindowStateType>
 CameraAppWindowStateController::GetCurrentWindowStates() {
   base::flat_set<CameraAppWindowStateController::WindowStateType> states;
diff --git a/ash/webui/camera_app_ui/camera_app_window_state_controller.h b/ash/webui/camera_app_ui/camera_app_window_state_controller.h
index 09f0a590b3..b1abd22 100644
--- a/ash/webui/camera_app_ui/camera_app_window_state_controller.h
+++ b/ash/webui/camera_app_ui/camera_app_window_state_controller.h
@@ -56,6 +56,7 @@
 
  private:
   void OnWindowStateChanged();
+  void OnWindowFocusChanged(bool is_focus);
   base::flat_set<WindowStateType> GetCurrentWindowStates();
 
   raw_ptr<views::Widget, ExperimentalAsh> widget_;
diff --git a/ash/webui/camera_app_ui/resources/js/device/preview.ts b/ash/webui/camera_app_ui/resources/js/device/preview.ts
index 22c7aa9e..ca5ca6ea 100644
--- a/ash/webui/camera_app_ui/resources/js/device/preview.ts
+++ b/ash/webui/camera_app_ui/resources/js/device/preview.ts
@@ -342,7 +342,8 @@
         this.vidPid = await deviceOperator.getVidPid(deviceId);
       }
 
-      assert(this.onPreviewExpired === null);
+      assert(
+          this.onPreviewExpired === null || this.onPreviewExpired.isSignaled());
       this.onPreviewExpired = new WaitableEvent();
       state.set(state.State.STREAMING, true);
     } catch (e) {
@@ -374,7 +375,6 @@
 
     if (this.onPreviewExpired !== null) {
       this.onPreviewExpired.signal();
-      this.onPreviewExpired = null;
     }
     state.set(state.State.STREAMING, false);
   }
diff --git a/ash/webui/camera_app_ui/resources/js/js.gni b/ash/webui/camera_app_ui/resources/js/js.gni
index 670855b..cdebe155 100644
--- a/ash/webui/camera_app_ui/resources/js/js.gni
+++ b/ash/webui/camera_app_ui/resources/js/js.gni
@@ -66,6 +66,7 @@
   "mojo/image_capture.ts",
   "mojo/type.ts",
   "mojo/util.ts",
+  "multi_window_manager.ts",
   "nav.ts",
   "perf.ts",
   "snackbar.ts",
diff --git a/ash/webui/camera_app_ui/resources/js/main.ts b/ash/webui/camera_app_ui/resources/js/main.ts
index eb9f2d6..2f627c01 100644
--- a/ash/webui/camera_app_ui/resources/js/main.ts
+++ b/ash/webui/camera_app_ui/resources/js/main.ts
@@ -21,6 +21,7 @@
 import {GalleryButton} from './gallerybutton.js';
 import {I18nString} from './i18n_string.js';
 import {Intent} from './intent.js';
+import * as Comlink from './lib/comlink.js';
 import {loadSvgImages} from './lit/svg_wrapper.js';
 import * as metrics from './metrics.js';
 import * as filesystem from './models/file_system.js';
@@ -28,6 +29,8 @@
 import * as localStorage from './models/local_storage.js';
 import {ChromeHelper} from './mojo/chrome_helper.js';
 import {DeviceOperator} from './mojo/device_operator.js';
+import {WindowStateType} from './mojo/type.js';
+import {WindowInstance} from './multi_window_manager.js';
 import * as nav from './nav.js';
 import {PerfLogger} from './perf.js';
 import {preloadImagesList} from './preload_images.js';
@@ -118,7 +121,7 @@
     }, {passive: false, capture: true});
 
     window.addEventListener('resize', () => nav.layoutShownViews());
-    windowController.addListener(() => nav.layoutShownViews());
+    windowController.addWindowStateListener(() => nav.layoutShownViews());
 
     util.setupI18nElements(document.body);
     this.setupTooltip();
@@ -310,23 +313,7 @@
     })();
 
     const cameraResourceInitialized = new WaitableEvent();
-    const exploitUsage = async () => {
-      if (cameraResourceInitialized.isSignaled()) {
-        this.resume();
-      } else {
-        // CCA must get camera usage for completing its initialization when
-        // first launched.
-        await this.cameraManager.initialize(this.cameraView);
-        await this.cameraView.initialize();
-        cameraResourceInitialized.signal();
-      }
-    };
-    const releaseUsage = async () => {
-      assert(cameraResourceInitialized.isSignaled());
-      await this.suspend();
-    };
-    await ChromeHelper.getInstance().initCameraUsageMonitor(
-        exploitUsage, releaseUsage);
+    await this.setupMultiWindowHandling(cameraResourceInitialized);
 
     let cameraStartSuccessful = false;
 
@@ -398,6 +385,61 @@
   beginTake(shutterType: metrics.ShutterType): Promise<void>|null {
     return this.cameraView.beginTake(shutterType);
   }
+
+  async setupMultiWindowHandling(cameraResourceInitialized: WaitableEvent):
+      Promise<void> {
+    const exploitUsage = async () => {
+      if (cameraResourceInitialized.isSignaled()) {
+        this.resume();
+      } else {
+        // CCA must get camera usage for completing its initialization when
+        // first launched.
+        await this.cameraManager.initialize(this.cameraView);
+        await this.cameraView.initialize();
+        cameraResourceInitialized.signal();
+      }
+    };
+    const releaseUsage = async () => {
+      assert(cameraResourceInitialized.isSignaled());
+      await this.suspend();
+    };
+
+    const multiWindowManagerPath = '/js/multi_window_manager.js';
+    const multiWindowManagerWorker =
+        new SharedWorker(multiWindowManagerPath, {type: 'module'});
+    const windowInstance =
+        Comlink.wrap<WindowInstance>(multiWindowManagerWorker.port);
+    addUnloadCallback(() => {
+      windowInstance.onWindowClosed().catch((e) => {
+        reportError(
+            ErrorType.MULTI_WINDOW_HANDLING_FAILURE, ErrorLevel.ERROR,
+            assertInstanceof(e, Error));
+      });
+    });
+    await windowInstance.init(
+        Comlink.proxy(releaseUsage), Comlink.proxy(exploitUsage));
+    await ChromeHelper.getInstance().initCameraWindowController();
+    windowController.addWindowStateListener((states) => {
+      windowInstance
+          .onVisibilityChanged(!states.includes(WindowStateType.MINIMIZED))
+          .catch((e) => {
+            reportError(
+                ErrorType.MULTI_WINDOW_HANDLING_FAILURE, ErrorLevel.ERROR,
+                assertInstanceof(e, Error));
+          });
+    });
+    windowController.addWindowFocusListener((isFocused) => {
+      // If we change the focus to another CCA window, it should get the camera
+      // ownership.
+      if (isFocused) {
+        windowInstance.onVisibilityChanged(true).catch((e) => {
+          reportError(
+              ErrorType.MULTI_WINDOW_HANDLING_FAILURE, ErrorLevel.ERROR,
+              assertInstanceof(e, Error));
+        });
+      }
+    });
+  }
 }
 
 /**
diff --git a/ash/webui/camera_app_ui/resources/js/mojo/chrome_helper.ts b/ash/webui/camera_app_ui/resources/js/mojo/chrome_helper.ts
index e1404a1f..01bf48a 100644
--- a/ash/webui/camera_app_ui/resources/js/mojo/chrome_helper.ts
+++ b/ash/webui/camera_app_ui/resources/js/mojo/chrome_helper.ts
@@ -16,7 +16,6 @@
   CameraAppHelper,
   CameraAppHelperRemote,
   CameraIntentAction,
-  CameraUsageOwnershipMonitorCallbackRouter,
   DocumentOutputFormat,
   DocumentScannerReadyState,
   ExternalScreenMonitorCallbackRouter,
@@ -140,29 +139,10 @@
   }
 
   /**
-   * Starts camera usage monitor.
+   * Initializes the camera window controller and bootstraps the mojo
+   * communication to get window states.
    */
-  async initCameraUsageMonitor(
-      exploitUsage: () => Promise<void>,
-      releaseUsage: () => Promise<void>): Promise<void> {
-    const usageCallbackRouter =
-        wrapEndpoint(new CameraUsageOwnershipMonitorCallbackRouter());
-
-    usageCallbackRouter.onCameraUsageOwnershipChanged.addListener(
-        async (hasUsage: boolean) => {
-          if (hasUsage) {
-            await exploitUsage();
-          } else {
-            await releaseUsage();
-          }
-        });
-
-    const {isSuccess} = await this.remote.setCameraUsageMonitor(
-        usageCallbackRouter.$.bindNewPipeAndPassRemote());
-    if (!isSuccess) {
-      throw new Error('Failed to set camera usage monitor');
-    }
-
+  async initCameraWindowController(): Promise<void> {
     let {controller} = await this.remote.getWindowStateController();
     controller = wrapEndpoint(controller);
     await windowController.bind(controller);
diff --git a/ash/webui/camera_app_ui/resources/js/multi_window_manager.ts b/ash/webui/camera_app_ui/resources/js/multi_window_manager.ts
new file mode 100644
index 0000000..7c7d38fe
--- /dev/null
+++ b/ash/webui/camera_app_ui/resources/js/multi_window_manager.ts
@@ -0,0 +1,239 @@
+// 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.
+
+/**
+ * @file
+ *
+ * This is used to handle multiple windows of CCA.
+ * An example is when using the following windows at the same time:
+ * 1. CCA launched from the launcher.
+ * 2. CCA launched from the ARC camera intent.
+ *
+ * The design principles are (The "window" below means CCA window):
+ * 1. Only 0-1 windows can have the camera ownership at a time.
+ * 2. A window can only start the camera after its `resumeCallback` is called.
+ * 3. A window should stop the camera usage as soon as possible when the
+ *    `suspendCallback` is called.
+ * 4. When an active window is minimized or closed, the camera ownership is
+ *    released and the ownership will be transferred to the other window if it
+ *    is active or to nobody if there is no active window.
+ * 5. When a window is focused, it will request the camera ownership, and the
+ *    camera ownership will be transferred to the active window.
+ * 6. When transferring camera ownership, always suspend the current owner, and
+ *    then resume the next owner. The owner ID is changed right before resuming
+ *    or entering idle state.
+ * 7. If multiple windows request the camera ownership before the current owner
+ *    window is suspended, only the last requester will be recorded as the next
+ *    window owner.
+ */
+
+import {assertNotReached} from './assert.js';
+import * as Comlink from './lib/comlink.js';
+
+// This is needed since we currently have the same tsconfig for files running
+// in SharedWorker and in CCA.
+// TODO(b/213408699): Remove this after the tsconfig are separated.
+// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
+const sharedWorkerScope = self as SharedWorkerGlobalScope;
+
+interface WindowCallbacks {
+  suspendCallback: () => Promise<void>;
+  resumeCallback: () => Promise<void>;
+}
+
+enum OwnershipTransitionState {
+  IDLE,
+  SUSPENDING,
+  RESUMING,
+}
+
+/**
+ * Run in a shared worker to handle multi-window use case.
+ */
+class MultiWindowManager {
+  // Map from window ID to the corresponding callbacks.
+  private readonly windowCallbacksMap = new Map<number, WindowCallbacks>();
+
+  private windowCounter = 0;
+
+  /**
+   * The ID of the window owning the camera usage.
+   * Since the ID will be used as the target window when doing suspend/resume,
+   * the transition of the camera ownership happens before trying to resume the
+   * window.
+   */
+  private currentOwnerId: number|null = null;
+
+  /**
+   * The ID of the window which the camera ownership will be transferred to
+   * after suspension. We only keep one ID so if multiple windows request camera
+   * usage while suspending, only the last one will be recorded as the next
+   * owner.
+   */
+  private nextOwnerId: number|null = null;
+
+  /**
+   * The state to indicate the transition of the camera ownership. When
+   * transition cycle starts, it will switch between SUSPENDING/RESUMING until
+   * the next owner is empty. Once the transition is finished, the state should
+   * go back to IDLE.
+   */
+  private transitionState: OwnershipTransitionState =
+      OwnershipTransitionState.IDLE;
+
+  createWindowInstance() {
+    const newWindow = new WindowInstanceImpl(this.windowCounter);
+    this.windowCounter++;
+    return newWindow;
+  }
+
+  async registerWindow(id: number, windowCallbacks: WindowCallbacks):
+      Promise<void> {
+    this.windowCallbacksMap.set(id, windowCallbacks);
+    await this.notifyWindowRestored(id);
+  }
+
+  async notifyWindowClosed(id: number): Promise<void> {
+    this.windowCallbacksMap.delete(id);
+    if (this.nextOwnerId === id) {
+      this.nextOwnerId = null;
+    }
+    if (this.currentOwnerId === id) {
+      await this.resumeNextOrIdle();
+    }
+  }
+
+  async notifyWindowRestored(id: number): Promise<void> {
+    switch (this.transitionState) {
+      case OwnershipTransitionState.IDLE:
+        if (this.currentOwnerId === null) {
+          this.currentOwnerId = id;
+          await this.resumeWindow();
+        } else if (this.currentOwnerId !== id) {
+          this.nextOwnerId = id;
+          await this.suspendWindow();
+        }
+        break;
+      case OwnershipTransitionState.SUSPENDING:
+        this.nextOwnerId = id;
+        break;
+      case OwnershipTransitionState.RESUMING:
+        if (this.currentOwnerId === id) {
+          this.nextOwnerId = null;
+        } else {
+          this.nextOwnerId = id;
+        }
+        break;
+      default:
+        assertNotReached(
+            `Unexpected transition state: ${this.transitionState}`);
+    }
+  }
+
+  async notifyWindowMinimized(id: number) {
+    if (id === this.nextOwnerId) {
+      // It is when a window is activated while it is suspending. Therefore, we
+      // cannot return here.
+      this.nextOwnerId = null;
+    }
+
+    if (id !== this.currentOwnerId) {
+      return;
+    }
+
+    switch (this.transitionState) {
+      case OwnershipTransitionState.IDLE:
+        await this.suspendWindow();
+        break;
+      case OwnershipTransitionState.SUSPENDING:
+        break;
+      case OwnershipTransitionState.RESUMING:
+        this.nextOwnerId = null;
+        break;
+      default:
+        assertNotReached(
+            `Unexpected transition state: ${this.transitionState}`);
+    }
+  }
+
+  getActiveWindowCallbacks(): WindowCallbacks|null {
+    if (this.currentOwnerId === null) {
+      return null;
+    }
+    return this.windowCallbacksMap.get(this.currentOwnerId) ?? null;
+  }
+
+  async suspendWindow(): Promise<void> {
+    const callbacks = this.getActiveWindowCallbacks();
+    if (callbacks === null) {
+      return this.resumeNextOrIdle();
+    }
+    this.transitionState = OwnershipTransitionState.SUSPENDING;
+    await callbacks.suspendCallback();
+    await this.resumeNextOrIdle();
+  }
+
+  async resumeWindow(): Promise<void> {
+    const callbacks = this.getActiveWindowCallbacks();
+    if (callbacks === null) {
+      return this.resumeNextOrIdle();
+    }
+    this.transitionState = OwnershipTransitionState.RESUMING;
+    await callbacks.resumeCallback();
+    if (this.nextOwnerId !== null) {
+      await this.suspendWindow();
+    } else {
+      this.transitionState = OwnershipTransitionState.IDLE;
+    }
+  }
+
+  async resumeNextOrIdle(): Promise<void> {
+    this.currentOwnerId = this.nextOwnerId;
+    this.nextOwnerId = null;
+
+    if (this.currentOwnerId !== null) {
+      await this.resumeWindow();
+    } else {
+      this.transitionState = OwnershipTransitionState.IDLE;
+    }
+  }
+}
+
+class WindowInstanceImpl {
+  constructor(private readonly id: number) {}
+
+  async init(
+      suspendCallback: () => Promise<void>,
+      resumeCallback: () => Promise<void>): Promise<void> {
+    await windowManager.registerWindow(
+        this.id, {suspendCallback, resumeCallback});
+  }
+
+  async onVisibilityChanged(isVisible: boolean): Promise<void> {
+    if (isVisible) {
+      await windowManager.notifyWindowRestored(this.id);
+    } else {
+      await windowManager.notifyWindowMinimized(this.id);
+    }
+  }
+
+  async onWindowClosed(): Promise<void> {
+    await windowManager.notifyWindowClosed(this.id);
+  }
+}
+
+const windowManager = new MultiWindowManager();
+
+// Only export types to ensure that the file is not imported by other files at
+// runtime.
+export type WindowInstance = WindowInstanceImpl;
+
+/**
+ * Triggers when the Shared Worker is connected.
+ */
+sharedWorkerScope.onconnect = (event: MessageEvent) => {
+  const port = event.ports[0];
+  Comlink.expose(windowManager.createWindowInstance(), port);
+  port.start();
+};
diff --git a/ash/webui/camera_app_ui/resources/js/type.ts b/ash/webui/camera_app_ui/resources/js/type.ts
index b3afdf1..d8c4ef3 100644
--- a/ash/webui/camera_app_ui/resources/js/type.ts
+++ b/ash/webui/camera_app_ui/resources/js/type.ts
@@ -338,6 +338,7 @@
   IDLE_DETECTOR_FAILURE = 'idle-detector-failure',
   INVALID_REVIEW_UI_STATE = 'invalid-review-ui-state',
   METADATA_MAPPING_FAILURE = 'metadata-mapping-failure',
+  MULTI_WINDOW_HANDLING_FAILURE = 'multi-window-handling-failure',
   MULTIPLE_STREAMS_FAILURE = 'multiple-streams-failure',
   NO_AVAILABLE_LEVEL = 'no-available-level',
   PERF_METRICS_FAILURE = 'perf-metrics-failure',
diff --git a/ash/webui/camera_app_ui/resources/js/views/review.ts b/ash/webui/camera_app_ui/resources/js/views/review.ts
index 734305f3..278eaeb 100644
--- a/ash/webui/camera_app_ui/resources/js/views/review.ts
+++ b/ash/webui/camera_app_ui/resources/js/views/review.ts
@@ -109,8 +109,10 @@
     try {
       await new Promise<void>((resolve, reject) => {
         image.onload = () => resolve();
-        image.onerror = (e) =>
-            reject(new Error(`Failed to load review document image: ${e}`));
+        image.addEventListener('error', (e) => {
+          const msg = `Failed to load review document image: ${e.message}`;
+          reject(new Error(msg));
+        }, {once: true});
         image.src = URL.createObjectURL(blob);
       });
     } catch (e) {
diff --git a/ash/webui/camera_app_ui/resources/js/views/warning.ts b/ash/webui/camera_app_ui/resources/js/views/warning.ts
index ab250ab..26b67ed 100644
--- a/ash/webui/camera_app_ui/resources/js/views/warning.ts
+++ b/ash/webui/camera_app_ui/resources/js/views/warning.ts
@@ -35,7 +35,7 @@
  * Creates the warning-view controller.
  */
 export class Warning extends View {
-  private readonly errorNames: I18nString[] = [];
+  private errorNames: I18nString[] = [];
 
   constructor() {
     super(ViewName.WARNING);
@@ -63,21 +63,27 @@
     this.updateMessage();
   }
 
+  // If `value` is not specified in the `condition`, all the error will be
+  // cleared.
   override leaving(condition: LeaveCondition): boolean {
     assert(condition.kind === 'CLOSED');
 
-    // Recovered error-name for leaving the view.
-    const name = assertI18nString(condition.val);
+    if (condition.val === undefined) {
+      this.errorNames = [];
+    } else {
+      // Recovered error-name for leaving the view.
+      const name = assertI18nString(condition.val);
 
-    // Remove the recovered error from the stack but don't leave the view until
-    // there is no error left in the stack.
-    const index = this.errorNames.indexOf(name);
-    if (index !== -1) {
-      this.errorNames.splice(index, 1);
-    }
-    if (this.errorNames.length > 0) {
-      this.updateMessage();
-      return false;
+      // Remove the recovered error from the stack but don't leave the view
+      // until there is no error left in the stack.
+      const index = this.errorNames.indexOf(name);
+      if (index !== -1) {
+        this.errorNames.splice(index, 1);
+      }
+      if (this.errorNames.length > 0) {
+        this.updateMessage();
+        return false;
+      }
     }
     dom.get('#error-msg', HTMLElement).textContent = '';
     return true;
diff --git a/ash/webui/camera_app_ui/resources/js/window_controller.ts b/ash/webui/camera_app_ui/resources/js/window_controller.ts
index 5bb2259..dfefeee 100644
--- a/ash/webui/camera_app_ui/resources/js/window_controller.ts
+++ b/ash/webui/camera_app_ui/resources/js/window_controller.ts
@@ -12,6 +12,8 @@
 
 type WindowStateChangedEventListener = (states: WindowStateType[]) => void;
 
+type WindowFocusChangedEventListener = (isFocused: boolean) => void;
+
 /**
  * Controller to get/set/listener for window state.
  */
@@ -29,7 +31,14 @@
   /**
    * Set of the listeners for window state changed events.
    */
-  private readonly listeners = new Set<WindowStateChangedEventListener>();
+  private readonly windowStateListeners =
+      new Set<WindowStateChangedEventListener>();
+
+  /**
+   * Set of the listeners for window focus changed events.
+   */
+  private readonly windowFocusListeners =
+      new Set<WindowFocusChangedEventListener>();
 
   /**
    * Binds the controller remote from Mojo interface.
@@ -42,10 +51,16 @@
     windowMonitorCallbackRouter.onWindowStateChanged.addListener(
         (states: WindowStateType[]) => {
           this.windowStates = states;
-          for (const listener of this.listeners) {
+          for (const listener of this.windowStateListeners) {
             listener(states);
           }
         });
+    windowMonitorCallbackRouter.onWindowFocusChanged.addListener(
+        (isFocused: boolean) => {
+          for (const listener of this.windowFocusListeners) {
+            listener(isFocused);
+          }
+        });
     const {states} = await this.windowStateController.addMonitor(
         windowMonitorCallbackRouter.$.bindNewPipeAndPassRemote());
     this.windowStates = states;
@@ -114,8 +129,15 @@
   /**
    * Adds listener for the window state changed events.
    */
-  addListener(listener: WindowStateChangedEventListener): void {
-    this.listeners.add(listener);
+  addWindowStateListener(listener: WindowStateChangedEventListener): void {
+    this.windowStateListeners.add(listener);
+  }
+
+  /**
+   * Adds listener for the window focus changed events.
+   */
+  addWindowFocusListener(listener: WindowFocusChangedEventListener): void {
+    this.windowFocusListeners.add(listener);
   }
 }
 
diff --git a/ash/webui/eche_app_ui/eche_connection_status_handler.cc b/ash/webui/eche_app_ui/eche_connection_status_handler.cc
index 9f03622..0c1380d 100644
--- a/ash/webui/eche_app_ui/eche_connection_status_handler.cc
+++ b/ash/webui/eche_app_ui/eche_connection_status_handler.cc
@@ -33,17 +33,21 @@
   NotifyConnectionStatusChanged(connection_status);
 
   // Anytime we have a successful connection to the phone (app stream or
-  // prewarm) we should make sure the UI is enabled.
-  if (connection_status ==
-      mojom::ConnectionStatus::kConnectionStatusConnected) {
-    SetConnectionStatusForUi(connection_status);
-    return;
-  }
+  // prewarm) we should make sure the UI is enabled.  Failures triggered from
+  // background connection attempts as app stream failures can happen for other
+  // reasons, these are updated from EcheTray.
+  switch (connection_status) {
+    case eche_app::mojom::ConnectionStatus::kConnectionStatusConnected:
+      SetConnectionStatusForUi(connection_status);
+      [[fallthrough]];
+    case eche_app::mojom::ConnectionStatus::kConnectionStatusConnecting:
+      is_connecting_or_connected_ = true;
+      break;
 
-  // Only track failures triggered from background connection attempts (app
-  // stream failures can happen for other reasons).
-  if (connection_status == mojom::ConnectionStatus::kConnectionStatusFailed) {
-    SetConnectionStatusForUi(connection_status);
+    case eche_app::mojom::ConnectionStatus::kConnectionStatusDisconnected:
+    case eche_app::mojom::ConnectionStatus::kConnectionStatusFailed:
+      is_connecting_or_connected_ = false;
+      break;
   }
 }
 
@@ -97,6 +101,7 @@
   last_update_timestamp_ = base::Time();
   connection_status_for_ui_ =
       mojom::ConnectionStatus::kConnectionStatusConnecting;
+  NotifyConnectionStatusForUiChanged(connection_status_for_ui_);
 }
 
 void EcheConnectionStatusHandler::CheckConnectionStatusForUi() {
@@ -104,6 +109,17 @@
     return;
   }
 
+  if (is_connecting_or_connected_) {
+    PA_LOG(INFO)
+        << "Already have an active connection (connecting or connected), new "
+           "background connection attempt is not required.";
+    return;
+  }
+
+  if (status_check_delay_timer_) {
+    status_check_delay_timer_.reset();
+  }
+
   base::TimeDelta time_since_last_check =
       base::Time::Now() - last_update_timestamp_;
   if (time_since_last_check >
diff --git a/ash/webui/eche_app_ui/eche_connection_status_handler.h b/ash/webui/eche_app_ui/eche_connection_status_handler.h
index bc32e21..be973d3 100644
--- a/ash/webui/eche_app_ui/eche_connection_status_handler.h
+++ b/ash/webui/eche_app_ui/eche_connection_status_handler.h
@@ -78,6 +78,7 @@
       mojom::ConnectionStatus connection_status);
   void NotifyRequestBackgroundConnectionAttempt();
 
+  void TriggerBackgroundConnectionIfNecessary();
   void ResetConnectionStatus();
 
   void set_feature_status_for_test(FeatureStatus feature_status) {
@@ -87,6 +88,11 @@
   mojom::ConnectionStatus connection_status_for_ui_ =
       mojom::ConnectionStatus::kConnectionStatusDisconnected;
   base::Time last_update_timestamp_ = base::Time();
+
+  // Tracks the current status of the eche connection (app stream or
+  // background).
+  bool is_connecting_or_connected_ = false;
+
   std::unique_ptr<base::OneShotTimer> status_check_delay_timer_{};
   FeatureStatus feature_status_ = FeatureStatus::kDisconnected;
   mojo::Receiver<mojom::ConnectionStatusObserver> connection_status_receiver_{
diff --git a/ash/webui/eche_app_ui/eche_connection_status_handler_unittest.cc b/ash/webui/eche_app_ui/eche_connection_status_handler_unittest.cc
index 438b64d..05c99e8d 100644
--- a/ash/webui/eche_app_ui/eche_connection_status_handler_unittest.cc
+++ b/ash/webui/eche_app_ui/eche_connection_status_handler_unittest.cc
@@ -249,9 +249,6 @@
   EXPECT_EQ(GetLastConnectionChangedStatus(),
             mojom::ConnectionStatus::kConnectionStatusConnected);
   EXPECT_EQ(GetNumConnectionStatusChangedCalls(), 2u);
-  EXPECT_EQ(GetLastConnectionForUiChangedStatus(),
-            mojom::ConnectionStatus::kConnectionStatusConnected);
-  EXPECT_EQ(GetNumConnectionStatusForUiChangedCalls(), 2u);
 }
 
 TEST_F(EcheConnectionStatusHandlerTest,
@@ -270,7 +267,10 @@
             mojom::ConnectionStatus::kConnectionStatusConnected);
   EXPECT_EQ(GetNumConnectionStatusForUiChangedCalls(), 1u);
 
-  // After more than 10 seconds pass, extra calls should happen.
+  // After more than 10 seconds pass, extra calls should happen when there is no
+  // active stream.
+  NotifyConnectionStatusChanged(
+      mojom::ConnectionStatus::kConnectionStatusDisconnected);
   SetFeatureStatus(FeatureStatus::kConnected);
   task_environment_.FastForwardBy(base::Seconds(11));
   handler().CheckConnectionStatusForUi();
@@ -280,12 +280,23 @@
   EXPECT_EQ(GetNumConnectionStatusForUiChangedCalls(), 2u);
   EXPECT_EQ(GetNumRequestBackgroundConnectionAttemptCalls(), 1u);
 
+  // After more than 10 seconds pass, no extra calls should happen if there's an
+  // active stream.
+  NotifyConnectionStatusChanged(
+      mojom::ConnectionStatus::kConnectionStatusConnected);
+  task_environment_.FastForwardBy(base::Seconds(11));
+  handler().CheckConnectionStatusForUi();
+
+  EXPECT_EQ(GetLastConnectionForUiChangedStatus(),
+            mojom::ConnectionStatus::kConnectionStatusConnected);
+  EXPECT_EQ(GetNumConnectionStatusForUiChangedCalls(), 2u);        // no change
+  EXPECT_EQ(GetNumRequestBackgroundConnectionAttemptCalls(), 1u);  // no change
+
   // Reset to Disconnected
   handler().SetConnectionStatusForUi(
       mojom::ConnectionStatus::kConnectionStatusDisconnected);
   EXPECT_EQ(GetNumConnectionStatusForUiChangedCalls(), 3u);
   EXPECT_EQ(GetNumRequestBackgroundConnectionAttemptCalls(), 1u);
-
   EXPECT_EQ(GetLastConnectionForUiChangedStatus(),
             mojom::ConnectionStatus::kConnectionStatusDisconnected);
 
@@ -294,6 +305,8 @@
       mojom::ConnectionStatus::kConnectionStatusConnected);
   EXPECT_EQ(GetNumConnectionStatusForUiChangedCalls(), 4u);
 
+  NotifyConnectionStatusChanged(
+      mojom::ConnectionStatus::kConnectionStatusDisconnected);
   task_environment_.FastForwardBy(base::Minutes(11));
   handler().CheckConnectionStatusForUi();
 
@@ -337,16 +350,17 @@
 
 TEST_F(EcheConnectionStatusHandlerTest, OnFeatureStatusChanged) {
   handler().OnFeatureStatusChanged(FeatureStatus::kDisconnected);
+  // always resets to "loading" on disconnections.
   EXPECT_EQ(GetLastConnectionForUiChangedStatus(),
-            mojom::ConnectionStatus::kConnectionStatusDisconnected);
-  EXPECT_EQ(GetNumConnectionStatusForUiChangedCalls(), 0u);
+            mojom::ConnectionStatus::kConnectionStatusConnecting);
+  EXPECT_EQ(GetNumConnectionStatusForUiChangedCalls(), 1u);
 
   handler().SetConnectionStatusForUi(
       mojom::ConnectionStatus::kConnectionStatusConnected);
 
   EXPECT_EQ(GetLastConnectionForUiChangedStatus(),
             mojom::ConnectionStatus::kConnectionStatusConnected);
-  EXPECT_EQ(GetNumConnectionStatusForUiChangedCalls(), 1u);
+  EXPECT_EQ(GetNumConnectionStatusForUiChangedCalls(), 2u);
 
   handler().OnFeatureStatusChanged(FeatureStatus::kConnected);
 
@@ -354,7 +368,7 @@
 
   EXPECT_EQ(GetLastConnectionForUiChangedStatus(),
             mojom::ConnectionStatus::kConnectionStatusConnected);
-  EXPECT_EQ(GetNumConnectionStatusForUiChangedCalls(), 2u);
+  EXPECT_EQ(GetNumConnectionStatusForUiChangedCalls(), 3u);
 }
 
 }  // namespace ash::eche_app
diff --git a/ash/wm/desks/desk.cc b/ash/wm/desks/desk.cc
index 314a801..0592dba1 100644
--- a/ash/wm/desks/desk.cc
+++ b/ash/wm/desks/desk.cc
@@ -4,7 +4,6 @@
 
 #include "ash/wm/desks/desk.h"
 
-#include <absl/cleanup/cleanup.h>
 #include <utility>
 
 #include "ash/constants/app_types.h"
@@ -370,10 +369,6 @@
     aura::Window* root = window->GetRootWindow();
     auto& adw_data = all_desk_window_stacking_[root];
 
-    if (!is_active_) {
-      last_active_root_ = root;
-    }
-
     // Find z-order of the added window.
     auto* container = GetDeskContainerForRoot(root);
     if (auto order =
@@ -517,10 +512,6 @@
 void Desk::Activate(bool update_window_activation) {
   DCHECK(!is_active_);
 
-  absl::Cleanup last_active_root_reset = [this] {
-    last_active_root_ = nullptr;
-  };
-
   if (!MaybeResetContainersOpacities()) {
     for (aura::Window* root : Shell::GetAllRootWindows())
       root->GetChildById(container_id_)->Show();
@@ -550,18 +541,13 @@
   auto mru_window_list =
       Shell::Get()->mru_window_tracker()->BuildMruWindowList(kActiveDesk);
 
-  // If there's an adw window that has order=0 (should be on top) and was on the
-  // last active root window, then we'll find it first and activate it. We use
-  // the MRU list here so that in the case that there are multiple roots that
-  // each have a topmost adw window, we'll activate the one most recently used.
+  // If there's an adw window that has order=0 (should be on top), then we'll
+  // find it first and activate it. We use the MRU list here so that in the
+  // case that there are multiple roots that each have a topmost adw window,
+  // we'll activate the one most recently used.
   if (features::IsPerDeskZOrderEnabled()) {
     for (auto* window : mru_window_list) {
       aura::Window* root = window->GetRootWindow();
-
-      if (last_active_root_ != nullptr && last_active_root_ != root) {
-        continue;
-      }
-
       auto& adw_data = all_desk_window_stacking_[root];
 
       if (!adw_data.empty() && adw_data.front().window == window &&
@@ -857,9 +843,6 @@
   // This function should not be invoked when this feature isn't enabled.
   DCHECK(features::IsPerDeskZOrderEnabled());
 
-  auto* active_window = window_util::GetActiveWindow();
-  last_active_root_ = active_window ? active_window->GetRootWindow() : nullptr;
-
   for (aura::Window* root : Shell::GetAllRootWindows()) {
     auto& adw_data = all_desk_window_stacking_[root];
     aura::Window* container = GetDeskContainerForRoot(root);
@@ -933,10 +916,6 @@
   aura::Window* root = window->GetRootWindow();
   auto& adw_data = all_desk_window_stacking_[root];
 
-  if (!is_active_) {
-    last_active_root_ = root;
-  }
-
   // Assume this window is going to be on top and bump remaining windows down.
   adw_data.insert(adw_data.begin(), {.window = window, .order = 0});
   for (size_t i = 1; i != adw_data.size(); ++i)
@@ -958,11 +937,6 @@
     return;
   }
 
-  // Reset `last_active_root_` if the adw being removed was the mru window.
-  if (!is_active_ && root == last_active_root_ && it->order == 0) {
-    last_active_root_ = nullptr;
-  }
-
   it = adw_data.erase(it);
   // Raise all remaining windows up.
   for (; it != adw_data.end(); ++it)
diff --git a/ash/wm/desks/desk.h b/ash/wm/desks/desk.h
index 6265a31..76cfdff2 100644
--- a/ash/wm/desks/desk.h
+++ b/ash/wm/desks/desk.h
@@ -350,10 +350,6 @@
   base::flat_map<aura::Window*, std::vector<AllDeskWindowStackingData>>
       all_desk_window_stacking_;
 
-  // Used to track the last active root when the desk is being deactivated.
-  // Should be null if the current desk is active.
-  aura::Window* last_active_root_ = nullptr;
-
   // Tracks whether |this| has been interacted with this week. This value is
   // reset by the DesksController.
   bool interacted_with_this_week_ = false;
diff --git a/ash/wm/desks/desks_unittests.cc b/ash/wm/desks/desks_unittests.cc
index 9012cdd..81369c1 100644
--- a/ash/wm/desks/desks_unittests.cc
+++ b/ash/wm/desks/desks_unittests.cc
@@ -285,11 +285,10 @@
   // DesksController::Observer:
   void OnDeskAdded(const Desk* desk) override {
     const size_t new_desk_index = DesksController::Get()->GetDeskIndex(desk);
-    if (new_desk_index > desks_.size()) {
+    if (new_desk_index > desks_.size())
       desks_.emplace_back(desk);
-    } else {
+    else
       desks_.insert(desks_.begin() + new_desk_index, desk);
-    }
     EXPECT_TRUE(DesksController::Get()->AreDesksBeingModified());
   }
   void OnDeskRemoved(const Desk* desk) override {
@@ -631,9 +630,8 @@
   EXPECT_TRUE(controller->CanCreateDesks());
 
   // Add desks until no longer possible.
-  while (controller->CanCreateDesks()) {
+  while (controller->CanCreateDesks())
     NewDesk();
-  }
 
   // Expect we've reached the max number of desks, and we've been notified only
   // with the newly created desks.
@@ -643,9 +641,8 @@
 
   // Remove all desks until no longer possible, and expect that there's always
   // one default desk remaining.
-  while (controller->CanRemoveDesks()) {
+  while (controller->CanRemoveDesks())
     RemoveDesk(observer.desks().back());
-  }
 
   EXPECT_EQ(1u, controller->desks().size());
   EXPECT_FALSE(controller->CanRemoveDesks());
@@ -2831,9 +2828,8 @@
   void Wait() { run_loop_.Run(); }
 
   void OnWindowVisibilityChanged(aura::Window* window, bool visible) override {
-    if (visible && window->GetId() == kShellWindowId_DesksBarWindow) {
+    if (visible && window->GetId() == kShellWindowId_DesksBarWindow)
       run_loop_.Quit();
-    }
   }
 
  private:
@@ -2908,9 +2904,8 @@
   ASSERT_EQ(desks_names.size(), desks_restore_names.size());
 
   size_t index = 0;
-  for (const auto& value : desks_restore_names) {
+  for (const auto& value : desks_restore_names)
     EXPECT_EQ(desks_names[index++], value.GetString());
-  }
 }
 
 // Returns the GUIDs in the given `user_prefs`.
@@ -3219,10 +3214,8 @@
 
   // aura::WindowObserver:
   void OnWindowVisibilityChanged(aura::Window* window, bool visible) override {
-    if (observer_.IsObservingSource(window) &&
-        on_visibility_changed_callback_) {
+    if (observer_.IsObservingSource(window) && on_visibility_changed_callback_)
       std::move(on_visibility_changed_callback_).Run();
-    }
   }
 
   void OnWindowDestroying(aura::Window* window) override {
@@ -4039,9 +4032,8 @@
   EXPECT_EQ(shelf_widget->GetWindowBoundsInScreen(), shown_shelf_bounds);
 
   // Let's wait until the shelf animates to a fully shown state.
-  while (shelf_widget->GetLayer()->transform() != gfx::Transform()) {
+  while (shelf_widget->GetLayer()->transform() != gfx::Transform())
     WaitForMilliseconds(200);
-  }
 
   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
 }
@@ -4227,16 +4219,13 @@
 struct PerDeskZOrderTestCase {
   std::string test_name;
 
-  // True when we want to run the test with multiple displays.
-  bool multi_display;
-
-  // Numerical identifiers of windows on desk 1 and 2, grouped by root window.
-  // Windows will be stacked in the order they appear, with .back() at top.
-  std::vector<std::vector<int>> desk_1_windows;
-  std::vector<std::vector<int>> desk_2_windows;
+  // Numerical identifiers of windows on desk 1 and 2. Windows will be stacked
+  // in the order they appear, with .back() at top.
+  std::vector<int> desk_1_windows;
+  std::vector<int> desk_2_windows;
 
   // Numerical identifiers of all-desk windows. Entries must match windows in
-  // `desk_1_windows`.
+  // desk_1_windows.
   std::set<int> adw_windows;
 
   // Windows to activate in order.
@@ -4244,9 +4233,9 @@
 
   // Once windows have been created and (some) promoted to all-desk, we start
   // the test by switching to desk 2. This is the list of windows that we expect
-  // to find on desk 1/2, grouped by root window.
-  std::vector<std::vector<int>> expected_desk_1_windows_before;
-  std::vector<std::vector<int>> expected_desk_2_windows_before;
+  // to find on desk 1/2.
+  std::vector<int> expected_desk_1_windows_before;
+  std::vector<int> expected_desk_2_windows_before;
 
   // We can then move some set of windows from desk 2 to desk 1. This must be a
   // subset of `desk_2_windows` and cannot contain entries from `adw_windows`
@@ -4258,389 +4247,115 @@
   // Windows to close while on the second desk. Can include any windows.
   std::vector<int> close_windows;
 
-  // We then switch back to desk 1 and expect to find windows in this order,
-  // grouped by root window.
-  std::vector<std::vector<int>> expected_desk_1_windows_after;
-  std::vector<std::vector<int>> expected_desk_2_windows_after;
-
-  // This is the window we expect to be active after we switch back to desk 1.
-  int expected_desk_1_final_active_window;
+  // We then switch back to desk 1 and expect to find windows in this order.
+  std::vector<int> expected_desk_1_windows_after;
+  std::vector<int> expected_desk_2_windows_after;
 };
 
 TEST_P(DesksTest, PerDeskZOrder) {
   const PerDeskZOrderTestCase tests[] = {
       {.test_name = "Single adw window 1",
-       .desk_1_windows = {{1}},
-       .desk_2_windows = {{}},
+       .desk_1_windows = {1},
+       .desk_2_windows = {},
        .adw_windows = {1},
-       .expected_desk_1_windows_before = {{1}},
-       .expected_desk_2_windows_before = {{1}},
+       .expected_desk_1_windows_before = {1},
+       .expected_desk_2_windows_before = {1},
        .move_windows = {},
        .close_windows = {},
-       .expected_desk_1_windows_after = {{1}},
-       .expected_desk_2_windows_after = {{1}},
-       .expected_desk_1_final_active_window = 1},
+       .expected_desk_1_windows_after = {1},
+       .expected_desk_2_windows_after = {1}},
       {.test_name = "Single adw window 2",
-       .desk_1_windows = {{1, 2, 3}},
-       .desk_2_windows = {{5, 4}},
+       .desk_1_windows = {1, 2, 3},
+       .desk_2_windows = {5, 4},
        .adw_windows = {1},
-       .expected_desk_1_windows_before = {{1, 2, 3}},
-       .expected_desk_2_windows_before = {{5, 4, 1}},
+       .expected_desk_1_windows_before = {1, 2, 3},
+       .expected_desk_2_windows_before = {5, 4, 1},
        .move_windows = {},
        .close_windows = {},
-       .expected_desk_1_windows_after = {{1, 2, 3}},
-       .expected_desk_2_windows_after = {{5, 4, 1}},
-       .expected_desk_1_final_active_window = 3},
+       .expected_desk_1_windows_after = {1, 2, 3},
+       .expected_desk_2_windows_after = {5, 4, 1}},
       {.test_name = "Single adw window 3",
-       .desk_1_windows = {{1, 2, 3}},
-       .desk_2_windows = {{5, 4}},
+       .desk_1_windows = {1, 2, 3},
+       .desk_2_windows = {5, 4},
        .adw_windows = {1},
-       .expected_desk_1_windows_before = {{1, 2, 3}},
-       .expected_desk_2_windows_before = {{5, 4, 1}},
+       .expected_desk_1_windows_before = {1, 2, 3},
+       .expected_desk_2_windows_before = {5, 4, 1},
        .move_windows = {5},
        .close_windows = {},
-       .expected_desk_1_windows_after = {{1, 2, 3, 5}},
-       .expected_desk_2_windows_after = {{4, 1}},
-       .expected_desk_1_final_active_window = 5},
+       .expected_desk_1_windows_after = {1, 2, 3, 5},
+       .expected_desk_2_windows_after = {4, 1}},
       {.test_name = "Single adw window 4",
-       .desk_1_windows = {{1, 2, 3}},
-       .desk_2_windows = {{5, 4}},
+       .desk_1_windows = {1, 2, 3},
+       .desk_2_windows = {5, 4},
        .adw_windows = {2},
-       .expected_desk_1_windows_before = {{1, 2, 3}},
-       .expected_desk_2_windows_before = {{5, 4, 2}},
+       .expected_desk_1_windows_before = {1, 2, 3},
+       .expected_desk_2_windows_before = {5, 4, 2},
        .move_windows = {5},
        .close_windows = {1},
-       .expected_desk_1_windows_after = {{2, 3, 5}},
-       .expected_desk_2_windows_after = {{4, 2}},
-       .expected_desk_1_final_active_window = 5},
+       .expected_desk_1_windows_after = {2, 3, 5},
+       .expected_desk_2_windows_after = {4, 2}},
       {.test_name = "Single adw window 5",
-       .desk_1_windows = {{1, 2, 3, 4, 5}},
-       .desk_2_windows = {{6}},
+       .desk_1_windows = {1, 2, 3, 4, 5},
+       .desk_2_windows = {6},
        .adw_windows = {3},
-       .expected_desk_1_windows_before = {{1, 2, 3, 4, 5}},
-       .expected_desk_2_windows_before = {{6, 3}},
+       .expected_desk_1_windows_before = {1, 2, 3, 4, 5},
+       .expected_desk_2_windows_before = {6, 3},
        .move_windows = {6},
        .close_windows = {1, 2},
-       .expected_desk_1_windows_after = {{3, 4, 5, 6}},
-       .expected_desk_2_windows_after = {{3}},
-       .expected_desk_1_final_active_window = 6},
+       .expected_desk_1_windows_after = {3, 4, 5, 6},
+       .expected_desk_2_windows_after = {3}},
       {.test_name = "Multiple adw windows 1",
-       .desk_1_windows = {{1, 2, 3, 4, 5}},
-       .desk_2_windows = {{6, 7}},
+       .desk_1_windows = {1, 2, 3, 4, 5},
+       .desk_2_windows = {6, 7},
        .adw_windows = {2, 4},
-       .expected_desk_1_windows_before = {{1, 2, 3, 4, 5}},
-       .expected_desk_2_windows_before = {{6, 7, 2, 4}},
+       .expected_desk_1_windows_before = {1, 2, 3, 4, 5},
+       .expected_desk_2_windows_before = {6, 7, 2, 4},
        .move_windows = {},
        .close_windows = {},
-       .expected_desk_1_windows_after = {{1, 2, 3, 4, 5}},
-       .expected_desk_2_windows_after = {{6, 7, 2, 4}},
-       .expected_desk_1_final_active_window = 5},
+       .expected_desk_1_windows_after = {1, 2, 3, 4, 5},
+       .expected_desk_2_windows_after = {6, 7, 2, 4}},
       {.test_name = "Multiple adw windows 2",
-       .desk_1_windows = {{1, 2, 3, 4, 5}},
-       .desk_2_windows = {{6, 7}},
+       .desk_1_windows = {1, 2, 3, 4, 5},
+       .desk_2_windows = {6, 7},
        .adw_windows = {1, 3, 5},
-       .expected_desk_1_windows_before = {{1, 2, 3, 4, 5}},
-       .expected_desk_2_windows_before = {{6, 7, 1, 3, 5}},
+       .expected_desk_1_windows_before = {1, 2, 3, 4, 5},
+       .expected_desk_2_windows_before = {6, 7, 1, 3, 5},
        .move_windows = {},
        .close_windows = {},
-       .expected_desk_1_windows_after = {{1, 2, 3, 4, 5}},
-       .expected_desk_2_windows_after = {{6, 7, 1, 3, 5}},
-       .expected_desk_1_final_active_window = 5},
+       .expected_desk_1_windows_after = {1, 2, 3, 4, 5},
+       .expected_desk_2_windows_after = {6, 7, 1, 3, 5}},
       {.test_name = "Multiple adw windows 3",
-       .desk_1_windows = {{1, 2}},
-       .desk_2_windows = {{}},
+       .desk_1_windows = {1, 2},
+       .desk_2_windows = {},
        .adw_windows = {1, 2},
-       .expected_desk_1_windows_before = {{1, 2}},
-       .expected_desk_2_windows_before = {{1, 2}},
+       .expected_desk_1_windows_before = {1, 2},
+       .expected_desk_2_windows_before = {1, 2},
        .move_windows = {},
        .close_windows = {},
-       .expected_desk_1_windows_after = {{1, 2}},
-       .expected_desk_2_windows_after = {{1, 2}},
-       .expected_desk_1_final_active_window = 2},
+       .expected_desk_1_windows_after = {1, 2},
+       .expected_desk_2_windows_after = {1, 2}},
       {.test_name = "Multiple adw windows 4",
-       .desk_1_windows = {{1, 2, 3, 4}},
-       .desk_2_windows = {{}},
+       .desk_1_windows = {1, 2, 3, 4},
+       .desk_2_windows = {},
        .adw_windows = {1, 4},
        .activate_windows = {4, 3, 2, 1},
-       .expected_desk_1_windows_before = {{4, 3, 2, 1}},
-       .expected_desk_2_windows_before = {{1, 4}},
+       .expected_desk_1_windows_before = {4, 3, 2, 1},
+       .expected_desk_2_windows_before = {1, 4},
        .move_windows = {},
        .close_windows = {},
-       .expected_desk_1_windows_after = {{4, 3, 2, 1}},
-       .expected_desk_2_windows_after = {{1, 4}},
-       .expected_desk_1_final_active_window = 1},
+       .expected_desk_1_windows_after = {4, 3, 2, 1},
+       .expected_desk_2_windows_after = {1, 4}},
       {.test_name = "Multiple adw windows 5",
-       .desk_1_windows = {{1, 2, 3, 4}},
-       .desk_2_windows = {{5}},
+       .desk_1_windows = {1, 2, 3, 4},
+       .desk_2_windows = {5},
        .adw_windows = {1, 3},
        .activate_windows = {1, 2, 3, 4},
-       .expected_desk_1_windows_before = {{1, 2, 3, 4}},
-       .expected_desk_2_windows_before = {{5, 1, 3}},
+       .expected_desk_1_windows_before = {1, 2, 3, 4},
+       .expected_desk_2_windows_before = {5, 1, 3},
        .move_windows = {},
        .close_windows = {},
-       .expected_desk_1_windows_after = {{1, 2, 3, 4}},
-       .expected_desk_2_windows_after = {{5, 1, 3}},
-       .expected_desk_1_final_active_window = 4},
-      {.test_name = "Multiple displays single adw 1",
-       .multi_display = true,
-       .desk_1_windows = {{1}, {2, 3, 4}},
-       .desk_2_windows = {{}, {5}},
-       .adw_windows = {1},
-       .activate_windows = {1, 2, 3, 4},
-       .expected_desk_1_windows_before = {{1}, {2, 3, 4}},
-       .expected_desk_2_windows_before = {{1}, {5}},
-       .move_windows = {},
-       .close_windows = {},
-       .expected_desk_1_windows_after = {{1}, {2, 3, 4}},
-       .expected_desk_2_windows_after = {{1}, {5}},
-       .expected_desk_1_final_active_window = 4},
-      {.test_name = "Multiple displays single adw 2",
-       .multi_display = true,
-       .desk_1_windows = {{1}, {2, 3, 4}},
-       .desk_2_windows = {{}, {5}},
-       .adw_windows = {1},
-       .activate_windows = {1, 2, 3, 4},
-       .expected_desk_1_windows_before = {{1}, {2, 3, 4}},
-       .expected_desk_2_windows_before = {{1}, {5}},
-       .move_windows = {},
-       .close_windows = {1},
-       .expected_desk_1_windows_after = {{}, {2, 3, 4}},
-       .expected_desk_2_windows_after = {{}, {5}},
-       .expected_desk_1_final_active_window = 4},
-      {.test_name = "Multiple displays single adw 3",
-       .multi_display = true,
-       .desk_1_windows = {{1}, {2, 3, 4}},
-       .desk_2_windows = {{}, {5}},
-       .adw_windows = {1},
-       .activate_windows = {4, 3, 2, 1},
-       .expected_desk_1_windows_before = {{1}, {4, 3, 2}},
-       .expected_desk_2_windows_before = {{1}, {5}},
-       .move_windows = {},
-       .close_windows = {1},
-       .expected_desk_1_windows_after = {{}, {4, 3, 2}},
-       .expected_desk_2_windows_after = {{}, {5}},
-       .expected_desk_1_final_active_window = 2},
-      {.test_name = "Multiple displays single adw 4",
-       .multi_display = true,
-       .desk_1_windows = {{1}, {2, 3, 4}},
-       .desk_2_windows = {{}, {5}},
-       .adw_windows = {1},
-       .activate_windows = {4, 3, 2, 1},
-       .expected_desk_1_windows_before = {{1}, {4, 3, 2}},
-       .expected_desk_2_windows_before = {{1}, {5}},
-       .move_windows = {},
-       .close_windows = {},
-       .expected_desk_1_windows_after = {{1}, {4, 3, 2}},
-       .expected_desk_2_windows_after = {{1}, {5}},
-       .expected_desk_1_final_active_window = 1},
-      {.test_name = "Multiple displays single adw 5",
-       .multi_display = true,
-       .desk_1_windows = {{1}, {2, 3, 4}},
-       .desk_2_windows = {{}, {5}},
-       .adw_windows = {4},
-       .activate_windows = {1, 2, 4, 3},
-       .expected_desk_1_windows_before = {{1}, {2, 4, 3}},
-       .expected_desk_2_windows_before = {{}, {5, 4}},
-       .move_windows = {},
-       .close_windows = {},
-       .expected_desk_1_windows_after = {{1}, {2, 4, 3}},
-       .expected_desk_2_windows_after = {{}, {5, 4}},
-       .expected_desk_1_final_active_window = 3},
-      {.test_name = "Multiple displays single adw 6",
-       .multi_display = true,
-       .desk_1_windows = {{1, 2}, {3, 4}},
-       .desk_2_windows = {{5}, {6}},
-       .adw_windows = {3},
-       .activate_windows = {1, 2, 3, 4},
-       .expected_desk_1_windows_before = {{1, 2}, {3, 4}},
-       .expected_desk_2_windows_before = {{5}, {6, 3}},
-       .move_windows = {},
-       .close_windows = {},
-       .expected_desk_1_windows_after = {{1, 2}, {3, 4}},
-       .expected_desk_2_windows_after = {{5}, {6, 3}},
-       .expected_desk_1_final_active_window = 4},
-      {.test_name = "Multiple displays single adw 7",  // error
-       .multi_display = true,
-       .desk_1_windows = {{1}, {2, 3, 4}},
-       .desk_2_windows = {{}, {5}},
-       .adw_windows = {1},
-       .activate_windows = {4, 3, 2, 1},
-       .expected_desk_1_windows_before = {{1}, {4, 3, 2}},
-       .expected_desk_2_windows_before = {{1}, {5}},
-       .move_windows = {5},
-       .close_windows = {},
-       .expected_desk_1_windows_after = {{1}, {4, 3, 2, 5}},
-       .expected_desk_2_windows_after = {{1}, {}},
-       .expected_desk_1_final_active_window = 5},
-      {.test_name = "Multiple displays single adw 8",
-       .multi_display = true,
-       .desk_1_windows = {{1}, {2, 3, 4}},
-       .desk_2_windows = {{5}, {}},
-       .adw_windows = {1},
-       .activate_windows = {4, 3, 2, 1},
-       .expected_desk_1_windows_before = {{1}, {4, 3, 2}},
-       .expected_desk_2_windows_before = {{5, 1}, {}},
-       .move_windows = {5},
-       .close_windows = {},
-       .expected_desk_1_windows_after = {{1, 5}, {4, 3, 2}},
-       .expected_desk_2_windows_after = {{1}, {}},
-       .expected_desk_1_final_active_window = 5},
-      {.test_name = "Multiple displays multiple adw 1",
-       .multi_display = true,
-       .desk_1_windows = {{1}, {2, 3, 4}},
-       .desk_2_windows = {{}, {5}},
-       .adw_windows = {1, 4},
-       .activate_windows = {1, 2, 3, 4},
-       .expected_desk_1_windows_before = {{1}, {2, 3, 4}},
-       .expected_desk_2_windows_before = {{1}, {5, 4}},
-       .move_windows = {},
-       .close_windows = {},
-       .expected_desk_1_windows_after = {{1}, {2, 3, 4}},
-       .expected_desk_2_windows_after = {{1}, {5, 4}},
-       .expected_desk_1_final_active_window = 4},
-      {.test_name = "Multiple displays multiple adw 2",
-       .multi_display = true,
-       .desk_1_windows = {{1}, {2, 3, 4}},
-       .desk_2_windows = {{}, {5}},
-       .adw_windows = {1, 4},
-       .activate_windows = {2, 3, 4, 1},
-       .expected_desk_1_windows_before = {{1}, {2, 3, 4}},
-       .expected_desk_2_windows_before = {{1}, {5, 4}},
-       .move_windows = {},
-       .close_windows = {},
-       .expected_desk_1_windows_after = {{1}, {2, 3, 4}},
-       .expected_desk_2_windows_after = {{1}, {5, 4}},
-       .expected_desk_1_final_active_window = 1},
-      {.test_name = "Multiple displays multiple adw 3",
-       .multi_display = true,
-       .desk_1_windows = {{1}, {2, 3, 4}},
-       .desk_2_windows = {{}, {5}},
-       .adw_windows = {1, 4},
-       .activate_windows = {1, 2, 3, 4},
-       .expected_desk_1_windows_before = {{1}, {2, 3, 4}},
-       .expected_desk_2_windows_before = {{1}, {5, 4}},
-       .move_windows = {},
-       .close_windows = {1},
-       .expected_desk_1_windows_after = {{}, {2, 3, 4}},
-       .expected_desk_2_windows_after = {{}, {5, 4}},
-       .expected_desk_1_final_active_window = 4},
-      {.test_name = "Multiple displays multiple adw 4",
-       .multi_display = true,
-       .desk_1_windows = {{1}, {2, 3, 4}},
-       .desk_2_windows = {{}, {5}},
-       .adw_windows = {1, 4},
-       .activate_windows = {2, 3, 4, 1},
-       .expected_desk_1_windows_before = {{1}, {2, 3, 4}},
-       .expected_desk_2_windows_before = {{1}, {5, 4}},
-       .move_windows = {},
-       .close_windows = {1},
-       .expected_desk_1_windows_after = {{}, {2, 3, 4}},
-       .expected_desk_2_windows_after = {{}, {5, 4}},
-       .expected_desk_1_final_active_window = 4},
-      {.test_name = "Multiple displays multiple adw 5",
-       .multi_display = true,
-       .desk_1_windows = {{1}, {2, 3, 4}},
-       .desk_2_windows = {{}, {5}},
-       .adw_windows = {1, 4},
-       .activate_windows = {4, 3, 2, 1},
-       .expected_desk_1_windows_before = {{1}, {4, 3, 2}},
-       .expected_desk_2_windows_before = {{1}, {5, 4}},
-       .move_windows = {},
-       .close_windows = {4},
-       .expected_desk_1_windows_after = {{1}, {3, 2}},
-       .expected_desk_2_windows_after = {{1}, {5}},
-       .expected_desk_1_final_active_window = 1},
-      {.test_name = "Multiple displays multiple adw 6",
-       .multi_display = true,
-       .desk_1_windows = {{1}, {2, 3, 4}},
-       .desk_2_windows = {{}, {5}},
-       .adw_windows = {1, 4},
-       .activate_windows = {4, 3, 2, 1},
-       .expected_desk_1_windows_before = {{1}, {4, 3, 2}},
-       .expected_desk_2_windows_before = {{1}, {5, 4}},
-       .move_windows = {5},
-       .close_windows = {},
-       .expected_desk_1_windows_after = {{1}, {4, 3, 2, 5}},
-       .expected_desk_2_windows_after = {{1}, {4}},
-       .expected_desk_1_final_active_window = 5},
-      {.test_name = "Multiple displays multiple adw 7",
-       .multi_display = true,
-       .desk_1_windows = {{1}, {2, 3, 4}},
-       .desk_2_windows = {{}, {5}},
-       .adw_windows = {1, 4},
-       .activate_windows = {1, 2, 3, 4},
-       .expected_desk_1_windows_before = {{1}, {2, 3, 4}},
-       .expected_desk_2_windows_before = {{1}, {5, 4}},
-       .move_windows = {5},
-       .close_windows = {},
-       .expected_desk_1_windows_after = {{1}, {2, 3, 4, 5}},
-       .expected_desk_2_windows_after = {{1}, {4}},
-       .expected_desk_1_final_active_window = 5},
-      {.test_name = "Multiple displays multiple adw 8",
-       .multi_display = true,
-       .desk_1_windows = {{1}, {2, 3, 4}},
-       .desk_2_windows = {{5}, {}},
-       .adw_windows = {1, 4},
-       .activate_windows = {4, 3, 2, 1},
-       .expected_desk_1_windows_before = {{1}, {4, 3, 2}},
-       .expected_desk_2_windows_before = {{5, 1}, {4}},
-       .move_windows = {5},
-       .close_windows = {},
-       .expected_desk_1_windows_after = {{1, 5}, {4, 3, 2}},
-       .expected_desk_2_windows_after = {{1}, {4}},
-       .expected_desk_1_final_active_window = 5},
-      {.test_name = "Multiple displays multiple adw 9",
-       .multi_display = true,
-       .desk_1_windows = {{1}, {2, 3, 4}},
-       .desk_2_windows = {{5}, {}},
-       .adw_windows = {1, 4},
-       .activate_windows = {1, 2, 3, 4},
-       .expected_desk_1_windows_before = {{1}, {2, 3, 4}},
-       .expected_desk_2_windows_before = {{5, 1}, {4}},
-       .move_windows = {5},
-       .close_windows = {},
-       .expected_desk_1_windows_after = {{1, 5}, {2, 3, 4}},
-       .expected_desk_2_windows_after = {{1}, {4}},
-       .expected_desk_1_final_active_window = 5},
-      {.test_name = "Multiple displays multiple adw on same root 1",
-       .multi_display = true,
-       .desk_1_windows = {{1, 2}, {3, 4}},
-       .desk_2_windows = {{}, {5}},
-       .adw_windows = {1, 2},
-       .activate_windows = {4, 3, 2, 1},
-       .expected_desk_1_windows_before = {{2, 1}, {4, 3}},
-       .expected_desk_2_windows_before = {{1, 2}, {5}},
-       .move_windows = {},
-       .close_windows = {},
-       .expected_desk_1_windows_after = {{2, 1}, {4, 3}},
-       .expected_desk_2_windows_after = {{1, 2}, {5}},
-       .expected_desk_1_final_active_window = 1},
-      {.test_name = "Multiple displays multiple adw on same root 2",
-       .multi_display = true,
-       .desk_1_windows = {{1, 2}, {3, 4}},
-       .desk_2_windows = {{5}, {}},
-       .adw_windows = {1, 2},
-       .activate_windows = {4, 3, 2, 1},
-       .expected_desk_1_windows_before = {{2, 1}, {4, 3}},
-       .expected_desk_2_windows_before = {{5, 1, 2}, {}},
-       .move_windows = {},
-       .close_windows = {},
-       .expected_desk_1_windows_after = {{2, 1}, {4, 3}},
-       .expected_desk_2_windows_after = {{5, 1, 2}, {}},
-       .expected_desk_1_final_active_window = 1},
-      {.test_name = "Multiple displays multiple adw on same root 3",
-       .multi_display = true,
-       .desk_1_windows = {{1, 2}, {3, 4}},
-       .desk_2_windows = {{}, {5}},
-       .adw_windows = {1, 2},
-       .activate_windows = {4, 3, 2, 1},
-       .expected_desk_1_windows_before = {{2, 1}, {4, 3}},
-       .expected_desk_2_windows_before = {{1, 2}, {5}},
-       .move_windows = {5},
-       .close_windows = {},
-       .expected_desk_1_windows_after = {{2, 1}, {4, 3, 5}},
-       .expected_desk_2_windows_after = {{1, 2}, {}},
-       .expected_desk_1_final_active_window = 5},
+       .expected_desk_1_windows_after = {1, 2, 3, 4},
+       .expected_desk_2_windows_after = {5, 1, 3}},
   };
 
   base::test::ScopedFeatureList scoped_feature_list;
@@ -4655,40 +4370,19 @@
   for (const auto& test : tests) {
     SCOPED_TRACE(test.test_name);
 
-    if (test.multi_display) {
-      UpdateDisplay("700x600,400x500");
-    } else {
-      UpdateDisplay("700x600");
-    }
-
     std::map<int, std::unique_ptr<aura::Window>> id_to_window;
     std::map<aura::Window*, int> window_to_id;
 
-    auto populate_desk =
-        [&](Desk* desk, const std::vector<std::vector<int>>& desk_windows) {
-          SCOPED_TRACE("Create windows for " + base::UTF16ToUTF8(desk->name()));
+    for (auto* window_ids : {&test.desk_1_windows, &test.desk_2_windows}) {
+      for (int id : *window_ids) {
+        auto window = CreateAppWindow(gfx::Rect(0 + id, 0 + id, 100, 100));
+        window_to_id[window.get()] = id;
+        id_to_window[id] = std::move(window);
+      }
 
-          // Verify we are on the correct desk.
-          ASSERT_TRUE(desk->is_active());
-
-          int offset = 0;
-          for (const auto& window_ids : desk_windows) {
-            for (int id : window_ids) {
-              auto window =
-                  CreateAppWindow(gfx::Rect(offset + id, 0 + id, 100, 100));
-              window_to_id[window.get()] = id;
-              id_to_window[id] = std::move(window);
-            }
-            // Increment the offset to ensure that the window will be created on
-            // the next root window.
-            offset += 700;
-          }
-        };
-
-    // Populate each of the desks with the desired windows.
-    populate_desk(desk_1, test.desk_1_windows);
-    ActivateDesk(desk_2);
-    populate_desk(desk_2, test.desk_2_windows);
+      if (!desk_2->is_active())
+        ActivateDesk(desk_2);
+    }
     ActivateDesk(desk_1);
 
     // Mark windows as awd.
@@ -4701,15 +4395,16 @@
       wm::ActivateWindow(id_to_window.at(id).get());
     }
 
-    // Verifies that the desk preview for the given root window is consistent
-    // with the expected per-desk Z-order. Since the layers are mirrored instead
-    // of the same instances, we verify by layer bounds here.
+    aura::Window* root = window_to_id.begin()->first->GetRootWindow();
+
+    // Verifies that the desk preview is consistent with the expected per-desk
+    // Z-order. Since the layers are mirrored instead of the same instances, we
+    // verify by layer bounds here.
     auto verify_desk_preview_mirrored_layer_tree =
-        [&](Desk* desk, aura::Window* root,
-            const std::vector<int>& expected_windows,
+        [&](Desk* desk, const std::vector<int>& expected_windows,
             const std::string& debug_info) {
           SCOPED_TRACE("Verify " + base::UTF16ToUTF8(desk->name()) + " " +
-                       root->GetName() + " " + debug_info);
+                       debug_info);
           ToggleOverview();
 
           // Retrieves the mirrored layers `mirrored_layers` of application
@@ -4732,44 +4427,35 @@
           ToggleOverview();
         };
 
-    // Verifies that windows on the given desk and root window are found in the
-    // expected order. Any windows that have not been created by the test will
-    // be ignored.
-    auto verify_windows = [&](Desk* desk, aura::Window* root,
+    // Verifies that windows on the given desk are found in the expected
+    // order. Any windows that have not been created by the test will be
+    // ignored.
+    auto verify_windows = [&](Desk* desk,
                               const std::vector<int>& expected_windows,
                               const std::string& debug_info) {
       SCOPED_TRACE("Verify " + base::UTF16ToUTF8(desk->name()) + " " +
-                   root->GetName() + " " + debug_info);
+                   debug_info);
       aura::Window* container = desk->GetDeskContainerForRoot(root);
 
       // Collect any test windows present on the desk.
       std::vector<int> actual_windows;
       for (aura::Window* child : container->children()) {
         auto it = window_to_id.find(child);
-        if (it != window_to_id.end()) {
+        if (it != window_to_id.end())
           actual_windows.push_back(it->second);
-        }
       }
 
       ASSERT_EQ(expected_windows.size(), actual_windows.size());
       EXPECT_EQ(expected_windows, actual_windows);
     };
 
-    auto root_windows = Shell::GetAllRootWindows();
-    ASSERT_EQ(test.multi_display ? 2u : 1u, root_windows.size());
-
     // Now we are ready to actually execute the test.
     ActivateDesk(desk_2);
-    for (size_t i = 0; i < root_windows.size(); i++) {
-      verify_windows(desk_2, root_windows[i],
-                     test.expected_desk_2_windows_before[i], "before");
-      verify_desk_preview_mirrored_layer_tree(
-          desk_1, root_windows[i], test.expected_desk_1_windows_before[i],
-          "before");
-      verify_desk_preview_mirrored_layer_tree(
-          desk_2, root_windows[i], test.expected_desk_2_windows_before[i],
-          "before");
-    }
+    verify_windows(desk_2, test.expected_desk_2_windows_before, "before");
+    verify_desk_preview_mirrored_layer_tree(
+        desk_1, test.expected_desk_1_windows_before, "before");
+    verify_desk_preview_mirrored_layer_tree(
+        desk_2, test.expected_desk_2_windows_before, "before");
 
     // Move specified windows to desk 1.
     for (int id : test.move_windows) {
@@ -4789,22 +4475,11 @@
     }
 
     ActivateDesk(desk_1);
-    for (size_t i = 0; i < root_windows.size(); i++) {
-      verify_windows(desk_1, root_windows[i],
-                     test.expected_desk_1_windows_after[i], "after");
-      verify_desk_preview_mirrored_layer_tree(
-          desk_1, root_windows[i], test.expected_desk_1_windows_after[i],
-          "after");
-      verify_desk_preview_mirrored_layer_tree(
-          desk_2, root_windows[i], test.expected_desk_2_windows_after[i],
-          "after");
-    }
-
-    // Verify that the correct window is activated. This is particularly
-    // important for when we have all desk windows and multiple displays.
-    // Please refer to b/274110274.
-    EXPECT_EQ(id_to_window[test.expected_desk_1_final_active_window].get(),
-              window_util::GetActiveWindow());
+    verify_windows(desk_1, test.expected_desk_1_windows_after, "after");
+    verify_desk_preview_mirrored_layer_tree(
+        desk_1, test.expected_desk_1_windows_after, "after");
+    verify_desk_preview_mirrored_layer_tree(
+        desk_2, test.expected_desk_2_windows_after, "after");
   }
 }
 
@@ -4898,9 +4573,8 @@
     ScopedListPrefUpdate update(prefs, prefs::kDesksNamesList);
     base::Value::List& pref_data = update.Get();
     ASSERT_TRUE(pref_data.empty());
-    for (auto desk_name : desk_names) {
+    for (auto desk_name : desk_names)
       pref_data.Append(desk_name);
-    }
   }
 
   void SimulateUserLogin(const AccountId& account_id) {
@@ -5527,9 +5201,8 @@
   ASSERT_TRUE(overview_session);
   // It's possible to move the highlighted window. |Move()| will cycle through
   // the desk items first, so call it until we are highlighting an OverviewItem.
-  while (!overview_session->GetHighlightedWindow()) {
+  while (!overview_session->GetHighlightedWindow())
     MoveOverviewHighlighter(overview_session);
-  }
   EXPECT_EQ(win0.get(), overview_session->GetHighlightedWindow());
   SendAccelerator(ui::VKEY_OEM_6, flags);
   EXPECT_FALSE(DoesActiveDeskContainWindow(win0.get()));
@@ -5938,11 +5611,10 @@
   // Switch desks.
   NewDesk();
   ActivateDesk(DesksController::Get()->desks()[1].get());
-  if (IsPerDeskShelfEnabled()) {
+  if (IsPerDeskShelfEnabled())
     EXPECT_TRUE(shelf_view->GetTransform().IsIdentity());
-  } else {
+  else
     EXPECT_EQ(scrolled_transform, shelf_view->GetTransform());
-  }
 }
 
 // Tests desks name nudges, i.e. when a user creates a new desk, focus + clear
@@ -6146,9 +5818,8 @@
 // corresponding scroll button.
 TEST_P(DesksTest, ScrollButtonsVisibility) {
   UpdateDisplay("501x600");
-  for (size_t i = 1; i < desks_util::GetMaxNumberOfDesks(); i++) {
+  for (size_t i = 1; i < desks_util::GetMaxNumberOfDesks(); i++)
     NewDesk();
-  }
 
   EXPECT_EQ(DesksController::Get()->desks().size(),
             desks_util::GetMaxNumberOfDesks());
@@ -6221,9 +5892,8 @@
   // bar with maximum number of desks.
   UpdateDisplay("800x150");
   const size_t max_desks_size = desks_util::GetMaxNumberOfDesks();
-  for (size_t i = 1; i < max_desks_size; i++) {
+  for (size_t i = 1; i < max_desks_size; i++)
     NewDesk();
-  }
 
   EnterOverview();
   auto* desks_bar =
@@ -6302,9 +5972,8 @@
       DeskBarViewBase::Type::kOverview));
 
   // Only the left gradient should be shown at the last page.
-  while (right_button->GetVisible()) {
+  while (right_button->GetVisible())
     ClickOnView(right_button, event_generator);
-  }
 
   EXPECT_EQ(scroll_view->contents()->bounds().width() - scroll_view->width(),
             scroll_view->GetVisibleRect().x());
@@ -6321,9 +5990,8 @@
   // Make a flat long window to generate multiple pages on desks bar.
   UpdateDisplay("800x150");
   const size_t max_desks_size = desks_util::GetMaxNumberOfDesks();
-  for (size_t i = 1; i < max_desks_size; i++) {
+  for (size_t i = 1; i < max_desks_size; i++)
     NewDesk();
-  }
 
   auto* desks_controller = DesksController::Get();
   EXPECT_EQ(desks_controller->desks().size(), max_desks_size);
@@ -6340,9 +6008,8 @@
   int desks_in_one_page = page_size / mini_view_width;
   float fractional_page = static_cast<float>(page_size % mini_view_width) /
                           static_cast<float>(mini_view_width);
-  if (fractional_page > 0.5) {
+  if (fractional_page > 0.5)
     desks_in_one_page++;
-  }
 
   int current_index = 0;
   ScrollArrowButton* left_button = DesksTestApi::GetDeskBarLeftScrollButton(
@@ -6389,9 +6056,8 @@
 
   // Release and click a few times to make sure we end up at the maximum offset.
   event_generator->ReleaseLeftButton();
-  for (int i = 0; i != 3; ++i) {
+  for (int i = 0; i != 3; ++i)
     event_generator->ClickLeftButton();
-  }
 
   EXPECT_EQ(scroll_view->GetVisibleRect().x(),
             scroll_view->contents()->width() - page_size);
@@ -6435,9 +6101,8 @@
 // the focused mini view inside the visible bounds.
 TEST_P(DesksTest, FocusedMiniViewIsVisible) {
   UpdateDisplay("501x600");
-  for (size_t i = 1; i < desks_util::GetMaxNumberOfDesks(); i++) {
+  for (size_t i = 1; i < desks_util::GetMaxNumberOfDesks(); i++)
     NewDesk();
-  }
 
   EXPECT_EQ(DesksController::Get()->desks().size(),
             desks_util::GetMaxNumberOfDesks());
@@ -7395,9 +7060,8 @@
   int desks_in_one_page = page_size / mini_view_width;
   float fractional_page = static_cast<float>(page_size % mini_view_width) /
                           static_cast<float>(mini_view_width);
-  if (fractional_page > 0.5) {
+  if (fractional_page > 0.5)
     desks_in_one_page++;
-  }
 
   int current_index = 0;
   ScrollArrowButton* left_button = DesksTestApi::GetDeskBarLeftScrollButton(
@@ -7988,9 +7652,8 @@
   WindowHolder& operator=(const WindowHolder&) = delete;
 
   ~WindowHolder() override {
-    if (window_) {
+    if (window_)
       window_->RemoveObserver(this);
-    }
     // `window_` is destroyed automatically here through the unique pointer.
   }
 
@@ -8893,9 +8556,8 @@
 // before the toast asking if the user would like to undo goes away.
 TEST_P(DesksCloseAllTest, CanAddLastDeskWhileUndoToastIsBeingDisplayed) {
   auto* controller = DesksController::Get();
-  while (controller->desks().size() < desks_util::GetMaxNumberOfDesks()) {
+  while (controller->desks().size() < desks_util::GetMaxNumberOfDesks())
     NewDesk();
-  }
   ASSERT_EQ(desks_util::GetMaxNumberOfDesks(), controller->desks().size());
 
   // Create a window to ensure that closing windows after removing the last desk
@@ -8922,9 +8584,8 @@
   auto* event_generator = GetEventGenerator();
   auto* scroll_right_button = DesksTestApi::GetDeskBarRightScrollButton(
       DeskBarViewBase::Type::kOverview);
-  for (int i = 0; i != 3; ++i) {
+  for (int i = 0; i != 3; ++i)
     ClickOnView(scroll_right_button, event_generator);
-  }
 
   // If we click on the `new_desk_button`, we should create a new desk and
   // destroy the previously removed desk and the window inside of it.
diff --git a/base/allocator/partition_alloc_support.cc b/base/allocator/partition_alloc_support.cc
index 77ea5e7..74e1213 100644
--- a/base/allocator/partition_alloc_support.cc
+++ b/base/allocator/partition_alloc_support.cc
@@ -694,8 +694,8 @@
   // pointers errors are never ignored, by crashing at exit, as a last resort.
   // This makes quarantine memory bloat more likely to be detected.
   static bool first_run_in_process = true;
-  if (!first_run_in_process) {
-    first_run_in_process = true;
+  if (first_run_in_process) {
+    first_run_in_process = false;
     AtExitManager::RegisterTask(base::BindOnce(CheckDanglingRawPtrBufferEmpty));
   }
 
diff --git a/base/allocator/partition_allocator/tagging.cc b/base/allocator/partition_allocator/tagging.cc
index ea7ac2a..6f0d49d 100644
--- a/base/allocator/partition_allocator/tagging.cc
+++ b/base/allocator/partition_allocator/tagging.cc
@@ -230,14 +230,18 @@
   }
   int status = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);
   PA_CHECK(status >= 0);
-  if ((status & PR_TAGGED_ADDR_ENABLE) && (status & PR_MTE_TCF_SYNC)) {
-    return TagViolationReportingMode::kSynchronous;
-  }
+  // Check for Asynchronous first because ASYNC on Android sets both
+  // PR_MTE_TCF_ASYNC and PR_MTE_TCF_SYNC bits.
   if ((status & PR_TAGGED_ADDR_ENABLE) && (status & PR_MTE_TCF_ASYNC)) {
     return TagViolationReportingMode::kAsynchronous;
   }
-#endif  // PA_CONFIG(HAS_MEMORY_TAGGING)
+  if ((status & PR_TAGGED_ADDR_ENABLE) && (status & PR_MTE_TCF_SYNC)) {
+    return TagViolationReportingMode::kSynchronous;
+  }
+  return TagViolationReportingMode::kDisabled;
+#else
   return TagViolationReportingMode::kUndefined;
+#endif  // PA_CONFIG(HAS_MEMORY_TAGGING)
 }
 
 }  // namespace internal
diff --git a/base/allocator/partition_allocator/tagging.h b/base/allocator/partition_allocator/tagging.h
index d49e062c..858c5c3f 100644
--- a/base/allocator/partition_allocator/tagging.h
+++ b/base/allocator/partition_allocator/tagging.h
@@ -51,7 +51,8 @@
 void ChangeMemoryTaggingModeForAllThreadsPerProcess(TagViolationReportingMode);
 #endif
 
-// Gets the memory tagging mode for the calling thread.
+// Gets the memory tagging mode for the calling thread. Returns kUndefined if
+// MTE support is not available.
 PA_COMPONENT_EXPORT(PARTITION_ALLOC)
 TagViolationReportingMode GetMemoryTaggingModeForCurrentThread();
 
diff --git a/base/allocator/partition_allocator/tagging_unittest.cc b/base/allocator/partition_allocator/tagging_unittest.cc
index 47f62ac..5c25a46 100644
--- a/base/allocator/partition_allocator/tagging_unittest.cc
+++ b/base/allocator/partition_allocator/tagging_unittest.cc
@@ -144,4 +144,73 @@
 }
 #endif  // defined(ARCH_CPU_64_BITS)
 
+#if PA_CONFIG(HAS_MEMORY_TAGGING)
+#if BUILDFLAG(IS_ANDROID)
+TEST(PartitionAllocMemoryTaggingTest,
+     ChangeMemoryTaggingModeForAllThreadsPerProcess) {
+  base::CPU cpu;
+  // If the underlying platform does not support MTE, skip this test to avoid
+  // hiding failures.
+  if (!cpu.has_mte()) {
+    GTEST_SKIP();
+  }
+
+  // The mode should be set to synchronous on startup by AndroidManifest.xml
+  // for base_unittests.
+  EXPECT_EQ(GetMemoryTaggingModeForCurrentThread(),
+            TagViolationReportingMode::kSynchronous);
+
+  // Skip changing to kDisabled, because scudo does not support enabling MTE
+  // once it is disabled.
+  ChangeMemoryTaggingModeForAllThreadsPerProcess(
+      TagViolationReportingMode::kAsynchronous);
+  EXPECT_EQ(GetMemoryTaggingModeForCurrentThread(),
+            TagViolationReportingMode::kAsynchronous);
+  ChangeMemoryTaggingModeForAllThreadsPerProcess(
+      TagViolationReportingMode::kSynchronous);
+  // End with mode changed back to synchronous.
+  EXPECT_EQ(GetMemoryTaggingModeForCurrentThread(),
+            TagViolationReportingMode::kSynchronous);
+}
+#endif  // BUILDFLAG(IS_ANDROID)
+
+TEST(PartitionAllocMemoryTaggingTest, ChangeMemoryTaggingModeForCurrentThread) {
+  base::CPU cpu;
+  // If the underlying platform does not support MTE, skip this test to avoid
+  // hiding failures.
+  if (!cpu.has_mte()) {
+    GTEST_SKIP();
+  }
+
+  TagViolationReportingMode original_mode =
+      GetMemoryTaggingModeForCurrentThread();
+
+  ChangeMemoryTaggingModeForCurrentThread(TagViolationReportingMode::kDisabled);
+  EXPECT_EQ(GetMemoryTaggingModeForCurrentThread(),
+            TagViolationReportingMode::kDisabled);
+  ChangeMemoryTaggingModeForCurrentThread(
+      TagViolationReportingMode::kSynchronous);
+  EXPECT_EQ(GetMemoryTaggingModeForCurrentThread(),
+            TagViolationReportingMode::kSynchronous);
+  ChangeMemoryTaggingModeForCurrentThread(
+      TagViolationReportingMode::kAsynchronous);
+  EXPECT_EQ(GetMemoryTaggingModeForCurrentThread(),
+            TagViolationReportingMode::kAsynchronous);
+  ChangeMemoryTaggingModeForCurrentThread(
+      TagViolationReportingMode::kSynchronous);
+  EXPECT_EQ(GetMemoryTaggingModeForCurrentThread(),
+            TagViolationReportingMode::kSynchronous);
+  ChangeMemoryTaggingModeForCurrentThread(TagViolationReportingMode::kDisabled);
+  EXPECT_EQ(GetMemoryTaggingModeForCurrentThread(),
+            TagViolationReportingMode::kDisabled);
+  ChangeMemoryTaggingModeForCurrentThread(
+      TagViolationReportingMode::kAsynchronous);
+  EXPECT_EQ(GetMemoryTaggingModeForCurrentThread(),
+            TagViolationReportingMode::kAsynchronous);
+
+  // Restore mode to original.
+  ChangeMemoryTaggingModeForCurrentThread(original_mode);
+}
+#endif  // PA_CONFIG(HAS_MEMORY_TAGGING)
+
 }  // namespace partition_alloc::internal
diff --git a/base/containers/enum_set.h b/base/containers/enum_set.h
index 441dd234..dd4b949 100644
--- a/base/containers/enum_set.h
+++ b/base/containers/enum_set.h
@@ -181,7 +181,15 @@
 
   // Returns an EnumSet with all possible values.
   static constexpr EnumSet All() {
-    return EnumSet(EnumBitSet((1ULL << kValueCount) - 1));
+    if (kValueCount == 0) {
+      return EnumSet();
+    }
+    // Since `1 << kValueCount` may trigger shift-count-overflow warning if
+    // the `kValueCount` is 64, instead of returning `(1 << kValueCount) - 1`,
+    // the bitmask will be constructed from two parts: the most significant bits
+    // and the remaining.
+    uint64_t mask = 1ULL << (kValueCount - 1);
+    return EnumSet(EnumBitSet(mask - 1 + mask));
   }
 
   // Returns an EnumSet with all the values from start to end, inclusive.
diff --git a/base/containers/enum_set_unittest.cc b/base/containers/enum_set_unittest.cc
index fb3ab1d..e6ebe06 100644
--- a/base/containers/enum_set_unittest.cc
+++ b/base/containers/enum_set_unittest.cc
@@ -138,6 +138,15 @@
   EXPECT_TRUE(enums.Has(TestEnum::TEST_5));
 }
 
+TEST_F(EnumSetTest, AllExtreme) {
+  const TestEnumExtremeSet enums(TestEnumExtremeSet::All());
+  EXPECT_FALSE(enums.Empty());
+  EXPECT_EQ(static_cast<size_t>(64), enums.Size());
+  EXPECT_TRUE(enums.Has(TestEnumExtreme::TEST_0));
+  EXPECT_TRUE(enums.Has(TestEnumExtreme::TEST_63));
+  EXPECT_FALSE(enums.Has(TestEnumExtreme::TEST_64_OUT_OF_BOUNDS));
+}
+
 TEST_F(EnumSetTest, FromRange) {
   EXPECT_EQ(TestEnumSet({TestEnum::TEST_2, TestEnum::TEST_3, TestEnum::TEST_4}),
             TestEnumSet::FromRange(TestEnum::TEST_2, TestEnum::TEST_4));
diff --git a/base/process/launch_win.cc b/base/process/launch_win.cc
index 503d60e..384c771 100644
--- a/base/process/launch_win.cc
+++ b/base/process/launch_win.cc
@@ -336,9 +336,13 @@
 
   if (options.stdin_handle || options.stdout_handle || options.stderr_handle) {
     DCHECK(inherit_handles);
-    DCHECK(options.stdin_handle);
-    DCHECK(options.stdout_handle);
-    DCHECK(options.stderr_handle);
+    // If an explicit handle inheritance list is not set, require that all
+    // stdio handle values be explicitly specified.
+    if (options.handles_to_inherit.empty()) {
+      CHECK(options.stdin_handle);
+      CHECK(options.stdout_handle);
+      CHECK(options.stderr_handle);
+    }
     startup_info->dwFlags |= STARTF_USESTDHANDLES;
     startup_info->hStdInput = options.stdin_handle;
     startup_info->hStdOutput = options.stdout_handle;
diff --git a/chrome/VERSION b/chrome/VERSION
index 213f9a9..d6fcafd 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=115
 MINOR=0
-BUILD=5788
+BUILD=5789
 PATCH=0
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index fd83e9e..a3986b3 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -1501,6 +1501,9 @@
       <message name="IDS_MANAGED_BY" desc="The text label of the 'Managed by' UI in the app menu, for enterprise users. MANAGER can be a domain or an email address.">
         Managed by <ph name="MANAGER">$1<ex>example.com</ex></ph>
       </message>
+      <message name="IDS_MANAGED_BY_PARENT" desc="The text label shown in the app menu for users subject to parental controls.">
+        Managed by your parent
+      </message>
       <message name="IDS_CHROME_TIPS" desc="The text label of the Help menu item which takes the user to the Chrome Tips page.">
         Tips for Chrome
       </message>
@@ -10446,6 +10449,9 @@
         <message name="IDS_MANAGED_BY_WITH_HYPERLINK" desc="Message to end users in Enterprise/EDU, with a link for more info (non-ChromeOS). MANAGER can be a domain or an email address.">
           Your <ph name="BEGIN_LINK">&lt;a href="$1"&gt;</ph>browser is managed<ph name="END_LINK">&lt;/a&gt;</ph> by <ph name="MANAGER">$2<ex>example.com</ex></ph>
         </message>
+        <message name="IDS_MANAGED_BY_PARENT_WITH_HYPERLINK" desc="Message to supervised end users, with a link for more info.">
+          Your <ph name="BEGIN_LINK">&lt;a href="$1"&gt;</ph>browser is managed<ph name="END_LINK">&lt;/a&gt;</ph> by your parent
+        </message>
       </if>
 
       <!-- Cookies Window -->
diff --git a/chrome/app/generated_resources_grd/IDS_MANAGED_BY_PARENT.png.sha1 b/chrome/app/generated_resources_grd/IDS_MANAGED_BY_PARENT.png.sha1
new file mode 100644
index 0000000..bdcd7f65
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_MANAGED_BY_PARENT.png.sha1
@@ -0,0 +1 @@
+306c47f2b24107bf7f5bf3090439badb588d5275
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_MANAGED_BY_PARENT_WITH_HYPERLINK.png.sha1 b/chrome/app/generated_resources_grd/IDS_MANAGED_BY_PARENT_WITH_HYPERLINK.png.sha1
new file mode 100644
index 0000000..51b6f6d
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_MANAGED_BY_PARENT_WITH_HYPERLINK.png.sha1
@@ -0,0 +1 @@
+7f0f30fbab33a59de48f77db61f5a771f25442d9
\ No newline at end of file
diff --git a/chrome/app/theme/borealis/logo_borealis_steam_pending_192.png b/chrome/app/theme/borealis/logo_borealis_steam_pending_192.png
new file mode 100644
index 0000000..f88fb4e8
--- /dev/null
+++ b/chrome/app/theme/borealis/logo_borealis_steam_pending_192.png
Binary files differ
diff --git a/chrome/app/theme/chrome_unscaled_resources.grd b/chrome/app/theme/chrome_unscaled_resources.grd
index 47cfdd7..04441f0 100644
--- a/chrome/app/theme/chrome_unscaled_resources.grd
+++ b/chrome/app/theme/chrome_unscaled_resources.grd
@@ -149,6 +149,7 @@
         <!-- Borealis icons -->
         <include name="IDR_LOGO_BOREALIS_DEFAULT_192" file="borealis/logo_borealis_default_192.png" type="BINDATA" />
         <include name="IDR_LOGO_BOREALIS_STEAM_192" file="borealis/logo_borealis_steam_192.png" type="BINDATA" />
+        <include name="IDR_LOGO_BOREALIS_STEAM_PENDING_192" file="borealis/logo_borealis_steam_pending_192.png" type="BINDATA" />
         <include name="IDR_LOGO_BOREALIS_SPLASH" file="borealis/logo_borealis_splash.png" type="BINDATA" />
         <include name="IDR_LOGO_BOREALIS_FLAIR" file="borealis/logo_borealis_flair_64.png" type="BINDATA" />
         <!-- TODO(b/248938308): Replace the below large .png files with svg/lottie when we update to WebUI. -->
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 03851ab..109debfc 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -2483,9 +2483,10 @@
       "renderer_context_menu/pdf_ocr_menu_observer.h",
     ]
     deps += [
+      "//chrome/browser/screen_ai:prefs",
+      "//chrome/browser/screen_ai:screen_ai_install_state",
+      "//chrome/browser/screen_ai:screen_ai_service_router_factory",
       "//components/services/screen_ai",
-      "//components/services/screen_ai/public/cpp:screen_ai_install_state",
-      "//components/services/screen_ai/public/cpp:screen_ai_service_router_factory",
       "//components/services/screen_ai/public/cpp:utilities",
       "//components/services/screen_ai/public/mojom",
     ]
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index b92395f..2cfb36800 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -9097,6 +9097,13 @@
      flag_descriptions::kExtensionWebFileHandlersDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(extensions_features::kExtensionWebFileHandlers)},
 #endif  // IS_CHROMEOS_ASH
+#if BUILDFLAG(IS_WIN)
+    {"launch-windows-native-hosts-directly",
+     flag_descriptions::kLaunchWindowsNativeHostsDirectlyName,
+     flag_descriptions::kLaunchWindowsNativeHostsDirectlyDescription, kOsWin,
+     FEATURE_VALUE_TYPE(
+         extensions_features::kLaunchWindowsNativeHostsDirectly)},
+#endif  // IS_WIN
 #endif  // ENABLE_EXTENSIONS
 
     {"canvas-oop-rasterization", flag_descriptions::kCanvasOopRasterizationName,
@@ -9299,6 +9306,15 @@
      FEATURE_VALUE_TYPE(
          autofill::features::kAutofillEnableUpdateVirtualCardEnrollment)},
 
+    {"autofill-move-legal-terms-and-icon-for-new-card-enrollment",
+     flag_descriptions::kAutofillMoveLegalTermsAndIconForNewCardEnrollmentName,
+     flag_descriptions::
+         kAutofillMoveLegalTermsAndIconForNewCardEnrollmentDescription,
+     kOsDesktop,
+     FEATURE_VALUE_TYPE(
+         autofill::features::
+             kAutofillMoveLegalTermsAndIconForNewCardEnrollment)},
+
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
 
     {"enable-lacros-aura-capture", flag_descriptions::kLacrosAuraCaptureName,
diff --git a/chrome/browser/accessibility/ax_screen_ai_annotator.cc b/chrome/browser/accessibility/ax_screen_ai_annotator.cc
index 79cfa6b0..e1897365 100644
--- a/chrome/browser/accessibility/ax_screen_ai_annotator.cc
+++ b/chrome/browser/accessibility/ax_screen_ai_annotator.cc
@@ -11,9 +11,9 @@
 #include "base/strings/strcat.h"
 #include "base/task/sequenced_task_runner.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/screen_ai/screen_ai_service_router.h"
+#include "chrome/browser/screen_ai/screen_ai_service_router_factory.h"
 #include "chrome/browser/ui/browser.h"
-#include "components/services/screen_ai/public/cpp/screen_ai_service_router.h"
-#include "components/services/screen_ai/public/cpp/screen_ai_service_router_factory.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/accessibility/ax_tree_update.h"
diff --git a/chrome/browser/accessibility/ax_screen_ai_annotator.h b/chrome/browser/accessibility/ax_screen_ai_annotator.h
index 418116b..e9c5d2b8 100644
--- a/chrome/browser/accessibility/ax_screen_ai_annotator.h
+++ b/chrome/browser/accessibility/ax_screen_ai_annotator.h
@@ -10,8 +10,8 @@
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/scoped_observation.h"
+#include "chrome/browser/screen_ai/screen_ai_install_state.h"
 #include "components/keyed_service/core/keyed_service.h"
-#include "components/services/screen_ai/public/cpp/screen_ai_install_state.h"
 #include "components/services/screen_ai/public/mojom/screen_ai_service.mojom.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
diff --git a/chrome/browser/accessibility/pdf_ocr_controller.cc b/chrome/browser/accessibility/pdf_ocr_controller.cc
index f2e3c66..519d782 100644
--- a/chrome/browser/accessibility/pdf_ocr_controller.cc
+++ b/chrome/browser/accessibility/pdf_ocr_controller.cc
@@ -6,16 +6,22 @@
 
 #include "base/check_is_test.h"
 #include "base/check_op.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/screen_ai/screen_ai_service_router.h"
+#include "chrome/browser/screen_ai/screen_ai_service_router_factory.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/common/pdf_util.h"
 #include "chrome/common/pref_names.h"
+#include "chrome/grit/generated_resources.h"
 #include "components/prefs/pref_service.h"
-#include "components/services/screen_ai/public/cpp/screen_ai_service_router.h"
-#include "components/services/screen_ai/public/cpp/screen_ai_service_router_factory.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host.h"
 #include "content/public/browser/render_widget_host_iterator.h"
 #include "content/public/browser/web_contents.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/views/accessibility/view_accessibility.h"
 
 namespace {
 
@@ -63,6 +69,23 @@
   return result;
 }
 
+// Invoke screen reader alert to notify the user of the state.
+void AnnounceToScreenReader(const int message_id) {
+  const Browser* browser = BrowserList::GetInstance()->GetLastActive();
+  if (!browser) {
+    VLOG(2) << "Browser is not ready to announce";
+    return;
+  }
+  BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser);
+  if (!browser_view) {
+    VLOG(2) << "Browser is not ready to announce";
+    return;
+  }
+
+  browser_view->GetViewAccessibility().AnnounceText(
+      l10n_util::GetStringUTF16(message_id));
+}
+
 }  // namespace
 
 namespace screen_ai {
@@ -77,8 +100,6 @@
       base::BindRepeating(&PdfOcrController::OnPdfOcrAlwaysActiveChanged,
                           weak_ptr_factory_.GetWeakPtr()));
 
-  component_ready_observer_.Observe(ScreenAIInstallState::GetInstance());
-
   // Trigger if the preference is already set.
   if (profile_->GetPrefs()->GetBoolean(
           prefs::kAccessibilityPdfOcrAlwaysActive)) {
@@ -102,6 +123,14 @@
     CHECK_IS_TEST();
     return;
   }
+
+  if (MaybeAddObserverOrTriggerDownload(web_contents)) {
+    // If we added an observer for `ScreenAIInstallState` or triggered
+    // downloading the Screen AI library, return here; the request will be
+    // handled when the library is ready or discarded if it fails to load it.
+    return;
+  }
+
   // `web_contents` should be a PDF Viewer Mimehandler.
   DCHECK_EQ(web_contents->GetContentsMimeType(), kHtmlMimeType);
 
@@ -112,7 +141,8 @@
 
 bool PdfOcrController::IsEnabled() const {
   return profile_->GetPrefs()->GetBoolean(
-      prefs::kAccessibilityPdfOcrAlwaysActive);
+             prefs::kAccessibilityPdfOcrAlwaysActive) &&
+         !send_always_active_state_when_service_is_ready_;
 }
 
 void PdfOcrController::OnPdfOcrAlwaysActiveChanged() {
@@ -121,13 +151,11 @@
   VLOG(2) << "PDF OCR Always Active changed: " << is_always_active;
 
   if (is_always_active) {
-    // If Screen AI service is not ready and user is requesting OCR, keep the
-    // request until service is up.
-    if (screen_ai::ScreenAIInstallState::GetInstance()->get_state() !=
-        ScreenAIInstallState::State::kReady) {
-      // TODO(crbug.com/1393069): Consider letting user know that OCR will run
-      // when service is ready.
-      send_always_active_state_when_service_is_ready_ = true;
+    if (MaybeAddObserverOrTriggerDownload(
+            /*web_contents_for_only_once_request=*/nullptr)) {
+      // If we added an observer for `ScreenAIInstallState` or triggered
+      // downloading the Screen AI library, return here; the request will be
+      // handled when the library is ready or discarded if it fails to load it.
       return;
     }
   } else {
@@ -154,24 +182,87 @@
   }
 }
 
+bool PdfOcrController::MaybeAddObserverOrTriggerDownload(
+    content::WebContents* web_contents_for_only_once_request) {
+  ScreenAIInstallState::State current_install_state =
+      ScreenAIInstallState::GetInstance()->get_state();
+
+  if (current_install_state == ScreenAIInstallState::State::kReady) {
+    return false;
+  }
+
+  if (!component_ready_observer_.IsObserving()) {
+    // Start observing ScreenAIInstallState when the user activates PDF OCR. It
+    // triggers downloading the Screen AI library if it's not downloaded. Keep
+    // the request until the library is ready.
+    if (web_contents_for_only_once_request) {
+      // PDF OCR once request. Keep its weak pointer of the web contents
+      // requested for this.
+      last_webcontents_requested_for_run_once_ =
+          web_contents_for_only_once_request->GetWeakPtr();
+    } else {
+      // PDF OCR always request.
+      send_always_active_state_when_service_is_ready_ = true;
+    }
+    component_ready_observer_.Observe(ScreenAIInstallState::GetInstance());
+    return true;
+  }
+
+  if (current_install_state == ScreenAIInstallState::State::kFailed) {
+    // Try downloading the Screen AI library again if it failed before. Keep the
+    // request until the library is ready; this request will be discarded
+    // if it fails to download it again.
+    // TODO(crbug.com/127829): Make sure requesting a failed download will
+    // trigger a new one.
+    if (web_contents_for_only_once_request) {
+      // PDF OCR once request. Keep its weak pointer of the web contents
+      // requested for this.
+      last_webcontents_requested_for_run_once_ =
+          web_contents_for_only_once_request->GetWeakPtr();
+    } else {
+      // PDF OCR always request.
+      send_always_active_state_when_service_is_ready_ = true;
+    }
+    ScreenAIInstallState::GetInstance()->DownloadComponent();
+    return true;
+  }
+
+  return false;
+}
+
 void PdfOcrController::StateChanged(ScreenAIInstallState::State state) {
   switch (state) {
     case ScreenAIInstallState::State::kNotDownloaded:
       break;
 
     case ScreenAIInstallState::State::kDownloading:
+      AnnounceToScreenReader(IDS_SETTINGS_PDF_OCR_DOWNLOADING);
       break;
 
     case ScreenAIInstallState::State::kFailed:
-      // TODO(crbug.com/1393069): Disable menu items.
+      AnnounceToScreenReader(IDS_SETTINGS_PDF_OCR_DOWNLOAD_ERROR);
+      if (last_webcontents_requested_for_run_once_) {
+        last_webcontents_requested_for_run_once_.reset();
+      }
+      if (send_always_active_state_when_service_is_ready_) {
+        // Update the PDF OCR pref to be false to toggle off the button.
+        profile_->GetPrefs()->SetBoolean(
+            prefs::kAccessibilityPdfOcrAlwaysActive, false);
+        send_always_active_state_when_service_is_ready_ = false;
+      }
       break;
 
     case ScreenAIInstallState::State::kDownloaded:
+      AnnounceToScreenReader(IDS_SETTINGS_PDF_OCR_DOWNLOAD_COMPLETE);
       screen_ai::ScreenAIServiceRouterFactory::GetForBrowserContext(profile_)
           ->InitializeOCRIfNeeded();
       break;
 
     case ScreenAIInstallState::State::kReady:
+      if (last_webcontents_requested_for_run_once_) {
+        RunPdfOcrOnlyOnce(last_webcontents_requested_for_run_once_.get());
+        last_webcontents_requested_for_run_once_.reset();
+      }
       if (send_always_active_state_when_service_is_ready_) {
         send_always_active_state_when_service_is_ready_ = false;
         SendPdfOcrAlwaysActiveToAll(true);
diff --git a/chrome/browser/accessibility/pdf_ocr_controller.h b/chrome/browser/accessibility/pdf_ocr_controller.h
index 26e12f16..09980c17 100644
--- a/chrome/browser/accessibility/pdf_ocr_controller.h
+++ b/chrome/browser/accessibility/pdf_ocr_controller.h
@@ -8,9 +8,9 @@
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/scoped_observation.h"
+#include "chrome/browser/screen_ai/screen_ai_install_state.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/prefs/pref_change_registrar.h"
-#include "components/services/screen_ai/public/cpp/screen_ai_install_state.h"
 
 class Profile;
 
@@ -36,8 +36,10 @@
   static std::vector<content::WebContents*> GetAllPdfWebContentsesForTesting(
       Profile* profile);
 
-  // Return true if the PDF OCR pref is true; false otherwise.
+  // Return true if the PDF OCR pref is true and we are not waiting for the
+  // service to become ready.
   bool IsEnabled() const;
+
   // Run PDF OCR only once regardless of the PDF OCR pref value. This function
   // doesn't update the PDF OCR pref value.
   void RunPdfOcrOnlyOnce(content::WebContents* web_contents);
@@ -55,6 +57,12 @@
   // Sends Pdf Ocr Always Active state to all relevant WebContents.
   void SendPdfOcrAlwaysActiveToAll(bool is_always_active);
 
+  // Return true if it added an observer for `ScreenAIInstallState` or
+  // triggered downloading the Screen AI library. In this case, we need to keep
+  // the request until the library is ready.
+  bool MaybeAddObserverOrTriggerDownload(
+      content::WebContents* web_contents_for_only_once_request);
+
   // Observes changes in Screen AI component download and readiness state.
   base::ScopedObservation<ScreenAIInstallState, ScreenAIInstallState::Observer>
       component_ready_observer_{this};
@@ -69,6 +77,12 @@
   // Screen AI service to be ready to send this bit.
   bool send_always_active_state_when_service_is_ready_{false};
 
+  // Store a weak pointer to `content::WebContents` the user requested last for
+  // the "Just once" option. Having a valid pointer indicates that user has
+  // requested running just once on WebContents, and we are waiting for the
+  // Screen AI service to be ready for the user request.
+  base::WeakPtr<content::WebContents> last_webcontents_requested_for_run_once_;
+
   base::WeakPtrFactory<PdfOcrController> weak_ptr_factory_{this};
 };
 
diff --git a/chrome/browser/apps/app_deduplication_service/app_deduplication_service.cc b/chrome/browser/apps/app_deduplication_service/app_deduplication_service.cc
index 0f1e47da..53e9a0e 100644
--- a/chrome/browser/apps/app_deduplication_service/app_deduplication_service.cc
+++ b/chrome/browser/apps/app_deduplication_service/app_deduplication_service.cc
@@ -23,11 +23,36 @@
 #include "components/prefs/pref_service.h"
 #include "components/services/app_service/public/cpp/app_types.h"
 #include "components/services/app_service/public/cpp/types_util.h"
+#include "third_party/crashpad/crashpad/util/string/split_string.h"
 
 namespace {
 // Folder path to where the deduplication data will be stored on disk.
 constexpr char kAppDeduplicationFolderPath[] =
     "app_deduplication_service/deduplication_data/";
+
+// Converts PackageId strings to EntryIds when the source is Website.
+absl::optional<apps::deduplication::EntryId> GetEntryIdForWebsite(
+    const std::string& id) {
+  size_t separator = id.find_first_of(':');
+  apps::deduplication::EntryId entry_id;
+
+  if (separator == std::string::npos || separator == id.size() - 1) {
+    LOG(ERROR) << "Source is an unsupported type.";
+    return absl::nullopt;
+  }
+
+  std::string app_type = id.substr(0, separator);
+  std::string app_id = id.substr(separator + 1);
+  GURL entry_url = GURL(app_id);
+
+  if (entry_url.is_valid() && app_type == "website") {
+    entry_id = apps::deduplication::EntryId(entry_url);
+  } else {
+    LOG(ERROR) << "Source is an unsupported type.";
+    return absl::nullopt;
+  }
+  return entry_id;
+}
 }  // namespace
 
 namespace apps::deduplication {
@@ -147,8 +172,6 @@
         entry_id = EntryId(app_id, AppType::kArc);
       } else if (source == "web") {
         entry_id = EntryId(app_id, AppType::kWeb);
-      } else if (source == "phonehub") {
-        entry_id = EntryId(app_id);
       } else if (source == "website") {
         GURL entry_url = GURL(app_id);
         if (entry_url.is_valid()) {
@@ -322,21 +345,24 @@
     DuplicateGroup duplicate_group;
     for (auto const& id : group.package_id()) {
       absl::optional<PackageId> package_id = PackageId::FromString(id);
-      if (!package_id.has_value()) {
-        // TODO(sharminzaman@): Add support for websites.
-        continue;
-      }
-
-      AppType source = package_id.value().app_type();
-      std::string app_id = package_id.value().identifier();
+      std::string app_id;
       EntryId entry_id;
-
-      if (source == AppType::kArc || source == AppType::kWeb) {
-        entry_id = EntryId(app_id, source);
+      if (!package_id.has_value()) {
+        absl::optional<EntryId> web_id = GetEntryIdForWebsite(id);
+        if (!web_id.has_value()) {
+          continue;
+        }
+        entry_id = web_id.value();
       } else {
-        LOG(ERROR) << "Source is an unsupported type.";
-        NOTREACHED();
+        AppType source = package_id.value().app_type();
+        app_id = package_id.value().identifier();
+        if (source != AppType::kArc && source != AppType::kWeb) {
+          LOG(ERROR) << "Source is an unsupported type.";
+          NOTREACHED();
+        }
+        entry_id = EntryId(app_id, source);
       }
+
       entry_to_group_map_[entry_id] = index;
       // Initialize entry status.
       entry_status_[entry_id] = entry_id.entry_type == EntryType::kApp
@@ -345,8 +371,10 @@
       Entry entry(std::move(entry_id));
       duplicate_group.entries.push_back(std::move(entry));
     }
-    duplication_map_[index] = std::move(duplicate_group);
-    index++;
+    if (!duplicate_group.entries.empty()) {
+      duplication_map_[index] = std::move(duplicate_group);
+      index++;
+    }
   }
 
   apps::AppServiceProxy* proxy =
diff --git a/chrome/browser/apps/app_deduplication_service/app_deduplication_service.h b/chrome/browser/apps/app_deduplication_service/app_deduplication_service.h
index 2869c93..cb68fe2 100644
--- a/chrome/browser/apps/app_deduplication_service/app_deduplication_service.h
+++ b/chrome/browser/apps/app_deduplication_service/app_deduplication_service.h
@@ -63,6 +63,10 @@
   FRIEND_TEST_ALL_PREFIXES(AppDeduplicationServiceAlmanacTest,
                            DeduplicateDataToEntries);
   FRIEND_TEST_ALL_PREFIXES(AppDeduplicationServiceAlmanacTest,
+                           DeduplicateDataToEntriesInvalidAppType);
+  FRIEND_TEST_ALL_PREFIXES(AppDeduplicationServiceAlmanacTest,
+                           DeduplicateDataToEntriesInvalidAppId);
+  FRIEND_TEST_ALL_PREFIXES(AppDeduplicationServiceAlmanacTest,
                            PrefUnchangedAfterServerError);
   FRIEND_TEST_ALL_PREFIXES(AppDeduplicationServiceAlmanacTest,
                            PrefSetAfterServerSuccess);
diff --git a/chrome/browser/apps/app_deduplication_service/app_deduplication_service_unittest.cc b/chrome/browser/apps/app_deduplication_service/app_deduplication_service_unittest.cc
index 333c64b9..25ab08e8 100644
--- a/chrome/browser/apps/app_deduplication_service/app_deduplication_service_unittest.cc
+++ b/chrome/browser/apps/app_deduplication_service/app_deduplication_service_unittest.cc
@@ -148,16 +148,10 @@
   ASSERT_NE(it, service->entry_to_group_map_.end());
   EXPECT_EQ(skype_test_index, it->second);
 
-  std::string skype_phonehub_app_id = "com.skype.raider";
-  it = service->entry_to_group_map_.find(EntryId(skype_phonehub_app_id));
-  ASSERT_NE(it, service->entry_to_group_map_.end());
-  EXPECT_EQ(skype_test_index, it->second);
-
   auto map_it = service->duplication_map_.find(skype_test_index);
   ASSERT_FALSE(map_it == service->duplication_map_.end());
   EXPECT_THAT(map_it->second.entries,
-              ElementsAre(Entry(EntryId(skype_phonehub_app_id)),
-                          Entry(EntryId(skype_arc_app_id, AppType::kArc)),
+              ElementsAre(Entry(EntryId(skype_arc_app_id, AppType::kArc)),
                           Entry(EntryId(skype_web_app_id, AppType::kWeb))));
 
   uint32_t whatsapp_test_index = 2;
@@ -173,16 +167,10 @@
   ASSERT_NE(it, service->entry_to_group_map_.end());
   EXPECT_EQ(whatsapp_test_index, it->second);
 
-  std::string whatsapp_phonehub_app_id = "com.whatsapp";
-  it = service->entry_to_group_map_.find(EntryId(whatsapp_phonehub_app_id));
-  ASSERT_NE(it, service->entry_to_group_map_.end());
-  EXPECT_EQ(whatsapp_test_index, it->second);
-
   map_it = service->duplication_map_.find(whatsapp_test_index);
   ASSERT_FALSE(map_it == service->duplication_map_.end());
   EXPECT_THAT(map_it->second.entries,
-              ElementsAre(Entry(EntryId(whatsapp_phonehub_app_id)),
-                          Entry(EntryId(whatsapp_arc_app_id, AppType::kArc)),
+              ElementsAre(Entry(EntryId(whatsapp_arc_app_id, AppType::kArc)),
                           Entry(EntryId(whatsapp_web_app_id, AppType::kWeb))));
 }
 
@@ -220,66 +208,34 @@
 
   EntryId skype_arc_entry_id(skype_arc_app_id, apps::AppType::kArc);
   EntryId skype_web_entry_id(skype_web_app_id, apps::AppType::kWeb);
-  EntryId skype_phonehub_entry_id("com.skype.raider");
   EntryId whatsapp_arc_entry_id(whatsapp_arc_app_id, apps::AppType::kArc);
   EntryId whatsapp_web_entry_id(whatsapp_web_app_id, apps::AppType::kWeb);
-  EntryId whatsapp_phonehub_entry_id("com.whatsapp");
 
   EXPECT_THAT(
       service->GetDuplicates(skype_arc_entry_id),
-      ElementsAre(Entry(skype_phonehub_entry_id), Entry(skype_arc_entry_id),
-                  Entry(skype_web_entry_id)));
+      ElementsAre(Entry(skype_arc_entry_id), Entry(skype_web_entry_id)));
   EXPECT_THAT(
       service->GetDuplicates(skype_web_entry_id),
-      ElementsAre(Entry(skype_phonehub_entry_id), Entry(skype_arc_entry_id),
-                  Entry(skype_web_entry_id)));
-  EXPECT_THAT(
-      service->GetDuplicates(skype_phonehub_entry_id),
-      ElementsAre(Entry(skype_phonehub_entry_id), Entry(skype_arc_entry_id),
-                  Entry(skype_web_entry_id)));
+      ElementsAre(Entry(skype_arc_entry_id), Entry(skype_web_entry_id)));
   EXPECT_THAT(
       service->GetDuplicates(whatsapp_web_entry_id),
-      ElementsAre(Entry(whatsapp_phonehub_entry_id),
-                  Entry(whatsapp_arc_entry_id), Entry(whatsapp_web_entry_id)));
+      ElementsAre(Entry(whatsapp_arc_entry_id), Entry(whatsapp_web_entry_id)));
   EXPECT_THAT(
       service->GetDuplicates(whatsapp_arc_entry_id),
-      ElementsAre(Entry(whatsapp_phonehub_entry_id),
-                  Entry(whatsapp_arc_entry_id), Entry(whatsapp_web_entry_id)));
-  EXPECT_THAT(
-      service->GetDuplicates(whatsapp_phonehub_entry_id),
-      ElementsAre(Entry(whatsapp_phonehub_entry_id),
-                  Entry(whatsapp_arc_entry_id), Entry(whatsapp_web_entry_id)));
+      ElementsAre(Entry(whatsapp_arc_entry_id), Entry(whatsapp_web_entry_id)));
 
   EXPECT_TRUE(service->AreDuplicates(skype_arc_entry_id, skype_web_entry_id));
   EXPECT_TRUE(
-      service->AreDuplicates(skype_arc_entry_id, skype_phonehub_entry_id));
-  EXPECT_TRUE(
-      service->AreDuplicates(skype_phonehub_entry_id, skype_web_entry_id));
-  EXPECT_TRUE(
       service->AreDuplicates(whatsapp_arc_entry_id, whatsapp_web_entry_id));
-  EXPECT_TRUE(service->AreDuplicates(whatsapp_arc_entry_id,
-                                     whatsapp_phonehub_entry_id));
-  EXPECT_TRUE(service->AreDuplicates(whatsapp_web_entry_id,
-                                     whatsapp_phonehub_entry_id));
 
   EXPECT_FALSE(
       service->AreDuplicates(skype_arc_entry_id, whatsapp_arc_entry_id));
   EXPECT_FALSE(
       service->AreDuplicates(skype_arc_entry_id, whatsapp_web_entry_id));
   EXPECT_FALSE(
-      service->AreDuplicates(skype_arc_entry_id, whatsapp_phonehub_entry_id));
-  EXPECT_FALSE(
       service->AreDuplicates(skype_web_entry_id, whatsapp_arc_entry_id));
   EXPECT_FALSE(
       service->AreDuplicates(skype_web_entry_id, whatsapp_web_entry_id));
-  EXPECT_FALSE(
-      service->AreDuplicates(skype_web_entry_id, whatsapp_phonehub_entry_id));
-  EXPECT_FALSE(
-      service->AreDuplicates(skype_phonehub_entry_id, whatsapp_arc_entry_id));
-  EXPECT_FALSE(
-      service->AreDuplicates(skype_phonehub_entry_id, whatsapp_web_entry_id));
-  EXPECT_FALSE(service->AreDuplicates(skype_phonehub_entry_id,
-                                      whatsapp_phonehub_entry_id));
 
   EntryId not_duplicate_app_id("not_duplicate_app_id", apps::AppType::kWeb);
   EXPECT_TRUE(service->GetDuplicates(not_duplicate_app_id).empty());
@@ -288,13 +244,9 @@
   EXPECT_FALSE(
       service->AreDuplicates(not_duplicate_app_id, skype_web_entry_id));
   EXPECT_FALSE(
-      service->AreDuplicates(not_duplicate_app_id, skype_phonehub_entry_id));
-  EXPECT_FALSE(
       service->AreDuplicates(not_duplicate_app_id, whatsapp_arc_entry_id));
   EXPECT_FALSE(
       service->AreDuplicates(not_duplicate_app_id, whatsapp_web_entry_id));
-  EXPECT_FALSE(
-      service->AreDuplicates(not_duplicate_app_id, whatsapp_phonehub_entry_id));
 }
 
 TEST_F(AppDeduplicationServiceTest, Installation) {
@@ -320,34 +272,27 @@
 
   EntryId skype_arc_entry_id(skype_arc_app_id, apps::AppType::kArc);
   EntryId skype_web_entry_id(skype_web_app_id, apps::AppType::kWeb);
-  EntryId skype_phonehub_entry_id("com.skype.raider");
   EntryId whatsapp_arc_entry_id(whatsapp_arc_app_id, apps::AppType::kArc);
   EntryId whatsapp_web_entry_id(whatsapp_web_app_id, apps::AppType::kWeb);
-  EntryId whatsapp_phonehub_entry_id("com.whatsapp");
 
   // If nothing is installed, should only return phonehub app.
-  EXPECT_THAT(service->GetDuplicates(skype_arc_entry_id),
-              ElementsAre(Entry(skype_phonehub_entry_id)));
-  EXPECT_THAT(service->GetDuplicates(whatsapp_web_entry_id),
-              ElementsAre(Entry(whatsapp_phonehub_entry_id)));
+  EXPECT_THAT(service->GetDuplicates(skype_arc_entry_id), ElementsAre());
+  EXPECT_THAT(service->GetDuplicates(whatsapp_web_entry_id), ElementsAre());
 
   UpdateAppReadiness(proxy, "app1", skype_arc_app_id, apps::AppType::kArc,
                      Readiness::kReady);
-  EXPECT_THAT(
-      service->GetDuplicates(skype_web_entry_id),
-      ElementsAre(Entry(skype_phonehub_entry_id), Entry(skype_arc_entry_id)));
+  EXPECT_THAT(service->GetDuplicates(skype_web_entry_id),
+              ElementsAre(Entry(skype_arc_entry_id)));
 
   UpdateAppReadiness(proxy, "app2", whatsapp_web_app_id, apps::AppType::kWeb,
                      Readiness::kReady);
   EXPECT_THAT(service->GetDuplicates(whatsapp_arc_entry_id),
-              ElementsAre(Entry(whatsapp_phonehub_entry_id),
-                          Entry(whatsapp_web_entry_id)));
+              ElementsAre(Entry(whatsapp_web_entry_id)));
 
   // Uninstall the app removes it from duplicates.
   UpdateAppReadiness(proxy, "app1", skype_arc_app_id, apps::AppType::kArc,
                      Readiness::kUninstalledByUser);
-  EXPECT_THAT(service->GetDuplicates(skype_arc_entry_id),
-              ElementsAre(Entry(skype_phonehub_entry_id)));
+  EXPECT_THAT(service->GetDuplicates(skype_arc_entry_id), ElementsAre());
 }
 
 TEST_F(AppDeduplicationServiceTest, Websites) {
@@ -435,12 +380,10 @@
 
   EntryId skype_arc_entry_id(skype_arc_app_id, apps::AppType::kArc);
   EntryId skype_web_entry_id(skype_web_app_id, apps::AppType::kWeb);
-  EntryId skype_phonehub_entry_id("com.skype.raider");
 
   EXPECT_THAT(
       service->GetDuplicates(skype_arc_entry_id),
-      ElementsAre(Entry(skype_phonehub_entry_id), Entry(skype_arc_entry_id),
-                  Entry(skype_web_entry_id)));
+      ElementsAre(Entry(skype_arc_entry_id), Entry(skype_web_entry_id)));
   EXPECT_TRUE(service->AreDuplicates(skype_arc_entry_id, skype_web_entry_id));
 
   EntryId not_duplicate_app_id("not_duplicate_app_id", apps::AppType::kWeb);
@@ -492,6 +435,8 @@
   skype_group->set_package_id(0, "android:com.skype.raider");
   skype_group->add_package_id();
   skype_group->set_package_id(1, "web:https://web.skype.com/");
+  skype_group->add_package_id();
+  skype_group->set_package_id(2, "website:https://web.skype.com/");
 
   auto* duo_group = data.add_app_group();
   duo_group->set_app_group_uuid("1d460a2b-d6d5-471d-b1e6-bbfc87971ea8");
@@ -527,19 +472,24 @@
   ASSERT_NE(it, service->entry_to_group_map_.end());
   EXPECT_EQ(skype_test_index, it->second);
 
+  it = service->entry_to_group_map_.find(EntryId(GURL(skype_web_id)));
+  ASSERT_NE(it, service->entry_to_group_map_.end());
+  EXPECT_EQ(skype_test_index, it->second);
+
   auto map_it = service->duplication_map_.find(skype_test_index);
   ASSERT_FALSE(map_it == service->duplication_map_.end());
   EXPECT_THAT(map_it->second.entries,
               ElementsAre(Entry(EntryId(skype_android_app_id, AppType::kArc)),
-                          Entry(EntryId(skype_web_id, AppType::kWeb))));
+                          Entry(EntryId(skype_web_id, AppType::kWeb)),
+                          Entry(EntryId(GURL(skype_web_id)))));
 
   uint32_t duo_test_index = 2;
 
   std::string duo_android_app_id = "com.google.duo";
   it = service->entry_to_group_map_.find(
-      EntryId(skype_android_app_id, AppType::kArc));
+      EntryId(duo_android_app_id, AppType::kArc));
   ASSERT_NE(it, service->entry_to_group_map_.end());
-  EXPECT_EQ(skype_test_index, it->second);
+  EXPECT_EQ(duo_test_index, it->second);
 
   std::string duo_web_app_id = "https://duo.google.com/?lfhs=2";
   it =
@@ -548,14 +498,64 @@
   EXPECT_EQ(duo_test_index, it->second);
 
   std::string duo_website_app_id = "https://duo.google.com/?lfhs=2";
-  it = service->entry_to_group_map_.find(EntryId(duo_website_app_id));
-  EXPECT_EQ(it, service->entry_to_group_map_.end());
+  it = service->entry_to_group_map_.find(EntryId(GURL(duo_website_app_id)));
+  ASSERT_NE(it, service->entry_to_group_map_.end());
+  EXPECT_EQ(duo_test_index, it->second);
 
   map_it = service->duplication_map_.find(duo_test_index);
   ASSERT_FALSE(map_it == service->duplication_map_.end());
   EXPECT_THAT(map_it->second.entries,
               ElementsAre(Entry(EntryId(duo_android_app_id, AppType::kArc)),
-                          Entry(EntryId(duo_web_app_id, AppType::kWeb))));
+                          Entry(EntryId(duo_web_app_id, AppType::kWeb)),
+                          Entry(EntryId(GURL(duo_website_app_id)))));
+}
+
+TEST_F(AppDeduplicationServiceAlmanacTest,
+       DeduplicateDataToEntriesInvalidAppType) {
+  proto::DeduplicateData data;
+
+  auto* skype_group = data.add_app_group();
+  skype_group->set_app_group_uuid("15ca3ac3-c8cd-4a0c-a195-2ea210ea922c");
+  skype_group->add_package_id();
+  skype_group->set_package_id(0, "notatype:com.skype.raider");
+
+  TestingProfile profile;
+  ASSERT_TRUE(AppDeduplicationServiceFactory::
+                  IsAppDeduplicationServiceAvailableForProfile(&profile));
+  auto* service = AppDeduplicationServiceFactory::GetForProfile(&profile);
+  EXPECT_NE(nullptr, service);
+
+  // This function is called to populate the duplicate map, or else IsServiceOn
+  // will return false.
+  service->DeduplicateDataToEntries(data);
+
+  // IsServiceOn should return false as the duplicate map will be empty as it
+  // has received invalid data for population.
+  EXPECT_FALSE(service->IsServiceOn());
+}
+
+TEST_F(AppDeduplicationServiceAlmanacTest,
+       DeduplicateDataToEntriesInvalidAppId) {
+  proto::DeduplicateData data;
+
+  auto* skype_group = data.add_app_group();
+  skype_group->set_app_group_uuid("15ca3ac3-c8cd-4a0c-a195-2ea210ea922c");
+  skype_group->add_package_id();
+  skype_group->set_package_id(0, "website:notavalidwebsite");
+
+  TestingProfile profile;
+  ASSERT_TRUE(AppDeduplicationServiceFactory::
+                  IsAppDeduplicationServiceAvailableForProfile(&profile));
+  auto* service = AppDeduplicationServiceFactory::GetForProfile(&profile);
+  EXPECT_NE(nullptr, service);
+
+  // This function is called to populate the duplicate map, or else IsServiceOn
+  // will return false.
+  service->DeduplicateDataToEntries(data);
+
+  // IsServiceOn should return false as the duplicate map will be empty as it
+  // has received invalid data for population.
+  EXPECT_FALSE(service->IsServiceOn());
 }
 
 TEST_F(AppDeduplicationServiceAlmanacTest, PrefUnchangedAfterServerError) {
diff --git a/chrome/browser/apps/app_deduplication_service/entry_types.cc b/chrome/browser/apps/app_deduplication_service/entry_types.cc
index 25b86cc..2bdadb7b 100644
--- a/chrome/browser/apps/app_deduplication_service/entry_types.cc
+++ b/chrome/browser/apps/app_deduplication_service/entry_types.cc
@@ -14,9 +14,6 @@
     : entry_type(EntryType::kApp), id(std::move(app_id)), app_type(app_type) {}
 EntryId::EntryId(const GURL& url)
     : entry_type(EntryType::kWebPage), id(url.spec()) {}
-EntryId::EntryId(std::string phone_hub_app_package_name)
-    : entry_type(EntryType::kPhoneHubApp),
-      id(std::move(phone_hub_app_package_name)) {}
 
 bool EntryId::operator==(const EntryId& other) const {
   return entry_type == other.entry_type && id == other.id &&
diff --git a/chrome/browser/apps/app_deduplication_service/entry_types.h b/chrome/browser/apps/app_deduplication_service/entry_types.h
index ea1d3f9c..d3f4910 100644
--- a/chrome/browser/apps/app_deduplication_service/entry_types.h
+++ b/chrome/browser/apps/app_deduplication_service/entry_types.h
@@ -28,9 +28,6 @@
   // Constructor for web pages.
   explicit EntryId(const GURL& url);
 
-  // Constructor for phone hub app.
-  explicit EntryId(std::string phone_hub_app_package_name);
-
   EntryId(const EntryId&) = default;
   EntryId& operator=(const EntryId&) = default;
   EntryId(EntryId&&) = default;
diff --git a/chrome/browser/apps/app_service/publishers/borealis_apps.cc b/chrome/browser/apps/app_service/publishers/borealis_apps.cc
index ae71c43..dda2e01 100644
--- a/chrome/browser/apps/app_service/publishers/borealis_apps.cc
+++ b/chrome/browser/apps/app_service/publishers/borealis_apps.cc
@@ -133,9 +133,9 @@
       l10n_util::GetStringUTF8(IDS_BOREALIS_INSTALLER_APP_NAME),
       apps::InstallReason::kDefault, apps::InstallSource::kSystem);
   InitializeApp(*installer_app, shown);
-  installer_app->icon_key =
-      apps::IconKey(apps::IconKey::kDoesNotChangeOverTime,
-                    IDR_LOGO_BOREALIS_DEFAULT_192, apps::IconEffects::kNone);
+  installer_app->icon_key = apps::IconKey(apps::IconKey::kDoesNotChangeOverTime,
+                                          IDR_LOGO_BOREALIS_STEAM_PENDING_192,
+                                          apps::IconEffects::kNone);
   installer_app->show_in_launcher = false;
   installer_app->show_in_management = false;
   installer_app->show_in_search = false;
diff --git a/chrome/browser/ash/BUILD.gn b/chrome/browser/ash/BUILD.gn
index b20e2e2..3e0c7f1 100644
--- a/chrome/browser/ash/BUILD.gn
+++ b/chrome/browser/ash/BUILD.gn
@@ -3819,6 +3819,7 @@
     "//chrome/browser/resources:component_extension_resources",
     "//chrome/browser/resources/chromeos:app_icon_resources",
     "//chrome/browser/resources/settings/chromeos:resources",
+    "//chrome/browser/screen_ai:screen_ai_chromeos_installer",
     "//chrome/browser/ui/ash/system_web_apps",
     "//chrome/browser/ui/webui/ash/cloud_upload:mojo_bindings_shared",
     "//chrome/browser/ui/webui/ash/crostini_upgrader:mojo_bindings",
@@ -3973,7 +3974,6 @@
     "//components/services/app_service/public/cpp:types",
     "//components/services/app_service/public/protos",
     "//components/services/filesystem/public/mojom",
-    "//components/services/screen_ai/public/cpp:screen_ai_chromeos_installer",
     "//components/services/unzip/content",
     "//components/services/unzip/public/mojom",
     "//components/signin/public/base",
@@ -5812,6 +5812,7 @@
     "//chrome/browser/policy/messaging_layer/proto:crd_event_proto",
     "//chrome/browser/policy/messaging_layer/proto:log_upload_event_proto",
     "//chrome/browser/profiles:profile",
+    "//chrome/browser/screen_ai:screen_ai_install_state",
     "//chrome/browser/ui",
     "//chrome/browser/ui:ash_test_support",
     "//chrome/browser/ui:test_support",
@@ -6083,7 +6084,6 @@
     "//components/services/app_service/public/cpp:test_support",
     "//components/services/app_service/public/protos",
     "//components/services/filesystem/public/mojom",
-    "//components/services/screen_ai/public/cpp:screen_ai_install_state",
     "//components/session_manager:base",
     "//components/session_manager/core",
     "//components/sessions:test_support",
diff --git a/chrome/browser/ash/app_list/search/local_images/image_annotation_worker.cc b/chrome/browser/ash/app_list/search/local_images/image_annotation_worker.cc
index 2716d1e2..19db3d8 100644
--- a/chrome/browser/ash/app_list/search/local_images/image_annotation_worker.cc
+++ b/chrome/browser/ash/app_list/search/local_images/image_annotation_worker.cc
@@ -22,10 +22,10 @@
 #include "base/time/time.h"
 #include "chrome/browser/ash/app_list/search/local_images/annotation_storage.h"
 #include "chrome/browser/ash/app_list/search/local_images/search_utils.h"
+#include "chrome/browser/screen_ai/screen_ai_install_state.h"
 #include "chromeos/services/machine_learning/public/cpp/service_connection.h"
 #include "chromeos/services/machine_learning/public/mojom/image_content_annotation.mojom.h"
 #include "chromeos/services/machine_learning/public/mojom/machine_learning_service.mojom.h"
-#include "components/services/screen_ai/public/cpp/screen_ai_install_state.h"
 
 namespace app_list {
 namespace {
diff --git a/chrome/browser/ash/app_list/search/local_images/image_annotation_worker.h b/chrome/browser/ash/app_list/search/local_images/image_annotation_worker.h
index 4bfdbfe3..4c8392a 100644
--- a/chrome/browser/ash/app_list/search/local_images/image_annotation_worker.h
+++ b/chrome/browser/ash/app_list/search/local_images/image_annotation_worker.h
@@ -17,9 +17,9 @@
 #include "base/sequence_checker.h"
 #include "base/task/sequenced_task_runner.h"
 #include "chrome/browser/ash/app_list/search/local_images/annotation_storage.h"
+#include "chrome/browser/screen_ai/screen_ai_service_router.h"
 #include "chromeos/services/machine_learning/public/mojom/image_content_annotation.mojom.h"
 #include "chromeos/services/machine_learning/public/mojom/machine_learning_service.mojom.h"
-#include "components/services/screen_ai/public/cpp/screen_ai_service_router.h"
 #include "mojo/public/cpp/bindings/remote.h"
 
 namespace base {
diff --git a/chrome/browser/ash/crosapi/BUILD.gn b/chrome/browser/ash/crosapi/BUILD.gn
index 92f18b9..ff52a78 100644
--- a/chrome/browser/ash/crosapi/BUILD.gn
+++ b/chrome/browser/ash/crosapi/BUILD.gn
@@ -144,6 +144,8 @@
     "image_writer_ash.h",
     "in_session_auth_ash.cc",
     "in_session_auth_ash.h",
+    "kerberos_in_browser_ash.cc",
+    "kerberos_in_browser_ash.h",
     "keystore_service_ash.cc",
     "keystore_service_ash.h",
     "keystore_service_factory_ash.cc",
diff --git a/chrome/browser/ash/crosapi/crosapi_ash.cc b/chrome/browser/ash/crosapi/crosapi_ash.cc
index 0a08fa6..e067822f 100644
--- a/chrome/browser/ash/crosapi/crosapi_ash.cc
+++ b/chrome/browser/ash/crosapi/crosapi_ash.cc
@@ -61,6 +61,7 @@
 #include "chrome/browser/ash/crosapi/idle_service_ash.h"
 #include "chrome/browser/ash/crosapi/image_writer_ash.h"
 #include "chrome/browser/ash/crosapi/in_session_auth_ash.h"
+#include "chrome/browser/ash/crosapi/kerberos_in_browser_ash.h"
 #include "chrome/browser/ash/crosapi/keystore_service_ash.h"
 #include "chrome/browser/ash/crosapi/kiosk_session_service_ash.h"
 #include "chrome/browser/ash/crosapi/local_printer_ash.h"
@@ -124,6 +125,7 @@
 #include "chromeos/crosapi/mojom/file_manager.mojom.h"
 #include "chromeos/crosapi/mojom/firewall_hole.mojom.h"
 #include "chromeos/crosapi/mojom/image_writer.mojom.h"
+#include "chromeos/crosapi/mojom/kerberos_in_browser.mojom.h"
 #include "chromeos/crosapi/mojom/keystore_service.mojom.h"
 #include "chromeos/crosapi/mojom/local_printer.mojom.h"
 #include "chromeos/crosapi/mojom/message_center.mojom.h"
@@ -225,6 +227,7 @@
       idle_service_ash_(std::make_unique<IdleServiceAsh>()),
       image_writer_ash_(std::make_unique<ImageWriterAsh>()),
       in_session_auth_ash_(std::make_unique<InSessionAuthAsh>()),
+      kerberos_in_browser_ash_(std::make_unique<KerberosInBrowserAsh>()),
       keystore_service_ash_(std::make_unique<KeystoreServiceAsh>()),
       kiosk_session_service_ash_(std::make_unique<KioskSessionServiceAsh>()),
       local_printer_ash_(std::make_unique<LocalPrinterAsh>()),
@@ -570,6 +573,11 @@
   in_session_auth_ash_->BindReceiver(std::move(receiver));
 }
 
+void CrosapiAsh::BindKerberosInBrowser(
+    mojo::PendingReceiver<crosapi::mojom::KerberosInBrowser> receiver) {
+  kerberos_in_browser_ash_->BindReceiver(std::move(receiver));
+}
+
 void CrosapiAsh::BindKeystoreService(
     mojo::PendingReceiver<crosapi::mojom::KeystoreService> receiver) {
   keystore_service_ash_->BindReceiver(std::move(receiver));
diff --git a/chrome/browser/ash/crosapi/crosapi_ash.h b/chrome/browser/ash/crosapi/crosapi_ash.h
index 68f5ff55..8ba20c8 100644
--- a/chrome/browser/ash/crosapi/crosapi_ash.h
+++ b/chrome/browser/ash/crosapi/crosapi_ash.h
@@ -76,6 +76,7 @@
 class IdleServiceAsh;
 class ImageWriterAsh;
 class InSessionAuthAsh;
+class KerberosInBrowserAsh;
 class KeystoreServiceAsh;
 class KioskSessionServiceAsh;
 class LocalPrinterAsh;
@@ -238,6 +239,8 @@
       mojo::PendingReceiver<mojom::ImageWriter> receiver) override;
   void BindInSessionAuth(
       mojo::PendingReceiver<mojom::InSessionAuth> receiver) override;
+  void BindKerberosInBrowser(
+      mojo::PendingReceiver<mojom::KerberosInBrowser> receiver) override;
   void BindKeystoreService(
       mojo::PendingReceiver<mojom::KeystoreService> receiver) override;
   void BindKioskSessionService(
@@ -555,6 +558,7 @@
   std::unique_ptr<IdleServiceAsh> idle_service_ash_;
   std::unique_ptr<ImageWriterAsh> image_writer_ash_;
   std::unique_ptr<InSessionAuthAsh> in_session_auth_ash_;
+  std::unique_ptr<KerberosInBrowserAsh> kerberos_in_browser_ash_;
   std::unique_ptr<KeystoreServiceAsh> keystore_service_ash_;
   std::unique_ptr<KioskSessionServiceAsh> kiosk_session_service_ash_;
   std::unique_ptr<LocalPrinterAsh> local_printer_ash_;
diff --git a/chrome/browser/ash/crosapi/crosapi_util.cc b/chrome/browser/ash/crosapi/crosapi_util.cc
index 7f4a5e4..8d9e174a 100644
--- a/chrome/browser/ash/crosapi/crosapi_util.cc
+++ b/chrome/browser/ash/crosapi/crosapi_util.cc
@@ -86,6 +86,7 @@
 #include "chromeos/crosapi/mojom/identity_manager.mojom.h"
 #include "chromeos/crosapi/mojom/image_writer.mojom.h"
 #include "chromeos/crosapi/mojom/in_session_auth.mojom.h"
+#include "chromeos/crosapi/mojom/kerberos_in_browser.mojom.h"
 #include "chromeos/crosapi/mojom/keystore_service.mojom.h"
 #include "chromeos/crosapi/mojom/kiosk_session_service.mojom.h"
 #include "chromeos/crosapi/mojom/launcher_search.mojom.h"
@@ -267,7 +268,7 @@
   return {T::Uuid_, T::Version_};
 }
 
-static_assert(crosapi::mojom::Crosapi::Version_ == 107,
+static_assert(crosapi::mojom::Crosapi::Version_ == 108,
               "If you add a new crosapi, please add it to "
               "kInterfaceVersionEntries below.");
 
@@ -327,6 +328,7 @@
     MakeInterfaceVersionEntry<crosapi::mojom::ImageWriter>(),
     MakeInterfaceVersionEntry<crosapi::mojom::InputMethodTestInterface>(),
     MakeInterfaceVersionEntry<crosapi::mojom::InSessionAuth>(),
+    MakeInterfaceVersionEntry<crosapi::mojom::KerberosInBrowser>(),
     MakeInterfaceVersionEntry<crosapi::mojom::KeystoreService>(),
     MakeInterfaceVersionEntry<crosapi::mojom::KioskSessionService>(),
     MakeInterfaceVersionEntry<crosapi::mojom::LocalPrinter>(),
diff --git a/chrome/browser/ash/crosapi/kerberos_in_browser_ash.cc b/chrome/browser/ash/crosapi/kerberos_in_browser_ash.cc
new file mode 100644
index 0000000..1556b25
--- /dev/null
+++ b/chrome/browser/ash/crosapi/kerberos_in_browser_ash.cc
@@ -0,0 +1,24 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/crosapi/kerberos_in_browser_ash.h"
+
+#include "chrome/browser/ui/webui/ash/kerberos/kerberos_in_browser_dialog.h"
+
+namespace crosapi {
+
+KerberosInBrowserAsh::KerberosInBrowserAsh() = default;
+
+KerberosInBrowserAsh::~KerberosInBrowserAsh() = default;
+
+void KerberosInBrowserAsh::BindReceiver(
+    mojo::PendingReceiver<mojom::KerberosInBrowser> receiver) {
+  receivers_.Add(this, std::move(receiver));
+}
+
+void KerberosInBrowserAsh::ShowKerberosInBrowserDialog() {
+  ash::KerberosInBrowserDialog::Show();
+}
+
+}  // namespace crosapi
diff --git a/chrome/browser/ash/crosapi/kerberos_in_browser_ash.h b/chrome/browser/ash/crosapi/kerberos_in_browser_ash.h
new file mode 100644
index 0000000..c552b3f
--- /dev/null
+++ b/chrome/browser/ash/crosapi/kerberos_in_browser_ash.h
@@ -0,0 +1,34 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ASH_CROSAPI_KERBEROS_IN_BROWSER_ASH_H_
+#define CHROME_BROWSER_ASH_CROSAPI_KERBEROS_IN_BROWSER_ASH_H_
+
+#include "chromeos/crosapi/mojom/kerberos_in_browser.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+
+namespace crosapi {
+
+// Implements the crosapi KerberosInBrowser interface. Lives in ash-chrome on
+// the UI thread. Shows Kerberos UI in response to mojo IPCs from lacros-chrome.
+class KerberosInBrowserAsh : public mojom::KerberosInBrowser {
+ public:
+  KerberosInBrowserAsh();
+  KerberosInBrowserAsh(const KerberosInBrowserAsh&) = delete;
+  KerberosInBrowserAsh& operator=(const KerberosInBrowserAsh&) = delete;
+  ~KerberosInBrowserAsh() override;
+
+  void BindReceiver(mojo::PendingReceiver<mojom::KerberosInBrowser> receiver);
+
+  // crosapi::mojom::KerberosInBrowser
+  void ShowKerberosInBrowserDialog() override;
+
+ private:
+  mojo::ReceiverSet<mojom::KerberosInBrowser> receivers_;
+};
+
+}  // namespace crosapi
+
+#endif  // CHROME_BROWSER_ASH_CROSAPI_KERBEROS_IN_BROWSER_ASH_H_
diff --git a/chrome/browser/ash/drive/drive_integration_service.cc b/chrome/browser/ash/drive/drive_integration_service.cc
index 067a0271..1b1ca6a 100644
--- a/chrome/browser/ash/drive/drive_integration_service.cc
+++ b/chrome/browser/ash/drive/drive_integration_service.cc
@@ -56,6 +56,7 @@
 #include "chromeos/ash/components/network/network_state_handler.h"
 #include "chromeos/ash/components/network/network_state_handler_observer.h"
 #include "chromeos/components/drivefs/mojom/drivefs_native_messaging.mojom.h"
+#include "chromeos/constants/chromeos_features.h"
 #include "chromeos/crosapi/mojom/drive_integration_service.mojom.h"
 #include "components/drive/drive_api_util.h"
 #include "components/drive/drive_notification_manager.h"
@@ -1663,8 +1664,9 @@
 void DriveIntegrationService::ForceReSyncFile(const base::FilePath& local_path,
                                               base::OnceClosure callback) {
   base::FilePath drive_path;
-  if (!ash::features::IsForceReSyncDriveEnabled() || !IsMounted() ||
-      !GetDriveFsInterface() ||
+  bool is_feature_enabled = ash::features::IsForceReSyncDriveEnabled() &&
+                            chromeos::features::IsUploadOfficeToCloudEnabled();
+  if (!is_feature_enabled || !IsMounted() || !GetDriveFsInterface() ||
       !GetRelativeDrivePath(local_path, &drive_path)) {
     std::move(callback).Run();
     return;
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest.cc b/chrome/browser/ash/file_manager/file_manager_browsertest.cc
index 69e7e7ee..a2ef0db 100644
--- a/chrome/browser/ash/file_manager/file_manager_browsertest.cc
+++ b/chrome/browser/ash/file_manager/file_manager_browsertest.cc
@@ -1568,6 +1568,8 @@
         TestCase("driveFoldersRetainPinnedPropertyWhenBulkPinningEnabled")
             .EnableBulkPinning(),
         TestCase("drivePinToggleIsEnabledInSharedWithMeWhenBulkPinningEnabled")
+            .EnableBulkPinning(),
+        TestCase("driveCantPinItemsShouldHaveClassNameAndGetUpdatedWhenCanPin")
             .EnableBulkPinning()
         // TODO(b/189173190): Enable
         // TestCase("driveEnableDocsOfflineDialog"),
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc b/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc
index fc4b644..8fe5d05 100644
--- a/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc
+++ b/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc
@@ -443,6 +443,7 @@
     bool pinned = false;                // Whether the file should be pinned.
     bool available_offline = false;  // Whether the file is available_offline.
     std::string alternate_url;       // Entry's alternate URL on Drive.
+    bool can_pin = true;             // Whether the file can be pinned.
 
     TestEntryInfo& SetSharedOption(SharedOption option) {
       shared_option = option;
@@ -532,6 +533,7 @@
                                    &TestEntryInfo::available_offline);
       converter->RegisterStringField("alternateUrl",
                                      &TestEntryInfo::alternate_url);
+      converter->RegisterBoolField("canPin", &TestEntryInfo::can_pin);
     }
 
     // Maps |value| to an EntryType. Returns true on success.
@@ -1391,6 +1393,7 @@
         entry.folder_feature.is_external_media;
     metadata.alternate_url = entry.alternate_url;
     metadata.shortcut = (entry.entry_type == AddEntriesMessage::LINK);
+    metadata.can_pin = entry.can_pin;
     fake_drivefs_helper_->fake_drivefs().SetMetadata(std::move(metadata));
 
     ASSERT_TRUE(UpdateModifiedTime(entry));
@@ -1454,6 +1457,22 @@
     return fake_drivefs_helper_->fake_drivefs().IsItemPinned(path);
   }
 
+  void SetCanPin(const std::string& path, bool can_pin) {
+    ASSERT_TRUE(fake_drivefs_helper_->fake_drivefs().SetCanPin(path, can_pin));
+
+    const base::FilePath file_path(path);
+    absl::optional<drivefs::FakeDriveFs::FileMetadata> metadata =
+        fake_drivefs_helper_->fake_drivefs().GetItemMetadata(file_path);
+    ASSERT_TRUE(metadata.has_value()) << "No file metadata with path: " << path;
+
+    std::vector<drivefs::mojom::FileChangePtr> file_changes;
+    file_changes.emplace_back(absl::in_place, file_path,
+                              drivefs::mojom::FileChange::Type::kModify,
+                              metadata.value().stable_id);
+    auto& drivefs_delegate = fake_drivefs_helper_->fake_drivefs().delegate();
+    drivefs_delegate->OnFilesChanged(std::move(file_changes));
+  }
+
  private:
   base::RepeatingCallback<std::unique_ptr<drivefs::DriveFsBootstrapListener>()>
   CreateDriveFsBootstrapListener() {
@@ -3544,6 +3563,15 @@
     return;
   }
 
+  if (name == "setCanPin") {
+    const std::string* path = value.FindString("path");
+    ASSERT_TRUE(path) << "No supplied path to setCanPin";
+    absl::optional<bool> can_pin = value.FindBool("canPin");
+    ASSERT_TRUE(can_pin.has_value()) << "Need to supply canPin";
+    drive_volume_->SetCanPin(*path, can_pin.value());
+    return;
+  }
+
   if (name == "sendDriveCloudDeleteEvent") {
     const std::string* path = value.FindString("path");
     ASSERT_TRUE(path) << "No supplied path to sendDriveFilesChangedEvent";
diff --git a/chrome/browser/ash/file_manager/file_manager_string_util.cc b/chrome/browser/ash/file_manager/file_manager_string_util.cc
index caeb8f9c..fd8992a 100644
--- a/chrome/browser/ash/file_manager/file_manager_string_util.cc
+++ b/chrome/browser/ash/file_manager/file_manager_string_util.cc
@@ -222,6 +222,8 @@
              IDS_FILE_BROWSER_BULK_PINNING_NOT_ENOUGH_SPACE_LABEL);
   SET_STRING("DRIVE_PREPARING_TO_SYNC",
              IDS_FILE_BROWSER_BULK_PINNING_PREPARING_TO_SYNC);
+  SET_STRING("DRIVE_ITEM_UNAVAILABLE_OFFLINE",
+             IDS_FILE_BROWSER_BULK_PINNING_ITEM_UNAVAILABLE_OFFLINE);
 }
 
 void AddStringsForMediaView(base::Value::Dict* dict) {
diff --git a/chrome/browser/ash/file_system_provider/odfs_metrics.cc b/chrome/browser/ash/file_system_provider/odfs_metrics.cc
index 00ed93c1..eb749872 100644
--- a/chrome/browser/ash/file_system_provider/odfs_metrics.cc
+++ b/chrome/browser/ash/file_system_provider/odfs_metrics.cc
@@ -79,7 +79,8 @@
   request.latency_timer.Begin();
 }
 
-void ODFSMetrics::OnRequestDestroyed(int request_id) {
+void ODFSMetrics::OnRequestDestroyed(int request_id,
+                                     OperationCompletion completion) {
   auto it = requests_.find(request_id);
   if (it == requests_.end()) {
     return;
@@ -87,6 +88,8 @@
   Request& request = it->second;
   base::UmaHistogramMediumTimes(GetHistogramName("Time", request.request_type),
                                 request.latency_timer.Elapsed());
+  base::UmaHistogramEnumeration(
+      GetHistogramName("Completion", request.request_type), completion);
   requests_.erase(it);
 }
 
diff --git a/chrome/browser/ash/file_system_provider/odfs_metrics.h b/chrome/browser/ash/file_system_provider/odfs_metrics.h
index 829dc46..5e50e8a 100644
--- a/chrome/browser/ash/file_system_provider/odfs_metrics.h
+++ b/chrome/browser/ash/file_system_provider/odfs_metrics.h
@@ -19,7 +19,8 @@
   ~ODFSMetrics() override;
   // RequestManager::Observer overrides:
   void OnRequestCreated(int request_id, RequestType type) override;
-  void OnRequestDestroyed(int request_id) override;
+  void OnRequestDestroyed(int request_id,
+                          OperationCompletion completion) override;
   void OnRequestExecuted(int request_id) override;
   void OnRequestFulfilled(int request_id,
                           const RequestValue& result,
diff --git a/chrome/browser/ash/file_system_provider/operation_request_manager.cc b/chrome/browser/ash/file_system_provider/operation_request_manager.cc
index 64bd085f2..864f4603 100644
--- a/chrome/browser/ash/file_system_provider/operation_request_manager.cc
+++ b/chrome/browser/ash/file_system_provider/operation_request_manager.cc
@@ -32,11 +32,19 @@
     observer.OnRequestTimedOut(request_id);
 
   if (!notification_manager_) {
-    RejectRequest(request_id, RequestValue(), base::File::FILE_ERROR_ABORT);
+    RejectRequestInternal(request_id, RequestValue(),
+                          base::File::FILE_ERROR_ABORT,
+                          OperationCompletion::kAbortedInternally);
+    return;
+  }
+
+  auto request_it = requests_.find(request_id);
+  if (request_it == requests_.end()) {
     return;
   }
 
   if (!IsInteractingWithUser()) {
+    request_it->second->shown_unresponsive_notification = true;
     notification_manager_->ShowUnresponsiveNotification(
         request_id,
         base::BindOnce(
diff --git a/chrome/browser/ash/file_system_provider/operation_request_manager_unittest.cc b/chrome/browser/ash/file_system_provider/operation_request_manager_unittest.cc
index 84041ef..9270503 100644
--- a/chrome/browser/ash/file_system_provider/operation_request_manager_unittest.cc
+++ b/chrome/browser/ash/file_system_provider/operation_request_manager_unittest.cc
@@ -20,6 +20,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/run_loop.h"
 #include "chrome/browser/ash/file_system_provider/notification_manager_interface.h"
+#include "chrome/browser/ash/file_system_provider/request_manager.h"
 #include "chrome/browser/ash/file_system_provider/request_value.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/test/browser_task_environment.h"
@@ -294,6 +295,17 @@
     base::File::Error error_;
   };
 
+  class DestroyedEvent : public Event {
+   public:
+    DestroyedEvent(int request_id, OperationCompletion completion)
+        : Event(request_id), completion_(completion) {}
+
+    OperationCompletion completion() const { return completion_; }
+
+   private:
+    OperationCompletion completion_;
+  };
+
   RequestObserver() {}
 
   RequestObserver(const RequestObserver&) = delete;
@@ -307,8 +319,9 @@
   }
 
   // RequestManager::Observer overrides.
-  void OnRequestDestroyed(int request_id) override {
-    destroyed_.push_back(Event(request_id));
+  void OnRequestDestroyed(int request_id,
+                          OperationCompletion completion) override {
+    destroyed_.push_back(DestroyedEvent(request_id, completion));
   }
 
   // RequestManager::Observer overrides.
@@ -336,7 +349,7 @@
   }
 
   const std::vector<CreatedEvent>& created() const { return created_; }
-  const std::vector<Event>& destroyed() const { return destroyed_; }
+  const std::vector<DestroyedEvent>& destroyed() const { return destroyed_; }
   const std::vector<Event>& executed() const { return executed_; }
   const std::vector<FulfilledEvent>& fulfilled() const { return fulfilled_; }
   const std::vector<RejectedEvent>& rejected() const { return rejected_; }
@@ -344,7 +357,7 @@
 
  private:
   std::vector<CreatedEvent> created_;
-  std::vector<Event> destroyed_;
+  std::vector<DestroyedEvent> destroyed_;
   std::vector<Event> executed_;
   std::vector<FulfilledEvent> fulfilled_;
   std::vector<RejectedEvent> rejected_;
@@ -464,6 +477,8 @@
 
   ASSERT_EQ(1u, observer.destroyed().size());
   EXPECT_EQ(request_id, observer.destroyed()[0].request_id());
+  EXPECT_EQ(OperationCompletion::kCompletedNormally,
+            observer.destroyed()[0].completion());
   EXPECT_EQ(0u, observer.timed_out().size());
 
   request_manager_->RemoveObserver(&observer);
@@ -602,6 +617,8 @@
 
   ASSERT_EQ(1u, observer.destroyed().size());
   EXPECT_EQ(request_id, observer.destroyed()[0].request_id());
+  EXPECT_EQ(OperationCompletion::kCompletedNormally,
+            observer.destroyed()[0].completion());
   EXPECT_EQ(0u, observer.timed_out().size());
 
   request_manager_->RemoveObserver(&observer);
@@ -765,6 +782,8 @@
   EXPECT_EQ(request_id, observer.rejected()[0].request_id());
   EXPECT_EQ(base::File::FILE_ERROR_ABORT, observer.rejected()[0].error());
   ASSERT_EQ(1u, observer.destroyed().size());
+  EXPECT_EQ(OperationCompletion::kAbortedInternally,
+            observer.destroyed()[0].completion());
 }
 
 TEST_F(FileSystemProviderRequestManagerTest, AbortOnTimeout) {
@@ -810,6 +829,8 @@
   EXPECT_EQ(request_id, observer.timed_out()[0].request_id());
   ASSERT_EQ(1u, observer.destroyed().size());
   EXPECT_EQ(request_id, observer.destroyed()[0].request_id());
+  EXPECT_EQ(OperationCompletion::kAbortedFromNotification,
+            observer.destroyed()[0].completion());
 
   request_manager_->RemoveObserver(&observer);
 }
@@ -854,6 +875,18 @@
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1u, notification_manager_->size());
 
+  // Fulfill and check that operation completion mode changes.
+  const base::File::Error result = request_manager_->FulfillRequest(
+      request_id,
+      RequestValue(RequestValue::CreateForTesting("i-like-vanilla")),
+      /*has_more=*/false);
+  EXPECT_EQ(base::File::FILE_OK, result);
+
+  ASSERT_EQ(1u, observer.fulfilled().size());
+  ASSERT_EQ(1u, observer.destroyed().size());
+  EXPECT_EQ(OperationCompletion::kCompletedAfterWarning,
+            observer.destroyed()[0].completion());
+
   request_manager_->RemoveObserver(&observer);
 }
 
diff --git a/chrome/browser/ash/file_system_provider/provided_file_system.cc b/chrome/browser/ash/file_system_provider/provided_file_system.cc
index 49a77ebd..1dcf7d2 100644
--- a/chrome/browser/ash/file_system_provider/provided_file_system.cc
+++ b/chrome/browser/ash/file_system_provider/provided_file_system.cc
@@ -37,6 +37,7 @@
 #include "chrome/browser/ash/file_system_provider/operations/unmount.h"
 #include "chrome/browser/ash/file_system_provider/operations/write_file.h"
 #include "chrome/browser/ash/file_system_provider/request_dispatcher_impl.h"
+#include "chrome/browser/ash/file_system_provider/request_manager.h"
 #include "chrome/browser/chromeos/extensions/file_system_provider/service_worker_lifetime_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/extensions/api/file_system_provider.h"
diff --git a/chrome/browser/ash/file_system_provider/request_manager.cc b/chrome/browser/ash/file_system_provider/request_manager.cc
index 069fad1..572cdbb 100644
--- a/chrome/browser/ash/file_system_provider/request_manager.cc
+++ b/chrome/browser/ash/file_system_provider/request_manager.cc
@@ -29,7 +29,9 @@
   while (it != requests_.end()) {
     const int request_id = it->first;
     ++it;
-    RejectRequest(request_id, RequestValue(), base::File::FILE_ERROR_ABORT);
+    RejectRequestInternal(request_id, RequestValue(),
+                          base::File::FILE_ERROR_ABORT,
+                          OperationCompletion::kAbortedInternally);
   }
 
   DCHECK_EQ(0u, requests_.size());
@@ -62,7 +64,7 @@
   // extension is not listening for the request event being sent.
   // In such case, we should abort as soon as possible.
   if (!requests_[request_id]->handler->Execute(request_id)) {
-    DestroyRequest(request_id);
+    DestroyRequest(request_id, OperationCompletion::kCompletedNormally);
     return 0;
   }
 
@@ -82,10 +84,13 @@
   for (auto& observer : observers_)
     observer.OnRequestFulfilled(request_id, response, has_more);
 
-  request_it->second->handler->OnSuccess(request_id, response, has_more);
+  const Request& request = *request_it->second;
+  request.handler->OnSuccess(request_id, response, has_more);
 
   if (!has_more) {
-    DestroyRequest(request_id);
+    DestroyRequest(request_id, request.shown_unresponsive_notification
+                                   ? OperationCompletion::kCompletedAfterWarning
+                                   : OperationCompletion::kCompletedNormally);
   } else {
     if (notification_manager_)
       notification_manager_->HideUnresponsiveNotification(request_id);
@@ -99,19 +104,14 @@
                                                 const RequestValue& response,
                                                 base::File::Error error) {
   auto request_it = requests_.find(request_id);
-  if (request_it == requests_.end())
+  if (request_it == requests_.end()) {
     return base::File::FILE_ERROR_NOT_FOUND;
-
-  if (error == base::File::FILE_ERROR_ABORT) {
-    request_it->second->handler->OnAbort(request_id);
   }
-
-  for (auto& observer : observers_)
-    observer.OnRequestRejected(request_id, response, error);
-  request_it->second->handler->OnError(request_id, response, error);
-  DestroyRequest(request_id);
-
-  return base::File::FILE_OK;
+  const Request& request = *request_it->second;
+  return RejectRequestInternal(request_id, response, error,
+                               request.shown_unresponsive_notification
+                                   ? OperationCompletion::kCompletedAfterWarning
+                                   : OperationCompletion::kCompletedNormally);
 }
 
 void RequestManager::SetTimeoutForTesting(const base::TimeDelta& timeout) {
@@ -148,10 +148,18 @@
     observer.OnRequestTimedOut(request_id);
 
   if (!notification_manager_) {
-    RejectRequest(request_id, RequestValue(), base::File::FILE_ERROR_ABORT);
+    RejectRequestInternal(request_id, RequestValue(),
+                          base::File::FILE_ERROR_ABORT,
+                          OperationCompletion::kAbortedInternally);
     return;
   }
 
+  auto request_it = requests_.find(request_id);
+  if (request_it == requests_.end()) {
+    return;
+  }
+
+  request_it->second->shown_unresponsive_notification = true;
   notification_manager_->ShowUnresponsiveNotification(
       request_id,
       base::BindOnce(&RequestManager::OnUnresponsiveNotificationResult,
@@ -170,7 +178,9 @@
     return;
   }
 
-  RejectRequest(request_id, RequestValue(), base::File::FILE_ERROR_ABORT);
+  RejectRequestInternal(request_id, RequestValue(),
+                        base::File::FILE_ERROR_ABORT,
+                        OperationCompletion::kAbortedFromNotification);
 }
 
 void RequestManager::ResetTimer(int request_id) {
@@ -184,7 +194,31 @@
                      weak_ptr_factory_.GetWeakPtr(), request_id));
 }
 
-void RequestManager::DestroyRequest(int request_id) {
+base::File::Error RequestManager::RejectRequestInternal(
+    int request_id,
+    const RequestValue& response,
+    base::File::Error error,
+    OperationCompletion completion) {
+  auto request_it = requests_.find(request_id);
+  if (request_it == requests_.end()) {
+    return base::File::FILE_ERROR_NOT_FOUND;
+  }
+
+  if (error == base::File::FILE_ERROR_ABORT) {
+    request_it->second->handler->OnAbort(request_id);
+  }
+
+  for (auto& observer : observers_) {
+    observer.OnRequestRejected(request_id, response, error);
+  }
+  request_it->second->handler->OnError(request_id, response, error);
+  DestroyRequest(request_id, completion);
+
+  return base::File::FILE_OK;
+}
+
+void RequestManager::DestroyRequest(int request_id,
+                                    OperationCompletion completion) {
   auto request_it = requests_.find(request_id);
   if (request_it == requests_.end())
     return;
@@ -195,7 +229,7 @@
     notification_manager_->HideUnresponsiveNotification(request_id);
 
   for (auto& observer : observers_)
-    observer.OnRequestDestroyed(request_id);
+    observer.OnRequestDestroyed(request_id, completion);
 
   TRACE_EVENT_NESTABLE_ASYNC_END0("file_system_provider",
                                   "RequestManager::Request",
diff --git a/chrome/browser/ash/file_system_provider/request_manager.h b/chrome/browser/ash/file_system_provider/request_manager.h
index 607d72f..993c2a0 100644
--- a/chrome/browser/ash/file_system_provider/request_manager.h
+++ b/chrome/browser/ash/file_system_provider/request_manager.h
@@ -48,6 +48,16 @@
   kWriteFile,
 };
 
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class OperationCompletion {
+  kCompletedNormally = 0,
+  kCompletedAfterWarning = 1,
+  kAbortedFromNotification = 2,
+  kAbortedInternally = 3,
+  kMaxValue = kAbortedInternally,
+};
+
 // Manages requests between the service, async utils and the providing
 // extension or native provider.
 class RequestManager {
@@ -90,7 +100,8 @@
     virtual void OnRequestCreated(int request_id, RequestType type) = 0;
 
     // Called when the request is destroyed.
-    virtual void OnRequestDestroyed(int request_id) = 0;
+    virtual void OnRequestDestroyed(int request_id,
+                                    OperationCompletion completion) = 0;
 
     // Called when the request is executed.
     virtual void OnRequestExecuted(int request_id) = 0;
@@ -151,7 +162,7 @@
   void RemoveObserver(Observer* observer);
 
   // Destroys the request with the passed |request_id|.
-  void DestroyRequest(int request_id);
+  void DestroyRequest(int request_id, OperationCompletion completion);
 
  protected:
   struct Request {
@@ -167,6 +178,10 @@
 
     // Handler tied to this request.
     std::unique_ptr<HandlerInterface> handler;
+
+    // Indicates if this operation timed out and a warning has been shown to the
+    // user.
+    bool shown_unresponsive_notification = false;
   };
 
   // Called when a request with |request_id| timeouts.
@@ -181,6 +196,12 @@
   // Resets the timeout timer for the specified request.
   void ResetTimer(int request_id);
 
+  // Reject a request specifying how it was completed.
+  base::File::Error RejectRequestInternal(int request_id,
+                                          const RequestValue& response,
+                                          base::File::Error error,
+                                          OperationCompletion completion);
+
   raw_ptr<Profile> profile_;  // Not owned.
   std::map<int, std::unique_ptr<Request>> requests_;
   raw_ptr<NotificationManagerInterface> notification_manager_;  // Not owned.
diff --git a/chrome/browser/ash/input_method/suggestions_service_client.cc b/chrome/browser/ash/input_method/suggestions_service_client.cc
index 73fffd9..650a5c3 100644
--- a/chrome/browser/ash/input_method/suggestions_service_client.cc
+++ b/chrome/browser/ash/input_method/suggestions_service_client.cc
@@ -9,6 +9,7 @@
 #include "base/metrics/field_trial_params.h"
 #include "base/metrics/histogram_functions.h"
 #include "chrome/browser/ash/input_method/suggestion_enums.h"
+#include "chrome/browser/ash/input_method/text_utils.h"
 #include "chromeos/services/machine_learning/public/cpp/service_connection.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
@@ -69,13 +70,6 @@
                              .text = candidate->get_multi_word()->text};
 }
 
-std::string TrimText(const std::string& text) {
-  size_t text_length = text.length();
-  return text_length > kMaxNumberCharsSent
-             ? text.substr(text_length - kMaxNumberCharsSent)
-             : text;
-}
-
 MultiWordSuggestionType ToSuggestionType(
     const ime::AssistiveSuggestionMode& suggestion_mode) {
   switch (suggestion_mode) {
@@ -148,7 +142,7 @@
   RecordRequestCandidates(suggestion_mode);
 
   auto query = TextSuggesterQuery::New();
-  query->text = TrimText(preceding_text);
+  query->text = GetLastNCodepoints(preceding_text, kMaxNumberCharsSent);
   query->suggestion_mode = ToTextSuggestionModeMojom(suggestion_mode);
 
   for (const auto& candidate : completion_candidates) {
diff --git a/chrome/browser/ash/input_method/text_utils.cc b/chrome/browser/ash/input_method/text_utils.cc
index 0a99a6f2..1ed8be1 100644
--- a/chrome/browser/ash/input_method/text_utils.cc
+++ b/chrome/browser/ash/input_method/text_utils.cc
@@ -3,6 +3,8 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/ash/input_method/text_utils.h"
+#include "base/i18n/char_iterator.h"
+#include "base/strings/utf_string_conversions.h"
 
 // TODO(crbug/1223597) The rules to detect sentence end is not perfect, and we
 // may want to use regex to improve readability.
@@ -180,5 +182,17 @@
                   text.substr(start, end - start + 1));
 }
 
+std::string GetLastNCodepoints(const std::string& text, size_t N) {
+  std::u16string u16text = base::UTF8ToUTF16(text);
+  for (auto iter = base::i18n::UTF16CharIterator::LowerBound(
+           u16text, u16text.length() - 1);
+       !iter.start(); iter.Rewind()) {
+    if ((size_t)iter.char_offset() == -N + 1) {
+      return base::UTF16ToUTF8(u16text.substr(iter.array_pos()));
+    }
+  }
+  return text;
+}
+
 }  // namespace input_method
 }  // namespace ash
diff --git a/chrome/browser/ash/input_method/text_utils.h b/chrome/browser/ash/input_method/text_utils.h
index 646e919..e90c496 100644
--- a/chrome/browser/ash/input_method/text_utils.h
+++ b/chrome/browser/ash/input_method/text_utils.h
@@ -44,6 +44,7 @@
 // Find the sentence containing the cursor position |pos|.
 Sentence FindCurrentSentence(const std::u16string& text, uint32_t pos);
 
+std::string GetLastNCodepoints(const std::string& text, size_t N);
 }  // namespace input_method
 }  // namespace ash
 
diff --git a/chrome/browser/ash/input_method/text_utils_unittest.cc b/chrome/browser/ash/input_method/text_utils_unittest.cc
index d41efdc..1d53f6b 100644
--- a/chrome/browser/ash/input_method/text_utils_unittest.cc
+++ b/chrome/browser/ash/input_method/text_utils_unittest.cc
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/ash/input_method/text_utils.h"
-
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace ash {
@@ -106,6 +105,17 @@
             Sentence(gfx::Range(0, 13), u"This is a dog"));
 }
 
+TEST(TextUtilsTest, GetCodepointsWithEmoji) {
+  EXPECT_EQ(GetLastNCodepoints("😀😀😀", 2), "😀😀");
+  EXPECT_EQ(GetLastNCodepoints("😁😁Hey", 3), "Hey");
+  EXPECT_EQ(GetLastNCodepoints("😁😁Hey", 4), "😁Hey");
+  EXPECT_EQ(GetLastNCodepoints("Nice job! 😀😀😀", 8), "job! 😀😀😀");
+}
+
+TEST(TextUtilsTest, GetCodepointsWithChineseCharacters) {
+  EXPECT_EQ(GetLastNCodepoints("你好 Rob!", 6), "好 Rob!");
+}
+
 }  // namespace
 }  // namespace input_method
 }  // namespace ash
diff --git a/chrome/browser/ash/login/screens/arc_vm_data_migration_screen.cc b/chrome/browser/ash/login/screens/arc_vm_data_migration_screen.cc
index be46bf6ac..190a58b 100644
--- a/chrome/browser/ash/login/screens/arc_vm_data_migration_screen.cc
+++ b/chrome/browser/ash/login/screens/arc_vm_data_migration_screen.cc
@@ -431,11 +431,9 @@
       android_data_size_dest, free_disk_space);
   VLOG(1) << "Desired disk size for the migration is " << disk_size_;
 
-  // TODO(b/280248293): Fix calculation of required free disk space using
-  // `android_data_size_src`.
   const uint64_t required_free_disk_space =
       arc::GetRequiredFreeDiskSpaceForArcVmDataMigrationInBytes(
-          android_data_size_dest, free_disk_space);
+          android_data_size_src, android_data_size_dest, free_disk_space);
   VLOG(1) << "Required free disk space for the migration is "
           << required_free_disk_space;
   bool has_enough_free_disk_space = free_disk_space >= required_free_disk_space;
diff --git a/chrome/browser/ash/login/screens/arc_vm_data_migration_screen_unittest.cc b/chrome/browser/ash/login/screens/arc_vm_data_migration_screen_unittest.cc
index 37a2407..e2e84c5 100644
--- a/chrome/browser/ash/login/screens/arc_vm_data_migration_screen_unittest.cc
+++ b/chrome/browser/ash/login/screens/arc_vm_data_migration_screen_unittest.cc
@@ -195,6 +195,7 @@
     arc::SetArcVmDataMigrationStatus(profile_->GetPrefs(),
                                      arc::ArcVmDataMigrationStatus::kConfirmed);
     arc::data_migrator::GetAndroidDataInfoResponse response;
+    response.set_total_allocated_space_src(kDefaultAndroidDataSize);
     response.set_total_allocated_space_dest(kDefaultAndroidDataSize);
     FakeArcVmDataMigratorClient::Get()->set_get_android_data_info_response(
         response);
diff --git a/chrome/browser/ash/login/session/user_session_initializer.cc b/chrome/browser/ash/login/session/user_session_initializer.cc
index cd2b14a..2f8f7009 100644
--- a/chrome/browser/ash/login/session/user_session_initializer.cc
+++ b/chrome/browser/ash/login/session/user_session_initializer.cc
@@ -40,6 +40,7 @@
 #include "chrome/browser/net/nss_service.h"
 #include "chrome/browser/net/nss_service_factory.h"
 #include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/screen_ai/screen_ai_chromeos_installer.h"
 #include "chrome/browser/ui/ash/calendar/calendar_keyed_service_factory.h"
 #include "chrome/browser/ui/ash/clipboard_image_model_factory_impl.h"
 #include "chrome/browser/ui/ash/glanceables/chrome_glanceables_delegate.h"
@@ -55,7 +56,6 @@
 #include "chromeos/ash/components/peripheral_notification/peripheral_notification_manager.h"
 #include "components/live_caption/caption_util.h"
 #include "components/prefs/pref_service.h"
-#include "components/services/screen_ai/public/cpp/screen_ai_chromeos_installer.h"
 #include "components/user_manager/user_manager.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc
index 3fe1b8a..0d339c9 100644
--- a/chrome/browser/chrome_browser_interface_binders.cc
+++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -102,8 +102,8 @@
 #include "ui/accessibility/accessibility_features.h"
 
 #if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
-#include "components/services/screen_ai/public/cpp/screen_ai_service_router.h"
-#include "components/services/screen_ai/public/cpp/screen_ai_service_router_factory.h"
+#include "chrome/browser/screen_ai/screen_ai_service_router.h"
+#include "chrome/browser/screen_ai/screen_ai_service_router_factory.h"
 #endif
 
 #if BUILDFLAG(ENABLE_UNHANDLED_TAP)
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index a7b1f7b3..0bfc0c9 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -24,6 +24,7 @@
 #include "base/memory/raw_ptr.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/metrics/field_trial_params.h"
+#include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/no_destructor.h"
 #include "base/path_service.h"
@@ -680,6 +681,7 @@
 #include "chrome/browser/ui/views/chrome_browser_main_extra_parts_views_lacros.h"
 #include "chrome/common/chrome_descriptors.h"
 #include "chromeos/constants/chromeos_features.h"
+#include "chromeos/crosapi/mojom/kerberos_in_browser.mojom.h"
 #include "chromeos/lacros/lacros_service.h"
 #include "chromeos/startup/browser_init_params.h"
 #include "chromeos/startup/browser_postlogin_params.h"
@@ -4738,11 +4740,15 @@
 
 bool ChromeContentBrowserClient::IsRendererCodeIntegrityEnabled() {
   PrefService* local_state = g_browser_process->local_state();
-  if (local_state &&
-      local_state->HasPrefPath(prefs::kRendererCodeIntegrityEnabled) &&
-      !local_state->GetBoolean(prefs::kRendererCodeIntegrityEnabled))
-    return false;
-  return true;
+
+  // Code integrity defaults to enabled, unless specifically overridden by a
+  // policy controlled pref being set to false.
+  const bool is_code_integrity_enabled =
+      !local_state->HasPrefPath(prefs::kRendererCodeIntegrityEnabled) ||
+      local_state->GetBoolean(prefs::kRendererCodeIntegrityEnabled);
+  base::UmaHistogramBoolean("Windows.RendererCodeIntegrityEnabled",
+                            is_code_integrity_enabled);
+  return is_code_integrity_enabled;
 }
 
 // Note: Only use sparingly to add Chrome specific sandbox functionality here.
@@ -6366,7 +6372,7 @@
     scoped_refptr<net::HttpResponseHeaders> response_headers,
     bool first_auth_attempt,
     LoginAuthRequiredCallback auth_required_callback) {
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_CHROMEOS)
   // Negotiate challenge is handled via GSSAPI library, which can not receive
   // external credentials. However, on ChromeOS we can suggest the user to
   // create a TGT using their credentials. Note that the credentials are NOT
@@ -6375,10 +6381,19 @@
   if (base::FeatureList::IsEnabled(net::features::kKerberosInBrowserRedirect) &&
       auth_info.scheme ==
           net::HttpAuth::SchemeToString(net::HttpAuth::AUTH_SCHEME_NEGOTIATE)) {
+#if BUILDFLAG(IS_CHROMEOS_ASH)
     ash::KerberosInBrowserDialog::Show();
+#else
+    // Requests to show Kerberos ui via crosapi mojo call.
+    chromeos::LacrosService::Get()
+        ->GetRemote<crosapi::mojom::KerberosInBrowser>()
+        ->ShowKerberosInBrowserDialog();
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
     return nullptr;
   }
+#endif  // BUILDFLAG(IS_CHROMEOS)
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
   auto* system_proxy_manager = ash::SystemProxyManager::Get();
   // For Managed Guest Session and Kiosk devices, the credentials configured
   // via the policy SystemProxySettings may be used for proxy authentication.
diff --git a/chrome/browser/chromeos/extensions/file_system_provider/file_system_provider_apitest.cc b/chrome/browser/chromeos/extensions/file_system_provider/file_system_provider_apitest.cc
index f4534d1..3b9866a 100644
--- a/chrome/browser/chromeos/extensions/file_system_provider/file_system_provider_apitest.cc
+++ b/chrome/browser/chromeos/extensions/file_system_provider/file_system_provider_apitest.cc
@@ -30,6 +30,7 @@
 
 using ash::file_system_provider::MountContext;
 using ash::file_system_provider::Observer;
+using ash::file_system_provider::OperationCompletion;
 using ash::file_system_provider::ProvidedFileSystemInfo;
 using ash::file_system_provider::ProvidedFileSystemInterface;
 using ash::file_system_provider::RequestManager;
@@ -53,7 +54,8 @@
 
   // RequestManager::Observer overrides.
   void OnRequestCreated(int request_id, RequestType type) override {}
-  void OnRequestDestroyed(int request_id) override {}
+  void OnRequestDestroyed(int request_id,
+                          OperationCompletion completion) override {}
   void OnRequestExecuted(int request_id) override {}
   void OnRequestFulfilled(int request_id,
                           const RequestValue& result,
diff --git a/chrome/browser/chromeos/extensions/smart_card_provider_private/smart_card_provider_private_api.cc b/chrome/browser/chromeos/extensions/smart_card_provider_private/smart_card_provider_private_api.cc
index 7121f6d..1de1619 100644
--- a/chrome/browser/chromeos/extensions/smart_card_provider_private/smart_card_provider_private_api.cc
+++ b/chrome/browser/chromeos/extensions/smart_card_provider_private/smart_card_provider_private_api.cc
@@ -532,6 +532,23 @@
           .Append(base::Value(std::move(data))));
 }
 
+void SmartCardProviderPrivateAPI::SendGetAttrib(ContextId scard_context,
+                                                Handle handle,
+                                                uint32_t id,
+                                                GetAttribCallback callback) {
+  auto process_result =
+      base::BindOnce(&SmartCardProviderPrivateAPI::ProcessDataResult,
+                     weak_ptr_factory_.GetWeakPtr());
+
+  DispatchEventWithTimeout(
+      scard_context, scard_api::OnGetAttribRequested::kEventName,
+      extensions::events::SMART_CARD_PROVIDER_PRIVATE_ON_GET_ATTRIB_REQUESTED,
+      std::move(process_result), std::move(callback),
+      &SmartCardProviderPrivateAPI::OnGetAttribTimeout,
+      /*event_arguments=*/
+      base::Value::List().Append(handle.GetUnsafeValue()).Append(int(id)));
+}
+
 void SmartCardProviderPrivateAPI::ReportResult(
     RequestId request_id,
     ResultArgs result_args,
@@ -1057,6 +1074,20 @@
                      control_code, std::move(data), std::move(callback)));
 }
 
+void SmartCardProviderPrivateAPI::GetAttrib(uint32_t id,
+                                            GetAttribCallback callback) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  const auto& [context_id, handle] = connection_receivers_.current_context();
+  CHECK(context_id);
+  CHECK(handle);
+
+  RunOrQueueRequest(context_id,
+                    base::BindOnce(&SmartCardProviderPrivateAPI::SendGetAttrib,
+                                   weak_ptr_factory_.GetWeakPtr(), context_id,
+                                   handle, id, std::move(callback)));
+}
+
 SmartCardProviderPrivateAPI::ContextData&
 SmartCardProviderPrivateAPI::GetContextData(ContextId scard_context) {
   auto it = context_data_map_.find(scard_context);
@@ -1130,6 +1161,11 @@
                 std::vector<uint8_t>(),
                 SmartCardResult::NewError(SmartCardError::kNoService))
 
+ON_TIMEOUT_IMPL(GetAttrib,
+                ReportResult,
+                std::vector<uint8_t>(),
+                SmartCardResult::NewError(SmartCardError::kNoService))
+
 #undef ON_TIMEOUT_IMPL
 
 #define REPORT_RESULT_FUNCTION_IMPL(FunctionName, ReportResultName, ...)    \
diff --git a/chrome/browser/chromeos/extensions/smart_card_provider_private/smart_card_provider_private_api.h b/chrome/browser/chromeos/extensions/smart_card_provider_private/smart_card_provider_private_api.h
index d2201db..ec67d51 100644
--- a/chrome/browser/chromeos/extensions/smart_card_provider_private/smart_card_provider_private_api.h
+++ b/chrome/browser/chromeos/extensions/smart_card_provider_private/smart_card_provider_private_api.h
@@ -102,6 +102,7 @@
   void Control(uint32_t control_code,
                const std::vector<uint8_t>& data,
                ControlCallback callback) override;
+  void GetAttrib(uint32_t id, GetAttribCallback callback) override;
 
   // Called by extension functions:
   void ReportResult(RequestId request_id,
@@ -181,6 +182,10 @@
                    uint32_t control_code,
                    const std::vector<uint8_t>& data,
                    ControlCallback callback);
+  void SendGetAttrib(ContextId scard_context,
+                     Handle handle,
+                     uint32_t id,
+                     GetAttribCallback callback);
 
   // Called when a device::mojom::SmartCardContext loses its mojo connection.
   // eg: because its mojo Remote was destroyed.
@@ -214,6 +219,8 @@
                          RequestId request_id);
   void OnControlTimeout(const std::string& provider_extension_id,
                         RequestId request_id);
+  void OnGetAttribTimeout(const std::string& provider_extension_id,
+                          RequestId request_id);
 
   template <typename ResultPtr>
   void DispatchEventWithTimeout(
diff --git a/chrome/browser/chromeos/extensions/smart_card_provider_private/smart_card_provider_private_apitest.cc b/chrome/browser/chromeos/extensions/smart_card_provider_private/smart_card_provider_private_apitest.cc
index 43ba3daf..7cb2470 100644
--- a/chrome/browser/chromeos/extensions/smart_card_provider_private/smart_card_provider_private_apitest.cc
+++ b/chrome/browser/chromeos/extensions/smart_card_provider_private/smart_card_provider_private_apitest.cc
@@ -1201,4 +1201,59 @@
   EXPECT_THAT(result_future.Take(), IsError(SmartCardError::kNoService));
 }
 
+IN_PROC_BROWSER_TEST_F(SmartCardProviderPrivateApiTest, GetAttrib) {
+  LoadFakeProviderExtension({kEstablishContextJs, kConnectJs, R"(
+      chrome.smartCardProviderPrivate.onGetAttribRequested.addListener(
+          getAttrib);
+
+      function getAttrib(requestId, scardHandle, attribId) {
+        if (scardHandle !== validHandle || attribId !== 111) {
+          chrome.smartCardProviderPrivate.reportDataResult(requestId,
+            new Uint8Array().buffer,
+            "INVALID_PARAMETER");
+          return;
+        }
+
+        let responseData = new Uint8Array([1, 100, 255]);
+
+        chrome.smartCardProviderPrivate.reportDataResult(requestId,
+          responseData.buffer, "SUCCESS");
+      }
+      )"});
+
+  auto [context, connection] = CreateContextAndConnection();
+  ASSERT_TRUE(connection.is_bound());
+
+  base::test::TestFuture<device::mojom::SmartCardDataResultPtr> result_future;
+
+  connection->GetAttrib(111u, result_future.GetCallback());
+
+  device::mojom::SmartCardDataResultPtr result = result_future.Take();
+  ASSERT_TRUE(result->is_data());
+
+  EXPECT_EQ(result->get_data(), std::vector<uint8_t>({1u, 100u, 255u}));
+}
+
+IN_PROC_BROWSER_TEST_F(SmartCardProviderPrivateApiTest, GetAttribTimeout) {
+  ProviderAPI().SetResponseTimeLimitForTesting(base::Seconds(1));
+
+  LoadFakeProviderExtension({kEstablishContextJs, kConnectJs, R"(
+      chrome.smartCardProviderPrivate.onGetAttribRequested.addListener(
+          function (requestId, scardHandle, attribId) {
+            // Do nothing.
+          });
+      )"});
+
+  auto [context, connection] = CreateContextAndConnection();
+  ASSERT_TRUE(connection.is_bound());
+
+  base::test::TestFuture<device::mojom::SmartCardDataResultPtr> result_future;
+
+  connection->GetAttrib(111u, result_future.GetCallback());
+
+  device::mojom::SmartCardDataResultPtr result = result_future.Take();
+  ASSERT_TRUE(result->is_error());
+  EXPECT_EQ(result->get_error(), SmartCardError::kNoService);
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/component_updater/screen_ai_component_installer.cc b/chrome/browser/component_updater/screen_ai_component_installer.cc
index a882f16..22d3007 100644
--- a/chrome/browser/component_updater/screen_ai_component_installer.cc
+++ b/chrome/browser/component_updater/screen_ai_component_installer.cc
@@ -8,9 +8,9 @@
 #include "base/files/file_util.h"
 #include "base/logging.h"
 #include "base/values.h"
+#include "chrome/browser/screen_ai/screen_ai_install_state.h"
 #include "components/component_updater/component_updater_service.h"
 #include "components/crx_file/id_util.h"
-#include "components/services/screen_ai/public/cpp/screen_ai_install_state.h"
 #include "components/services/screen_ai/public/cpp/utilities.h"
 #include "components/update_client/update_client_errors.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/extensions/api/BUILD.gn b/chrome/browser/extensions/api/BUILD.gn
index e995542f..07a14aa 100644
--- a/chrome/browser/extensions/api/BUILD.gn
+++ b/chrome/browser/extensions/api/BUILD.gn
@@ -84,3 +84,14 @@
     deps += [ "//chrome/browser/chromeos/extensions:constants" ]
   }
 }
+
+if (is_win) {
+  # The ampersand in the filename is required to exercise the code that properly
+  # launches Native Hosts with paths containing characters that are problematic
+  # for cmd.exe. crbug.com/335558
+  executable("native_messaging_test_echo_&_host") {
+    testonly = true
+    sources = [ "messaging/native_messaging_test_echo_host.cc" ]
+    deps = [ "//base" ]
+  }
+}
diff --git a/chrome/browser/extensions/api/messaging/native_messaging_apitest.cc b/chrome/browser/extensions/api/messaging/native_messaging_apitest.cc
index 2f80639..c64f72ca 100644
--- a/chrome/browser/extensions/api/messaging/native_messaging_apitest.cc
+++ b/chrome/browser/extensions/api/messaging/native_messaging_apitest.cc
@@ -25,9 +25,14 @@
 #include "components/keep_alive_registry/keep_alive_types.h"
 #include "content/public/test/browser_test.h"
 #include "extensions/browser/process_manager.h"
+#include "extensions/common/extension_features.h"
 #include "extensions/test/extension_background_page_waiter.h"
 #include "extensions/test/result_catcher.h"
 
+#if BUILDFLAG(IS_WIN)
+#include <windows.h>
+#endif
+
 namespace extensions {
 namespace {
 
@@ -61,6 +66,50 @@
   ASSERT_TRUE(RunExtensionTest("native_messaging_send_native_message"));
 }
 
+#if BUILDFLAG(IS_WIN)
+// On Windows, a new codepath is used to directly launch .EXE-based Native
+// Hosts. This codepath allows launching of Native Hosts even when cmd.exe is
+// disabled, or if the path to the host contains a character that prevents
+// cmd.exe from successfully launching it (e.g. "&" in this test).
+class NativeMessagingLaunchExeTest : public NativeMessagingApiTestBase,
+                                     public testing::WithParamInterface<bool> {
+ public:
+  NativeMessagingLaunchExeTest() {
+    feature_list_.InitWithFeatureState(
+        extensions_features::kLaunchWindowsNativeHostsDirectly,
+        IsDirectLaunchEnabled());
+  }
+
+  bool IsDirectLaunchEnabled() const { return GetParam(); }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+INSTANTIATE_TEST_SUITE_P(NativeMessagingLaunchExe,
+                         NativeMessagingLaunchExeTest,
+                         testing::Bool());
+
+IN_PROC_BROWSER_TEST_P(NativeMessagingLaunchExeTest, SendNativeMessageWinExe) {
+  ASSERT_NO_FATAL_FAILURE(test_host_.RegisterTestExeHost(/*user_level=*/false));
+
+  // The extension works properly only if the host launches successfully, which
+  // requires the kLaunchWindowsNativeHostsDirectly feature to be enabled.
+  ASSERT_EQ(IsDirectLaunchEnabled(),
+            RunExtensionTest("native_messaging_send_native_message_exe"));
+}
+
+IN_PROC_BROWSER_TEST_P(NativeMessagingLaunchExeTest,
+                       UserLevelSendNativeMessageWinExe) {
+  ASSERT_NO_FATAL_FAILURE(test_host_.RegisterTestExeHost(/*user_level=*/true));
+
+  // The extension works properly only if the host launches successfully, which
+  // requires the kLaunchWindowsNativeHostsDirectly feature to be enabled.
+  ASSERT_EQ(IsDirectLaunchEnabled(),
+            RunExtensionTest("native_messaging_send_native_message_exe"));
+}
+#endif
+
 class NativeMessagingApiTest : public NativeMessagingApiTestBase,
                                public testing::WithParamInterface<ContextType> {
  public:
diff --git a/chrome/browser/extensions/api/messaging/native_messaging_test_echo_host.cc b/chrome/browser/extensions/api/messaging/native_messaging_test_echo_host.cc
new file mode 100644
index 0000000..94b02854
--- /dev/null
+++ b/chrome/browser/extensions/api/messaging/native_messaging_test_echo_host.cc
@@ -0,0 +1,44 @@
+// 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.
+
+// This is a simple Native Message Host application. It echoes any messages
+// it receives.
+#include <string.h>
+#include <windows.h>
+
+#include "base/files/file.h"
+
+int main(int argc, char* argv[]) {
+  base::File read_stream = base::File(GetStdHandle(STD_INPUT_HANDLE));
+  base::File write_stream = base::File(GetStdHandle(STD_OUTPUT_HANDLE));
+
+  uint32_t message_len = 0;
+
+  // Read and echo messages in a loop.
+  while (true) {
+    // Read the message's length prefix.
+    size_t bytes_read = read_stream.ReadAtCurrentPos(
+        reinterpret_cast<char*>(&message_len), sizeof(message_len));
+
+    // If stdin was closed, the host should exit.
+    if (bytes_read != sizeof(message_len)) {
+      break;
+    }
+
+    // Read the message body.
+    std::string message_body(message_len, '\0');
+    bytes_read =
+        read_stream.ReadAtCurrentPos(std::data(message_body), message_len);
+
+    // Bail if we failed to read the entire message.
+    if (bytes_read != message_len) {
+      break;
+    }
+
+    // Reply by echoing the message length and body.
+    write_stream.WriteAtCurrentPos(reinterpret_cast<char*>(&message_len),
+                                   sizeof(message_len));
+    write_stream.WriteAtCurrentPos(message_body.data(), message_len);
+  }
+}
diff --git a/chrome/browser/extensions/api/messaging/native_messaging_test_util.cc b/chrome/browser/extensions/api/messaging/native_messaging_test_util.cc
index 1ba6f915d..3861f5e 100644
--- a/chrome/browser/extensions/api/messaging/native_messaging_test_util.cc
+++ b/chrome/browser/extensions/api/messaging/native_messaging_test_util.cc
@@ -73,13 +73,16 @@
         "com.google.chrome.test.inbound_native_echo";
 const char ScopedTestNativeMessagingHost::kExtensionId[] =
     "knldjmfmopnpolahpmmgbagdohdnhkik";
+#if BUILDFLAG(IS_WIN)
+const char ScopedTestNativeMessagingHost::kHostExeName[] =
+    "com.google.chrome.test.exe.echo";
+#endif
 
 ScopedTestNativeMessagingHost::ScopedTestNativeMessagingHost() {}
 
 void ScopedTestNativeMessagingHost::RegisterTestHost(bool user_level) {
   base::ScopedAllowBlockingForTesting allow_blocking;
   ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-  ScopedTestNativeMessagingHost test_host;
 
   base::FilePath test_user_data_dir;
   ASSERT_TRUE(
@@ -124,6 +127,32 @@
       host_path, user_level, true));
 }
 
+#if BUILDFLAG(IS_WIN)
+// On Windows, a new codepath is used to directly launch .EXE-based Native
+// Hosts.
+void ScopedTestNativeMessagingHost::RegisterTestExeHost(bool user_level) {
+  base::ScopedAllowBlockingForTesting allow_blocking;
+  ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+
+  base::FilePath binary_dir;
+  ASSERT_TRUE(base::PathService::Get(base::DIR_EXE, &binary_dir));
+  HKEY root_key = user_level ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
+  ASSERT_NO_FATAL_FAILURE(registry_override_.OverrideRegistry(root_key));
+
+  // Unlike in the |RegisterTestHost| case above, we must leave the Host
+  // .exe where it was built, because the Host will fail to run from the
+  // temp_dir_ if is_component_build is set for the build.
+  //
+  // The Host's filename deliberately contains the character '&' which causes
+  // the Host to fail to launch if cmd.exe is used as an intermediary between
+  // the extension and the host executable. crbug.com/335558
+  base::FilePath host_path =
+      binary_dir.AppendASCII("native_messaging_test_echo_&_host.exe");
+  ASSERT_NO_FATAL_FAILURE(WriteTestNativeHostManifest(
+      temp_dir_.GetPath(), kHostExeName, host_path, user_level, false));
+}
+#endif
+
 ScopedTestNativeMessagingHost::~ScopedTestNativeMessagingHost() {
   base::ScopedAllowBlockingForTesting allow_blocking;
   std::ignore = temp_dir_.Delete();
diff --git a/chrome/browser/extensions/api/messaging/native_messaging_test_util.h b/chrome/browser/extensions/api/messaging/native_messaging_test_util.h
index 27ee68a..525fc3e1 100644
--- a/chrome/browser/extensions/api/messaging/native_messaging_test_util.h
+++ b/chrome/browser/extensions/api/messaging/native_messaging_test_util.h
@@ -30,6 +30,11 @@
   static const char kBinaryMissingHostName[];
   static const char kSupportsNativeInitiatedConnectionsHostName[];
 
+#if BUILDFLAG(IS_WIN)
+  // When run on Windows, an additional .EXE backed NativeHost is available.
+  static const char kHostExeName[];
+#endif
+
   static const char kExtensionId[];
 
   ScopedTestNativeMessagingHost();
@@ -41,6 +46,11 @@
   ~ScopedTestNativeMessagingHost();
 
   void RegisterTestHost(bool user_level);
+#if BUILDFLAG(IS_WIN)
+  // Register the Windows-only |native_messaging_test_echo_host.exe| Native
+  // Host.
+  void RegisterTestExeHost(bool user_level);
+#endif
 
   const base::FilePath& temp_dir() { return temp_dir_.GetPath(); }
 
diff --git a/chrome/browser/extensions/api/messaging/native_process_launcher_win.cc b/chrome/browser/extensions/api/messaging/native_process_launcher_win.cc
index 191b4c1..20680fb 100644
--- a/chrome/browser/extensions/api/messaging/native_process_launcher_win.cc
+++ b/chrome/browser/extensions/api/messaging/native_process_launcher_win.cc
@@ -7,6 +7,8 @@
 #include <windows.h>
 #include <stdint.h>
 
+#include <shellapi.h>
+
 #include <string>
 
 #include "base/command_line.h"
@@ -14,12 +16,14 @@
 #include "base/process/launch.h"
 #include "base/process/process.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/win/registry.h"
 #include "base/win/scoped_handle.h"
 #include "build/branding_buildflags.h"
 #include "crypto/random.h"
+#include "extensions/common/extension_features.h"
 
 namespace extensions {
 
@@ -77,6 +81,76 @@
              root_key, KEY_WOW64_64KEY, host_name, result);
 }
 
+// If the Host is an executable, we will invoke it directly to avoid problems
+// if CMD.exe is unavailable due to OS policy or other configuration issues
+// on the client. See https://crbug.com/335558 for details.
+base::Process LaunchNativeExeDirectly(const std::wstring& command,
+                                      base::LaunchOptions& options,
+                                      const std::wstring& in_pipe_name,
+                                      const std::wstring& out_pipe_name) {
+  // When calling the Host executable directly, we must first wrap our Named
+  // Pipes into HANDLEs returned from CreateFileW(). We must configure the
+  // handle's security attributes to allow the file handle to be inherited
+  // into the launched process.
+  SECURITY_ATTRIBUTES sa_attr = {};
+  sa_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
+  sa_attr.bInheritHandle = TRUE;
+  sa_attr.lpSecurityDescriptor = nullptr;
+
+  base::win::ScopedHandle stdout_file(
+      ::CreateFileW(out_pipe_name.c_str(), FILE_WRITE_DATA | SYNCHRONIZE, 0,
+                    &sa_attr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0));
+  if (!stdout_file.IsValid()) {
+    LOG(ERROR) << "Failed to open write handle for stdout.";
+    return base::Process();
+  }
+
+  base::win::ScopedHandle stdin_file(
+      ::CreateFileW(in_pipe_name.c_str(), FILE_READ_DATA | SYNCHRONIZE, 0,
+                    &sa_attr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0));
+  if (!stdin_file.IsValid()) {
+    LOG(ERROR) << "Failed to open read handle for stdin.";
+    return base::Process();
+  }
+
+  options.stdin_handle = stdin_file.Get();
+  options.stdout_handle = stdout_file.Get();
+  options.stderr_handle = ::GetStdHandle(STD_ERROR_HANDLE);
+  options.handles_to_inherit.push_back(options.stdin_handle);
+  options.handles_to_inherit.push_back(options.stdout_handle);
+
+  // Inherit Chrome's STD_ERROR_HANDLE, if set, into the Native Host. If Chrome
+  // was not started with standard error redirected, this value will be null.
+  if (options.stderr_handle != NULL) {
+    options.handles_to_inherit.push_back(options.stderr_handle);
+  }
+
+  return base::LaunchProcess(command, options);
+}
+
+// For non-executable Hosts, we will use the legacy approach whereby we
+// invoke CMD.exe and instruct it to launch the Host, passing references to
+// our Named Pipes.
+base::Process LaunchNativeHostViaCmd(const std::wstring& command,
+                                     base::LaunchOptions& options,
+                                     const std::wstring& in_pipe_name,
+                                     const std::wstring& out_pipe_name) {
+  DWORD comspec_length = ::GetEnvironmentVariable(L"COMSPEC", NULL, 0);
+  if (comspec_length == 0) {
+    LOG(ERROR) << "COMSPEC is not set";
+    return base::Process();
+  }
+  std::wstring comspec;
+  ::GetEnvironmentVariable(
+      L"COMSPEC", base::WriteInto(&comspec, comspec_length), comspec_length);
+
+  std::wstring wrapped_command = base::StringPrintf(
+      L"%ls /d /c %ls < %ls > %ls", comspec.c_str(), command.c_str(),
+      in_pipe_name.c_str(), out_pipe_name.c_str());
+
+  return base::LaunchProcess(wrapped_command, options);
+}
+
 }  // namespace
 
 // static
@@ -136,64 +210,74 @@
       L"\\\\.\\pipe\\chrome.nativeMessaging.in.%llx", pipe_name_token);
 
   // Create the pipes to read and write from.
-  base::win::ScopedHandle stdout_pipe(
-      CreateNamedPipeW(out_pipe_name.c_str(),
-                       PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED |
-                           FILE_FLAG_FIRST_PIPE_INSTANCE,
-                       PIPE_TYPE_BYTE, 1, kBufferSize, kBufferSize,
-                       kTimeoutMs, NULL));
+  base::win::ScopedHandle stdout_pipe(::CreateNamedPipeW(
+      out_pipe_name.c_str(),
+      PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED |
+          FILE_FLAG_FIRST_PIPE_INSTANCE,
+      PIPE_TYPE_BYTE, 1, kBufferSize, kBufferSize, kTimeoutMs, NULL));
   if (!stdout_pipe.IsValid()) {
     LOG(ERROR) << "Failed to create pipe " << out_pipe_name;
     return false;
   }
 
-  base::win::ScopedHandle stdin_pipe(
-      CreateNamedPipeW(in_pipe_name.c_str(),
-                       PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED |
-                           FILE_FLAG_FIRST_PIPE_INSTANCE,
-                       PIPE_TYPE_BYTE, 1, kBufferSize, kBufferSize,
-                       kTimeoutMs, NULL));
+  base::win::ScopedHandle stdin_pipe(::CreateNamedPipeW(
+      in_pipe_name.c_str(),
+      PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED |
+          FILE_FLAG_FIRST_PIPE_INSTANCE,
+      PIPE_TYPE_BYTE, 1, kBufferSize, kBufferSize, kTimeoutMs, NULL));
   if (!stdin_pipe.IsValid()) {
     LOG(ERROR) << "Failed to create pipe " << in_pipe_name;
     return false;
   }
 
-  DWORD comspec_length = ::GetEnvironmentVariable(L"COMSPEC", NULL, 0);
-  if (comspec_length == 0) {
-    LOG(ERROR) << "COMSPEC is not set";
-    return false;
-  }
-  std::unique_ptr<wchar_t[]> comspec(new wchar_t[comspec_length]);
-  ::GetEnvironmentVariable(L"COMSPEC", comspec.get(), comspec_length);
-
-  std::wstring command_line_string = command_line.GetCommandLineString();
-
-  std::wstring command = base::StringPrintf(
-      L"%ls /d /c %ls < %ls > %ls", comspec.get(), command_line_string.c_str(),
-      in_pipe_name.c_str(), out_pipe_name.c_str());
-
+  std::wstring command = command_line.GetCommandLineString();
   base::LaunchOptions options;
-  options.start_hidden = true;
   options.current_directory = command_line.GetProgram().DirName();
-  base::Process cmd_process = base::LaunchProcess(command, options);
-  if (!cmd_process.IsValid()) {
+  options.start_hidden = true;
+
+  bool use_direct_launch =
+      base::FeatureList::IsEnabled(
+          extensions_features::kLaunchWindowsNativeHostsDirectly) &&
+      command_line.GetProgram().MatchesFinalExtension(L".exe");
+
+  base::Process launched_process;
+  if (use_direct_launch) {
+    // Compat: If the target is SUBSYSTEM_WINDOWS, then don't set |start_hidden|
+    // in order to mimic legacy behavior: https://crbug.com/1442359.
+    // A Windows executable will have LOWORD of 0x4550. A GUI executable will
+    // have a non-Zero HIWORD while a console executable will have a 0 HIWORD.
+    uintptr_t exe_type = ::SHGetFileInfoW(
+        command_line.GetProgram().value().c_str(), 0, NULL, 0, SHGFI_EXETYPE);
+    if ((LOWORD(exe_type) == 0x4550) && (HIWORD(exe_type) != 0)) {
+      options.start_hidden = false;
+    }
+
+    launched_process =
+        LaunchNativeExeDirectly(command, options, in_pipe_name, out_pipe_name);
+  } else {
+    launched_process =
+        LaunchNativeHostViaCmd(command, options, in_pipe_name, out_pipe_name);
+  }
+
+  if (!launched_process.IsValid()) {
     LOG(ERROR) << "Error launching process "
                << command_line.GetProgram().MaybeAsASCII();
     return false;
   }
 
+  // Wait for the named pipes to be opened by the host.
   bool stdout_connected = ConnectNamedPipe(stdout_pipe.Get(), NULL) ?
       TRUE : GetLastError() == ERROR_PIPE_CONNECTED;
   bool stdin_connected = ConnectNamedPipe(stdin_pipe.Get(), NULL) ?
       TRUE : GetLastError() == ERROR_PIPE_CONNECTED;
   if (!stdout_connected || !stdin_connected) {
-    cmd_process.Terminate(0, false);
+    launched_process.Terminate(0, false);
     LOG(ERROR) << "Failed to connect IO pipes when starting "
                << command_line.GetProgram().MaybeAsASCII();
     return false;
   }
 
-  *process = std::move(cmd_process);
+  *process = std::move(launched_process);
   *read_file = base::File(std::move(stdout_pipe), true /* async */);
   *write_file = base::File(std::move(stdin_pipe), true /* async */);
   return true;
diff --git a/chrome/browser/extensions/api/tabs/tabs_apitest.cc b/chrome/browser/extensions/api/tabs/tabs_apitest.cc
index a521b772..b6fcf2e 100644
--- a/chrome/browser/extensions/api/tabs/tabs_apitest.cc
+++ b/chrome/browser/extensions/api/tabs/tabs_apitest.cc
@@ -132,9 +132,7 @@
       << message_;
 }
 
-// TODO(crbug.com/521410): Flaky on Wayland. Disabled for now on all platforms
-// pending further testing.
-IN_PROC_BROWSER_TEST_P(ExtensionApiTabTestWithContextType, DISABLED_Muted) {
+IN_PROC_BROWSER_TEST_P(ExtensionApiTabTestWithContextType, Muted) {
   ASSERT_TRUE(RunExtensionTest("tabs/basics/muted")) << message_;
 }
 
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index d35e57a..bf18ce4 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -607,6 +607,11 @@
     "expiry_milestone": 120
   },
   {
+    "name": "autofill-move-legal-terms-and-icon-for-new-card-enrollment",
+    "owners": [ "yishuil@google.com" ],
+    "expiry_milestone": 123
+  },
+  {
     "name": "autofill-offer-to-save-card-with-same-last-four",
     "owners": [ "qihuizhao@google.com", "jsaul@google.com" ],
     "expiry_milestone": 120
@@ -1670,7 +1675,7 @@
   {
     "name": "drive-fs-chrome-networking",
     "owners": [ "travislane@google.com" ],
-    "expiry_milestone": 115
+    "expiry_milestone": 119
   },
   {
     "name": "drop-input-events-before-first-paint",
@@ -4867,6 +4872,11 @@
     "expiry_milestone": 105
   },
   {
+    "name": "launch-windows-native-hosts-directly",
+    "owners": ["ericlaw@microsoft.com"],
+    "expiry_milestone": 122
+  },
+  {
     "name": "launcher-fuzzy-match-for-omnibox",
     "owners": ["wrong", "laurencom"],
     "expiry_milestone": 120
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 7b511fe..75acccc 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -504,6 +504,13 @@
     "and other values that are not changed by accepting the preview should "
     "not be highlighted.";
 
+const char kAutofillMoveLegalTermsAndIconForNewCardEnrollmentName[] =
+    "Move legal terms and icon for new card enrollment";
+const char kAutofillMoveLegalTermsAndIconForNewCardEnrollmentDescription[] =
+    "When enabled, legal terms will be moved before action buttons and GPay "
+    "icon will be moved after the title in autofill save card and virtual "
+    "card enrollment bubbles and dialogs.";
+
 const char kAutofillOfferToSaveCardWithSameLastFourName[] =
     "Offer credit card save for cards with same last-4 but different "
     "expiration dates";
@@ -4886,6 +4893,13 @@
     "Use Windows Runtime MIDI API for WebMIDI (effective only on Windows 10 or "
     "later).";
 
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+const char kLaunchWindowsNativeHostsDirectlyName[] =
+    "Force Native Host Executables to Launch Directly";
+const char kLaunchWindowsNativeHostsDirectlyDescription[] =
+    "Force Native Host executables to launch directly via CreateProcess.";
+#endif  // ENABLE_EXTENSIONS
+
 #if BUILDFLAG(ENABLE_PRINTING)
 const char kPrintWithPostScriptType42FontsName[] =
     "Print with PostScript Type 42 fonts";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index ba1ae6d7..77c58ac 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -281,6 +281,10 @@
 extern const char kAutofillHighlightOnlyChangedValuesInPreviewModeName[];
 extern const char kAutofillHighlightOnlyChangedValuesInPreviewModeDescription[];
 
+extern const char kAutofillMoveLegalTermsAndIconForNewCardEnrollmentName[];
+extern const char
+    kAutofillMoveLegalTermsAndIconForNewCardEnrollmentDescription[];
+
 extern const char kAutofillOfferToSaveCardWithSameLastFourName[];
 extern const char kAutofillOfferToSaveCardWithSameLastFourDescription[];
 
@@ -2795,6 +2799,11 @@
 extern const char kUseWinrtMidiApiName[];
 extern const char kUseWinrtMidiApiDescription[];
 
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+extern const char kLaunchWindowsNativeHostsDirectlyName[];
+extern const char kLaunchWindowsNativeHostsDirectlyDescription[];
+#endif  // ENABLE_EXTENSIONS
+
 #if BUILDFLAG(ENABLE_PRINTING)
 extern const char kPrintWithPostScriptType42FontsName[];
 extern const char kPrintWithPostScriptType42FontsDescription[];
diff --git a/chrome/browser/lacros/input_method_lacros_browsertest.cc b/chrome/browser/lacros/input_method_lacros_browsertest.cc
index 597ab1e..9b96c58 100644
--- a/chrome/browser/lacros/input_method_lacros_browsertest.cc
+++ b/chrome/browser/lacros/input_method_lacros_browsertest.cc
@@ -682,10 +682,6 @@
 
 IN_PROC_BROWSER_TEST_P(InputMethodLacrosBrowserTest,
                        CommitTextReplacesSelection) {
-  if (!GetParam().fix_265853952) {
-    GTEST_SKIP() << "Temporarily disabled for crbug.com/1445055";
-  }
-
   mojo::Remote<InputMethodTestInterface> input_method =
       BindInputMethodTestInterface(
           GetParam(),
@@ -1053,10 +1049,6 @@
 
 IN_PROC_BROWSER_TEST_P(InputMethodLacrosBrowserTest,
                        SendLeftArrowKeyWithSelectionCollapsesSelectionLeft) {
-  if (!GetParam().fix_265853952) {
-    GTEST_SKIP() << "Temporarily disabled for crbug.com/1445055";
-  }
-
   mojo::Remote<InputMethodTestInterface> input_method =
       BindInputMethodTestInterface(
           GetParam(),
@@ -1087,10 +1079,6 @@
 
 IN_PROC_BROWSER_TEST_P(InputMethodLacrosBrowserTest,
                        SendRightArrowKeyWithSelectionCollapsesSelectionRight) {
-  if (!GetParam().fix_265853952) {
-    GTEST_SKIP() << "Temporarily disabled for crbug.com/1445055";
-  }
-
   mojo::Remote<InputMethodTestInterface> input_method =
       BindInputMethodTestInterface(
           GetParam(),
@@ -1121,10 +1109,6 @@
 
 IN_PROC_BROWSER_TEST_P(InputMethodLacrosBrowserTest,
                        SendKeyEventShortcutsModifiesSelection) {
-  if (!GetParam().fix_265853952) {
-    GTEST_SKIP() << "Temporarily disabled for crbug.com/1445055";
-  }
-
   mojo::Remote<InputMethodTestInterface> input_method =
       BindInputMethodTestInterface(
           GetParam(),
@@ -1561,10 +1545,6 @@
 
 IN_PROC_BROWSER_TEST_P(InputMethodLacrosBrowserTest,
                        ConfirmCompositionWithSelectionAndNoComposition) {
-  if (!GetParam().fix_265853952) {
-    GTEST_SKIP() << "Temporarily disabled for crbug.com/1445055";
-  }
-
   mojo::Remote<InputMethodTestInterface> input_method =
       BindInputMethodTestInterface(
           GetParam(),
@@ -1643,10 +1623,6 @@
 // See b/267944900 for more information.
 IN_PROC_BROWSER_TEST_P(InputMethodLacrosBrowserTest,
                        EscapeAfterResetKeepsSelection) {
-  if (!GetParam().fix_265853952) {
-    GTEST_SKIP() << "Temporarily disabled for crbug.com/1445055";
-  }
-
   mojo::Remote<InputMethodTestInterface> input_method =
       BindInputMethodTestInterface(
           GetParam(),
diff --git a/chrome/browser/net/profile_network_context_service.cc b/chrome/browser/net/profile_network_context_service.cc
index 81851ba..cf11f6a 100644
--- a/chrome/browser/net/profile_network_context_service.cc
+++ b/chrome/browser/net/profile_network_context_service.cc
@@ -1001,9 +1001,10 @@
   network_context_params->split_auth_cache_by_network_anonymization_key =
       ShouldSplitAuthCacheByNetworkIsolationKey();
 
-  // All consumers of the main NetworkContext must provide NetworkIsolationKeys
-  // / IsolationInfos, so storage can be isolated on a per-site basis.
-  network_context_params->require_network_isolation_key = true;
+  // All consumers of the main NetworkContext must provide
+  // NetworkAnonymizationKeys / IsolationInfos, so storage can be isolated on a
+  // per-site basis.
+  network_context_params->require_network_anonymization_key = true;
 
   ContentSetting anti_abuse_content_setting =
       HostContentSettingsMapFactory::GetForProfile(profile_)
diff --git a/chrome/browser/policy/test/developer_tools_policy_browsertest.cc b/chrome/browser/policy/test/developer_tools_policy_browsertest.cc
index 8e9eaf24..53d06435 100644
--- a/chrome/browser/policy/test/developer_tools_policy_browsertest.cc
+++ b/chrome/browser/policy/test/developer_tools_policy_browsertest.cc
@@ -336,15 +336,8 @@
 // blocked or allowed for different pages depending on the
 // DeveloperToolsAvailability policy setting. Note: javascript URLs are always
 // blocked on extension schemes, regardless of the policy setting.
-#if BUILDFLAG(GOOGLE_CHROME_BRANDING) || BUILDFLAG(IS_LINUX)
-#define MAYBE_DebugURLsDisabledByDeveloperToolsAvailability \
-  DISABLED_DebugURLsDisabledByDeveloperToolsAvailability
-#else
-#define MAYBE_DebugURLsDisabledByDeveloperToolsAvailability \
-  DebugURLsDisabledByDeveloperToolsAvailability
-#endif
 IN_PROC_BROWSER_TEST_F(PolicyTest,
-                       MAYBE_DebugURLsDisabledByDeveloperToolsAvailability) {
+                       DebugURLsDisabledByDeveloperToolsAvailability) {
   // Get a url for a standard web page.
   ASSERT_TRUE(embedded_test_server()->Start());
   GURL tab_url(embedded_test_server()->GetURL("/empty.html"));
@@ -354,6 +347,11 @@
       base::FilePath().AppendASCII("devtools").AppendASCII("extensions"),
       base::FilePath().AppendASCII("options.crx")));
   extensions::ChromeTestExtensionLoader loader(browser()->profile());
+  // TODO(1447936): We shouldn't need to ignore manifest warnings here, but
+  // there's an issue related to the _metadata folder added for content
+  // verification when force-installing an off-store crx in a branded build,
+  // which produces an install warning.
+  loader.set_ignore_manifest_warnings(true);
   loader.set_location(ManifestLocation::kExternalPolicyDownload);
   scoped_refptr<const extensions::Extension> extension =
       loader.LoadExtension(crx_path);
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 3792484..2bc5695 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -221,7 +221,7 @@
 #endif  // BUILDFLAG(ENABLE_PDF)
 
 #if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
-#include "components/services/screen_ai/public/cpp/pref_names.h"  // nogncheck
+#include "chrome/browser/screen_ai/pref_names.h"
 #endif
 
 #if BUILDFLAG(ENABLE_SUPERVISED_USERS)
diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
index d7a7fe7..1c3ad5fc 100644
--- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
+++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
@@ -427,7 +427,7 @@
 #if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
 #include "chrome/browser/accessibility/ax_screen_ai_annotator_factory.h"
 #include "chrome/browser/accessibility/pdf_ocr_controller_factory.h"
-#include "components/services/screen_ai/public/cpp/screen_ai_service_router_factory.h"
+#include "chrome/browser/screen_ai/screen_ai_service_router_factory.h"
 #endif
 
 #if BUILDFLAG(USE_NSS_CERTS)
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
index 422f0735..c75a578 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -246,7 +246,7 @@
 #endif  // BUILDFLAG(ENABLE_PRINTING)
 
 #if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
-#include "components/services/screen_ai/public/cpp/screen_ai_install_state.h"
+#include "chrome/browser/screen_ai/screen_ai_install_state.h"
 #endif
 
 #if BUILDFLAG(ENABLE_SUPERVISED_USERS)
@@ -1778,6 +1778,15 @@
 }
 
 void RenderViewContextMenu::AppendSearchWebForImageItems() {
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  if (!crosapi::browser_util::IsAshWebBrowserEnabled()) {
+    // If Lacros is the only browser, disable image search in Ash because we
+    // have decided not to support this feature in the system UI so as not to
+    // confuse users by opening an Ash browser window.
+    return;
+  }
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+
   // TODO(b/266624865): Image Search items do not function correctly when
   // |GetBrowser| returns nullptr, as is the case for a context menu in the
   // side panel, so for now we do not append image items in that case.
@@ -3472,6 +3481,15 @@
 
 bool RenderViewContextMenu::IsRegionSearchEnabled() const {
 #if BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  if (!crosapi::browser_util::IsAshWebBrowserEnabled()) {
+    // If Lacros is the only browser, disable region search in Ash because we
+    // have decided not to support this feature in the system UI so as not to
+    // confuse users by opening an Ash browser window.
+    return false;
+  }
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+
   // TODO(nguyenbryan): Refactor to use lens_region_search_helper.cc after PDF
   // support is cleaned up.
   if (!GetBrowser())
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
index 234b2f2..f6a48adf 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
@@ -134,7 +134,7 @@
 #endif
 
 #if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
-#include "components/services/screen_ai/public/cpp/screen_ai_install_state.h"
+#include "chrome/browser/screen_ai/screen_ai_install_state.h"
 #endif
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
@@ -737,7 +737,7 @@
         WebAppProvider::GetForTest(browser()->profile());
     base::RunLoop run_loop;
 
-    ASSERT_TRUE(provider->install_finalizer().CanUserUninstallWebApp(app_id));
+    ASSERT_TRUE(provider->registrar_unsafe().CanUserUninstallWebApp(app_id));
     provider->install_finalizer().UninstallWebApp(
         app_id, webapps::WebappUninstallSource::kAppMenu,
         base::BindLambdaForTesting([&](webapps::UninstallResultCode code) {
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_unittest.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_unittest.cc
index 2cd29c6..9fb0fb5 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu_unittest.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu_unittest.cc
@@ -79,6 +79,11 @@
 #include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager_test_utils.h"
 #endif
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+#include "ash/constants/ash_features.h"
+#include "chrome/browser/ash/crosapi/browser_util.h"
+#endif
+
 using extensions::Extension;
 using extensions::MenuItem;
 using extensions::MenuManager;
@@ -1129,6 +1134,36 @@
   EXPECT_FALSE(menu.IsItemPresent(IDC_CONTENT_CONTEXT_TRANSLATEIMAGEWITHLENS));
 }
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+// Verify that the Lens Image Search menu item is disabled on image content in
+// Ash, if Lacros is the only browser.
+TEST_F(RenderViewContextMenuPrefsTest,
+       LensImageSearchDisabledIfAshBrowserIsDisabled) {
+  auto scoped_lacros_primary =
+      crosapi::browser_util::SetLacrosPrimaryBrowserForTest(true);
+  base::test::ScopedFeatureList features;
+  features.InitWithFeatures(
+      {lens::features::kLensStandalone, lens::features::kEnableImageTranslate,
+       ash::features::kLacrosOnly},
+      {});
+  ASSERT_FALSE(crosapi::browser_util::IsAshWebBrowserEnabled());
+
+  SetUserSelectedDefaultSearchProvider("https://www.google.com",
+                                       /*supports_image_search=*/true);
+  content::ContextMenuParams params = CreateParams(MenuItem::IMAGE);
+  params.has_image_contents = true;
+  TestRenderViewContextMenu menu(*web_contents()->GetPrimaryMainFrame(),
+                                 params);
+  menu.SetBrowser(GetBrowser());
+  menu.Init();
+
+  EXPECT_FALSE(menu.IsItemPresent(IDC_CONTENT_CONTEXT_SEARCHWEBFORIMAGE));
+  EXPECT_FALSE(menu.IsItemPresent(IDC_CONTENT_CONTEXT_SEARCHLENSFORIMAGE));
+  EXPECT_FALSE(menu.IsItemPresent(IDC_CONTENT_CONTEXT_TRANSLATEIMAGEWITHWEB));
+  EXPECT_FALSE(menu.IsItemPresent(IDC_CONTENT_CONTEXT_TRANSLATEIMAGEWITHLENS));
+}
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+
 // Verify that the Lens Image Search menu item is enabled for Progressive Web
 // Apps
 TEST_F(RenderViewContextMenuPrefsTest, LensImageSearchForProgressiveWebApp) {
@@ -1305,6 +1340,30 @@
   EXPECT_TRUE(menu.IsItemPresent(IDC_CONTENT_CONTEXT_LENS_REGION_SEARCH));
 }
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+// Verify that the Lens Region Search menu item is not displayed even when the
+// feature is enabled if Lacros is the only browser.
+TEST_F(RenderViewContextMenuPrefsTest,
+       LensRegionSearchDisabledIfAshBrowserIsDisabled) {
+  auto scoped_lacros_primary =
+      crosapi::browser_util::SetLacrosPrimaryBrowserForTest(true);
+  base::test::ScopedFeatureList features;
+  features.InitWithFeatures(
+      {lens::features::kLensStandalone, ash::features::kLacrosOnly}, {});
+  ASSERT_FALSE(crosapi::browser_util::IsAshWebBrowserEnabled());
+
+  SetUserSelectedDefaultSearchProvider("https://www.google.com",
+                                       /*supports_image_search=*/true);
+  content::ContextMenuParams params = CreateParams(MenuItem::PAGE);
+  TestRenderViewContextMenu menu(*web_contents()->GetPrimaryMainFrame(),
+                                 params);
+  menu.SetBrowser(GetBrowser());
+  menu.Init();
+
+  EXPECT_FALSE(menu.IsItemPresent(IDC_CONTENT_CONTEXT_LENS_REGION_SEARCH));
+}
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+
 TEST_F(RenderViewContextMenuPrefsTest, LensRegionSearchPdfEnabled) {
   base::test::ScopedFeatureList features;
   features.InitAndEnableFeature(lens::features::kLensStandalone);
diff --git a/chrome/browser/resources/settings/chromeos/device_page/keyboard.ts b/chrome/browser/resources/settings/chromeos/device_page/keyboard.ts
index 7ce6a95f..410f41e 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/keyboard.ts
+++ b/chrome/browser/resources/settings/chromeos/device_page/keyboard.ts
@@ -138,6 +138,17 @@
           Setting.kShowDiacritic,
         ]),
       },
+
+      /**
+       * Whether settings should be split per device.
+       */
+      isDeviceSettingsSplitEnabled_: {
+        type: Boolean,
+        value() {
+          return loadTimeData.getBoolean('enableInputDeviceSettingsSplit');
+        },
+        readOnly: true,
+      },
     };
   }
 
@@ -151,6 +162,7 @@
   private showExternalMetaKey_: boolean;
   private shouldShowDiacriticSetting_ =
       loadTimeData.getBoolean('allowDiacriticsOnPhysicalKeyboardLongpress');
+  private isDeviceSettingsSplitEnabled_: boolean;
 
   constructor() {
     super();
@@ -172,7 +184,16 @@
     if (route !== routes.KEYBOARD) {
       return;
     }
-
+    if (Router.getInstance().currentRoute === routes.KEYBOARD &&
+        this.isDeviceSettingsSplitEnabled_) {
+      // Call setCurrentRoute function to go to the per device keyboard subpage
+      // when the feature flag is turned on. We don't use navigateTo function
+      // since we don't want to navigate back to the previous keyboard subpage.
+      setTimeout(() => {
+        Router.getInstance().setCurrentRoute(
+            routes.PER_DEVICE_KEYBOARD, new URLSearchParams(), false);
+      });
+    }
     this.attemptDeepLink();
   }
 
diff --git a/chrome/browser/resources/settings/chromeos/device_page/pointers.ts b/chrome/browser/resources/settings/chromeos/device_page/pointers.ts
index 0d8a3a4..2d035c2 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/pointers.ts
+++ b/chrome/browser/resources/settings/chromeos/device_page/pointers.ts
@@ -23,7 +23,7 @@
 import {Setting} from '../mojom-webui/setting.mojom-webui.js';
 import {routes} from '../os_settings_routes.js';
 import {RouteObserverMixin} from '../route_observer_mixin.js';
-import {Route} from '../router.js';
+import {Route, Router} from '../router.js';
 
 import {getTemplate} from './pointers.html.js';
 
@@ -140,9 +140,22 @@
           Setting.kMouseSpeed,
         ]),
       },
+
+      /**
+       * Whether settings should be split per device.
+       */
+      isDeviceSettingsSplitEnabled_: {
+        type: Boolean,
+        value() {
+          return loadTimeData.getBoolean('enableInputDeviceSettingsSplit');
+        },
+        readOnly: true,
+      },
     };
   }
 
+  private isDeviceSettingsSplitEnabled_: boolean;
+
   /**
    * Headings should only be visible if more than one subsection is present.
    */
@@ -172,7 +185,16 @@
     if (route !== routes.POINTERS) {
       return;
     }
-
+    if (Router.getInstance().currentRoute === routes.POINTERS &&
+        this.isDeviceSettingsSplitEnabled_) {
+      // Call setCurrentRoute function to go to the device page when
+      // the feature flag is turned on. We don't use navigateTo function since
+      // we don't want to navigate back to the previous point page.
+      setTimeout(() => {
+        Router.getInstance().setCurrentRoute(
+            routes.DEVICE, new URLSearchParams(), false);
+      });
+    }
     this.attemptDeepLink();
   }
 
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/borealis_page/borealis_detail_view.html b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/borealis_page/borealis_detail_view.html
index f45bcdd..2adad05 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/borealis_page/borealis_detail_view.html
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/borealis_page/borealis_detail_view.html
@@ -27,11 +27,9 @@
         <div class="horizontal-align">
           <iron-icon id="icon" icon="cr:help-outline"></iron-icon>
           <template is="dom-if" if="[[isMainApp_(app_.*)]]" restamp>
-            <!-- TODO(b/194640944): Add link to borealis learn more page -->
             <localized-link
                 id="mainLink"
-                localized-string="$i18n{borealisMainPermissionText}"
-                link-url="https://www.youtube.com/watch?v=dQw4w9WgXcQ">
+                localized-string="$i18n{borealisMainPermissionText}">
             </localized-link>
           </template>
           <template is="dom-if" if="[[!isMainApp_(app_.*)]]" restamp>
diff --git a/chrome/browser/screen_ai/BUILD.gn b/chrome/browser/screen_ai/BUILD.gn
new file mode 100644
index 0000000..43f87a8
--- /dev/null
+++ b/chrome/browser/screen_ai/BUILD.gn
@@ -0,0 +1,62 @@
+# Copyright 2023 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/ui.gni")
+
+if (is_chromeos_ash) {
+  source_set("screen_ai_chromeos_installer") {
+    sources = [
+      "screen_ai_chromeos_installer.cc",
+      "screen_ai_chromeos_installer.h",
+    ]
+
+    deps = [
+      ":screen_ai_install_state",
+      "//chromeos/ash/components/dbus/dlcservice",
+      "//chromeos/ash/components/dbus/dlcservice:dlcservice_proto",
+      "//components/services/screen_ai/public/cpp:utilities",
+    ]
+  }
+}
+
+source_set("screen_ai_install_state") {
+  sources = [
+    "screen_ai_install_state.cc",
+    "screen_ai_install_state.h",
+  ]
+
+  deps = [
+    ":prefs",
+    "//base",
+    "//components/prefs",
+    "//components/services/screen_ai/public/cpp:utilities",
+    "//ui/accessibility:ax_base",
+  ]
+}
+
+source_set("screen_ai_service_router_factory") {
+  sources = [
+    "screen_ai_service_router.cc",
+    "screen_ai_service_router.h",
+    "screen_ai_service_router_factory.cc",
+    "screen_ai_service_router_factory.h",
+  ]
+
+  deps = [
+    ":screen_ai_install_state",
+    "//components/keyed_service/content",
+    "//components/keyed_service/core",
+    "//components/services/screen_ai/public/mojom",
+    "//content/public/browser",
+  ]
+}
+
+source_set("prefs") {
+  sources = [
+    "pref_names.cc",
+    "pref_names.h",
+  ]
+
+  deps = [ "//components/prefs" ]
+}
diff --git a/chrome/browser/screen_ai/DEPS b/chrome/browser/screen_ai/DEPS
new file mode 100644
index 0000000..7e7224c5
--- /dev/null
+++ b/chrome/browser/screen_ai/DEPS
@@ -0,0 +1,7 @@
+include_rules = [
+  "+components/keyed_service/core",
+  "+components/keyed_service/content",
+  "+components/prefs",
+  "+components/component_updater",
+  "+chromeos/ash/components/dbus/dlcservice"
+]
diff --git a/chrome/browser/screen_ai/OWNERS b/chrome/browser/screen_ai/OWNERS
new file mode 100644
index 0000000..b17fac0b
--- /dev/null
+++ b/chrome/browser/screen_ai/OWNERS
@@ -0,0 +1,2 @@
+rhalavati@chromium.org
+file://ui/accessibility/OWNERS
diff --git a/components/services/screen_ai/public/cpp/pref_names.cc b/chrome/browser/screen_ai/pref_names.cc
similarity index 90%
rename from components/services/screen_ai/public/cpp/pref_names.cc
rename to chrome/browser/screen_ai/pref_names.cc
index da4b287..92d2dbe0 100644
--- a/components/services/screen_ai/public/cpp/pref_names.cc
+++ b/chrome/browser/screen_ai/pref_names.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/services/screen_ai/public/cpp/pref_names.h"
+#include "chrome/browser/screen_ai/pref_names.h"
 
 #include "base/files/file_path.h"
 #include "components/prefs/pref_registry_simple.h"
@@ -21,4 +21,4 @@
                              base::Time());
 }
 
-}  // namespace screen_ai
\ No newline at end of file
+}  // namespace screen_ai
diff --git a/components/services/screen_ai/public/cpp/pref_names.h b/chrome/browser/screen_ai/pref_names.h
similarity index 73%
rename from components/services/screen_ai/public/cpp/pref_names.h
rename to chrome/browser/screen_ai/pref_names.h
index 5ab2aa02..3d9ee81 100644
--- a/components/services/screen_ai/public/cpp/pref_names.h
+++ b/chrome/browser/screen_ai/pref_names.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_SERVICES_SCREEN_AI_PUBLIC_CPP_PREF_NAMES_H_
-#define COMPONENTS_SERVICES_SCREEN_AI_PUBLIC_CPP_PREF_NAMES_H_
+#ifndef CHROME_BROWSER_SCREEN_AI_PREF_NAMES_H_
+#define CHROME_BROWSER_SCREEN_AI_PREF_NAMES_H_
 
 class PrefRegistrySimple;
 
@@ -21,4 +21,4 @@
 
 }  // namespace screen_ai
 
-#endif  // COMPONENTS_SERVICES_SCREEN_AI_PUBLIC_CPP_PREF_NAMES_H_
+#endif  // CHROME_BROWSER_SCREEN_AI_PREF_NAMES_H_
diff --git a/components/services/screen_ai/public/cpp/screen_ai_chromeos_installer.cc b/chrome/browser/screen_ai/screen_ai_chromeos_installer.cc
similarity index 91%
rename from components/services/screen_ai/public/cpp/screen_ai_chromeos_installer.cc
rename to chrome/browser/screen_ai/screen_ai_chromeos_installer.cc
index 165953a..feb1db7 100644
--- a/components/services/screen_ai/public/cpp/screen_ai_chromeos_installer.cc
+++ b/chrome/browser/screen_ai/screen_ai_chromeos_installer.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/services/screen_ai/public/cpp/screen_ai_chromeos_installer.h"
+#include "chrome/browser/screen_ai/screen_ai_chromeos_installer.h"
 
 #include "base/functional/bind.h"
 #include "base/logging.h"
 #include "base/task/thread_pool.h"
+#include "chrome/browser/screen_ai/screen_ai_install_state.h"
 #include "chromeos/ash/components/dbus/dlcservice/dlcservice.pb.h"
-#include "components/services/screen_ai/public/cpp/screen_ai_install_state.h"
 #include "components/services/screen_ai/public/cpp/utilities.h"
 
 namespace {
@@ -34,8 +34,9 @@
 }
 
 void OnUninstallCompleted(const std::string& err) {
-  if (err != dlcservice::kErrorNone)
+  if (err != dlcservice::kErrorNone) {
     VLOG(0) << "Unistall failed: " << err;
+  }
 }
 
 void OnInstallProgress(double progress) {
diff --git a/components/services/screen_ai/public/cpp/screen_ai_chromeos_installer.h b/chrome/browser/screen_ai/screen_ai_chromeos_installer.h
similarity index 67%
rename from components/services/screen_ai/public/cpp/screen_ai_chromeos_installer.h
rename to chrome/browser/screen_ai/screen_ai_chromeos_installer.h
index 0b830d6..6c9a799 100644
--- a/components/services/screen_ai/public/cpp/screen_ai_chromeos_installer.h
+++ b/chrome/browser/screen_ai/screen_ai_chromeos_installer.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_SERVICES_SCREEN_AI_PUBLIC_CPP_SCREEN_AI_CHROMEOS_INSTALLER_H_
-#define COMPONENTS_SERVICES_SCREEN_AI_PUBLIC_CPP_SCREEN_AI_CHROMEOS_INSTALLER_H_
+#ifndef CHROME_BROWSER_SCREEN_AI_SCREEN_AI_CHROMEOS_INSTALLER_H_
+#define CHROME_BROWSER_SCREEN_AI_SCREEN_AI_CHROMEOS_INSTALLER_H_
 
 #include "chromeos/ash/components/dbus/dlcservice/dlcservice_client.h"
 
@@ -17,4 +17,4 @@
 
 }  // namespace screen_ai::chrome_os_installer
 
-#endif  // COMPONENTS_SERVICES_SCREEN_AI_PUBLIC_CPP_SCREEN_AI_CHROMEOS_INSTALLER_H_
+#endif  // CHROME_BROWSER_SCREEN_AI_SCREEN_AI_CHROMEOS_INSTALLER_H_
diff --git a/components/services/screen_ai/public/cpp/screen_ai_install_state.cc b/chrome/browser/screen_ai/screen_ai_install_state.cc
similarity index 93%
rename from components/services/screen_ai/public/cpp/screen_ai_install_state.cc
rename to chrome/browser/screen_ai/screen_ai_install_state.cc
index 93e90323..dd96085 100644
--- a/components/services/screen_ai/public/cpp/screen_ai_install_state.cc
+++ b/chrome/browser/screen_ai/screen_ai_install_state.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/services/screen_ai/public/cpp/screen_ai_install_state.h"
+#include "chrome/browser/screen_ai/screen_ai_install_state.h"
 
 #include <memory>
 
@@ -12,8 +12,8 @@
 #include "base/ranges/algorithm.h"
 #include "base/task/thread_pool.h"
 #include "base/time/time.h"
+#include "chrome/browser/screen_ai/pref_names.h"
 #include "components/prefs/pref_service.h"
-#include "components/services/screen_ai/public/cpp/pref_names.h"
 #include "components/services/screen_ai/public/cpp/utilities.h"
 #include "ui/accessibility/accessibility_features.h"
 
@@ -24,7 +24,7 @@
 namespace {
 const int kScreenAICleanUpDelayInDays = 30;
 const char kMinExpectedVersion[] = "114.0";
-}
+}  // namespace
 
 namespace {
 
@@ -76,8 +76,9 @@
 
 // static
 bool ScreenAIInstallState::ShouldUninstall(PrefService* local_state) {
-  if (features::IsScreenAIServiceNeeded())
+  if (features::IsScreenAIServiceNeeded()) {
     return false;
+  }
 
   base::Time deletion_time =
       local_state->GetTime(prefs::kScreenAIScheduledDeletionTimePrefName);
@@ -107,8 +108,9 @@
 void ScreenAIInstallState::RemoveObserver(
     ScreenAIInstallState::Observer* observer) {
   auto pos = base::ranges::find(observers_, observer);
-  if (pos != observers_.end())
+  if (pos != observers_.end()) {
     observers_.erase(pos);
+  }
 }
 
 void ScreenAIInstallState::SetComponentFolder(
@@ -140,8 +142,9 @@
   }
 
   state_ = state;
-  for (ScreenAIInstallState::Observer* observer : observers_)
+  for (ScreenAIInstallState::Observer* observer : observers_) {
     observer->StateChanged(state_);
+  }
 }
 
 void ScreenAIInstallState::DownloadComponent() {
@@ -151,8 +154,9 @@
 
 void ScreenAIInstallState::SetDownloadProgress(double progress) {
   DCHECK_EQ(state_, State::kDownloading);
-  for (ScreenAIInstallState::Observer* observer : observers_)
+  for (ScreenAIInstallState::Observer* observer : observers_) {
     observer->DownloadProgressChanged(progress);
+  }
 }
 
 bool ScreenAIInstallState::IsComponentAvailable() {
diff --git a/components/services/screen_ai/public/cpp/screen_ai_install_state.h b/chrome/browser/screen_ai/screen_ai_install_state.h
similarity index 92%
rename from components/services/screen_ai/public/cpp/screen_ai_install_state.h
rename to chrome/browser/screen_ai/screen_ai_install_state.h
index 2ef4f1c..dcc135a 100644
--- a/components/services/screen_ai/public/cpp/screen_ai_install_state.h
+++ b/chrome/browser/screen_ai/screen_ai_install_state.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_SERVICES_SCREEN_AI_PUBLIC_CPP_SCREEN_AI_INSTALL_STATE_H_
-#define COMPONENTS_SERVICES_SCREEN_AI_PUBLIC_CPP_SCREEN_AI_INSTALL_STATE_H_
+#ifndef CHROME_BROWSER_SCREEN_AI_SCREEN_AI_INSTALL_STATE_H_
+#define CHROME_BROWSER_SCREEN_AI_SCREEN_AI_INSTALL_STATE_H_
 
 #include <vector>
 
@@ -94,4 +94,4 @@
 
 }  // namespace screen_ai
 
-#endif  // COMPONENTS_SERVICES_SCREEN_AI_PUBLIC_CPP_SCREEN_AI_INSTALL_STATE_H_
+#endif  // CHROME_BROWSER_SCREEN_AI_SCREEN_AI_INSTALL_STATE_H_
diff --git a/components/services/screen_ai/public/cpp/screen_ai_install_state_unittest.cc b/chrome/browser/screen_ai/screen_ai_install_state_unittest.cc
similarity index 95%
rename from components/services/screen_ai/public/cpp/screen_ai_install_state_unittest.cc
rename to chrome/browser/screen_ai/screen_ai_install_state_unittest.cc
index bbdf2501..b8b6c73e 100644
--- a/components/services/screen_ai/public/cpp/screen_ai_install_state_unittest.cc
+++ b/chrome/browser/screen_ai/screen_ai_install_state_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/services/screen_ai/public/cpp/screen_ai_install_state.h"
+#include "chrome/browser/screen_ai/screen_ai_install_state.h"
 
 #include "base/files/file_path.h"
 #include "base/scoped_observation.h"
diff --git a/components/services/screen_ai/public/cpp/screen_ai_service_router.cc b/chrome/browser/screen_ai/screen_ai_service_router.cc
similarity index 97%
rename from components/services/screen_ai/public/cpp/screen_ai_service_router.cc
rename to chrome/browser/screen_ai/screen_ai_service_router.cc
index 67d070a..c618b6fc 100644
--- a/components/services/screen_ai/public/cpp/screen_ai_service_router.cc
+++ b/chrome/browser/screen_ai/screen_ai_service_router.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/services/screen_ai/public/cpp/screen_ai_service_router.h"
+#include "chrome/browser/screen_ai/screen_ai_service_router.h"
 
 #include <utility>
 
@@ -11,7 +11,7 @@
 #include "base/functional/bind.h"
 #include "base/location.h"
 #include "base/task/thread_pool.h"
-#include "components/services/screen_ai/public/cpp/screen_ai_install_state.h"
+#include "chrome/browser/screen_ai/screen_ai_install_state.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/service_process_host.h"
 #include "content/public/browser/service_process_host_passkeys.h"
diff --git a/components/services/screen_ai/public/cpp/screen_ai_service_router.h b/chrome/browser/screen_ai/screen_ai_service_router.h
similarity index 88%
rename from components/services/screen_ai/public/cpp/screen_ai_service_router.h
rename to chrome/browser/screen_ai/screen_ai_service_router.h
index 1025b6e..60c718b 100644
--- a/components/services/screen_ai/public/cpp/screen_ai_service_router.h
+++ b/chrome/browser/screen_ai/screen_ai_service_router.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_SERVICES_SCREEN_AI_PUBLIC_CPP_SCREEN_AI_SERVICE_ROUTER_H_
-#define COMPONENTS_SERVICES_SCREEN_AI_PUBLIC_CPP_SCREEN_AI_SERVICE_ROUTER_H_
+#ifndef CHROME_BROWSER_SCREEN_AI_SCREEN_AI_SERVICE_ROUTER_H_
+#define CHROME_BROWSER_SCREEN_AI_SCREEN_AI_SERVICE_ROUTER_H_
 
 #include "base/memory/weak_ptr.h"
 #include "components/keyed_service/core/keyed_service.h"
@@ -57,4 +57,4 @@
 
 }  // namespace screen_ai
 
-#endif  // COMPONENTS_SERVICES_SCREEN_AI_PUBLIC_CPP_SCREEN_AI_SERVICE_ROUTER_H_
+#endif  // CHROME_BROWSER_SCREEN_AI_SCREEN_AI_SERVICE_ROUTER_H_
diff --git a/components/services/screen_ai/public/cpp/screen_ai_service_router_factory.cc b/chrome/browser/screen_ai/screen_ai_service_router_factory.cc
similarity index 89%
rename from components/services/screen_ai/public/cpp/screen_ai_service_router_factory.cc
rename to chrome/browser/screen_ai/screen_ai_service_router_factory.cc
index b806fef0..25dfeee05 100644
--- a/components/services/screen_ai/public/cpp/screen_ai_service_router_factory.cc
+++ b/chrome/browser/screen_ai/screen_ai_service_router_factory.cc
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/services/screen_ai/public/cpp/screen_ai_service_router_factory.h"
+#include "chrome/browser/screen_ai/screen_ai_service_router_factory.h"
 
+#include "chrome/browser/screen_ai/screen_ai_service_router.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "components/services/screen_ai/public/cpp/screen_ai_service_router.h"
 #include "content/public/browser/browser_context.h"
 
 namespace screen_ai {
diff --git a/components/services/screen_ai/public/cpp/screen_ai_service_router_factory.h b/chrome/browser/screen_ai/screen_ai_service_router_factory.h
similarity index 81%
rename from components/services/screen_ai/public/cpp/screen_ai_service_router_factory.h
rename to chrome/browser/screen_ai/screen_ai_service_router_factory.h
index edfc32665..84a1699 100644
--- a/components/services/screen_ai/public/cpp/screen_ai_service_router_factory.h
+++ b/chrome/browser/screen_ai/screen_ai_service_router_factory.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_SERVICES_SCREEN_AI_PUBLIC_CPP_SCREEN_AI_SERVICE_ROUTER_FACTORY_H_
-#define COMPONENTS_SERVICES_SCREEN_AI_PUBLIC_CPP_SCREEN_AI_SERVICE_ROUTER_FACTORY_H_
+#ifndef CHROME_BROWSER_SCREEN_AI_SCREEN_AI_SERVICE_ROUTER_FACTORY_H_
+#define CHROME_BROWSER_SCREEN_AI_SCREEN_AI_SERVICE_ROUTER_FACTORY_H_
 
 #include "base/no_destructor.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
@@ -41,4 +41,4 @@
 
 }  // namespace screen_ai
 
-#endif  // COMPONENTS_SERVICES_SCREEN_AI_PUBLIC_CPP_SCREEN_AI_SERVICE_ROUTER_FACTORY_H_
+#endif  // CHROME_BROWSER_SCREEN_AI_SCREEN_AI_SERVICE_ROUTER_FACTORY_H_
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 62a378f..8e0ef2e 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -5814,8 +5814,8 @@
 
     if (enable_screen_ai_service) {
       deps += [
-        "//components/services/screen_ai/public/cpp:screen_ai_install_state",
-        "//components/services/screen_ai/public/cpp:screen_ai_service_router_factory",
+        "//chrome/browser/screen_ai:screen_ai_install_state",
+        "//chrome/browser/screen_ai:screen_ai_service_router_factory",
       ]
     }
   }
diff --git a/chrome/browser/ui/managed_ui.cc b/chrome/browser/ui/managed_ui.cc
index fb213d6..f97201a 100644
--- a/chrome/browser/ui/managed_ui.cc
+++ b/chrome/browser/ui/managed_ui.cc
@@ -42,6 +42,12 @@
 #include "components/policy/core/common/policy_loader_lacros.h"
 #endif
 
+#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
+#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
+#include "components/supervised_user/core/browser/supervised_user_service.h"
+#include "components/supervised_user/core/common/features.h"
+#endif
+
 namespace chrome {
 
 namespace {
@@ -73,6 +79,32 @@
   return domain;
 }
 
+bool ShouldDisplayManagedByParentUi(Profile* profile) {
+#if !BUILDFLAG(ENABLE_SUPERVISED_USERS) || BUILDFLAG(IS_CHROMEOS)
+  // Don't display the managed by parent UI:
+  // * on unsupervised platforms
+  // * on ChromeOS, because similar UI is displayed at the OS level.
+  return false;
+#else
+
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
+  // The EnableManagedByParentUiOnDesktop flag depends on
+  // EnableSupervisionOnDesktopAndIOS.
+  CHECK(
+      base::FeatureList::IsEnabled(
+          supervised_user::kEnableSupervisionOnDesktopAndIOS) ||
+      !base::FeatureList::IsEnabled(supervised_user::kEnableManagedByParentUi));
+#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
+
+  const auto* const supervised_user_service =
+      SupervisedUserServiceFactory::GetForProfile(profile);
+  return supervised_user_service &&
+         supervised_user_service->IsSubjectToParentalControls() &&
+         base::FeatureList::IsEnabled(
+             supervised_user::kEnableManagedByParentUi);
+#endif  // !BUILDFLAG(ENABLE_SUPERVISED_USERS) || BUILDFLAG(IS_CHROMEOS)
+}
+
 }  // namespace
 
 bool ShouldDisplayManagedUi(Profile* profile) {
@@ -88,26 +120,33 @@
     return false;
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
 
-  return enterprise_util::IsBrowserManaged(profile);
+  return enterprise_util::IsBrowserManaged(profile) ||
+         ShouldDisplayManagedByParentUi(profile);
 }
 
 #if !BUILDFLAG(IS_ANDROID)
 std::u16string GetManagedUiMenuItemLabel(Profile* profile) {
+  CHECK(ShouldDisplayManagedUi(profile));
   absl::optional<std::string> manager = GetAccountManagerIdentity(profile);
   if (!manager &&
       base::FeatureList::IsEnabled(features::kFlexOrgManagementDisclosure)) {
     manager = GetDeviceManagerIdentity();
   }
 
-  int string_id = IDS_MANAGED;
-  std::vector<std::u16string> replacements;
+  if (enterprise_util::IsBrowserManaged(profile)) {
+    int string_id = IDS_MANAGED;
+    std::vector<std::u16string> replacements;
 
-  if (manager && !manager->empty()) {
-    string_id = IDS_MANAGED_BY;
-    replacements.push_back(base::UTF8ToUTF16(*manager));
+    if (manager && !manager->empty()) {
+      string_id = IDS_MANAGED_BY;
+      replacements.push_back(base::UTF8ToUTF16(*manager));
+    }
+
+    return l10n_util::GetStringFUTF16(string_id, replacements, nullptr);
   }
 
-  return l10n_util::GetStringFUTF16(string_id, replacements, nullptr);
+  CHECK(ShouldDisplayManagedByParentUi(profile));
+  return l10n_util::GetStringUTF16(IDS_MANAGED_BY_PARENT);
 }
 
 std::u16string GetManagedUiWebUILabel(Profile* profile) {
@@ -117,15 +156,29 @@
     manager = GetDeviceManagerIdentity();
   }
 
-  int string_id = IDS_MANAGED_WITH_HYPERLINK;
-  std::vector<std::u16string> replacements;
-  replacements.push_back(base::UTF8ToUTF16(chrome::kChromeUIManagementURL));
-  if (manager && !manager->empty()) {
-    string_id = IDS_MANAGED_BY_WITH_HYPERLINK;
-    replacements.push_back(base::UTF8ToUTF16(*manager));
+  if (enterprise_util::IsBrowserManaged(profile)) {
+    int string_id = IDS_MANAGED_WITH_HYPERLINK;
+    std::vector<std::u16string> replacements = {
+        base::UTF8ToUTF16(chrome::kChromeUIManagementURL)};
+    if (manager && !manager->empty()) {
+      string_id = IDS_MANAGED_BY_WITH_HYPERLINK;
+      replacements.push_back(base::UTF8ToUTF16(*manager));
+    }
+
+    return l10n_util::GetStringFUTF16(string_id, replacements, nullptr);
   }
 
-  return l10n_util::GetStringFUTF16(string_id, replacements, nullptr);
+#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
+  if (ShouldDisplayManagedByParentUi(profile)) {
+    std::vector<std::u16string> replacements = {base::UTF8ToUTF16(
+        supervised_user::kManagedByParentUiMoreInfoUrl.Get())};
+    return l10n_util::GetStringFUTF16(IDS_MANAGED_BY_PARENT_WITH_HYPERLINK,
+                                      replacements, nullptr);
+  }
+#endif
+
+  // This method can be called even if we shouldn't display the managed UI.
+  return std::u16string();
 }
 #endif  // !BUILDFLAG(IS_ANDROID)
 
diff --git a/chrome/browser/ui/managed_ui.h b/chrome/browser/ui/managed_ui.h
index 1f05893..dc712561 100644
--- a/chrome/browser/ui/managed_ui.h
+++ b/chrome/browser/ui/managed_ui.h
@@ -15,7 +15,7 @@
 
 namespace chrome {
 
-// Returns true if a 'Managed by your organization' message should appear in
+// Returns true if a 'Managed by <...>' message should appear in
 // Chrome's App Menu, and on the following chrome:// pages:
 // - chrome://bookmarks
 // - chrome://downloads
@@ -23,16 +23,23 @@
 // - chrome://history
 // - chrome://settings
 //
+// This applies to all forms of management (eg. both Enterprise and Parental
+// controls), a suitable string will be returned by the methods below.
+//
 // N.B.: This is independent of Chrome OS's system tray message for enterprise
 // users.
 bool ShouldDisplayManagedUi(Profile* profile);
 
 #if !BUILDFLAG(IS_ANDROID)
 // The label for the App Menu item for Managed UI.
+//
+// Must only be called if ShouldDisplayManagedUi(profile) is true.
 std::u16string GetManagedUiMenuItemLabel(Profile* profile);
 
 // The label for the WebUI footnote for Managed UI indicating that the browser
 // is managed. These strings contain HTML for an <a> element.
+//
+// Returns an empty string if ShouldDisplayManagedUi(profile) is false.
 std::u16string GetManagedUiWebUILabel(Profile* profile);
 #endif  // !BUILDFLAG(IS_ANDROID)
 
diff --git a/chrome/browser/ui/managed_ui_browsertest.cc b/chrome/browser/ui/managed_ui_browsertest.cc
index 9193b2995..9240e59 100644
--- a/chrome/browser/ui/managed_ui_browsertest.cc
+++ b/chrome/browser/ui/managed_ui_browsertest.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/managed_ui.h"
 
 #include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/values.h"
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/enterprise/browser_management/management_service_factory.h"
@@ -13,6 +14,7 @@
 #include "chrome/browser/profiles/profile_attributes_storage.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/managed_ui.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
@@ -20,6 +22,7 @@
 #include "components/policy/core/common/management/management_service.h"
 #include "components/policy/core/common/management/scoped_management_service_override_for_testing.h"
 #include "components/policy/core/common/mock_configuration_policy_provider.h"
+#include "components/supervised_user/core/common/features.h"
 #include "content/public/test/browser_test.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
@@ -31,9 +34,23 @@
 #include "components/policy/core/common/policy_loader_lacros.h"
 #endif
 
-class ManagedUiTest : public InProcessBrowserTest {
+class ManagedUiTest : public InProcessBrowserTest,
+                      public testing::WithParamInterface<bool> {
  public:
-  ManagedUiTest() = default;
+  ManagedUiTest() {
+    const std::vector<base::test::FeatureRef> features_to_toggle = {
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
+      supervised_user::kEnableSupervisionOnDesktopAndIOS,
+#endif
+      supervised_user::kEnableManagedByParentUi
+    };
+
+    if (IsManagedUiEnabledForSupervisedUsers()) {
+      scoped_feature_list_.InitWithFeatures(features_to_toggle, {});
+    } else {
+      scoped_feature_list_.InitWithFeatures({}, features_to_toggle);
+    }
+  }
 
   ManagedUiTest(const ManagedUiTest&) = delete;
   ManagedUiTest& operator=(const ManagedUiTest&) = delete;
@@ -49,20 +66,46 @@
 
   policy::MockConfigurationPolicyProvider* provider() { return &provider_; }
 
+  void AddEnterpriseManagedPolicies() {
+    policy::PolicyMap policy_map;
+    policy_map.Set("test-policy", policy::POLICY_LEVEL_MANDATORY,
+                   policy::POLICY_SCOPE_MACHINE, policy::POLICY_SOURCE_PLATFORM,
+                   base::Value("hello world"), nullptr);
+    provider()->UpdateChromePolicy(policy_map);
+  }
+
+  // Returns whether this parameterised test variant enables the behaviour to
+  // enable the management UI for supervised users.
+  bool IsManagedUiEnabledForSupervisedUsers() const { return GetParam(); }
+
+  // Returns whether we expect the management UI to actually be displayed for
+  // supervised users in this test (this depends on both
+  // IsManagedUiEnabledForSupervisedUsers() and also the platform under test).
+  bool ExpectManagedUiForSupervisedUsers() const {
+#if BUILDFLAG(IS_CHROMEOS)
+    return false;
+#else
+    return IsManagedUiEnabledForSupervisedUsers();
+#endif
+  }
+
  private:
   testing::NiceMock<policy::MockConfigurationPolicyProvider> provider_;
+  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
-IN_PROC_BROWSER_TEST_F(ManagedUiTest, ShouldDisplayManagedUiNoPolicies) {
+INSTANTIATE_TEST_SUITE_P(ManagedUiTest, ManagedUiTest, testing::Bool());
+
+IN_PROC_BROWSER_TEST_P(
+    ManagedUiTest,
+    ShouldDisplayManagedUiNoPoliciesNotSupervisedReturnsFalse) {
   EXPECT_FALSE(chrome::ShouldDisplayManagedUi(browser()->profile()));
 }
 
-IN_PROC_BROWSER_TEST_F(ManagedUiTest, ShouldDisplayManagedUiOnDesktop) {
-  policy::PolicyMap policy_map;
-  policy_map.Set("test-policy", policy::POLICY_LEVEL_MANDATORY,
-                 policy::POLICY_SCOPE_MACHINE, policy::POLICY_SOURCE_PLATFORM,
-                 base::Value("hello world"), nullptr);
-  provider()->UpdateChromePolicy(policy_map);
+IN_PROC_BROWSER_TEST_P(
+    ManagedUiTest,
+    ShouldDisplayManagedUiWithPoliciesNotSupervisedReturnsTrueOnDesktop) {
+  AddEnterpriseManagedPolicies();
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   EXPECT_FALSE(chrome::ShouldDisplayManagedUi(browser()->profile()));
@@ -71,18 +114,24 @@
 #endif
 }
 
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
-IN_PROC_BROWSER_TEST_F(ManagedUiTest, DoNotDisplayManagedUiForAChild) {
+IN_PROC_BROWSER_TEST_P(ManagedUiTest, ShouldDisplayManagedUiSupervised) {
   TestingProfile::Builder builder;
   builder.SetIsSupervisedProfile();
   std::unique_ptr<TestingProfile> profile = builder.Build();
 
-  EXPECT_FALSE(chrome::ShouldDisplayManagedUi(profile.get()));
+  EXPECT_EQ(ExpectManagedUiForSupervisedUsers(),
+            chrome::ShouldDisplayManagedUi(profile.get()));
 }
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
 
-IN_PROC_BROWSER_TEST_F(ManagedUiTest, GetManagedUiMenuItemLabel) {
+// TODO(crbug.com/1447988): update the tests below to not depend on the exact
+// value of the user-visible string (to make string updates simpler).
+
+// On ChromeOS we don't display the management UI for enterprise or supervised
+// users.
+#if !BUILDFLAG(IS_CHROMEOS)
+IN_PROC_BROWSER_TEST_P(ManagedUiTest, GetManagedUiMenuItemLabelEnterprise) {
   // Simulate a managed profile.
+  AddEnterpriseManagedPolicies();
   policy::ScopedManagementServiceOverrideForTesting browser_management(
       policy::ManagementServiceFactory::GetForProfile(browser()->profile()),
       policy::EnterpriseManagementAuthority::CLOUD);
@@ -103,16 +152,42 @@
   ASSERT_TRUE(entry);
   entry->SetHostedDomain("hosteddomain.com");
 
+  // Simulate a supervised profile.
+  TestingProfile::Builder builder_supervised;
+  builder_supervised.SetIsSupervisedProfile();
+  std::unique_ptr<TestingProfile> profile_supervised =
+      builder_supervised.Build();
+
   EXPECT_EQ(u"Managed by your organization",
             chrome::GetManagedUiMenuItemLabel(profile.get()));
   EXPECT_EQ(u"Managed by example.com",
             chrome::GetManagedUiMenuItemLabel(profile_with_domain.get()));
   EXPECT_EQ(u"Managed by hosteddomain.com",
             chrome::GetManagedUiMenuItemLabel(profile_with_hosted_domain));
+  // Enterprise management takes precedence over supervision in the management
+  // UI.
+  EXPECT_EQ(u"Managed by your organization",
+            chrome::GetManagedUiMenuItemLabel(profile_supervised.get()));
 }
 
-IN_PROC_BROWSER_TEST_F(ManagedUiTest, GetManagedUiWebUILabel) {
+IN_PROC_BROWSER_TEST_P(ManagedUiTest, GetManagedUiMenuItemLabelSupervised) {
+  if (!ExpectManagedUiForSupervisedUsers()) {
+    return;
+  }
+
+  // Simulate a supervised profile.
+  TestingProfile::Builder builder;
+  builder.SetIsSupervisedProfile();
+  std::unique_ptr<TestingProfile> profile = builder.Build();
+
+  EXPECT_EQ(u"Managed by your parent",
+            chrome::GetManagedUiMenuItemLabel(profile.get()));
+}
+#endif  // !BUILDFLAG(IS_CHROMEOS)
+
+IN_PROC_BROWSER_TEST_P(ManagedUiTest, GetManagedUiWebUILabelEnterprise) {
   // Simulate a managed profile.
+  AddEnterpriseManagedPolicies();
   policy::ScopedManagementServiceOverrideForTesting browser_management(
       policy::ManagementServiceFactory::GetForProfile(browser()->profile()),
       policy::EnterpriseManagementAuthority::CLOUD);
@@ -133,10 +208,27 @@
   ASSERT_TRUE(entry);
   entry->SetHostedDomain("hosteddomain.com");
 
+  // Simulate a supervised profile.
+  TestingProfile::Builder builder_supervised;
+  builder_supervised.SetIsSupervisedProfile();
+  std::unique_ptr<TestingProfile> profile_supervised =
+      builder_supervised.Build();
+
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  EXPECT_TRUE(chrome::GetManagedUiWebUILabel(profile.get()).empty());
+  EXPECT_TRUE(chrome::GetManagedUiWebUILabel(profile_supervised.get()).empty());
+#else
   EXPECT_EQ(
       u"Your <a href=\"chrome://management\">browser is managed</a> by your "
       u"organization",
       chrome::GetManagedUiWebUILabel(profile.get()));
+  // Enterprise management takes precedence over supervision in the management
+  // UI.
+  EXPECT_EQ(
+      u"Your <a href=\"chrome://management\">browser is managed</a> by your "
+      u"organization",
+      chrome::GetManagedUiWebUILabel(profile_supervised.get()));
+#endif
   EXPECT_EQ(
       u"Your <a href=\"chrome://management\">browser is managed</a> by "
       u"example.com",
@@ -147,6 +239,22 @@
       chrome::GetManagedUiWebUILabel(profile_with_hosted_domain));
 }
 
+IN_PROC_BROWSER_TEST_P(ManagedUiTest, GetManagedUiWebUILabelSupervised) {
+  // Simulate a supervised profile.
+  TestingProfile::Builder builder;
+  builder.SetIsSupervisedProfile();
+  std::unique_ptr<TestingProfile> profile = builder.Build();
+
+  if (ExpectManagedUiForSupervisedUsers()) {
+    EXPECT_EQ(
+        u"Your <a href=\"https://familylink.google.com/setting/resource/94\">"
+        u"browser is managed</a> by your parent",
+        chrome::GetManagedUiWebUILabel(profile.get()));
+  } else {
+    EXPECT_TRUE(chrome::GetManagedUiWebUILabel(profile.get()).empty());
+  }
+}
+
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 using ManagedUiTestCros = policy::DevicePolicyCrosBrowserTest;
 IN_PROC_BROWSER_TEST_F(ManagedUiTestCros, GetManagedUiWebUILabel) {
@@ -163,11 +271,11 @@
 #endif
 
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
-IN_PROC_BROWSER_TEST_F(ManagedUiTest, GetSessionManagerIdentity_Unmanaged) {
+IN_PROC_BROWSER_TEST_P(ManagedUiTest, GetSessionManagerIdentity_Unmanaged) {
   EXPECT_EQ(absl::nullopt, chrome::GetSessionManagerIdentity());
 }
 
-IN_PROC_BROWSER_TEST_F(ManagedUiTest, GetSessionManagerIdentity_Managed) {
+IN_PROC_BROWSER_TEST_P(ManagedUiTest, GetSessionManagerIdentity_Managed) {
   enterprise_management::PolicyData profile_policy_data;
   profile_policy_data.add_user_affiliation_ids("affiliation-id-1");
   profile_policy_data.set_managed_by("domain.com");
diff --git a/chrome/browser/ui/views/autofill/payments/dialog_view_ids.h b/chrome/browser/ui/views/autofill/payments/dialog_view_ids.h
index 0a4e960..b0c5af7 100644
--- a/chrome/browser/ui/views/autofill/payments/dialog_view_ids.h
+++ b/chrome/browser/ui/views/autofill/payments/dialog_view_ids.h
@@ -22,6 +22,8 @@
                              // save bubble
   FOOTNOTE_VIEW,             // The footnote view of either an upload
                              // save bubble or a manage cards view.
+  LEGAL_MESSAGE_VIEW,        // The view containing terms of service and
+                             // the privacy notice
   SIGN_IN_PROMO_VIEW,        // Contains the sign-in promo view
   MANAGE_CARDS_VIEW,         // The manage cards view
   MANAGE_IBANS_VIEW,         // The manage IBANs view
diff --git a/chrome/browser/ui/views/autofill/payments/payments_view_util.cc b/chrome/browser/ui/views/autofill/payments/payments_view_util.cc
index 37ac4e4..ce9ca580 100644
--- a/chrome/browser/ui/views/autofill/payments/payments_view_util.cc
+++ b/chrome/browser/ui/views/autofill/payments/payments_view_util.cc
@@ -35,6 +35,7 @@
 #include "ui/views/controls/styled_label.h"
 #include "ui/views/controls/throbber.h"
 #include "ui/views/layout/box_layout.h"
+#include "ui/views/layout/box_layout_view.h"
 #include "ui/views/layout/layout_provider.h"
 #include "ui/views/style/typography.h"
 #include "ui/views/widget/widget.h"
@@ -70,6 +71,10 @@
         // a rectangular area at the top. CreateTiledImage() will correctly clip
         // it whereas setting the icon size would rescale it incorrectly and
         // keep the bottom empty portion.
+        //
+        // TODO(crbug.com/1447908): clipping icon with the default (40x40) size
+        // into a 40x16 painting area instead of using CreateTiledImage to avoid
+        // asymmetric rescale.
         image = gfx::ImageSkiaOperations::CreateTiledImage(
             gfx::CreateVectorIcon(
                 vector_icons::kGooglePayLogoIcon,
@@ -100,6 +105,8 @@
 
 }  // namespace
 
+// TODO(crbug.com/1447913): Replace TableLayout with BoxLayout or FlexLayout,
+// since this view is not tabular data.
 TitleWithIconAndSeparatorView::TitleWithIconAndSeparatorView(
     const std::u16string& window_title,
     Icon icon_to_show) {
@@ -120,16 +127,15 @@
   separator->SetPreferredLength(kSeparatorHeight);
   auto* separator_ptr = AddChildView(std::move(separator));
 
-  auto title_label = std::make_unique<views::Label>(
-      window_title, views::style::CONTEXT_DIALOG_TITLE);
+  auto* title_label = AddChildView(std::make_unique<views::Label>(
+      window_title, views::style::CONTEXT_DIALOG_TITLE));
   title_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
   title_label->SetMultiLine(true);
-  auto* title_label_ptr = AddChildView(std::move(title_label));
 
   // Add vertical padding to the icon and the separator so they are aligned with
   // the first line of title label. This needs to be done after we create the
   // title label, so that we can use its preferred size.
-  const int title_label_height = title_label_ptr->GetPreferredSize().height();
+  const int title_label_height = title_label->GetPreferredSize().height();
   icon_view_ptr->SetBorder(views::CreateEmptyBorder(
       gfx::Insets::TLBR((title_label_height - kIconHeight) / 2, 0, 0, 0)));
   // TODO(crbug.com/873140): DISTANCE_RELATED_BUTTON_HORIZONTAL isn't the right
@@ -143,18 +149,61 @@
       0, separator_horizontal_padding)));
 }
 
-TitleWithIconAndSeparatorView::~TitleWithIconAndSeparatorView() {}
+TitleWithIconAndSeparatorView::~TitleWithIconAndSeparatorView() = default;
 
 gfx::Size TitleWithIconAndSeparatorView::GetMinimumSize() const {
-  // View::GetMinimum() defaults to GridLayout::GetPreferredSize(), but that
-  // gives a larger frame width, so the dialog will become wider than it should.
+  // Default View::GetMinimumSize() will make dialogs wider than it should.
   // To avoid that, just return 0x0.
+  //
+  // TODO(crbug.com/1447933): Replace GetMinimumSize() may generate views
+  // narrower than expected. The ideal solution should be limit the width of
+  // multi-line text views.
   return gfx::Size(0, 0);
 }
 
 BEGIN_METADATA(TitleWithIconAndSeparatorView, views::View)
 END_METADATA
 
+TitleWithIconAfterLabelView::TitleWithIconAfterLabelView(
+    const std::u16string& window_title,
+    TitleWithIconAndSeparatorView::Icon icon_to_show) {
+  SetBetweenChildSpacing(ChromeLayoutProvider::Get()->GetDistanceMetric(
+      views::DISTANCE_RELATED_LABEL_HORIZONTAL));
+  // Align to the top instead of center in vertical direction so that we
+  // can adjust the icon location to align with the first line of title label
+  SetCrossAxisAlignment(views::BoxLayout::CrossAxisAlignment::kStart);
+
+  auto* title_label = AddChildView(std::make_unique<views::Label>(
+      window_title, views::style::CONTEXT_DIALOG_TITLE));
+  title_label->SetHorizontalAlignment(gfx::ALIGN_TO_HEAD);
+  title_label->SetMultiLine(true);
+  auto* icon_view = AddChildView(std::make_unique<IconView>(icon_to_show));
+
+  // Center the icon against the first line of the title label. This needs to be
+  // done after we create the title label, so that we can use its preferred
+  // size.
+  const int title_label_height = title_label->GetPreferredSize().height();
+  icon_view->SetBorder(views::CreateEmptyBorder(
+      gfx::Insets::TLBR((title_label_height - kIconHeight) / 2, 0, 0, 0)));
+
+  // Flex |title_label| to fill up remaining space and tail align the GPay icon.
+  SetFlexForView(title_label, 1);
+}
+
+TitleWithIconAfterLabelView::~TitleWithIconAfterLabelView() = default;
+
+// TODO(crbug.com/1447933): Replace GetMinimumSize() may generate views
+// narrower than expected. The ideal solution should be limit the width of
+// multi-line text views.
+gfx::Size TitleWithIconAfterLabelView::GetMinimumSize() const {
+  // Default View::GetMinimumSize() will make dialogs wider than it should.
+  // To avoid that, just return 0x0.
+  return gfx::Size(0, 0);
+}
+
+BEGIN_METADATA(TitleWithIconAfterLabelView, views::View)
+END_METADATA
+
 LegalMessageView::LegalMessageView(
     const LegalMessageLines& legal_message_lines,
     absl::optional<std::u16string> optional_user_email,
diff --git a/chrome/browser/ui/views/autofill/payments/payments_view_util.h b/chrome/browser/ui/views/autofill/payments/payments_view_util.h
index 1c459d0..1408771 100644
--- a/chrome/browser/ui/views/autofill/payments/payments_view_util.h
+++ b/chrome/browser/ui/views/autofill/payments/payments_view_util.h
@@ -33,6 +33,9 @@
  public:
   METADATA_HEADER(TitleWithIconAndSeparatorView);
 
+  // TODO(crbug.com/1433075): This enum is also used by
+  // TitleWithIconAfterLabelView, and should be refactored to be outside of
+  // TitleWithIconAndSeparatorView.
   enum class Icon {
     // Google Pay icon. The "Pay" portion is recolored for light/dark mode.
     GOOGLE_PAY,
@@ -49,6 +52,25 @@
   gfx::Size GetMinimumSize() const override;
 };
 
+// Defines a title view with a label and an icon, to be used by dialogs
+// that need to present the Google or Google Pay logo and custom
+// horizontal padding.
+//
+// Unlike TitleWithIconAndSeparatorView, this view has no separator and places
+// the icon after the title rather than before.
+class TitleWithIconAfterLabelView : public views::BoxLayoutView {
+ public:
+  METADATA_HEADER(TitleWithIconAfterLabelView);
+
+  TitleWithIconAfterLabelView(const std::u16string& window_title,
+                              TitleWithIconAndSeparatorView::Icon icon_to_show);
+  ~TitleWithIconAfterLabelView() override;
+
+ private:
+  // views::View:
+  gfx::Size GetMinimumSize() const override;
+};
+
 // Defines a view with legal message. This class handles the legal message
 // parsing and the links clicking events.
 class LegalMessageView : public views::BoxLayoutView {
diff --git a/chrome/browser/ui/views/autofill/payments/save_card_bubble_views.cc b/chrome/browser/ui/views/autofill/payments/save_card_bubble_views.cc
index 3a79f4f5..455cb549 100644
--- a/chrome/browser/ui/views/autofill/payments/save_card_bubble_views.cc
+++ b/chrome/browser/ui/views/autofill/payments/save_card_bubble_views.cc
@@ -15,6 +15,7 @@
 #include "components/autofill/core/browser/metrics/autofill_metrics.h"
 #include "components/autofill/core/browser/payments/legal_message_line.h"
 #include "components/autofill/core/common/autofill_features.h"
+#include "components/autofill/core/common/autofill_payments_features.h"
 #include "components/strings/grit/components_strings.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -90,9 +91,16 @@
   if (!controller_->IsUploadSave())
     return;
 
-  GetBubbleFrameView()->SetTitleView(
-      std::make_unique<TitleWithIconAndSeparatorView>(
-          GetWindowTitle(), TitleWithIconAndSeparatorView::Icon::GOOGLE_PAY));
+  if (base::FeatureList::IsEnabled(
+          features::kAutofillMoveLegalTermsAndIconForNewCardEnrollment)) {
+    GetBubbleFrameView()->SetTitleView(
+        std::make_unique<TitleWithIconAfterLabelView>(
+            GetWindowTitle(), TitleWithIconAndSeparatorView::Icon::GOOGLE_PAY));
+  } else {
+    GetBubbleFrameView()->SetTitleView(
+        std::make_unique<TitleWithIconAndSeparatorView>(
+            GetWindowTitle(), TitleWithIconAndSeparatorView::Icon::GOOGLE_PAY));
+  }
 }
 
 std::u16string SaveCardBubbleViews::GetWindowTitle() const {
@@ -152,26 +160,15 @@
           .GetImageNamed(CreditCard::IconResourceId(card.network()))
           .AsImageSkia());
   card_network_icon->SetTooltipText(card.NetworkForDisplay());
+  auto* card_identifier_view =
+      description_view->AddChildView(GetCardIdentifierView());
 
-  auto* const card_identifier_label =
-      description_view->AddChildView(std::make_unique<views::Label>(
-          GetCardIdentifierString(), views::style::CONTEXT_DIALOG_BODY_TEXT,
-          views::style::STYLE_PRIMARY));
-  card_identifier_label->SetMultiLine(true);
-  card_identifier_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-
-  // Flex |card_identifier_label| to fill up remaining space and tail align the
-  // expiry date.
-  description_view->SetFlexForView(card_identifier_label, 1);
-
-  if (!card.IsExpired(base::Time::Now())) {
-    auto* expiration_date_label =
-        description_view->AddChildView(std::make_unique<views::Label>(
-            card.AbbreviatedExpirationDateForDisplay(false),
-            views::style::CONTEXT_DIALOG_BODY_TEXT,
-            views::style::STYLE_SECONDARY));
-    expiration_date_label->SetID(DialogViewId::EXPIRATION_DATE_LABEL);
+  // Flex |card_identifier_view| to fill up space before the expiry date.
+  if (!base::FeatureList::IsEnabled(
+          features::kAutofillMoveLegalTermsAndIconForNewCardEnrollment)) {
+    description_view->SetFlexForView(card_identifier_view, 1);
   }
+
   return view;
 }
 
@@ -181,6 +178,50 @@
   footnote_view_->SetID(DialogViewId::FOOTNOTE_VIEW);
 }
 
+std::unique_ptr<views::View> SaveCardBubbleViews::GetCardIdentifierView() {
+  // If feature enabled, display the expiration date of this view in a
+  // separate lines. Else, card name, last 4 digit and expiration date
+  // in the same line
+  auto card_identifier_view = std::make_unique<views::BoxLayoutView>();
+  if (base::FeatureList::IsEnabled(
+          features::kAutofillMoveLegalTermsAndIconForNewCardEnrollment)) {
+    card_identifier_view->SetOrientation(
+        views::BoxLayout::Orientation::kVertical);
+    card_identifier_view->SetCrossAxisAlignment(
+        views::BoxLayout::CrossAxisAlignment::kStart);
+  } else {
+    card_identifier_view->SetBetweenChildSpacing(
+        ChromeLayoutProvider::Get()->GetDistanceMetric(
+            views::DISTANCE_RELATED_BUTTON_HORIZONTAL));
+  }
+
+  auto* const card_identifier_label =
+      card_identifier_view->AddChildView(std::make_unique<views::Label>(
+          GetCardIdentifierString(), views::style::CONTEXT_DIALOG_BODY_TEXT,
+          views::style::STYLE_PRIMARY));
+  card_identifier_label->SetMultiLine(true);
+  card_identifier_label->SetHorizontalAlignment(gfx::ALIGN_TO_HEAD);
+
+  if (!base::FeatureList::IsEnabled(
+          features::kAutofillMoveLegalTermsAndIconForNewCardEnrollment)) {
+    // Flex |card_identifier_label| to fill up remaining space and tail align
+    // the expiry date.
+    card_identifier_view->SetFlexForView(card_identifier_label, 1);
+  }
+
+  const CreditCard& card = controller_->GetCard();
+  if (!card.IsExpired(base::Time::Now())) {
+    auto* expiration_date_label =
+        card_identifier_view->AddChildView(std::make_unique<views::Label>(
+            card.AbbreviatedExpirationDateForDisplay(false),
+            views::style::CONTEXT_DIALOG_BODY_TEXT,
+            views::style::STYLE_SECONDARY));
+    expiration_date_label->SetID(DialogViewId::EXPIRATION_DATE_LABEL);
+  }
+
+  return card_identifier_view;
+}
+
 void SaveCardBubbleViews::AssignIdsToDialogButtons() {
   auto* ok_button = GetOkButton();
   if (ok_button)
diff --git a/chrome/browser/ui/views/autofill/payments/save_card_bubble_views.h b/chrome/browser/ui/views/autofill/payments/save_card_bubble_views.h
index b591fe4..02a776a 100644
--- a/chrome/browser/ui/views/autofill/payments/save_card_bubble_views.h
+++ b/chrome/browser/ui/views/autofill/payments/save_card_bubble_views.h
@@ -77,6 +77,8 @@
  private:
   friend class SaveCardBubbleViewsFullFormBrowserTest;
 
+  std::unique_ptr<views::View> GetCardIdentifierView();
+
   raw_ptr<views::View> footnote_view_ = nullptr;
 
   raw_ptr<SaveCardBubbleController> controller_;  // Weak reference.
diff --git a/chrome/browser/ui/views/autofill/payments/save_card_bubble_views_browsertest.cc b/chrome/browser/ui/views/autofill/payments/save_card_bubble_views_browsertest.cc
index f218f1e..6e5624f 100644
--- a/chrome/browser/ui/views/autofill/payments/save_card_bubble_views_browsertest.cc
+++ b/chrome/browser/ui/views/autofill/payments/save_card_bubble_views_browsertest.cc
@@ -138,10 +138,8 @@
 class SaveCardBubbleViewsFullFormBrowserTest
     : public SyncTest,
       public CreditCardSaveManager::ObserverForTest,
-      public SaveCardBubbleControllerImpl::ObserverForTest {
- protected:
-  SaveCardBubbleViewsFullFormBrowserTest() : SyncTest(SINGLE_CLIENT) {}
-
+      public SaveCardBubbleControllerImpl::ObserverForTest,
+      public testing::WithParamInterface<bool> {
  public:
   SaveCardBubbleViewsFullFormBrowserTest(
       const SaveCardBubbleViewsFullFormBrowserTest&) = delete;
@@ -150,6 +148,13 @@
   ~SaveCardBubbleViewsFullFormBrowserTest() override = default;
 
  protected:
+  SaveCardBubbleViewsFullFormBrowserTest() : SyncTest(SINGLE_CLIENT) {
+    if (move_legal_terms_and_icon()) {
+      feature_list_.InitAndEnableFeature(
+          features::kAutofillMoveLegalTermsAndIconForNewCardEnrollment);
+    }
+  }
+
   class TestAutofillManager : public BrowserAutofillManager {
    public:
     TestAutofillManager(ContentAutofillDriver* driver, AutofillClient* client)
@@ -315,8 +320,10 @@
   void VerifyExpirationDateDropdownsAreVisible() {
     EXPECT_TRUE(FindViewInBubbleById(DialogViewId::MAIN_CONTENT_VIEW_UPLOAD)
                     ->GetVisible());
-    EXPECT_TRUE(
-        FindViewInBubbleById(DialogViewId::FOOTNOTE_VIEW)->GetVisible());
+    EXPECT_TRUE(FindViewInBubbleById(move_legal_terms_and_icon()
+                                         ? DialogViewId::LEGAL_MESSAGE_VIEW
+                                         : DialogViewId::FOOTNOTE_VIEW)
+                    ->GetVisible());
     EXPECT_TRUE(
         FindViewInBubbleById(DialogViewId::EXPIRATION_DATE_VIEW)->GetVisible());
     EXPECT_TRUE(FindViewInBubbleById(DialogViewId::EXPIRATION_DATE_DROPBOX_YEAR)
@@ -379,8 +386,10 @@
     ASSERT_TRUE(WaitForObservedEvent());
     EXPECT_TRUE(FindViewInBubbleById(DialogViewId::MAIN_CONTENT_VIEW_UPLOAD)
                     ->GetVisible());
-    EXPECT_TRUE(
-        FindViewInBubbleById(DialogViewId::FOOTNOTE_VIEW)->GetVisible());
+    EXPECT_TRUE(FindViewInBubbleById(move_legal_terms_and_icon()
+                                         ? DialogViewId::LEGAL_MESSAGE_VIEW
+                                         : DialogViewId::FOOTNOTE_VIEW)
+                    ->GetVisible());
   }
 
   void SubmitForm() {
@@ -743,6 +752,8 @@
     return &test_url_loader_factory_;
   }
 
+  bool move_legal_terms_and_icon() const { return GetParam(); }
+
   raw_ptr<CreditCardSaveManager, DanglingUntriaged> credit_card_save_manager_ =
       nullptr;
 
@@ -751,11 +762,16 @@
   scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
   TestAutofillManagerInjector<TestAutofillManager> autofill_manager_injector_;
   std::unique_ptr<device::ScopedGeolocationOverrider> geolocation_overrider_;
+  base::test::ScopedFeatureList feature_list_;
 };
 
+INSTANTIATE_TEST_SUITE_P(All,
+                         SaveCardBubbleViewsFullFormBrowserTest,
+                         ::testing::Bool());
+
 // Tests the local save bubble. Ensures that clicking the [No thanks] button
 // successfully causes the bubble to go away.
-IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest,
+IN_PROC_BROWSER_TEST_P(SaveCardBubbleViewsFullFormBrowserTest,
                        Local_ClickingNoThanksClosesBubble) {
   FillForm();
   SubmitFormAndWaitForCardLocalSaveBubble();
@@ -776,14 +792,25 @@
     : public SaveCardBubbleViewsFullFormBrowserTest {
  public:
   SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream() {
-    feature_list_.InitAndEnableFeature(features::kAutofillUpstream);
+    std::vector<base::test::FeatureRef> enabled_features = {
+        features::kAutofillUpstream};
+    if (move_legal_terms_and_icon()) {
+      enabled_features.push_back(
+          features::kAutofillMoveLegalTermsAndIconForNewCardEnrollment);
+    }
+    feature_list_.InitWithFeatures(enabled_features, {});
   }
 
  private:
   base::test::ScopedFeatureList feature_list_;
 };
 
-IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest,
+INSTANTIATE_TEST_SUITE_P(
+    All,
+    SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
+    ::testing::Bool());
+
+IN_PROC_BROWSER_TEST_P(SaveCardBubbleViewsFullFormBrowserTest,
                        AlertAccessibleEvent) {
   views::test::AXEventCounter counter(views::AXEventManager::Get());
   EXPECT_EQ(0, counter.GetCount(ax::mojom::Event::kAlert));
@@ -797,7 +824,10 @@
 class SaveCardBubbleViewsFullFormBrowserTestSettings
     : public SaveCardBubbleViewsFullFormBrowserTest {
  public:
-  SaveCardBubbleViewsFullFormBrowserTestSettings() = default;
+  SaveCardBubbleViewsFullFormBrowserTestSettings() {
+    feature_list_.InitAndEnableFeature(
+        features::kAutofillMoveLegalTermsAndIconForNewCardEnrollment);
+  }
 
   void SetUpOnMainThread() override {
     SaveCardBubbleViewsFullFormBrowserTest::SetUpOnMainThread();
@@ -832,11 +862,18 @@
     // Click on the redirect button.
     ClickOnDialogViewWithId(DialogViewId::MANAGE_CARDS_BUTTON);
   }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
 };
 
+INSTANTIATE_TEST_SUITE_P(All,
+                         SaveCardBubbleViewsFullFormBrowserTestSettings,
+                         ::testing::Bool());
+
 // Tests the manage cards bubble. Ensures that clicking the [Manage cards]
 // button redirects properly.
-IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTestSettings,
+IN_PROC_BROWSER_TEST_P(SaveCardBubbleViewsFullFormBrowserTestSettings,
                        Local_ManageCardsButtonRedirects) {
   base::HistogramTester histogram_tester;
   OpenSettingsFromManageCardsPrompt();
@@ -864,7 +901,7 @@
 #define MAYBE_Local_SynchronousCloseAfterAsynchronousClose \
   Local_SynchronousCloseAfterAsynchronousClose
 #endif
-IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest,
+IN_PROC_BROWSER_TEST_P(SaveCardBubbleViewsFullFormBrowserTest,
                        MAYBE_Local_SynchronousCloseAfterAsynchronousClose) {
   FillForm();
   SubmitFormAndWaitForCardLocalSaveBubble();
@@ -892,7 +929,7 @@
 // Tests the upload save bubble. Ensures that clicking the [Save] button
 // successfully causes the bubble to go away and sends an UploadCardRequest RPC
 // to Google Payments.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     // TODO(crbug.com/1447107): Flaky on multiple platforms.
     DISABLED_Upload_ClickingSaveClosesBubble) {
@@ -924,7 +961,13 @@
  protected:
   SaveCardBubbleViewsSyncTransportFullFormBrowserTest() {
     // Add wallet data type to the list of enabled types.
-    feature_list_.InitAndEnableFeature(features::kAutofillUpstream);
+    std::vector<base::test::FeatureRef> enabled_features = {
+        features::kAutofillUpstream};
+    if (move_legal_terms_and_icon()) {
+      enabled_features.push_back(
+          features::kAutofillMoveLegalTermsAndIconForNewCardEnrollment);
+    }
+    feature_list_.InitWithFeatures(enabled_features, {});
   }
 
  public:
@@ -960,10 +1003,14 @@
   base::CallbackListSubscription test_signin_client_subscription_;
 };
 
+INSTANTIATE_TEST_SUITE_P(All,
+                         SaveCardBubbleViewsSyncTransportFullFormBrowserTest,
+                         ::testing::Bool());
+
 // Tests the upload save bubble. Ensures that clicking the [Save] button
 // successfully causes the bubble to go away and sends an UploadCardRequest RPC
 // to Google Payments.
-IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsSyncTransportFullFormBrowserTest,
+IN_PROC_BROWSER_TEST_P(SaveCardBubbleViewsSyncTransportFullFormBrowserTest,
                        Upload_TransportMode_ClickingSaveClosesBubble) {
   SetUpForSyncTransportModeTest();
   FillForm();
@@ -982,7 +1029,7 @@
 
 // Tests the implicit sync state. Ensures that the (i) info icon appears for
 // upload save offers.
-IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsSyncTransportFullFormBrowserTest,
+IN_PROC_BROWSER_TEST_P(SaveCardBubbleViewsSyncTransportFullFormBrowserTest,
                        Upload_TransportMode_InfoTextIconExists) {
   SetUpForSyncTransportModeTest();
   FillForm();
@@ -995,7 +1042,7 @@
 
 // Tests the implicit sync state. Ensures that the (i) info icon does not appear
 // for local save offers.
-IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsSyncTransportFullFormBrowserTest,
+IN_PROC_BROWSER_TEST_P(SaveCardBubbleViewsSyncTransportFullFormBrowserTest,
                        Local_TransportMode_InfoTextIconDoesNotExist) {
   SetUpForSyncTransportModeTest();
   FillForm();
@@ -1019,7 +1066,7 @@
 // Tests the upload save bubble when sync transport for Wallet data is active.
 // Ensures that if cardholder name is explicitly requested, it is prefilled with
 // the name from the user's Google Account.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsSyncTransportFullFormBrowserTest,
     Upload_TransportMode_RequestedCardholderNameTextfieldIsPrefilledWithFocusName) {
   // Signing in (without granting sync consent or explicitly setting up Sync)
@@ -1051,7 +1098,7 @@
 
 // Tests the fully-syncing state. Ensures that the Butter (i) info icon does not
 // appear for fully-syncing users.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     Upload_NotTransportMode_InfoTextIconDoesNotExist) {
   // Start sync.
@@ -1067,7 +1114,7 @@
 
 // Tests the upload save bubble. Ensures that clicking the [No thanks] button
 // successfully causes the bubble to go away.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     Upload_ClickingNoThanksClosesBubble) {
   // Start sync.
@@ -1090,7 +1137,7 @@
 
 // Tests the upload save bubble. Ensures that clicking the top-right [X] close
 // button successfully causes the bubble to go away.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     Upload_ClickingCloseClosesBubble) {
   // Start sync.
@@ -1105,7 +1152,7 @@
 
 // Tests the upload save bubble. Ensures that the bubble does not surface the
 // cardholder name textfield if it is not needed.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     Upload_ShouldNotRequestCardholderNameInHappyPath) {
   // Start sync.
@@ -1120,7 +1167,7 @@
 
 // Tests the upload save bubble. Ensures that the bubble surfaces a textfield
 // requesting cardholder name if cardholder name is missing.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     Upload_SubmittingFormWithMissingNamesRequestsCardholderNameIfExpOn) {
   // Start sync.
@@ -1145,7 +1192,7 @@
 // To make test work one need to inject an existing address into the
 // PersonalDataManager. Alternatively, the import logic should try to get an
 // address candidate from the form even though no address was imported yet.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     DISABLED_Upload_SubmittingFormWithConflictingNamesRequestsCardholderNameIfExpOn) {
   // Start sync.
@@ -1164,7 +1211,7 @@
 
 // Tests the upload save bubble. Ensures that if the cardholder name textfield
 // is empty, the user is not allowed to click [Save] and close the dialog.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     Upload_SaveButtonIsDisabledIfNoCardholderNameAndCardholderNameRequested) {
   // Start sync.
@@ -1194,7 +1241,7 @@
 
 // Tests the upload save bubble. Ensures that if cardholder name is explicitly
 // requested, filling it and clicking [Save] closes the dialog.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     Upload_EnteringCardholderNameAndClickingSaveClosesBubbleIfCardholderNameRequested) {
   // Start sync.
@@ -1227,7 +1274,7 @@
 
 // Tests the upload save bubble. Ensures that if cardholder name is explicitly
 // requested, it is prefilled with the name from the user's Google Account.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     Upload_RequestedCardholderNameTextfieldIsPrefilledWithFocusName) {
   base::HistogramTester histogram_tester;
@@ -1258,7 +1305,7 @@
 // Tests the upload save bubble. Ensures that if cardholder name is explicitly
 // requested but the name on the user's Google Account is unable to be fetched
 // for any reason, the textfield is left blank.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     Upload_RequestedCardholderNameTextfieldIsNotPrefilledWithFocusNameIfMissing) {
   base::HistogramTester histogram_tester;
@@ -1286,7 +1333,7 @@
 // Tests the upload save bubble. Ensures that if cardholder name is explicitly
 // requested and the user accepts the dialog without changing it, the correct
 // metric is logged.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     Upload_CardholderNameRequested_SubmittingPrefilledValueLogsUneditedMetric) {
   // Start sync.
@@ -1312,7 +1359,7 @@
 // Tests the upload save bubble. Ensures that if cardholder name is explicitly
 // requested and the user accepts the dialog after changing it, the correct
 // metric is logged.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     Upload_CardholderNameRequested_SubmittingChangedValueLogsEditedMetric) {
   // Start sync.
@@ -1346,7 +1393,7 @@
 
 // Tests the upload save logic. Ensures that Chrome offers a local save when the
 // data is complete, even if Payments rejects the data.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     Logic_ShouldOfferLocalSaveIfPaymentsDeclines) {
   // Start sync.
@@ -1372,7 +1419,7 @@
 
 // Tests the upload save logic. Ensures that Chrome offers a local save when the
 // data is complete, even if the Payments upload fails unexpectedly.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     Logic_ShouldOfferLocalSaveIfPaymentsFails) {
   // Start sync.
@@ -1398,7 +1445,7 @@
 
 // Tests the upload save logic. Ensures that Chrome delegates the offer-to-save
 // call to Payments, and offers to upload save the card if Payments allows it.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     Logic_CanOfferToSaveEvenIfNothingFoundIfPaymentsAccepts) {
   // Start sync.
@@ -1414,7 +1461,7 @@
 
 // Tests the upload save logic. Ensures that Chrome offers a upload save for
 // dynamic change form.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     Logic_CanOfferToSaveDynamicForm) {
   // Start sync.
@@ -1438,7 +1485,7 @@
 // Tests the upload save logic. Ensures that Chrome delegates the offer-to-save
 // call to Payments, and still does not surface the offer to upload save dialog
 // if Payments declines it.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     Logic_ShouldNotOfferToSaveIfNothingFoundAndPaymentsDeclines) {
   // Start sync.
@@ -1462,7 +1509,7 @@
 
 // Tests the upload save logic. Ensures that Chrome lets Payments decide whether
 // upload save should be offered, even if CVC is not detected.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     Logic_ShouldAttemptToOfferToSaveIfCvcNotFound) {
   // Start sync.
@@ -1478,7 +1525,7 @@
 
 // Tests the upload save logic. Ensures that Chrome lets Payments decide whether
 // upload save should be offered, even if the detected CVC is invalid.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     Logic_ShouldAttemptToOfferToSaveIfInvalidCvcFound) {
   // Start sync.
@@ -1496,7 +1543,7 @@
 // Tests the upload save logic. Ensures that Chrome lets Payments decide whether
 // upload save should be offered, even if address/cardholder name is not
 // detected.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     // TODO(crbug.com/1447107): Flaky on multiple platforms.
     DISABLED_Logic_ShouldAttemptToOfferToSaveIfNameNotFound) {
@@ -1515,7 +1562,7 @@
 // Tests the upload save logic. Ensures that Chrome lets Payments decide whether
 // upload save should be offered, even if multiple conflicting names are
 // detected.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     Logic_ShouldAttemptToOfferToSaveIfNamesConflict) {
   // Start sync.
@@ -1536,7 +1583,7 @@
 
 // Tests the upload save logic. Ensures that Chrome lets Payments decide whether
 // upload save should be offered, even if billing address is not detected.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     Logic_ShouldAttemptToOfferToSaveIfAddressNotFound) {
   // Start sync.
@@ -1554,7 +1601,7 @@
 // Tests the upload save logic. Ensures that Chrome lets Payments decide whether
 // upload save should be offered, even if multiple conflicting billing address
 // postal codes are detected.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     // TODO(crbug.com/1439213): Re-enable this test
     DISABLED_Logic_ShouldAttemptToOfferToSaveIfPostalCodesConflict) {
@@ -1576,7 +1623,7 @@
 
 // Tests UMA logging for the upload save bubble. Ensures that if the user
 // declines upload, Autofill.UploadAcceptedCardOrigin is not logged.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     Upload_DecliningUploadDoesNotLogUserAcceptedCardOriginUMA) {
   base::HistogramTester histogram_tester;
@@ -1599,7 +1646,7 @@
 
 // Tests the upload save bubble. Ensures that the bubble surfaces a pair of
 // dropdowns requesting expiration date if expiration date is missing.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     Upload_SubmittingFormWithMissingExpirationDateRequestsExpirationDate) {
   SetUpForEditableExpirationDate();
@@ -1610,7 +1657,7 @@
 
 // Tests the upload save bubble. Ensures that the bubble surfaces a pair of
 // dropdowns requesting expiration date if expiration date is expired.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     Upload_SubmittingFormWithExpiredExpirationDateRequestsExpirationDate) {
   SetUpForEditableExpirationDate();
@@ -1621,7 +1668,7 @@
 
 // Tests the upload save bubble. Ensures that the bubble does not surface the
 // expiration date dropdowns if it is not needed.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     Upload_ShouldNotRequestExpirationDateInHappyPath) {
   SetUpForEditableExpirationDate();
@@ -1640,7 +1687,7 @@
 
 // Tests the upload save bubble. Ensures that if the expiration date drop down
 // box is changing, [Save] button will change status correctly.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     Upload_SaveButtonStatusResetBetweenExpirationDateSelectionChanges) {
   SetUpForEditableExpirationDate();
@@ -1672,7 +1719,7 @@
 
 // Tests the upload save bubble. Ensures that if the user is selecting an
 // expired expiration date, it is not allowed to click [Save].
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     Upload_SaveButtonIsDisabledIfExpiredExpirationDateAndExpirationDateRequested) {
   SetUpForEditableExpirationDate();
@@ -1698,7 +1745,7 @@
 // Tests the upload save bubble. Ensures that the bubble surfaces a pair of
 // dropdowns requesting expiration date with year pre-populated if year is valid
 // but month is missing.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     // TODO(crbug.com/1447107): Flaky on multiple platforms.
     DISABLED_Upload_SubmittingFormWithMissingExpirationDateMonthAndWithValidYear) {
@@ -1718,7 +1765,7 @@
 // Tests the upload save bubble. Ensures that the bubble surfaces a pair of
 // dropdowns requesting expiration date with month pre-populated if month is
 // detected but year is missing.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     // TODO(crbug.com/1447107): Flaky on multiple platforms.
     DISABLED_Upload_SubmittingFormWithMissingExpirationDateYearAndWithMonth) {
@@ -1737,7 +1784,7 @@
 // Tests the upload save bubble. Ensures that the bubble surfaces a pair of
 // dropdowns requesting expiration date if month is missing and year is detected
 // but out of the range of dropdown.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     Upload_SubmittingFormWithExpirationDateMonthAndWithYearIsOutOfRange) {
   SetUpForEditableExpirationDate();
@@ -1755,7 +1802,7 @@
 // Tests the upload save bubble. Ensures that the bubble surfaces a pair of
 // dropdowns requesting expiration date if expiration date month is missing and
 // year is detected but passed.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     Upload_SubmittingFormWithExpirationDateMonthAndYearExpired) {
   SetUpForEditableExpirationDate();
@@ -1773,7 +1820,7 @@
 // Tests the upload save bubble. Ensures that the bubble surfaces a pair of
 // dropdowns requesting expiration date if expiration date is expired but is
 // current year.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     Upload_SubmittingFormWithExpirationDateMonthAndCurrentYear) {
   SetUpForEditableExpirationDate();
@@ -1796,7 +1843,7 @@
 //                         boolean to branch local vs. upload logic.
 // Tests the local save bubble. Ensures that clicking the [No thanks] button
 // successfully causes a strike to be added.
-IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest,
+IN_PROC_BROWSER_TEST_P(SaveCardBubbleViewsFullFormBrowserTest,
                        StrikeDatabase_Local_AddStrikeIfBubbleDeclined) {
   FillForm();
   SubmitFormAndWaitForCardLocalSaveBubble();
@@ -1815,7 +1862,7 @@
 
 // Tests the upload save bubble. Ensures that clicking the [No thanks] button
 // successfully causes a strike to be added.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     StrikeDatabase_Upload_AddStrikeIfBubbleDeclined) {
   // Start sync.
@@ -1840,7 +1887,7 @@
 // example of declining the prompt three times and ensuring that the
 // offer-to-save bubble does not appear on the fourth try. Then, ensures that no
 // strikes are added if the card already has max strikes.
-IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest,
+IN_PROC_BROWSER_TEST_P(SaveCardBubbleViewsFullFormBrowserTest,
                        StrikeDatabase_Local_FullFlowTest) {
   // Show and ignore the bubble enough times in order to accrue maximum strikes.
   for (int i = 0;
@@ -1902,7 +1949,7 @@
 // example of declining the prompt three times and ensuring that the
 // offer-to-save bubble does not appear on the fourth try. Then, ensures that no
 // strikes are added if the card already has max strikes.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     StrikeDatabase_Upload_FullFlowTest) {
   // Start sync.
@@ -1950,7 +1997,10 @@
   ASSERT_TRUE(WaitForObservedEvent());
   EXPECT_TRUE(FindViewInBubbleById(DialogViewId::MAIN_CONTENT_VIEW_UPLOAD)
                   ->GetVisible());
-  EXPECT_TRUE(FindViewInBubbleById(DialogViewId::FOOTNOTE_VIEW)->GetVisible());
+  EXPECT_TRUE(FindViewInBubbleById(move_legal_terms_and_icon()
+                                       ? DialogViewId::LEGAL_MESSAGE_VIEW
+                                       : DialogViewId::FOOTNOTE_VIEW)
+                  ->GetVisible());
 
   ClickOnCancelButton();
 
@@ -1970,7 +2020,7 @@
 }
 
 // Tests to ensure the card nickname is shown correctly in the Upstream bubble.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     LocalCardHasNickname) {
   base::HistogramTester histogram_tester;
@@ -1990,7 +2040,7 @@
             card.NicknameAndLastFourDigitsForTesting());
 }
 
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream,
     LocalCardHasNoNickname) {
   base::HistogramTester histogram_tester;
@@ -2011,7 +2061,7 @@
 
 // Tests the local save bubble. Ensures that clicking the [Save] button
 // successfully causes the bubble to go away.
-IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest,
+IN_PROC_BROWSER_TEST_P(SaveCardBubbleViewsFullFormBrowserTest,
                        Local_ClickingSaveClosesBubble) {
   FillForm();
   SubmitFormAndWaitForCardLocalSaveBubble();
@@ -2033,7 +2083,7 @@
 
 // Tests the manage cards bubble. Ensures that it shows up by clicking the
 // credit card icon.
-IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest,
+IN_PROC_BROWSER_TEST_P(SaveCardBubbleViewsFullFormBrowserTest,
                        Local_ClickingIconShowsManageCards) {
   FillForm();
   SubmitFormAndWaitForCardLocalSaveBubble();
@@ -2062,7 +2112,7 @@
 
 // Tests the manage cards bubble. Ensures that clicking the [Done]
 // button closes the bubble.
-IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest,
+IN_PROC_BROWSER_TEST_P(SaveCardBubbleViewsFullFormBrowserTest,
                        Local_ManageCardsDoneButtonClosesBubble) {
   FillForm();
   SubmitFormAndWaitForCardLocalSaveBubble();
@@ -2092,7 +2142,7 @@
                   Bucket(ManageCardsPromptMetric::kManageCardsDone, 1)));
 }
 
-IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest,
+IN_PROC_BROWSER_TEST_P(SaveCardBubbleViewsFullFormBrowserTest,
                        IconViewAccessibleName) {
   EXPECT_EQ(GetSaveCardIconView()->GetAccessibleName(),
             l10n_util::GetStringUTF16(IDS_TOOLTIP_SAVE_CREDIT_CARD));
diff --git a/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.cc b/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.cc
index bc2713c3..3c606bc 100644
--- a/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.cc
+++ b/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.cc
@@ -82,24 +82,16 @@
     SaveCardBubbleController* controller)
     : SaveCardBubbleViews(anchor_view, web_contents, controller) {
   SetButtons(ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL);
-  const LegalMessageLines message_lines = controller->GetLegalMessageLines();
 
-  if (!message_lines.empty()) {
-    if (base::FeatureList::IsEnabled(
-            features::kAutofillEnableNewSaveCardBubbleUi)) {
-      legal_message_view_ = SetFootnoteView(std::make_unique<LegalMessageView>(
-          message_lines, base::UTF8ToUTF16(controller->GetAccountInfo().email),
-          GetProfileAvatar(controller->GetAccountInfo()),
-          base::BindRepeating(&SaveCardOfferBubbleViews::LinkClicked,
-                              base::Unretained(this))));
-    } else {
-      legal_message_view_ = SetFootnoteView(std::make_unique<LegalMessageView>(
-          message_lines, /*user_email=*/absl::nullopt,
-          /*user_avatar=*/absl::nullopt,
-          base::BindRepeating(&SaveCardOfferBubbleViews::LinkClicked,
-                              base::Unretained(this))));
+  if (!base::FeatureList::IsEnabled(
+          features::kAutofillMoveLegalTermsAndIconForNewCardEnrollment)) {
+    std::unique_ptr<LegalMessageView> legal_message_view =
+        CreateLegalMessageView();
+
+    if (legal_message_view != nullptr) {
+      legal_message_view_ = SetFootnoteView(std::move(legal_message_view));
+      InitFootnoteView(legal_message_view_);
     }
-    InitFootnoteView(legal_message_view_);
   }
 
   Profile* profile =
@@ -233,7 +225,7 @@
             views::style::CONTEXT_DIALOG_BODY_TEXT,
             views::style::STYLE_SECONDARY);
     cardholder_name_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-    cardholder_name_label_row->AddChildView(cardholder_name_label.release());
+    cardholder_name_label_row->AddChildView(std::move(cardholder_name_label));
 
     // Prepare the prefilled cardholder name.
     std::u16string prefilled_name =
@@ -256,7 +248,7 @@
           views::BubbleBorder::Arrow::TOP_LEFT);
       cardholder_name_tooltip->SetID(DialogViewId::CARDHOLDER_NAME_TOOLTIP);
       cardholder_name_label_row->AddChildView(
-          cardholder_name_tooltip.release());
+          std::move(cardholder_name_tooltip));
     }
 
     // Set up cardholder name textfield.
@@ -278,17 +270,53 @@
     cardholder_name_view->SetLayoutManager(std::make_unique<views::BoxLayout>(
         views::BoxLayout::Orientation::kVertical, gfx::Insets(),
         provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_VERTICAL)));
-    cardholder_name_view->AddChildView(cardholder_name_label_row.release());
+    cardholder_name_view->AddChildView(std::move(cardholder_name_label_row));
     cardholder_name_view->AddChildView(cardholder_name_textfield_.get());
-    view->AddChildView(cardholder_name_view.release());
+    view->AddChildView(std::move(cardholder_name_view));
   }
 
-  if (controller()->ShouldRequestExpirationDateFromUser())
-    view->AddChildView(CreateRequestExpirationDateView().release());
+  if (controller()->ShouldRequestExpirationDateFromUser()) {
+    view->AddChildView(CreateRequestExpirationDateView());
+  }
+
+  if (base::FeatureList::IsEnabled(
+          features::kAutofillMoveLegalTermsAndIconForNewCardEnrollment)) {
+    std::unique_ptr<views::View> legal_message_view = CreateLegalMessageView();
+
+    if (legal_message_view != nullptr) {
+      legal_message_view->SetID(DialogViewId::LEGAL_MESSAGE_VIEW);
+      view->AddChildView(std::move(legal_message_view));
+    }
+  }
 
   return view;
 }
 
+std::unique_ptr<LegalMessageView>
+SaveCardOfferBubbleViews::CreateLegalMessageView() {
+  const LegalMessageLines message_lines = controller()->GetLegalMessageLines();
+
+  if (message_lines.empty()) {
+    return nullptr;
+  }
+
+  LegalMessageView::LinkClickedCallback LegalMessageCallBack =
+      base::BindRepeating(&SaveCardOfferBubbleViews::LinkClicked,
+                          base::Unretained(this));
+
+  if (base::FeatureList::IsEnabled(
+          features::kAutofillEnableNewSaveCardBubbleUi)) {
+    return (std::make_unique<LegalMessageView>(
+        message_lines, base::UTF8ToUTF16(controller()->GetAccountInfo().email),
+        GetProfileAvatar(controller()->GetAccountInfo()),
+        LegalMessageCallBack));
+  }
+
+  return (std::make_unique<LegalMessageView>(
+      message_lines, /*user_email=*/absl::nullopt,
+      /*user_avatar=*/absl::nullopt, LegalMessageCallBack));
+}
+
 std::unique_ptr<views::View>
 SaveCardOfferBubbleViews::CreateRequestExpirationDateView() {
   auto expiration_date_view = std::make_unique<views::View>();
@@ -342,8 +370,8 @@
       views::style::CONTEXT_DIALOG_BODY_TEXT, views::style::STYLE_SECONDARY);
   expiration_date_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
 
-  expiration_date_view->AddChildView(expiration_date_label.release());
-  expiration_date_view->AddChildView(input_row.release());
+  expiration_date_view->AddChildView(std::move(expiration_date_label));
+  expiration_date_view->AddChildView(std::move(input_row));
 
   return expiration_date_view;
 }
diff --git a/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.h b/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.h
index 767c6af3..6fd7cd93 100644
--- a/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.h
+++ b/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.h
@@ -50,14 +50,13 @@
   ~SaveCardOfferBubbleViews() override;
 
   std::unique_ptr<views::View> CreateMainContentView() override;
-
   std::unique_ptr<views::View> CreateRequestExpirationDateView();
   std::unique_ptr<views::View> CreateUploadExplanationView();
+  std::unique_ptr<LegalMessageView> CreateLegalMessageView();
 
   void LinkClicked(const GURL& url);
 
   raw_ptr<views::Textfield> cardholder_name_textfield_ = nullptr;
-
   raw_ptr<LegalMessageView> legal_message_view_ = nullptr;
 
   // Holds expiration inputs:
diff --git a/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views.cc b/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views.cc
index 928c7f99..57555ce 100644
--- a/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views.cc
+++ b/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views.cc
@@ -17,6 +17,7 @@
 #include "components/autofill/core/browser/payments/payments_service_url.h"
 #include "components/autofill/core/browser/payments/virtual_card_enrollment_manager.h"
 #include "components/autofill/core/browser/ui/payments/virtual_card_enroll_bubble_controller.h"
+#include "components/autofill/core/common/autofill_payments_features.h"
 #include "components/grit/components_scaled_resources.h"
 #include "components/strings/grit/components_strings.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -49,9 +50,10 @@
   set_fixed_width(views::LayoutProvider::Get()->GetDistanceMetric(
       views::DISTANCE_BUBBLE_PREFERRED_WIDTH));
 
-  raw_ptr<views::View> legal_message_view =
-      SetFootnoteView(CreateLegalMessageView());
-  legal_message_view->SetID(DialogViewId::FOOTNOTE_VIEW);
+  if (!base::FeatureList::IsEnabled(
+          features::kAutofillMoveLegalTermsAndIconForNewCardEnrollment)) {
+    SetFootnoteView(CreateLegalMessageView())->SetID(DialogViewId::FOOTNOTE_VIEW);
+  }
 }
 
 VirtualCardEnrollBubbleViews::~VirtualCardEnrollBubbleViews() = default;
@@ -96,9 +98,16 @@
   header_view->AddChildView(std::move(image_view));
 
   GetBubbleFrameView()->SetHeaderView(std::move(header_view));
-  GetBubbleFrameView()->SetTitleView(
-      std::make_unique<TitleWithIconAndSeparatorView>(
-          GetWindowTitle(), TitleWithIconAndSeparatorView::Icon::GOOGLE_PAY));
+  if (base::FeatureList::IsEnabled(
+          features::kAutofillMoveLegalTermsAndIconForNewCardEnrollment)) {
+    GetBubbleFrameView()->SetTitleView(
+        std::make_unique<TitleWithIconAfterLabelView>(
+            GetWindowTitle(), TitleWithIconAndSeparatorView::Icon::GOOGLE_PAY));
+  } else {
+    GetBubbleFrameView()->SetTitleView(
+        std::make_unique<TitleWithIconAndSeparatorView>(
+            GetWindowTitle(), TitleWithIconAndSeparatorView::Icon::GOOGLE_PAY));
+  }
 }
 
 std::u16string VirtualCardEnrollBubbleViews::GetWindowTitle() const {
@@ -115,6 +124,14 @@
 
 void VirtualCardEnrollBubbleViews::Init() {
   ChromeLayoutProvider* const provider = ChromeLayoutProvider::Get();
+
+  // If terms of service on top enabled, add padding between TOS and Buttons
+  if (base::FeatureList::IsEnabled(
+          features::kAutofillMoveLegalTermsAndIconForNewCardEnrollment)) {
+    set_margins(provider->GetDialogInsetsForContentType(
+        views::DialogContentType::kText, views::DialogContentType::kControl));
+  }
+
   SetLayoutManager(std::make_unique<views::BoxLayout>(
       views::BoxLayout::Orientation::kVertical, gfx::Insets(),
       provider->GetDistanceMetric(views::DISTANCE_UNRELATED_CONTROL_VERTICAL)));
@@ -188,6 +205,12 @@
       l10n_util::GetStringUTF16(IDS_AUTOFILL_VIRTUAL_CARD_ENTRY_PREFIX),
       ChromeTextContext::CONTEXT_DIALOG_BODY_TEXT_SMALL,
       views::style::STYLE_SECONDARY));
+
+  if (base::FeatureList::IsEnabled(
+          features::kAutofillMoveLegalTermsAndIconForNewCardEnrollment)) {
+    AddChildView(CreateLegalMessageView())
+        ->SetID(DialogViewId::LEGAL_MESSAGE_VIEW);
+  }
 }
 
 std::unique_ptr<views::View>
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_browsertest.cc
index e8c253aa..9da888a1 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_browsertest.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_browsertest.cc
@@ -213,28 +213,6 @@
 #endif
 }
 
-// Verifies that the incognito window frame is always the right color.
-IN_PROC_BROWSER_TEST_F(BrowserNonClientFrameViewBrowserTest,
-                       IncognitoIsCorrectColor) {
-  // Set the color that's expected to be ignored.
-  auto* theme = ui::NativeTheme::GetInstanceForNativeUi();
-  theme->set_user_color(gfx::kGoogleBlue400);
-  theme->NotifyOnNativeThemeUpdated();
-
-  Browser* incognito_browser = CreateIncognitoBrowser(browser()->profile());
-
-  BrowserView* view = BrowserView::GetBrowserViewForBrowser(incognito_browser);
-  BrowserFrame* frame = view->frame();
-  BrowserNonClientFrameView* frame_view = frame->GetFrameView();
-
-  // Checking the exact color is brittle but there's no better way to ensure
-  // that it's not overridden by accident.
-  EXPECT_EQ(gfx::kGoogleGrey900,
-            frame_view->GetFrameColor(BrowserFrameActiveState::kActive));
-
-  incognito_browser->window()->Close();
-}
-
 // Checks that the title bar for hosted app windows is hidden when in fullscreen
 // for tab mode.
 IN_PROC_BROWSER_TEST_F(BrowserNonClientFrameViewBrowserTest,
@@ -447,54 +425,4 @@
   EXPECT_TRUE(path.isEmpty());
 #endif
 }
-
-class BrowserNonClientFrameViewRefreshedBrowserTest
-    : public BrowserNonClientFrameViewBrowserTest,
-      public ::testing::WithParamInterface<bool> {
- public:
-  BrowserNonClientFrameViewRefreshedBrowserTest() {}
-
-  void SetUp() override {
-    features_.InitWithFeatureState(features::kChromeRefresh2023, GetParam());
-    BrowserNonClientFrameViewBrowserTest::SetUp();
-  }
-
- private:
-  base::test::ScopedFeatureList features_;
-};
-
-INSTANTIATE_TEST_SUITE_P(All,
-                         BrowserNonClientFrameViewRefreshedBrowserTest,
-                         testing::Bool());
-
-// Verifies the frame color with the refresh feature enabled and disabled.
-// Verifies actual color to catch accidental changes.
-IN_PROC_BROWSER_TEST_P(BrowserNonClientFrameViewRefreshedBrowserTest,
-                       UnthemedFrameColor) {
-  // ChromeOS always has a system color so we replicate this here.
-  auto* theme = ui::NativeTheme::GetInstanceForNativeUi();
-  theme->set_user_color(gfx::kGoogleGreen300);
-  theme->NotifyOnNativeThemeUpdated();
-
-  Browser* normal_browser = CreateBrowser(browser()->profile());
-
-  BrowserView* view = BrowserView::GetBrowserViewForBrowser(normal_browser);
-  BrowserFrame* frame = view->frame();
-  BrowserNonClientFrameView* frame_view = frame->GetFrameView();
-
-  if (GetParam()) {
-    // When refresh is enabled, we derive the color from the `user_color` in the
-    // theme. Color should be a light green for light mode and Green300 seed. It
-    // should be equal to `kColorRefSecondary90`.
-    EXPECT_EQ(SkColorSetRGB(0xD2, 0xE8, 0xD4),
-              frame_view->GetFrameColor(BrowserFrameActiveState::kActive));
-  } else {
-    // When refresh is off, this should be the default unthemed color. i.e.
-    // `kColorFrameActiveUnthemed` in light mode (which is set to this value).
-    EXPECT_EQ(SkColorSetRGB(0xDE, 0xE1, 0xE6),
-              frame_view->GetFrameColor(BrowserFrameActiveState::kActive));
-  }
-
-  normal_browser->window()->Close();
-}
 #endif  // BUILDFLAG(IS_CHROMEOS)
diff --git a/chrome/browser/ui/views/side_panel/side_panel_coordinator.cc b/chrome/browser/ui/views/side_panel/side_panel_coordinator.cc
index d410b82..bd1ec01 100644
--- a/chrome/browser/ui/views/side_panel/side_panel_coordinator.cc
+++ b/chrome/browser/ui/views/side_panel/side_panel_coordinator.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/views/side_panel/side_panel_coordinator.h"
 #include <memory>
 #include <utility>
+#include <vector>
 
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
@@ -34,6 +35,7 @@
 #include "chrome/grit/generated_resources.h"
 #include "components/feature_engagement/public/feature_constants.h"
 #include "components/strings/grit/components_strings.h"
+#include "ui/accessibility/accessibility_features.h"
 #include "ui/base/interaction/element_tracker.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/metadata/metadata_header_macros.h"
@@ -200,10 +202,17 @@
   PopulateSidePanelCallback loaded_callback_;
 };
 
+// Get the list of distillable URLs defined by the Finch experiment parameter.
+std::vector<std::string> GetDistillableURLs() {
+  return base::SplitString(base::GetFieldTrialParamValueByFeature(
+                               features::kReadAnything, "distillable_urls"),
+                           ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+}
+
 }  // namespace
 
 SidePanelCoordinator::SidePanelCoordinator(BrowserView* browser_view)
-    : browser_view_(browser_view) {
+    : browser_view_(browser_view), distillable_urls_(GetDistillableURLs()) {
   combobox_model_ = std::make_unique<SidePanelComboboxModel>();
 
   auto global_registry = std::make_unique<SidePanelRegistry>();
@@ -213,6 +222,7 @@
                                        std::move(global_registry));
 
   browser_view_->browser()->tab_strip_model()->AddObserver(this);
+  Observe(GetActiveWebContents());
 
   SidePanelUtil::PopulateGlobalEntries(browser_view->browser(),
                                        global_registry_);
@@ -221,6 +231,7 @@
 SidePanelCoordinator::~SidePanelCoordinator() {
   browser_view_->browser()->tab_strip_model()->RemoveObserver(this);
   view_state_observers_.Clear();
+  Observe(nullptr);
 }
 
 // static
@@ -415,6 +426,8 @@
         feature_engagement::kIPHReadingListInSidePanelFeature);
     browser_view_->browser()->window()->CloseFeaturePromo(
         feature_engagement::kIPHPowerBookmarksSidePanelFeature);
+    browser_view_->browser()->window()->CloseFeaturePromo(
+        feature_engagement::kIPHReadingModeSidePanelFeature);
   }
 
   SidePanelContentSwappingContainer* content_wrapper =
@@ -614,8 +627,7 @@
 }
 
 SidePanelRegistry* SidePanelCoordinator::GetActiveContextualRegistry() const {
-  if (auto* web_contents =
-          browser_view_->browser()->tab_strip_model()->GetActiveWebContents()) {
+  if (auto* web_contents = GetActiveWebContents()) {
     return SidePanelRegistry::Get(web_contents);
   }
   return nullptr;
@@ -942,6 +954,9 @@
     Show(new_contextual_registry->active_entry().value(),
          SidePanelUtil::SidePanelOpenTrigger::kTabChanged);
   }
+
+  Observe(GetActiveWebContents());
+  MaybeShowReadingModeSidePanelIPH();
 }
 
 void SidePanelCoordinator::UpdateNewTabButtonState() {
@@ -981,3 +996,31 @@
                                                    views::View* starting_from) {
   UpdateToolbarButtonHighlight(observed_view->GetVisible());
 }
+
+void SidePanelCoordinator::DidStopLoading() {
+  MaybeShowReadingModeSidePanelIPH();
+}
+
+content::WebContents* SidePanelCoordinator::GetActiveWebContents() const {
+  return browser_view_->browser()->tab_strip_model()->GetActiveWebContents();
+}
+
+void SidePanelCoordinator::MaybeShowReadingModeSidePanelIPH() {
+  if (!features::IsReadAnythingEnabled()) {
+    return;
+  }
+  auto* web_contents = GetActiveWebContents();
+  if (!web_contents) {
+    return;
+  }
+  auto url = web_contents->GetLastCommittedURL();
+  for (auto distillable : distillable_urls_) {
+    // If the url's domain is found in distillable urls AND the url has a
+    // filename (i.e. it is not a home page or sub-home page), show the promo.
+    if (url.DomainIs(distillable) && !url.ExtractFileName().empty()) {
+      browser_view_->browser()->window()->MaybeShowFeaturePromo(
+          feature_engagement::kIPHReadingModeSidePanelFeature);
+      return;
+    }
+  }
+}
diff --git a/chrome/browser/ui/views/side_panel/side_panel_coordinator.h b/chrome/browser/ui/views/side_panel/side_panel_coordinator.h
index e9bc526..20309d5 100644
--- a/chrome/browser/ui/views/side_panel/side_panel_coordinator.h
+++ b/chrome/browser/ui/views/side_panel/side_panel_coordinator.h
@@ -17,6 +17,7 @@
 #include "chrome/browser/ui/views/side_panel/side_panel_registry_observer.h"
 #include "chrome/browser/ui/views/side_panel/side_panel_util.h"
 #include "chrome/browser/ui/views/side_panel/side_panel_view_state_observer.h"
+#include "content/public/browser/web_contents_observer.h"
 #include "extensions/common/extension_id.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/views/view_observer.h"
@@ -46,7 +47,8 @@
 class SidePanelCoordinator final : public SidePanelRegistryObserver,
                                    public TabStripModelObserver,
                                    public views::ViewObserver,
-                                   public SidePanelUI {
+                                   public SidePanelUI,
+                                   public content::WebContentsObserver {
  public:
   explicit SidePanelCoordinator(BrowserView* browser_view);
   SidePanelCoordinator(const SidePanelCoordinator&) = delete;
@@ -222,6 +224,14 @@
       const TabStripModelChange& change,
       const TabStripSelectionChange& selection) override;
 
+  // content::WebContentsObserver:
+  void DidStopLoading() override;
+
+  content::WebContents* GetActiveWebContents() const;
+
+  // Attempts to show in product help for reading mode.
+  void MaybeShowReadingModeSidePanelIPH();
+
   // When true, prevent loading delays when switching between side panel
   // entries.
   bool no_delays_for_testing_ = false;
@@ -260,6 +270,8 @@
 
   base::ObserverList<SidePanelViewStateObserver> view_state_observers_;
 
+  const base::flat_set<std::string> distillable_urls_;
+
   base::ScopedMultiSourceObservation<SidePanelRegistry,
                                      SidePanelRegistryObserver>
       registry_observations_{this};
diff --git a/chrome/browser/ui/views/side_panel/side_panel_toolbar_container.h b/chrome/browser/ui/views/side_panel/side_panel_toolbar_container.h
index 450a95af..870f89122 100644
--- a/chrome/browser/ui/views/side_panel/side_panel_toolbar_container.h
+++ b/chrome/browser/ui/views/side_panel/side_panel_toolbar_container.h
@@ -69,7 +69,7 @@
    private:
     std::unique_ptr<ui::MenuModel> CreateMenuModel();
 
-    raw_ptr<BrowserView> browser_view_;
+    raw_ptr<BrowserView, DanglingUntriaged> browser_view_;
     SidePanelEntry::Id id_;
   };
 
diff --git a/chrome/browser/ui/views/web_apps/web_app_uninstall_dialog_view.cc b/chrome/browser/ui/views/web_apps/web_app_uninstall_dialog_view.cc
index 8069db3..e484d8c 100644
--- a/chrome/browser/ui/views/web_apps/web_app_uninstall_dialog_view.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_uninstall_dialog_view.cc
@@ -167,7 +167,7 @@
   auto* provider = web_app::WebAppProvider::GetForWebApps(profile_);
   DCHECK(provider);
 
-  if (!provider->install_finalizer().CanUserUninstallWebApp(app_id_)) {
+  if (!provider->registrar_unsafe().CanUserUninstallWebApp(app_id_)) {
     std::exchange(dialog_, nullptr)->UninstallCancelled();
     return;
   }
diff --git a/chrome/browser/ui/web_applications/web_app_browser_controller.cc b/chrome/browser/ui/web_applications/web_app_browser_controller.cc
index 81a79bd3..b63e770 100644
--- a/chrome/browser/ui/web_applications/web_app_browser_controller.cc
+++ b/chrome/browser/ui/web_applications/web_app_browser_controller.cc
@@ -571,9 +571,7 @@
 }
 
 bool WebAppBrowserController::CanUserUninstall() const {
-  return WebAppUiManagerImpl::Get(&*provider_)
-      ->dialog_manager()
-      .CanUserUninstallWebApp(app_id());
+  return registrar().CanUserUninstallWebApp(app_id());
 }
 
 void WebAppBrowserController::Uninstall(
diff --git a/chrome/browser/ui/web_applications/web_app_browsertest.cc b/chrome/browser/ui/web_applications/web_app_browsertest.cc
index a15ed555..6c555cd 100644
--- a/chrome/browser/ui/web_applications/web_app_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_browsertest.cc
@@ -1352,13 +1352,13 @@
   AppId app_id =
       provider->registrar_unsafe().LookupExternalAppId(install_url).value();
 
-  EXPECT_FALSE(provider->install_finalizer().CanUserUninstallWebApp(app_id));
+  EXPECT_FALSE(provider->registrar_unsafe().CanUserUninstallWebApp(app_id));
 
   InstallWebAppFromPage(browser(), install_url);
 
   // Performing a user install on the page should not override the "policy"
   // install source.
-  EXPECT_FALSE(provider->install_finalizer().CanUserUninstallWebApp(app_id));
+  EXPECT_FALSE(provider->registrar_unsafe().CanUserUninstallWebApp(app_id));
   const WebApp& web_app = *provider->registrar_unsafe().GetAppById(app_id);
   EXPECT_TRUE(web_app.IsSynced());
   EXPECT_TRUE(web_app.IsPolicyInstalledApp());
diff --git a/chrome/browser/ui/web_applications/web_app_dialog_manager.cc b/chrome/browser/ui/web_applications/web_app_dialog_manager.cc
index 37f0b37..9f0223d 100644
--- a/chrome/browser/ui/web_applications/web_app_dialog_manager.cc
+++ b/chrome/browser/ui/web_applications/web_app_dialog_manager.cc
@@ -22,14 +22,6 @@
 
 WebAppDialogManager::~WebAppDialogManager() = default;
 
-bool WebAppDialogManager::CanUserUninstallWebApp(const AppId& app_id) const {
-  auto* provider = WebAppProvider::GetForWebApps(profile_);
-  if (!provider)
-    return false;
-
-  return provider->install_finalizer().CanUserUninstallWebApp(app_id);
-}
-
 void WebAppDialogManager::UninstallWebApp(
     const AppId& app_id,
     webapps::WebappUninstallSource uninstall_source,
diff --git a/chrome/browser/ui/web_applications/web_app_dialog_manager.h b/chrome/browser/ui/web_applications/web_app_dialog_manager.h
index f2948f7..8e205fb 100644
--- a/chrome/browser/ui/web_applications/web_app_dialog_manager.h
+++ b/chrome/browser/ui/web_applications/web_app_dialog_manager.h
@@ -35,7 +35,6 @@
 
   using Callback = base::OnceCallback<void(webapps::UninstallResultCode code)>;
 
-  bool CanUserUninstallWebApp(const AppId& app_id) const;
   // The uninstall dialog will be modal to |parent_window|, or a non-modal if
   // |parent_window| is nullptr.
   void UninstallWebApp(const AppId& app_id,
diff --git a/chrome/browser/ui/web_applications/web_app_ui_manager_impl.cc b/chrome/browser/ui/web_applications/web_app_ui_manager_impl.cc
index 8ef2617..9e71924 100644
--- a/chrome/browser/ui/web_applications/web_app_ui_manager_impl.cc
+++ b/chrome/browser/ui/web_applications/web_app_ui_manager_impl.cc
@@ -88,7 +88,7 @@
   std::unique_ptr<ScopedKeepAlive> scoped_keep_alive =
       std::make_unique<ScopedKeepAlive>(KeepAliveOrigin::WEB_APP_UNINSTALL,
                                         KeepAliveRestartOption::DISABLED);
-  if (provider->install_finalizer().CanUserUninstallWebApp(app_id)) {
+  if (provider->registrar_unsafe().CanUserUninstallWebApp(app_id)) {
     WebAppUiManagerImpl::Get(provider)->dialog_manager().UninstallWebApp(
         app_id, webapps::WebappUninstallSource::kOsSettings,
         gfx::kNullNativeWindow,
diff --git a/chrome/browser/ui/web_applications/web_app_uninstall_browsertest.cc b/chrome/browser/ui/web_applications/web_app_uninstall_browsertest.cc
index f55c93c..c975cce 100644
--- a/chrome/browser/ui/web_applications/web_app_uninstall_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_uninstall_browsertest.cc
@@ -46,7 +46,7 @@
     WebAppProvider* const provider = WebAppProvider::GetForTest(profile());
     base::RunLoop run_loop;
 
-    DCHECK(provider->install_finalizer().CanUserUninstallWebApp(app_id));
+    DCHECK(provider->registrar_unsafe().CanUserUninstallWebApp(app_id));
     provider->install_finalizer().UninstallWebApp(
         app_id, webapps::WebappUninstallSource::kAppMenu,
         base::BindLambdaForTesting([&](webapps::UninstallResultCode code) {
@@ -159,7 +159,7 @@
   // Trigger app uninstall without waiting for result.
   WebAppProvider* const provider = WebAppProvider::GetForTest(profile());
   EXPECT_TRUE(provider->registrar_unsafe().IsInstalled(app_id));
-  DCHECK(provider->install_finalizer().CanUserUninstallWebApp(app_id));
+  DCHECK(provider->registrar_unsafe().CanUserUninstallWebApp(app_id));
   provider->install_finalizer().UninstallWebApp(
       app_id, webapps::WebappUninstallSource::kAppMenu,
       base::BindLambdaForTesting([&](webapps::UninstallResultCode code) {
diff --git a/chrome/browser/ui/webui/app_home/app_home_page_handler.cc b/chrome/browser/ui/webui/app_home/app_home_page_handler.cc
index cbe7e06d..175e2ce5 100644
--- a/chrome/browser/ui/webui/app_home/app_home_page_handler.cc
+++ b/chrome/browser/ui/webui/app_home/app_home_page_handler.cc
@@ -400,7 +400,7 @@
 
   app_info->store_page_url = absl::nullopt;
   app_info->may_uninstall =
-      web_app_provider_->install_finalizer().CanUserUninstallWebApp(app_id);
+      web_app_provider_->registrar_unsafe().CanUserUninstallWebApp(app_id);
   app_info->is_deprecated_app = false;
   return app_info;
 }
@@ -504,7 +504,7 @@
 }
 
 void AppHomePageHandler::UninstallWebApp(const std::string& web_app_id) {
-  if (!web_app_provider_->install_finalizer().CanUserUninstallWebApp(
+  if (!web_app_provider_->registrar_unsafe().CanUserUninstallWebApp(
           web_app_id)) {
     LOG(ERROR) << "Attempt to uninstall a webapp that is non-usermanagable "
                   "was made. App id : "
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
index 4a1dc1e..a953f34 100644
--- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
+++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -183,32 +183,13 @@
 #endif  // BUILDFLAG(IS_ANDROID)
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-#include "ash/constants/ash_features.h"
-#include "ash/constants/ash_switches.h"
 #include "ash/webui/camera_app_ui/url_constants.h"
 #include "ash/webui/file_manager/url_constants.h"
 #include "ash/webui/files_internals/url_constants.h"
 #include "ash/webui/multidevice_debug/url_constants.h"
-#include "base/system/sys_info.h"
 #include "build/config/chromebox_for_meetings/buildflags.h"
-#include "chrome/browser/app_mode/app_mode_utils.h"
-#include "chrome/browser/ash/arc/arc_util.h"
 #include "chrome/browser/ash/extensions/url_constants.h"
-#include "chrome/browser/ash/login/easy_unlock/easy_unlock_service.h"
-#include "chrome/browser/ash/login/easy_unlock/easy_unlock_service_factory.h"
-#include "chrome/browser/ash/login/login_pref_names.h"
-#include "chrome/browser/ash/net/network_health/network_health_manager.h"
-#include "chrome/browser/ash/profiles/profile_helper.h"
-#include "chrome/browser/ash/system_web_apps/system_web_app_manager.h"
-#include "chrome/browser/ash/web_applications/files_internals_ui_delegate.h"
-#include "chrome/browser/feedback/feedback_dialog_utils.h"
-#include "chrome/browser/nearby_sharing/nearby_sharing_service_factory.h"
 #include "chrome/browser/ui/webui/ash/cellular_setup/mobile_setup_ui.h"
-#include "chromeos/ash/services/multidevice_setup/public/mojom/multidevice_setup.mojom.h"
-#include "chromeos/services/network_health/public/mojom/network_diagnostics.mojom.h"  // nogncheck
-#include "chromeos/services/network_health/public/mojom/network_health.mojom.h"  // nogncheck
-#include "content/public/common/content_switches.h"
-#include "mojo/public/cpp/bindings/pending_receiver.h"
 #endif
 
 #if BUILDFLAG(IS_CHROMEOS)
diff --git a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
index 52a0753..d2d390d0 100644
--- a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
+++ b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
@@ -220,9 +220,7 @@
 
   GetWebAppBasicInfo(app_id, registrar, &dict);
 
-  dict.Set(
-      "mayDisable",
-      web_app_provider_->install_finalizer().CanUserUninstallWebApp(app_id));
+  dict.Set("mayDisable", registrar.CanUserUninstallWebApp(app_id));
   bool is_locally_installed = registrar.IsLocallyInstalled(app_id);
   dict.Set("mayChangeLaunchType", is_locally_installed);
 
@@ -991,7 +989,7 @@
       !IsYoutubeExtension(extension_id)) {
     if (!extension_id_prompting_.empty())
       return;  // Only one prompt at a time.
-    if (!web_app_provider_->install_finalizer().CanUserUninstallWebApp(
+    if (!web_app_provider_->registrar_unsafe().CanUserUninstallWebApp(
             extension_id)) {
       LOG(ERROR) << "Attempt to uninstall a webapp that is non-usermanagable "
                  << "was made. App id : " << extension_id;
diff --git a/chrome/browser/ui/webui/settings/ash/files_page/google_drive_page_handler.cc b/chrome/browser/ui/webui/settings/ash/files_page/google_drive_page_handler.cc
index 686ae655..a1b42eb 100644
--- a/chrome/browser/ui/webui/settings/ash/files_page/google_drive_page_handler.cc
+++ b/chrome/browser/ui/webui/settings/ash/files_page/google_drive_page_handler.cc
@@ -43,16 +43,15 @@
     : profile_(profile),
       page_(std::move(page)),
       receiver_(this, std::move(receiver)) {
-  drive::DriveIntegrationService* const drive_service = GetDriveService();
-  drive_service->AddObserver(this);
+  if (drive::DriveIntegrationService* const drive_service = GetDriveService()) {
+    drive_service->AddObserver(this);
+  }
 }
 
 GoogleDrivePageHandler::~GoogleDrivePageHandler() {
-  drive::DriveIntegrationService* const drive_service = GetDriveService();
-  if (!drive_service) {
-    return;
+  if (drive::DriveIntegrationService* const drive_service = GetDriveService()) {
+    drive_service->RemoveObserver(this);
   }
-  drive_service->RemoveObserver(this);
 }
 
 void GoogleDrivePageHandler::CalculateRequiredSpace() {
diff --git a/chrome/browser/ui/webui/settings/ash/pdf_ocr_handler.cc b/chrome/browser/ui/webui/settings/ash/pdf_ocr_handler.cc
index 7920260..ed56b84 100644
--- a/chrome/browser/ui/webui/settings/ash/pdf_ocr_handler.cc
+++ b/chrome/browser/ui/webui/settings/ash/pdf_ocr_handler.cc
@@ -5,9 +5,9 @@
 #include <string>
 
 #include "base/feature_list.h"
+#include "chrome/browser/screen_ai/screen_ai_install_state.h"
 #include "chrome/browser/ui/webui/settings/ash/pdf_ocr_handler.h"
 #include "chrome/grit/generated_resources.h"
-#include "components/services/screen_ai/public/cpp/screen_ai_install_state.h"
 #include "ui/accessibility/accessibility_features.h"
 #include "ui/base/l10n/l10n_util.h"
 
diff --git a/chrome/browser/ui/webui/settings/ash/pdf_ocr_handler.h b/chrome/browser/ui/webui/settings/ash/pdf_ocr_handler.h
index ceb5009..f40a392 100644
--- a/chrome/browser/ui/webui/settings/ash/pdf_ocr_handler.h
+++ b/chrome/browser/ui/webui/settings/ash/pdf_ocr_handler.h
@@ -7,8 +7,8 @@
 
 #include "base/memory/weak_ptr.h"
 #include "base/scoped_observation.h"
+#include "chrome/browser/screen_ai/screen_ai_install_state.h"
 #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
-#include "components/services/screen_ai/public/cpp/screen_ai_install_state.h"
 
 namespace settings {
 
diff --git a/chrome/browser/ui/webui/settings/ash/pdf_ocr_handler_unittest.cc b/chrome/browser/ui/webui/settings/ash/pdf_ocr_handler_unittest.cc
index cc7ba38..8936b13 100644
--- a/chrome/browser/ui/webui/settings/ash/pdf_ocr_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/ash/pdf_ocr_handler_unittest.cc
@@ -7,8 +7,8 @@
 
 #include "base/memory/raw_ptr.h"
 #include "base/test/scoped_feature_list.h"
+#include "chrome/browser/screen_ai/screen_ai_install_state.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/services/screen_ai/public/cpp/screen_ai_install_state.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_task_environment.h"
 #include "content/public/test/test_web_ui.h"
diff --git a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_page_handler.cc b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_page_handler.cc
index 1741dda..c1dbccc 100644
--- a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_page_handler.cc
+++ b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_page_handler.cc
@@ -19,8 +19,8 @@
 #include "url/gurl.h"
 
 #if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
-#include "components/services/screen_ai/public/cpp/screen_ai_service_router.h"
-#include "components/services/screen_ai/public/cpp/screen_ai_service_router_factory.h"
+#include "chrome/browser/screen_ai/screen_ai_service_router.h"
+#include "chrome/browser/screen_ai/screen_ai_service_router_factory.h"
 #endif
 
 using read_anything::mojom::ReadAnythingTheme;
diff --git a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_page_handler.h b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_page_handler.h
index 26d9fab7e..610a25bd 100644
--- a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_page_handler.h
+++ b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_page_handler.h
@@ -21,7 +21,7 @@
 #include "mojo/public/cpp/bindings/remote.h"
 
 #if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
-#include "components/services/screen_ai/public/cpp/screen_ai_install_state.h"
+#include "chrome/browser/screen_ai/screen_ai_install_state.h"
 #endif
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc b/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc
index 03228c4..3cda157 100644
--- a/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc
+++ b/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc
@@ -404,9 +404,9 @@
     return;
   }
 
-  WebAppDialogManager& web_app_dialog_manager =
-      web_app_ui_manager->dialog_manager();
-  if (web_app_dialog_manager.CanUserUninstallWebApp(app_id)) {
+  if (provider->registrar_unsafe().CanUserUninstallWebApp(app_id)) {
+    WebAppDialogManager& web_app_dialog_manager =
+        web_app_ui_manager->dialog_manager();
     webapps::WebappUninstallSource webapp_uninstall_source =
         WebAppPublisherHelper::ConvertUninstallSourceToWebAppUninstallSource(
             uninstall_source);
@@ -785,7 +785,7 @@
 
   DCHECK(provider_);
   DCHECK(
-      provider_->install_finalizer().CanUserUninstallWebApp(web_app->app_id()));
+      provider_->registrar_unsafe().CanUserUninstallWebApp(web_app->app_id()));
   webapps::WebappUninstallSource webapp_uninstall_source =
       ConvertUninstallSourceToWebAppUninstallSource(uninstall_source);
   provider_->install_finalizer().UninstallWebApp(
diff --git a/chrome/browser/web_applications/extensions/externally_managed_app_install_task_unittest.cc b/chrome/browser/web_applications/extensions/externally_managed_app_install_task_unittest.cc
index 171c914..91f6296d 100644
--- a/chrome/browser/web_applications/extensions/externally_managed_app_install_task_unittest.cc
+++ b/chrome/browser/web_applications/extensions/externally_managed_app_install_task_unittest.cc
@@ -219,11 +219,6 @@
             }));
   }
 
-  bool CanUserUninstallWebApp(const AppId& app_id) const override {
-    NOTIMPLEMENTED();
-    return false;
-  }
-
   void UninstallWebApp(const AppId& app_id,
                        webapps::WebappUninstallSource uninstall_source,
                        UninstallWebAppCallback callback) override {
diff --git a/chrome/browser/web_applications/manifest_update_manager_browsertest.cc b/chrome/browser/web_applications/manifest_update_manager_browsertest.cc
index 2fb34ac..056e35a 100644
--- a/chrome/browser/web_applications/manifest_update_manager_browsertest.cc
+++ b/chrome/browser/web_applications/manifest_update_manager_browsertest.cc
@@ -1408,8 +1408,7 @@
   )";
   OverrideManifest(kManifestTemplate, {"blue", kInstallableIconList});
   AppId app_id = InstallPolicyApp();
-  EXPECT_FALSE(
-      GetProvider().install_finalizer().CanUserUninstallWebApp(app_id));
+  EXPECT_FALSE(GetProvider().registrar_unsafe().CanUserUninstallWebApp(app_id));
 
   OverrideManifest(kManifestTemplate, {"red", kInstallableIconList});
   EXPECT_EQ(GetResultAfterPageLoad(GetAppURL()),
@@ -1425,8 +1424,7 @@
 
   // Policy installed apps should continue to be not uninstallable by the user
   // after updating.
-  EXPECT_FALSE(
-      GetProvider().install_finalizer().CanUserUninstallWebApp(app_id));
+  EXPECT_FALSE(GetProvider().registrar_unsafe().CanUserUninstallWebApp(app_id));
 }
 
 IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerBrowserTest,
@@ -1443,8 +1441,7 @@
   )";
   OverrideManifest(kManifestTemplate, {"blue", kInstallableIconList});
   AppId app_id = InstallKioskApp();
-  EXPECT_FALSE(
-      GetProvider().install_finalizer().CanUserUninstallWebApp(app_id));
+  EXPECT_FALSE(GetProvider().registrar_unsafe().CanUserUninstallWebApp(app_id));
 
   OverrideManifest(kManifestTemplate, {"red", kInstallableIconList});
   EXPECT_EQ(GetResultAfterPageLoad(GetAppURL()),
@@ -1460,8 +1457,7 @@
 
   // Kiosk installed apps should continue to be not uninstallable by the user
   // after updating.
-  EXPECT_FALSE(
-      GetProvider().install_finalizer().CanUserUninstallWebApp(app_id));
+  EXPECT_FALSE(GetProvider().registrar_unsafe().CanUserUninstallWebApp(app_id));
 }
 
 IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerBrowserTest,
diff --git a/chrome/browser/web_applications/test/fake_install_finalizer.cc b/chrome/browser/web_applications/test/fake_install_finalizer.cc
index e57c943..7567b13 100644
--- a/chrome/browser/web_applications/test/fake_install_finalizer.cc
+++ b/chrome/browser/web_applications/test/fake_install_finalizer.cc
@@ -77,11 +77,6 @@
                      }));
 }
 
-bool FakeInstallFinalizer::CanUserUninstallWebApp(const AppId& app_id) const {
-  NOTIMPLEMENTED();
-  return false;
-}
-
 void FakeInstallFinalizer::UninstallWebApp(
     const AppId& app_id,
     webapps::WebappUninstallSource uninstall_source,
diff --git a/chrome/browser/web_applications/test/fake_install_finalizer.h b/chrome/browser/web_applications/test/fake_install_finalizer.h
index 5dfcc02..45fd6fe 100644
--- a/chrome/browser/web_applications/test/fake_install_finalizer.h
+++ b/chrome/browser/web_applications/test/fake_install_finalizer.h
@@ -42,7 +42,6 @@
       WebAppManagement::Type source,
       webapps::WebappUninstallSource uninstall_surface,
       UninstallWebAppCallback callback) override;
-  bool CanUserUninstallWebApp(const AppId& app_id) const override;
   void UninstallWebApp(const AppId& app_id,
                        webapps::WebappUninstallSource uninstall_source,
                        UninstallWebAppCallback callback) override;
diff --git a/chrome/browser/web_applications/test/web_app_install_test_utils.cc b/chrome/browser/web_applications/test/web_app_install_test_utils.cc
index 53d690f..98fc35af 100644
--- a/chrome/browser/web_applications/test/web_app_install_test_utils.cc
+++ b/chrome/browser/web_applications/test/web_app_install_test_utils.cc
@@ -122,7 +122,7 @@
   WebAppProvider* const provider = WebAppProvider::GetForTest(profile);
   base::RunLoop run_loop;
 
-  DCHECK(provider->install_finalizer().CanUserUninstallWebApp(app_id));
+  DCHECK(provider->registrar_unsafe().CanUserUninstallWebApp(app_id));
   provider->install_finalizer().UninstallWebApp(
       app_id, webapps::WebappUninstallSource::kAppMenu,
       base::BindLambdaForTesting([&](webapps::UninstallResultCode code) {
diff --git a/chrome/browser/web_applications/web_app_install_finalizer.cc b/chrome/browser/web_applications/web_app_install_finalizer.cc
index 724c7c4..f31d9bde 100644
--- a/chrome/browser/web_applications/web_app_install_finalizer.cc
+++ b/chrome/browser/web_applications/web_app_install_finalizer.cc
@@ -309,13 +309,6 @@
                           uninstall_source, std::move(callback));
 }
 
-bool WebAppInstallFinalizer::CanUserUninstallWebApp(const AppId& app_id) const {
-  DCHECK(started_);
-
-  const WebApp* app = GetWebAppRegistrar().GetAppById(app_id);
-  return app ? app->CanUserUninstallWebApp() : false;
-}
-
 void WebAppInstallFinalizer::UninstallWebApp(
     const AppId& app_id,
     webapps::WebappUninstallSource webapp_uninstall_source,
diff --git a/chrome/browser/web_applications/web_app_install_finalizer.h b/chrome/browser/web_applications/web_app_install_finalizer.h
index 27c6edf..e7775dd 100644
--- a/chrome/browser/web_applications/web_app_install_finalizer.h
+++ b/chrome/browser/web_applications/web_app_install_finalizer.h
@@ -138,8 +138,6 @@
                                webapps::WebappUninstallSource uninstall_surface,
                                UninstallWebAppCallback callback);
 
-  virtual bool CanUserUninstallWebApp(const AppId& app_id) const;
-
   virtual bool CanReparentTab(const AppId& app_id, bool shortcut_created) const;
   virtual void ReparentTab(const AppId& app_id,
                            bool shortcut_created,
diff --git a/chrome/browser/web_applications/web_app_registrar.cc b/chrome/browser/web_applications/web_app_registrar.cc
index 8303e528..bfb8363 100644
--- a/chrome/browser/web_applications/web_app_registrar.cc
+++ b/chrome/browser/web_applications/web_app_registrar.cc
@@ -797,6 +797,11 @@
   return web_app && web_app->IsSubAppInstalledApp();
 }
 
+bool WebAppRegistrar::CanUserUninstallWebApp(const AppId& app_id) const {
+  const WebApp* web_app = GetAppById(app_id);
+  return web_app && web_app->CanUserUninstallWebApp();
+}
+
 bool WebAppRegistrar::IsAllowedLaunchProtocol(
     const AppId& app_id,
     const std::string& protocol_scheme) const {
diff --git a/chrome/browser/web_applications/web_app_registrar.h b/chrome/browser/web_applications/web_app_registrar.h
index 90b9fc9..2e87f03 100644
--- a/chrome/browser/web_applications/web_app_registrar.h
+++ b/chrome/browser/web_applications/web_app_registrar.h
@@ -140,6 +140,10 @@
   // Returns true if the app was installed by the SubApp API.
   bool WasInstalledBySubApp(const AppId& app_id) const;
 
+  // Returns true if the app exists and is allowed to be uninstalled by the user
+  // e.g. it is not policy installed.
+  bool CanUserUninstallWebApp(const AppId& app_id) const;
+
   // Returns the AppIds and URLs of apps externally installed from
   // |install_source|.
   base::flat_map<AppId, base::flat_set<GURL>> GetExternallyInstalledApps(
diff --git a/chrome/browser/xsurface/BUILD.gn b/chrome/browser/xsurface/BUILD.gn
index db849c9..d83f0ef 100644
--- a/chrome/browser/xsurface/BUILD.gn
+++ b/chrome/browser/xsurface/BUILD.gn
@@ -34,6 +34,7 @@
     "android/java/src/org/chromium/chrome/browser/xsurface/feed/FeedUserInteractionReliabilityLogger.java",
     "android/java/src/org/chromium/chrome/browser/xsurface/feed/ReliabilityLoggingTestUtil.java",
     "android/java/src/org/chromium/chrome/browser/xsurface/feed/StreamType.java",
+    "android/java/src/org/chromium/chrome/browser/xsurface/pageinsights/PageInsightsActionsHandler.java",
     "android/java/src/org/chromium/chrome/browser/xsurface/pageinsights/PageInsightsSurfaceRenderer.java",
     "android/java/src/org/chromium/chrome/browser/xsurface/pageinsights/PageInsightsSurfaceScope.java",
     "android/java/src/org/chromium/chrome/browser/xsurface/pageinsights/PageInsightsSurfaceScopeDependencyProvider.java",
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/pageinsights/PageInsightsActionsHandler.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/pageinsights/PageInsightsActionsHandler.java
new file mode 100644
index 0000000..40b837b0
--- /dev/null
+++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/pageinsights/PageInsightsActionsHandler.java
@@ -0,0 +1,38 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.xsurface.pageinsights;
+
+/**
+ * Interface to handle actions invoked on server-provided UI in the Page Insights feature.
+ *
+ * Implemented in Chromium.
+ */
+public interface PageInsightsActionsHandler {
+    String KEY = "PageInsightsActionsHandler";
+
+    /**
+     * Opens the given URL.
+     *
+     * @param url URL to open.
+     * @param doesRequestSpecifySameSession whether the request specified the URL should be opened
+     *         in the same session.
+     */
+    default void openUrl(String url, boolean doesRequestSpecifySameSession) {}
+
+    /**
+     * Brings up sharing sheet to share the given URL.
+     *
+     * @param url the URL to be shared.
+     * @param title the title of the page at the URL.
+     */
+    default void share(String url, String title) {}
+
+    /**
+     * Navigates to a page within the Page Insights feature.
+     *
+     * @param pageId the ID of the page to navigate to.
+     */
+    default void navigateToPageInsightsPage(int pageId) {}
+}
diff --git a/chrome/build/lacros-arm64.pgo.txt b/chrome/build/lacros-arm64.pgo.txt
index 78d440d..f5af917 100644
--- a/chrome/build/lacros-arm64.pgo.txt
+++ b/chrome/build/lacros-arm64.pgo.txt
@@ -1 +1 @@
-chrome-chromeos-arm64-generic-main-1684778401-b5797460a83398c9fc6e51e78ab453739ad97d76.profdata
+chrome-chromeos-arm64-generic-main-1684800790-2eb37f1b962e98a82da74d41c53ff52e0905d5e0.profdata
diff --git a/chrome/build/lacros64.pgo.txt b/chrome/build/lacros64.pgo.txt
index 86d1b15..50b6c79 100644
--- a/chrome/build/lacros64.pgo.txt
+++ b/chrome/build/lacros64.pgo.txt
@@ -1 +1 @@
-chrome-chromeos-amd64-generic-main-1684785336-2e463c45a163afbf2f62d884ccc0e6a58e5f3666.profdata
+chrome-chromeos-amd64-generic-main-1684813306-b0a28f0efe03511d308be76420c405b9a8f27bee.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 6f714c2ce..b46d9cac 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1684778401-192ae64f69b26a07fc8a9efb282b00be6f56ee93.profdata
+chrome-linux-main-1684821564-421b6671dc07a56190e5f84fc024e68bb4f0f800.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index 7f6d2cf..5b9c03a 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1684792775-0882070163cde1b8d13c06cd5c4e55846cf65a0f.profdata
+chrome-mac-arm-main-1684828565-d089b1a7acbd62ae7b39c76a508b52cd12fe77fd.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 14e03e55..1a157f0 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1684778401-447b1904cbdcc13ab75d8a1c6a1372470eb6968a.profdata
+chrome-mac-main-1684821564-325844468c7319669ba9e236032f23ba915553c4.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 0818a97..98ccade 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1684756679-c8cf4c7c9fba95e3900211a854aed10336e4decc.profdata
+chrome-win32-main-1684821564-e32a42907879d19978a43e3e0d3b4f61b083bb28.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index b03f2e1..74b32f5 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1684788567-8fa1d990c0007eeebc585390e691e7a879c8106c.profdata
+chrome-win64-main-1684821564-6842b049a60ac141d2f6273b25fa436352ff0992.profdata
diff --git a/chrome/common/extensions/api/smart_card_provider_private.idl b/chrome/common/extensions/api/smart_card_provider_private.idl
index 2442c42..96befce 100644
--- a/chrome/common/extensions/api/smart_card_provider_private.idl
+++ b/chrome/common/extensions/api/smart_card_provider_private.idl
@@ -176,6 +176,12 @@
     // reportDataResult.
     [maxListeners=1] static void onControlRequested(long requestId,
         long scardHandle, long controlCode, ArrayBuffer data);
+
+    // Browser requested a SCardGetAttrib call.
+    // Extension must report the result to the browser by calling
+    // reportDataResult.
+    [maxListeners=1] static void onGetAttribRequested(long requestId,
+        long scardHandle, long attribId);
   };
 
   interface Functions {
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 43d87453..8282edeb 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -2563,8 +2563,8 @@
         "../browser/renderer_context_menu/pdf_ocr_menu_observer_browsertest.cc",
       ]
       deps += [
-        "//components/services/screen_ai/public/cpp:screen_ai_install_state",
-        "//components/services/screen_ai/public/cpp:screen_ai_service_router_factory",
+        "//chrome/browser/screen_ai:screen_ai_install_state",
+        "//chrome/browser/screen_ai:screen_ai_service_router_factory",
         "//components/services/screen_ai/public/mojom",
       ]
     }
@@ -3342,6 +3342,12 @@
         "../browser/user_bypass/user_bypass_web_contents_observer_browsertest.cc",
       ]
 
+      if (is_win) {
+        data_deps += [
+          "//chrome/browser/extensions/api:native_messaging_test_echo_&_host",
+        ]
+      }
+
       if (is_chromeos_ash && enable_extensions) {
         deps +=
             [ "//chromeos/ash/components/network/portal_detector:test_support" ]
diff --git a/chrome/test/data/extensions/api_test/native_messaging_send_native_message_exe/manifest.json b/chrome/test/data/extensions/api_test/native_messaging_send_native_message_exe/manifest.json
new file mode 100644
index 0000000..73124c9
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/native_messaging_send_native_message_exe/manifest.json
@@ -0,0 +1,14 @@
+{
+    // Extension ID: knldjmfmopnpolahpmmgbagdohdnhkik
+    "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDcBHwzDvyBQ6bDppkIs9MP4ksKqCMyXQ/A52JivHZKh4YO/9vJsT3oaYhSpDCE9RPocOEQvwsHsFReW2nUEc6OLLyoCFFxIb7KkLGsmfakkut/fFdNJYh0xOTbSN8YvLWcqph09XAY2Y/f0AL7vfO1cuCqtkMt8hFrBGWxDdf9CQIDAQAB",
+    "version": "1.0.0.0",
+    "manifest_version": 3,
+    "name": "native messaging Windows .EXE test",
+    "description": "Tests one time messaging functionality to a Windows .EXE host.",
+    "background": {
+      "service_worker": "test.js"
+    },
+    "permissions": [
+      "nativeMessaging"
+    ]
+  }
\ No newline at end of file
diff --git a/chrome/test/data/extensions/api_test/native_messaging_send_native_message_exe/test.js b/chrome/test/data/extensions/api_test/native_messaging_send_native_message_exe/test.js
new file mode 100644
index 0000000..e61a66669
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/native_messaging_send_native_message_exe/test.js
@@ -0,0 +1,25 @@
+// 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.
+
+var appName = 'com.google.chrome.test.exe.echo';
+
+chrome.test.getConfig(function(config) {
+  chrome.test.runTests([
+    function sendMessageWithCallback() {
+      var message = {echo: 'TryCallback', id: 1};
+      chrome.runtime.sendNativeMessage(
+          appName, message, chrome.test.callbackPass(function(response) {
+            chrome.test.assertEq(1, response.id);
+            chrome.test.assertEq('TryCallback', response.echo);
+          }));
+    },
+    async function sendMessageWithPromise() {
+      var message = {echo: 'TryPromise', id: 2};
+      const response = await chrome.runtime.sendNativeMessage(appName, message);
+      chrome.test.assertEq(2, response.id);
+      chrome.test.assertEq('TryPromise', response.echo);
+      chrome.test.succeed();
+    },
+  ]);
+});
\ No newline at end of file
diff --git a/chrome/test/data/extensions/api_test/tabs/basics/muted/muted.js b/chrome/test/data/extensions/api_test/tabs/basics/muted/muted.js
index 554d60d..00711d6f8 100644
--- a/chrome/test/data/extensions/api_test/tabs/basics/muted/muted.js
+++ b/chrome/test/data/extensions/api_test/tabs/basics/muted/muted.js
@@ -10,9 +10,17 @@
 loadScript.then(async function() {
 chrome.test.runTests([
   function createTab() {
-    chrome.tabs.create({}, pass(function(tab) {
+    chrome.tabs.create({}, function(tab) {
       testTabId_ = tab.id;
-    }));
+      // Wait for tab loading complete.
+      chrome.tabs.onUpdated.addListener(function local(tabId, changeInfo, tab) {
+        if (tabId != testTabId_ || changeInfo.status != 'complete') {
+          return;
+        }
+        chrome.tabs.onUpdated.removeListener(local);
+        chrome.test.succeed();
+      })
+    });
   },
 
   function mutedStartsFalse() {
@@ -36,6 +44,9 @@
     };
 
     chrome.tabs.onUpdated.addListener(function local(tabId, changeInfo, tab) {
+      if (tabId != testTabId_ || !changeInfo.mutedInfo) {
+        return;  // Ignore unrelated events.
+      }
       assertEq(expectedAfterMute, changeInfo.mutedInfo);
       chrome.tabs.onUpdated.removeListener(local);
       chrome.test.succeed();
@@ -46,16 +57,11 @@
 
   function testStaysMutedAfterChangingWindow() {
     chrome.windows.create({}, function(window) {
-      chrome.tabs.onUpdated.addListener(function local(tabId, changeInfo, tab) {
-        if (changeInfo.status != 'complete')
-          return;
-
-        chrome.tabs.onUpdated.removeListener(local);
-        chrome.test.succeed();
-      });
+      // chrome.tabs.onUpdated is not sent on tab movement.
       chrome.tabs.move(testTabId_, {windowId: window.id, index: -1},
                        function(tab) {
         assertEq(true, tab.mutedInfo.muted);
+        chrome.test.succeed();
       });
     });
   },
@@ -68,6 +74,9 @@
     };
 
     chrome.tabs.onUpdated.addListener(function local(tabId, changeInfo, tab) {
+      if (tabId != testTabId_ || !changeInfo.mutedInfo) {
+        return;  // Ignore unrelated events.
+      }
       chrome.tabs.onUpdated.removeListener(local);
       assertEq(expectedAfterUnmute, changeInfo.mutedInfo);
       chrome.test.succeed();
diff --git a/chromecast/cast_core/runtime/browser/cast_runtime_histogram_flattener_unittest.cc b/chromecast/cast_core/runtime/browser/cast_runtime_histogram_flattener_unittest.cc
index 9c1d51e..bf9ac8d 100644
--- a/chromecast/cast_core/runtime/browser/cast_runtime_histogram_flattener_unittest.cc
+++ b/chromecast/cast_core/runtime/browser/cast_runtime_histogram_flattener_unittest.cc
@@ -4,7 +4,10 @@
 
 #include "chromecast/cast_core/runtime/browser/cast_runtime_histogram_flattener.h"
 
+#include <memory>
+
 #include "base/metrics/histogram_macros.h"
+#include "base/metrics/statistics_recorder.h"
 #include "chromecast/cast_core/runtime/browser/cast_runtime_metrics_test_helpers.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -27,9 +30,25 @@
 class CastRuntimeHistogramFlattenerTest : public ::testing::Test {
  public:
   void SetUp() override {
+    // Create the temporary stats recorder to get a clean state
+    // for each test.
+    statistics_recorder_ =
+        base::StatisticsRecorder::CreateTemporaryForTesting();
+
     // Ensure existing deltas from previous tests in the process are cleared.
     ASSERT_TRUE(GetHistogramDeltas().empty());
   }
+
+  void TearDown() override {
+    // Destroy the temporary stats recorder, implicitly restoring
+    // the previous global stats recorder.
+    statistics_recorder_.reset();
+  }
+
+  // Stand-in `StatisticsRecorder` for this test suite, to ensure
+  // each test is isolated from everything else in the process that
+  // could emit histograms.
+  std::unique_ptr<base::StatisticsRecorder> statistics_recorder_;
 };
 
 TEST_F(CastRuntimeHistogramFlattenerTest, Empty) {
diff --git a/chromeos/ash/components/audio/audio_devices_pref_handler.h b/chromeos/ash/components/audio/audio_devices_pref_handler.h
index fb009f0..fc54afdd 100644
--- a/chromeos/ash/components/audio/audio_devices_pref_handler.h
+++ b/chromeos/ash/components/audio/audio_devices_pref_handler.h
@@ -72,18 +72,6 @@
   // Reads the audio output allowed value from prefs.
   virtual bool GetAudioOutputAllowedValue() const = 0;
 
-  // Reads the speak-on-mute detection enabled value from prefs.
-  virtual bool GetSpeakOnMuteDetectionEnabledValue() const = 0;
-
-  // Reads the should show speak-on-mute detection opt-in nudge value from
-  // prefs.
-  virtual bool GetShouldShowSpeakOnMuteOptInNudgeValue() const = 0;
-  // Sets the should show speak-on-mute detection opt-in nudge value from prefs.
-  // It should be set to false if user has changed the speak-on-mute detection
-  // enabled pref.
-  virtual void SetShouldShowSpeakOnMuteOptInNudgeValue(
-      bool should_show_opt_in_nudge) = 0;
-
   // Adds an audio preference observer.
   virtual void AddAudioPrefObserver(AudioPrefObserver* observer) = 0;
   // Removes an audio preference observer.
diff --git a/chromeos/ash/components/audio/audio_devices_pref_handler_impl.cc b/chromeos/ash/components/audio/audio_devices_pref_handler_impl.cc
index 771f3337..35a84389 100644
--- a/chromeos/ash/components/audio/audio_devices_pref_handler_impl.cc
+++ b/chromeos/ash/components/audio/audio_devices_pref_handler_impl.cc
@@ -347,21 +347,6 @@
   return local_state_->GetBoolean(prefs::kAudioOutputAllowed);
 }
 
-bool AudioDevicesPrefHandlerImpl::GetSpeakOnMuteDetectionEnabledValue() const {
-  return local_state_->GetBoolean(prefs::kUserSpeakOnMuteDetectionEnabled);
-}
-
-bool AudioDevicesPrefHandlerImpl::GetShouldShowSpeakOnMuteOptInNudgeValue()
-    const {
-  return local_state_->GetBoolean(prefs::kShouldShowSpeakOnMuteOptInNudge);
-}
-
-void AudioDevicesPrefHandlerImpl::SetShouldShowSpeakOnMuteOptInNudgeValue(
-    bool should_show_opt_in_nudge) {
-  local_state_->SetBoolean(prefs::kShouldShowSpeakOnMuteOptInNudge,
-                           should_show_opt_in_nudge);
-}
-
 void AudioDevicesPrefHandlerImpl::AddAudioPrefObserver(
     AudioPrefObserver* observer) {
   observers_.AddObserver(observer);
@@ -429,13 +414,6 @@
       base::BindRepeating(&AudioDevicesPrefHandlerImpl::NotifyAudioPolicyChange,
                           base::Unretained(this));
   pref_change_registrar_.Add(prefs::kAudioOutputAllowed, callback);
-
-  // Observe the change of speak-on-mute detection pref.
-  base::RepeatingClosure speak_on_mute_callback = base::BindRepeating(
-      &AudioDevicesPrefHandlerImpl::NotifySpeakOnMuteDetectionChange,
-      base::Unretained(this));
-  pref_change_registrar_.Add(prefs::kUserSpeakOnMuteDetectionEnabled,
-                             speak_on_mute_callback);
 }
 
 void AudioDevicesPrefHandlerImpl::LoadDevicesMutePref() {
@@ -546,12 +524,6 @@
     observer.OnAudioPolicyPrefChanged();
 }
 
-void AudioDevicesPrefHandlerImpl::NotifySpeakOnMuteDetectionChange() {
-  for (auto& observer : observers_) {
-    observer.OnSpeakOnMuteDetectionPrefChanged();
-  }
-}
-
 // static
 void AudioDevicesPrefHandlerImpl::RegisterPrefs(PrefRegistrySimple* registry) {
   registry->RegisterDictionaryPref(prefs::kAudioDevicesVolumePercent);
@@ -559,9 +531,6 @@
   registry->RegisterDictionaryPref(prefs::kAudioDevicesMute);
   registry->RegisterDictionaryPref(prefs::kAudioDevicesState);
   registry->RegisterBooleanPref(prefs::kInputNoiseCancellationEnabled, false);
-  registry->RegisterBooleanPref(prefs::kUserSpeakOnMuteDetectionEnabled, false);
-  registry->RegisterBooleanPref(prefs::kShouldShowSpeakOnMuteOptInNudge, true);
-  registry->RegisterIntegerPref(prefs::kSpeakOnMuteOptInNudgeShownCount, 0);
 
   // Register the prefs backing the audio muting policies.
   // Policy for audio input is handled by kAudioCaptureAllowed in the Chrome
diff --git a/chromeos/ash/components/audio/audio_devices_pref_handler_impl.h b/chromeos/ash/components/audio/audio_devices_pref_handler_impl.h
index cea0f33..c485314 100644
--- a/chromeos/ash/components/audio/audio_devices_pref_handler_impl.h
+++ b/chromeos/ash/components/audio/audio_devices_pref_handler_impl.h
@@ -60,12 +60,6 @@
 
   bool GetAudioOutputAllowedValue() const override;
 
-  bool GetSpeakOnMuteDetectionEnabledValue() const override;
-
-  bool GetShouldShowSpeakOnMuteOptInNudgeValue() const override;
-  void SetShouldShowSpeakOnMuteOptInNudgeValue(
-      bool should_show_opt_in_nudge) override;
-
   void AddAudioPrefObserver(AudioPrefObserver* observer) override;
   void RemoveAudioPrefObserver(AudioPrefObserver* observer) override;
 
@@ -137,9 +131,6 @@
   // Notifies the AudioPrefObserver for audio policy pref changes.
   void NotifyAudioPolicyChange();
 
-  // Notifies the AudioPrefObserver for speak-on-mute detection pref changes.
-  void NotifySpeakOnMuteDetectionChange();
-
   base::Value::Dict device_mute_settings_;
   base::Value::Dict device_volume_settings_;
   base::Value::Dict device_gain_settings_;
diff --git a/chromeos/ash/components/audio/audio_devices_pref_handler_impl_unittest.cc b/chromeos/ash/components/audio/audio_devices_pref_handler_impl_unittest.cc
index b5f11af..27dc6ca 100644
--- a/chromeos/ash/components/audio/audio_devices_pref_handler_impl_unittest.cc
+++ b/chromeos/ash/components/audio/audio_devices_pref_handler_impl_unittest.cc
@@ -478,13 +478,6 @@
   EXPECT_TRUE(audio_pref_handler_->GetNoiseCancellationState());
 }
 
-TEST_P(AudioDevicesPrefHandlerTest,
-       ShouldShowSpeakOnMuteOptInNudgePrefRegistered) {
-  EXPECT_TRUE(audio_pref_handler_->GetShouldShowSpeakOnMuteOptInNudgeValue());
-  audio_pref_handler_->SetShouldShowSpeakOnMuteOptInNudgeValue(false);
-  EXPECT_FALSE(audio_pref_handler_->GetShouldShowSpeakOnMuteOptInNudgeValue());
-}
-
 TEST_P(AudioDevicesPrefHandlerTest, UserPriority) {
   AudioDevice device = GetDeviceWithVersion(2);
   EXPECT_EQ(kUserPriorityNone, GetUserPriority(device));
diff --git a/chromeos/ash/components/audio/audio_devices_pref_handler_stub.cc b/chromeos/ash/components/audio/audio_devices_pref_handler_stub.cc
index b5152d9..6db3a1e5 100644
--- a/chromeos/ash/components/audio/audio_devices_pref_handler_stub.cc
+++ b/chromeos/ash/components/audio/audio_devices_pref_handler_stub.cc
@@ -133,20 +133,6 @@
   return is_audio_output_allowed_;
 }
 
-bool AudioDevicesPrefHandlerStub::GetSpeakOnMuteDetectionEnabledValue() const {
-  return is_speak_on_mute_detection_enabled_;
-}
-
-bool AudioDevicesPrefHandlerStub::GetShouldShowSpeakOnMuteOptInNudgeValue()
-    const {
-  return should_show_speak_on_mute_opt_in_nudge_;
-}
-
-void AudioDevicesPrefHandlerStub::SetShouldShowSpeakOnMuteOptInNudgeValue(
-    bool should_show_opt_in_nudge) {
-  should_show_speak_on_mute_opt_in_nudge_ = should_show_opt_in_nudge;
-}
-
 void AudioDevicesPrefHandlerStub::SetAudioOutputAllowedValue(
     bool is_audio_output_allowed) {
   is_audio_output_allowed_ = is_audio_output_allowed;
@@ -155,14 +141,6 @@
   }
 }
 
-void AudioDevicesPrefHandlerStub::SetSpeakOnMuteDetectionEnabledValue(
-    bool is_speak_on_mute_detection_enabled) {
-  is_speak_on_mute_detection_enabled_ = is_speak_on_mute_detection_enabled;
-  for (auto& observer : observers_) {
-    observer.OnSpeakOnMuteDetectionPrefChanged();
-  }
-}
-
 void AudioDevicesPrefHandlerStub::AddAudioPrefObserver(
     AudioPrefObserver* observer) {
   observers_.AddObserver(observer);
diff --git a/chromeos/ash/components/audio/audio_devices_pref_handler_stub.h b/chromeos/ash/components/audio/audio_devices_pref_handler_stub.h
index 30bbb439..a8792a5 100644
--- a/chromeos/ash/components/audio/audio_devices_pref_handler_stub.h
+++ b/chromeos/ash/components/audio/audio_devices_pref_handler_stub.h
@@ -54,12 +54,6 @@
       const std::vector<AudioDevice>& connected_devices,
       size_t keep_devices) override;
   bool GetAudioOutputAllowedValue() const override;
-  bool GetSpeakOnMuteDetectionEnabledValue() const override;
-
-  bool GetShouldShowSpeakOnMuteOptInNudgeValue() const override;
-  void SetShouldShowSpeakOnMuteOptInNudgeValue(
-      bool should_show_opt_in_nudge) override;
-
   void AddAudioPrefObserver(AudioPrefObserver* observer) override;
   void RemoveAudioPrefObserver(AudioPrefObserver* observer) override;
 
@@ -67,8 +61,6 @@
   void SetNoiseCancellationState(bool noise_cancellation_state) override;
 
   void SetAudioOutputAllowedValue(bool is_audio_output_allowed);
-  void SetSpeakOnMuteDetectionEnabledValue(
-      bool is_speak_on_mute_detection_enabled);
 
  protected:
   ~AudioDevicesPrefHandlerStub() override;
@@ -82,8 +74,6 @@
   base::ObserverList<AudioPrefObserver>::Unchecked observers_;
 
   bool is_audio_output_allowed_ = true;
-  bool is_speak_on_mute_detection_enabled_ = false;
-  bool should_show_speak_on_mute_opt_in_nudge_ = true;
   bool noise_cancellation_state_ = true;
 };
 
diff --git a/chromeos/ash/components/audio/audio_pref_observer.h b/chromeos/ash/components/audio/audio_pref_observer.h
index fa349be..bbd93de3 100644
--- a/chromeos/ash/components/audio/audio_pref_observer.h
+++ b/chromeos/ash/components/audio/audio_pref_observer.h
@@ -15,9 +15,6 @@
   // Called when audio policy prefs changed.
   virtual void OnAudioPolicyPrefChanged() = 0;
 
-  // Called when speak-on-mute detection prefs changed.
-  virtual void OnSpeakOnMuteDetectionPrefChanged() = 0;
-
  protected:
   virtual ~AudioPrefObserver() {}
 };
diff --git a/chromeos/ash/components/audio/cras_audio_handler.cc b/chromeos/ash/components/audio/cras_audio_handler.cc
index c74b863c..425a4fb 100644
--- a/chromeos/ash/components/audio/cras_audio_handler.cc
+++ b/chromeos/ash/components/audio/cras_audio_handler.cc
@@ -1254,10 +1254,6 @@
   ApplyAudioPolicy();
 }
 
-void CrasAudioHandler::OnSpeakOnMuteDetectionPrefChanged() {
-  ApplySpeakOnMuteDetectionState();
-}
-
 const AudioDevice* CrasAudioHandler::GetDeviceFromId(uint64_t device_id) const {
   AudioDeviceMap::const_iterator it = audio_devices_.find(device_id);
   if (it == audio_devices_.end())
@@ -1424,7 +1420,9 @@
   if (input_muted_by_microphone_mute_switch_)
     SetInputMute(true, InputMuteChangeMethod::kPhysicalShutter);
 
-  ApplySpeakOnMuteDetectionState();
+  // Sets speak-on-mute detection enabled based on feature flag.
+  CrasAudioClient::Get()->SetSpeakOnMuteDetection(
+      features::IsSpeakOnMuteEnabled());
 }
 
 void CrasAudioHandler::ApplyAudioPolicy() {
@@ -1439,27 +1437,6 @@
   // media system.
 }
 
-void CrasAudioHandler::ApplySpeakOnMuteDetectionState() {
-  if (!features::IsSpeakOnMuteEnabled()) {
-    return;
-  }
-
-  bool som_on = audio_pref_handler_->GetSpeakOnMuteDetectionEnabledValue();
-
-  if (speak_on_mute_detection_on_ == som_on) {
-    return;
-  }
-
-  speak_on_mute_detection_on_ = som_on;
-  // Sets speak-on-mute detection enabled based on pref value.
-  CrasAudioClient::Get()->SetSpeakOnMuteDetection(speak_on_mute_detection_on_);
-
-  // No longer shows the opt-in nudge as user has changed the speak-on-mute
-  // detection setting.
-  audio_pref_handler_->SetShouldShowSpeakOnMuteOptInNudgeValue(
-      /*should_show_opt_in_nudge=*/false);
-}
-
 void CrasAudioHandler::UpdateAudioMute() {
   if (output_mute_forced_by_policy_ ||
       output_mute_forced_by_security_curtain_) {
diff --git a/chromeos/ash/components/audio/cras_audio_handler.h b/chromeos/ash/components/audio/cras_audio_handler.h
index 2c9bedc..6af888de 100644
--- a/chromeos/ash/components/audio/cras_audio_handler.h
+++ b/chromeos/ash/components/audio/cras_audio_handler.h
@@ -557,7 +557,6 @@
 
   // AudioPrefObserver overrides.
   void OnAudioPolicyPrefChanged() override;
-  void OnSpeakOnMuteDetectionPrefChanged() override;
 
   // Sets the |active_device| to be active.
   // If |notify|, notifies Active*NodeChange.
@@ -608,10 +607,6 @@
   // change notification is received.
   void ApplyAudioPolicy();
 
-  // Applies the speak-on-mute detection whenever the user logs in or detection
-  // change notification is received.
-  void ApplySpeakOnMuteDetectionState();
-
   // Helper method to apply the conditional audio mute change.
   void UpdateAudioMute();
 
@@ -908,9 +903,6 @@
   bool input_device_selected_by_user_ = false;
   bool output_device_selected_by_user_ = false;
 
-  // Whether the speak-on-mute detection was enabled by user.
-  bool speak_on_mute_detection_on_ = false;
-
   // Task runner of browser main thread. All member variables should be accessed
   // on this thread.
   scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
diff --git a/chromeos/ash/components/audio/cras_audio_handler_unittest.cc b/chromeos/ash/components/audio/cras_audio_handler_unittest.cc
index 681891f..a6edc6d 100644
--- a/chromeos/ash/components/audio/cras_audio_handler_unittest.cc
+++ b/chromeos/ash/components/audio/cras_audio_handler_unittest.cc
@@ -10,7 +10,6 @@
 #include <memory>
 #include <vector>
 
-#include "ash/constants/ash_features.h"
 #include "base/functional/bind.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/ref_counted.h"
@@ -18,7 +17,6 @@
 #include "base/system/system_monitor.h"
 #include "base/task/single_thread_task_runner.h"
 #include "base/test/metrics/histogram_tester.h"
-#include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "base/values.h"
 #include "chromeos/ash/components/audio/audio_devices_pref_handler.h"
@@ -363,9 +361,7 @@
  public:
   CrasAudioHandlerTest()
       : task_environment_(
-            base::test::SingleThreadTaskEnvironment::MainThreadType::UI) {
-    scoped_feature_list_.InitAndEnableFeature(features::kSpeakOnMuteEnabled);
-  }
+            base::test::SingleThreadTaskEnvironment::MainThreadType::UI) {}
 
   CrasAudioHandlerTest(const CrasAudioHandlerTest&) = delete;
   CrasAudioHandlerTest& operator=(const CrasAudioHandlerTest&) = delete;
@@ -577,7 +573,6 @@
   std::unique_ptr<FakeMediaControllerManager> fake_manager_;
   std::unique_ptr<FakeVideoCaptureManager> video_capture_manager_;
   base::HistogramTester histogram_tester_;
-  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
 class HDMIRediscoverWaiter {
@@ -5153,39 +5148,4 @@
 
   EXPECT_EQ(1, test_observer_->noise_cancellation_state_change_count());
 }
-
-TEST_P(CrasAudioHandlerTest, SpeakOnMuteDetectionPrefSwitchTest) {
-  AudioNodeList audio_nodes = GenerateAudioNodeList({});
-  // Set up initial audio devices, only with internal mic.
-  AudioNode internalMic = GenerateAudioNode(kInternalMic);
-  audio_nodes.push_back(internalMic);
-  // Simulate enable pref for noise cancellation.
-  SetUpCrasAudioHandlerWithPrimaryActiveNode(audio_nodes, internalMic);
-
-  // Speak-on-mute detection should still be disabled since the pref is
-  // disabled by default.
-  EXPECT_FALSE(fake_cras_audio_client()->speak_on_mute_detection_enabled());
-  EXPECT_FALSE(audio_pref_handler_->GetSpeakOnMuteDetectionEnabledValue());
-  // `kShouldShowSpeakOnMuteOptInNudge` pref should be enabled by default.
-  EXPECT_TRUE(audio_pref_handler_->GetShouldShowSpeakOnMuteOptInNudgeValue());
-
-  // Simulate enable pref for speak-on-mute detection, which should enable
-  // speak-on-mute detection.
-  audio_pref_handler_->SetSpeakOnMuteDetectionEnabledValue(
-      /*is_speak_on_mute_detection_enabled=*/true);
-  EXPECT_TRUE(fake_cras_audio_client()->speak_on_mute_detection_enabled());
-  // `kShouldShowSpeakOnMuteOptInNudge` pref should be disabled as the
-  // `kUserSpeakOnMuteDetectionEnabled` pref has been changed.
-  EXPECT_FALSE(audio_pref_handler_->GetShouldShowSpeakOnMuteOptInNudgeValue());
-
-  // Simulate disable pref for speak-on-mute detection, which should disable
-  // speak-on-mute detection.
-  audio_pref_handler_->SetSpeakOnMuteDetectionEnabledValue(
-      /*is_speak_on_mute_detection_enabled=*/false);
-  EXPECT_FALSE(fake_cras_audio_client()->speak_on_mute_detection_enabled());
-  // `kShouldShowSpeakOnMuteOptInNudge` pref should be disabled as the
-  // `kUserSpeakOnMuteDetectionEnabled` pref has been changed.
-  EXPECT_FALSE(audio_pref_handler_->GetShouldShowSpeakOnMuteOptInNudgeValue());
-}
-
 }  // namespace ash
diff --git a/chromeos/ash/components/dbus/audio/fake_cras_audio_client.cc b/chromeos/ash/components/dbus/audio/fake_cras_audio_client.cc
index b4ade42..89b21c2 100644
--- a/chromeos/ash/components/dbus/audio/fake_cras_audio_client.cc
+++ b/chromeos/ash/components/dbus/audio/fake_cras_audio_client.cc
@@ -311,9 +311,7 @@
 
 void FakeCrasAudioClient::SetFlossEnabled(bool enabled) {}
 
-void FakeCrasAudioClient::SetSpeakOnMuteDetection(bool enabled) {
-  speak_on_mute_detection_enabled_ = enabled;
-}
+void FakeCrasAudioClient::SetSpeakOnMuteDetection(bool enabled) {}
 
 void FakeCrasAudioClient::AddActiveInputNode(uint64_t node_id) {
   for (size_t i = 0; i < node_list_.size(); ++i) {
diff --git a/chromeos/ash/components/dbus/audio/fake_cras_audio_client.h b/chromeos/ash/components/dbus/audio/fake_cras_audio_client.h
index c8a9d594..d1dcdb59 100644
--- a/chromeos/ash/components/dbus/audio/fake_cras_audio_client.h
+++ b/chromeos/ash/components/dbus/audio/fake_cras_audio_client.h
@@ -156,10 +156,6 @@
     return noise_cancellation_enabled_;
   }
 
-  bool speak_on_mute_detection_enabled() const {
-    return speak_on_mute_detection_enabled_;
-  }
-
  private:
   // Finds a node in the list based on the id.
   AudioNodeList::iterator FindNode(uint64_t node_id);
@@ -177,7 +173,6 @@
   uint32_t noise_cancellation_enabled_counter_ = 0;
   int32_t number_non_chrome_output_streams_ = 0;
   bool noise_cancellation_enabled_ = false;
-  bool speak_on_mute_detection_enabled_ = false;
   // Maps audio client type to the number of active input streams for clients
   // with the type specified
   ClientTypeToInputStreamCount active_input_streams_;
diff --git a/chromeos/ash/components/drivefs/fake_drivefs.cc b/chromeos/ash/components/drivefs/fake_drivefs.cc
index 339e23cc..ba06a6b 100644
--- a/chromeos/ash/components/drivefs/fake_drivefs.cc
+++ b/chromeos/ash/components/drivefs/fake_drivefs.cc
@@ -360,6 +360,7 @@
   stored_metadata.shared = metadata.shared;
   stored_metadata.shortcut = metadata.shortcut;
   stored_metadata.alternate_url = metadata.alternate_url;
+  stored_metadata.can_pin = metadata.can_pin;
 }
 
 void FakeDriveFs::DisplayConfirmDialog(
@@ -378,6 +379,16 @@
   return absl::nullopt;
 }
 
+bool FakeDriveFs::SetCanPin(const std::string& path, bool can_pin) {
+  for (auto& metadata : metadata_) {
+    if (metadata.first.value() == path) {
+      metadata.second.can_pin = can_pin;
+      return true;
+    }
+  }
+  return false;
+}
+
 absl::optional<FakeDriveFs::FileMetadata> FakeDriveFs::GetItemMetadata(
     const base::FilePath& path) {
   const auto& metadata = metadata_.find(path);
@@ -450,8 +461,11 @@
 
   metadata->capabilities = stored_metadata.capabilities.Clone();
   metadata->stable_id = stored_metadata.stable_id;
+  using CanPinStatus = mojom::FileMetadata::CanPinStatus;
+  metadata->can_pin =
+      (stored_metadata.can_pin) ? CanPinStatus::kOk : CanPinStatus::kDisabled;
   if (stored_metadata.hosted) {
-    metadata->can_pin = mojom::FileMetadata::CanPinStatus::kDisabled;
+    metadata->can_pin = CanPinStatus::kDisabled;
   }
   if (stored_metadata.shortcut) {
     metadata->shortcut_details = mojom::ShortcutDetails::New();
diff --git a/chromeos/ash/components/drivefs/fake_drivefs.h b/chromeos/ash/components/drivefs/fake_drivefs.h
index d563bf0..b30156a 100644
--- a/chromeos/ash/components/drivefs/fake_drivefs.h
+++ b/chromeos/ash/components/drivefs/fake_drivefs.h
@@ -41,6 +41,7 @@
   std::string doc_id;
   std::string alternate_url;
   bool shortcut = false;
+  bool can_pin = true;
 };
 
 class FakeDriveFsBootstrapListener : public DriveFsBootstrapListener {
@@ -125,6 +126,8 @@
 
   absl::optional<bool> IsItemPinned(const std::string& path);
 
+  bool SetCanPin(const std::string& path, bool can_pin);
+
   struct FileMetadata {
     FileMetadata();
     FileMetadata(const FileMetadata&);
@@ -143,6 +146,7 @@
     int64_t stable_id = 0;
     std::string alternate_url;
     bool shortcut = false;
+    bool can_pin = true;
   };
 
   absl::optional<FakeDriveFs::FileMetadata> GetItemMetadata(
diff --git a/chromeos/ash/components/phonehub/recent_apps_interaction_handler_impl_unittest.cc b/chromeos/ash/components/phonehub/recent_apps_interaction_handler_impl_unittest.cc
index e4a857f9f5..24f64f8 100644
--- a/chromeos/ash/components/phonehub/recent_apps_interaction_handler_impl_unittest.cc
+++ b/chromeos/ash/components/phonehub/recent_apps_interaction_handler_impl_unittest.cc
@@ -911,18 +911,20 @@
   EXPECT_EQ(handler().connection_status_for_testing(),
             ConnectionStatus::kConnectionStatusDisconnected);
 
+  // Any transition to "connected" should update ConnUX to connected.
   NotifyConnectionStatusChanged(ConnectionStatus::kConnectionStatusConnected);
   EXPECT_EQ(handler().connection_status_for_testing(),
             ConnectionStatus::kConnectionStatusConnected);
 
+  // Only background failures update the ConnUX state, app stream failures
+  // should not.
   NotifyConnectionStatusChanged(ConnectionStatus::kConnectionStatusFailed);
   EXPECT_EQ(handler().connection_status_for_testing(),
-            ConnectionStatus::kConnectionStatusFailed);
-
+            ConnectionStatus::kConnectionStatusConnected);
   NotifyConnectionStatusChanged(
       ConnectionStatus::kConnectionStatusDisconnected);
   EXPECT_EQ(handler().connection_status_for_testing(),
-            ConnectionStatus::kConnectionStatusFailed);
+            ConnectionStatus::kConnectionStatusConnected);
 }
 
 TEST_F(RecentAppsInteractionHandlerTest,
diff --git a/chromeos/crosapi/mojom/BUILD.gn b/chromeos/crosapi/mojom/BUILD.gn
index d70d8a41..8c09d1d 100644
--- a/chromeos/crosapi/mojom/BUILD.gn
+++ b/chromeos/crosapi/mojom/BUILD.gn
@@ -56,6 +56,7 @@
     "idle_service.mojom",
     "image_writer.mojom",
     "in_session_auth.mojom",
+    "kerberos_in_browser.mojom",
     "keystore_error.mojom",
     "keystore_service.mojom",
     "kiosk_session_service.mojom",
diff --git a/chromeos/crosapi/mojom/crosapi.mojom b/chromeos/crosapi/mojom/crosapi.mojom
index e1c58c1..d4dcf33 100644
--- a/chromeos/crosapi/mojom/crosapi.mojom
+++ b/chromeos/crosapi/mojom/crosapi.mojom
@@ -52,6 +52,7 @@
 import "chromeos/crosapi/mojom/idle_service.mojom";
 import "chromeos/crosapi/mojom/image_writer.mojom";
 import "chromeos/crosapi/mojom/in_session_auth.mojom";
+import "chromeos/crosapi/mojom/kerberos_in_browser.mojom";
 import "chromeos/crosapi/mojom/keystore_service.mojom";
 import "chromeos/crosapi/mojom/launcher_search.mojom";
 import "chromeos/crosapi/mojom/local_printer.mojom";
@@ -138,8 +139,8 @@
 // please note the milestone when you added it, to help us reason about
 // compatibility between the client applications and older ash-chrome binaries.
 //
-// Next version: 108
-// Next method id: 111
+// Next version: 109
+// Next method id: 112
 [Stable, Uuid="8b79c34f-2bf8-4499-979a-b17cac522c1e",
  RenamedFrom="crosapi.mojom.AshChromeService"]
 interface Crosapi {
@@ -406,6 +407,11 @@
   BindNetworkSettingsService@46(
       pending_receiver<NetworkSettingsService> receiver);
 
+  // Binds the KerberosInBrowser interface for showing Kerberos UI.
+  // Added in M114.
+  [MinVersion=108]
+  BindKerberosInBrowser@111(pending_receiver<KerberosInBrowser> receiver);
+
   // Binds the KeystoreService interface for challenging keys.
   // Added in M87.
   BindKeystoreService@2(pending_receiver<KeystoreService> receiver);
@@ -708,8 +714,6 @@
   // |browser_info| during startup.
   // Added in M87.
   [MinVersion=3] OnBrowserStartup@6(BrowserInfo browser_info);
-
-
 };
 
 [Stable, Extensible]
diff --git a/chromeos/crosapi/mojom/kerberos_in_browser.mojom b/chromeos/crosapi/mojom/kerberos_in_browser.mojom
new file mode 100644
index 0000000..25746e6
--- /dev/null
+++ b/chromeos/crosapi/mojom/kerberos_in_browser.mojom
@@ -0,0 +1,13 @@
+// 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.
+
+module crosapi.mojom;
+
+// This interface is implemented by ash-chrome. It allows lacros-chrome to
+// request ash-chrome to display Kerberos ui.
+[Stable, Uuid="2e9a66de-3463-4383-bf6a-ab35f8c47bed"]
+interface KerberosInBrowser {
+  // Displays the Kerberos ui.
+  ShowKerberosInBrowserDialog@0();
+};
diff --git a/chromeos/lacros/lacros_service.cc b/chromeos/lacros/lacros_service.cc
index cc22887d..62f5563 100644
--- a/chromeos/lacros/lacros_service.cc
+++ b/chromeos/lacros/lacros_service.cc
@@ -61,6 +61,7 @@
 #include "chromeos/crosapi/mojom/identity_manager.mojom.h"
 #include "chromeos/crosapi/mojom/image_writer.mojom.h"
 #include "chromeos/crosapi/mojom/in_session_auth.mojom.h"
+#include "chromeos/crosapi/mojom/kerberos_in_browser.mojom.h"
 #include "chromeos/crosapi/mojom/keystore_service.mojom.h"
 #include "chromeos/crosapi/mojom/kiosk_session_service.mojom.h"
 #include "chromeos/crosapi/mojom/launcher_search.mojom.h"
@@ -382,6 +383,10 @@
   ConstructRemote<crosapi::mojom::InSessionAuth,
                   &crosapi::mojom::Crosapi::BindInSessionAuth,
                   Crosapi::MethodMinVersions::kBindInSessionAuthMinVersion>();
+  ConstructRemote<
+      crosapi::mojom::KerberosInBrowser,
+      &crosapi::mojom::Crosapi::BindKerberosInBrowser,
+      Crosapi::MethodMinVersions::kBindKerberosInBrowserMinVersion>();
   ConstructRemote<crosapi::mojom::KeystoreService,
                   &crosapi::mojom::Crosapi::BindKeystoreService,
                   Crosapi::MethodMinVersions::kBindKeystoreServiceMinVersion>();
diff --git a/components/autofill/core/browser/autofill_profile_sync_util.cc b/components/autofill/core/browser/autofill_profile_sync_util.cc
index 904f227..25d9df6 100644
--- a/components/autofill/core/browser/autofill_profile_sync_util.cc
+++ b/components/autofill/core/browser/autofill_profile_sync_util.cc
@@ -105,8 +105,6 @@
   if (!entry.profile_label().empty())
     specifics->set_profile_label(entry.profile_label());
 
-  specifics->set_disallow_settings_visible_updates(
-      entry.disallow_settings_visible_updates());
   specifics->set_use_count(entry.use_count());
   specifics->set_use_date(entry.use_date().ToTimeT());
   specifics->set_address_home_language_code(
@@ -291,11 +289,6 @@
   if (specifics.has_profile_label())
     profile->set_profile_label(specifics.profile_label());
 
-  // Set the `disallow_settings_visible_updates state` if it exists.
-  if (specifics.has_disallow_settings_visible_updates())
-    profile->set_disallow_settings_visible_updates(
-        specifics.disallow_settings_visible_updates());
-
   // Set repeated fields.
   profile->SetRawInfoWithVerificationStatus(
       NAME_HONORIFIC_PREFIX,
diff --git a/components/autofill/core/browser/autofill_profile_sync_util_unittest.cc b/components/autofill/core/browser/autofill_profile_sync_util_unittest.cc
index bc2c3859..6b18712e 100644
--- a/components/autofill/core/browser/autofill_profile_sync_util_unittest.cc
+++ b/components/autofill/core/browser/autofill_profile_sync_util_unittest.cc
@@ -41,7 +41,6 @@
   profile.set_use_date(base::Time::FromTimeT(1423182152));
 
   profile.set_profile_label("profile_label");
-  profile.set_disallow_settings_visible_updates(true);
 
   // Set testing values and statuses for the name.
   profile.SetRawInfoWithVerificationStatus(NAME_HONORIFIC_PREFIX, u"Dr.",
@@ -147,7 +146,6 @@
   specifics.set_use_count(7);
   specifics.set_use_date(1423182152);
   specifics.set_profile_label("profile_label");
-  specifics.set_disallow_settings_visible_updates(true);
 
   // Set values and statuses for the names.
   specifics.add_name_honorific("Dr.");
diff --git a/components/autofill/core/browser/data_model/autofill_profile.cc b/components/autofill/core/browser/data_model/autofill_profile.cc
index f76bfef..c2bc096 100644
--- a/components/autofill/core/browser/data_model/autofill_profile.cc
+++ b/components/autofill/core/browser/data_model/autofill_profile.cc
@@ -247,8 +247,6 @@
   if (this == &profile)
     return *this;
 
-  set_disallow_settings_visible_updates(
-      profile.disallow_settings_visible_updates());
   set_use_count(profile.use_count());
   set_use_date(profile.use_date());
   set_previous_use_date(profile.previous_use_date());
@@ -1013,9 +1011,7 @@
 }
 
 bool AutofillProfile::EqualsSansGuid(const AutofillProfile& profile) const {
-  return disallow_settings_visible_updates() ==
-             profile.disallow_settings_visible_updates() &&
-         language_code() == profile.language_code() &&
+  return language_code() == profile.language_code() &&
          profile_label() == profile.profile_label() &&
          source() == profile.source() && Compare(profile) == 0;
 }
diff --git a/components/autofill/core/browser/data_model/autofill_profile.h b/components/autofill/core/browser/data_model/autofill_profile.h
index 90765fe..4dfcfd2 100644
--- a/components/autofill/core/browser/data_model/autofill_profile.h
+++ b/components/autofill/core/browser/data_model/autofill_profile.h
@@ -263,13 +263,6 @@
   // Sets the label of the profile.
   void set_profile_label(const std::string& label) { profile_label_ = label; }
 
-  bool disallow_settings_visible_updates() const {
-    return disallow_settings_visible_updates_;
-  }
-  void set_disallow_settings_visible_updates(bool disallow) {
-    disallow_settings_visible_updates_ = disallow;
-  }
-
   Source source() const { return source_; }
   void set_source_for_testing(AutofillProfile::Source source) {
     source_ = source;
@@ -353,12 +346,6 @@
   // The BCP 47 language code that can be used to format |address_| for display.
   std::string language_code_;
 
-  // The state indicates if the profile qualifies to get merged with a
-  // profile observed in a form submission. If true, the profile can still be
-  // updated silently, but it should not be considered for merges that need to
-  // involve user interactions.
-  bool disallow_settings_visible_updates_{false};
-
   // ID used for identifying this profile. Only set for SERVER_PROFILEs. This is
   // a hash of the contents.
   std::string server_id_;
diff --git a/components/autofill/core/browser/data_model/autofill_profile_unittest.cc b/components/autofill/core/browser/data_model/autofill_profile_unittest.cc
index 59211a5..1abaf0a7 100644
--- a/components/autofill/core/browser/data_model/autofill_profile_unittest.cc
+++ b/components/autofill/core/browser/data_model/autofill_profile_unittest.cc
@@ -1530,35 +1530,6 @@
   EXPECT_NE(p1, p2);
 }
 
-// Test that the state to disallow confirmable merges is correctly set and
-// retrieved from the profile.
-TEST(AutofillProfileTest, SetAndGetProfileDisallowConfirmableMergestate) {
-  AutofillProfile p;
-  EXPECT_EQ(p.disallow_settings_visible_updates(), false);
-
-  p.set_disallow_settings_visible_updates(true);
-  EXPECT_EQ(p.disallow_settings_visible_updates(), true);
-}
-
-TEST(AutofillProfileTest, LockStateInAssignmentAndComparisonOperator) {
-  AutofillProfile p1;
-  p1.set_disallow_settings_visible_updates(true);
-
-  AutofillProfile p2;
-  EXPECT_EQ(p2.disallow_settings_visible_updates(), false);
-
-  p2 = p1;
-
-  // Check that the lock state was assigned correctly to p2.
-  EXPECT_EQ(p2.disallow_settings_visible_updates(), true);
-
-  // Now test that the comparison returns false if the lock state is not the
-  // same.
-  ASSERT_EQ(p1, p2);
-  p2.set_disallow_settings_visible_updates(false);
-  EXPECT_NE(p1, p2);
-}
-
 TEST(AutofillProfileTest, GetMetadata) {
   AutofillProfile local_profile = test::GetFullProfile();
   local_profile.set_use_count(2);
diff --git a/components/autofill/core/browser/webdata/autofill_table.cc b/components/autofill/core/browser/webdata/autofill_table.cc
index e0479a1..135a99c 100644
--- a/components/autofill/core/browser/webdata/autofill_table.cc
+++ b/components/autofill/core/browser/webdata/autofill_table.cc
@@ -581,7 +581,6 @@
   profile->set_modification_date(base::Time::FromTimeT(s.ColumnInt64(index++)));
   profile->set_language_code(s.ColumnString(index++));
   profile->set_profile_label(s.ColumnString(index++));
-  profile->set_disallow_settings_visible_updates(s.ColumnBool(index++));
 }
 
 void BindEncryptedCardToColumn(sql::Statement* s,
@@ -912,7 +911,8 @@
   return result;
 }
 
-// All ServerFieldTypes stored for an AutofillProfile in `kContactInfoTable`.
+// All ServerFieldTypes stored for an AutofillProfile in
+// `GetProfileTypeTokensTable(profile-source)`
 // When introducing a new field type, it suffices to add it here. When removing
 // a field type, removing it from the list suffices (no additional clean-up in
 // the table necessary).
@@ -922,7 +922,7 @@
 // - Some supported types (like PHONE_HOME_CITY_CODE) are not stored.
 // - Some non-supported types are stored (usually types that don't have filling
 //   support yet).
-std::vector<ServerFieldType> GetStoredContactInfoTypes() {
+std::vector<ServerFieldType> GetStoredTypesForAutofillProfile() {
   return {COMPANY_NAME,
           NAME_HONORIFIC_PREFIX,
           NAME_FIRST,
@@ -1010,7 +1010,7 @@
   BindAutofillProfileToStatement(profile, modification_date, s);
   if (!s.Run())
     return false;
-  for (ServerFieldType type : GetStoredContactInfoTypes()) {
+  for (ServerFieldType type : GetStoredTypesForAutofillProfile()) {
     if (!base::FeatureList::IsEnabled(
             features::kAutofillEnableSupportForLandmark) &&
         type == ADDRESS_HOME_LANDMARK) {
@@ -1624,8 +1624,7 @@
   if (!SelectByGuid(db_, s, kAutofillProfilesTable,
                     {kCompanyName, kStreetAddress, kDependentLocality, kCity,
                      kState, kZipcode, kSortingCode, kCountryCode, kUseCount,
-                     kUseDate, kDateModified, kLanguageCode, kLabel,
-                     kDisallowSettingsVisibleUpdates},
+                     kUseDate, kDateModified, kLanguageCode, kLabel},
                     guid)) {
     return nullptr;
   }
diff --git a/components/autofill/core/browser/webdata/autofill_table_unittest.cc b/components/autofill/core/browser/webdata/autofill_table_unittest.cc
index f6dd66de..36d8f2f 100644
--- a/components/autofill/core/browser/webdata/autofill_table_unittest.cc
+++ b/components/autofill/core/browser/webdata/autofill_table_unittest.cc
@@ -172,14 +172,10 @@
  public:
   void SetUp() override {
     AutofillTableTest::SetUp();
-    if (profile_source() == AutofillProfile::Source::kAccount) {
-      // Only enable support for new setting visible features for kAccount
-      // source.
-      features_.InitWithFeatures(
-          {features::kAutofillEnableSupportForLandmark,
-           features::kAutofillEnableSupportForBetweenStreets},
-          {});
-    }
+    features_.InitWithFeatures(
+        {features::kAutofillEnableSupportForLandmark,
+         features::kAutofillEnableSupportForBetweenStreets},
+        {});
   }
   AutofillProfile::Source profile_source() const { return GetParam(); }
 
@@ -966,17 +962,11 @@
   home_profile.SetRawInfoWithVerificationStatus(
       ADDRESS_HOME_PREMISE_NAME, u"Premise", VerificationStatus::kUserVerified);
   ASSERT_EQ(home_profile.GetRawInfo(ADDRESS_HOME_STREET_NAME), u"Street Name");
-  if (base::FeatureList::IsEnabled(
-          features::kAutofillEnableSupportForLandmark)) {
-    home_profile.SetRawInfoWithVerificationStatus(
-        ADDRESS_HOME_LANDMARK, u"Red tree", VerificationStatus::kObserved);
-  }
-  if (base::FeatureList::IsEnabled(
-          features::kAutofillEnableSupportForBetweenStreets)) {
-    home_profile.SetRawInfoWithVerificationStatus(
-        ADDRESS_HOME_BETWEEN_STREETS, u"Marcos y Oliva",
-        VerificationStatus::kObserved);
-  }
+  home_profile.SetRawInfoWithVerificationStatus(
+      ADDRESS_HOME_LANDMARK, u"Red tree", VerificationStatus::kObserved);
+  home_profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_BETWEEN_STREETS,
+                                                u"Marcos y Oliva",
+                                                VerificationStatus::kObserved);
 
   home_profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"18181234567");
   home_profile.SetRawInfoAsInt(BIRTHDATE_DAY, 14);
@@ -1222,14 +1212,8 @@
   profile.SetRawInfo(ADDRESS_HOME_STATE, u"CA");
   profile.SetRawInfo(ADDRESS_HOME_ZIP, u"90025");
   profile.SetRawInfo(ADDRESS_HOME_COUNTRY, u"US");
-  if (base::FeatureList::IsEnabled(
-          features::kAutofillEnableSupportForLandmark)) {
-    profile.SetRawInfo(ADDRESS_HOME_LANDMARK, u"Red tree");
-  }
-  if (base::FeatureList::IsEnabled(
-          features::kAutofillEnableSupportForBetweenStreets)) {
-    profile.SetRawInfo(ADDRESS_HOME_BETWEEN_STREETS, u"Marcos y Oliva");
-  }
+  profile.SetRawInfo(ADDRESS_HOME_LANDMARK, u"Red tree");
+  profile.SetRawInfo(ADDRESS_HOME_BETWEEN_STREETS, u"Marcos y Oliva");
   profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"18181234567");
   profile.SetRawInfoAsInt(BIRTHDATE_DAY, 14);
   profile.SetRawInfoAsInt(BIRTHDATE_MONTH, 3);
diff --git a/components/autofill/core/common/autofill_payments_features.cc b/components/autofill/core/common/autofill_payments_features.cc
index b4e9b57..b34fa5d 100644
--- a/components/autofill/core/common/autofill_payments_features.cc
+++ b/components/autofill/core/common/autofill_payments_features.cc
@@ -181,6 +181,13 @@
              "AutofillFillMerchantPromoCodeFields",
              base::FEATURE_ENABLED_BY_DEFAULT);
 
+// When enabled, legal term of save card view and virtual card enroll view will
+// be moved before action buttons and icon will be moved after titles in those
+// views.
+BASE_FEATURE(kAutofillMoveLegalTermsAndIconForNewCardEnrollment,
+             "AutofillMoveLegalTermsAndIconForNewCardEnrollment",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 // When enabled, Autofill will offer saving a card to the users when the Chrome
 // detects a card number with the last 4 digits that matches an existing server
 // card but has a different expiration date.
diff --git a/components/autofill/core/common/autofill_payments_features.h b/components/autofill/core/common/autofill_payments_features.h
index 247fab5..e696cea4 100644
--- a/components/autofill/core/common/autofill_payments_features.h
+++ b/components/autofill/core/common/autofill_payments_features.h
@@ -37,6 +37,7 @@
 BASE_DECLARE_FEATURE(kAutofillEnforceDelaysInStrikeDatabase);
 BASE_DECLARE_FEATURE(kAutofillFillIbanFields);
 BASE_DECLARE_FEATURE(kAutofillFillMerchantPromoCodeFields);
+BASE_DECLARE_FEATURE(kAutofillMoveLegalTermsAndIconForNewCardEnrollment);
 BASE_DECLARE_FEATURE(kAutofillOfferToSaveCardWithSameLastFour);
 BASE_DECLARE_FEATURE(kAutofillParseIBANFields);
 BASE_DECLARE_FEATURE(kAutofillParseVcnCardOnFileStandaloneCvcFields);
diff --git a/components/autofill_payments_strings.grdp b/components/autofill_payments_strings.grdp
index 108b20a..746da8e 100644
--- a/components/autofill_payments_strings.grdp
+++ b/components/autofill_payments_strings.grdp
@@ -651,7 +651,7 @@
       Yes
   </message>
   <message name="IDS_AUTOFILL_VIRTUAL_CARD_ENROLLMENT_DIALOG_TITLE_LABEL" desc="Title encouraging users to enroll their card to VCN." formatter_data="android_java">
-      Make it more secure with a virtual card?
+      Make it more secure with a virtual card next time?
   </message>
   <message name="IDS_AUTOFILL_VIRTUAL_CARD_ENROLLMENT_DIALOG_CONTENT_LABEL" desc="Text explaining the benefit of enrolling a credit card as a virtual card. Also contains a link to learn more about virtual cards from IDS_AUTOFILL_VIRTUAL_CARD_ENROLLMENT_LEARN_MORE_LINK_LABEL.">
     A virtual card hides your actual card to help protect you from potential fraud. <ph name="IDS_AUTOFILL_VIRTUAL_CARD_ENROLLMENT_LEARN_MORE_LINK_LABEL">$1<ex>Learn about virtual cards</ex></ph>
diff --git a/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_ENROLLMENT_DIALOG_TITLE_LABEL.png.sha1 b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_ENROLLMENT_DIALOG_TITLE_LABEL.png.sha1
index ec93ae1..59cd285 100644
--- a/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_ENROLLMENT_DIALOG_TITLE_LABEL.png.sha1
+++ b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_ENROLLMENT_DIALOG_TITLE_LABEL.png.sha1
@@ -1 +1 @@
-5a8350413a7ae46696e9e09f50d30490e0783981
\ No newline at end of file
+15aeb1a6f5dbc9377db79ca0052d09441789f91a
\ No newline at end of file
diff --git a/components/media_router/common/providers/cast/channel/cast_socket.h b/components/media_router/common/providers/cast/channel/cast_socket.h
index e392bb5..9526e04b 100644
--- a/components/media_router/common/providers/cast/channel/cast_socket.h
+++ b/components/media_router/common/providers/cast/channel/cast_socket.h
@@ -435,7 +435,9 @@
 
   // Raw pointer to the auth handshake delegate. Used to get detailed error
   // information.
-  raw_ptr<AuthTransportDelegate> auth_delegate_;
+  // This pointer might dangle when running the following test:
+  // PageSpecificSiteDataDialogPrivacySandboxInteractiveUiTest.FirstPartyAllowed
+  raw_ptr<AuthTransportDelegate, FlakyDanglingUntriaged> auth_delegate_;
 
   // List of socket observers.
   base::ObserverList<Observer>::Unchecked observers_;
diff --git a/components/ml/OWNERS b/components/ml/OWNERS
new file mode 100644
index 0000000..fe00ff9
--- /dev/null
+++ b/components/ml/OWNERS
@@ -0,0 +1,2 @@
+amoylan@chromium.org
+qjw@chromium.org
diff --git a/components/ml/mojom/OWNERS b/components/ml/mojom/OWNERS
index 481f66d0..08850f4 100644
--- a/components/ml/mojom/OWNERS
+++ b/components/ml/mojom/OWNERS
@@ -1,5 +1,2 @@
-amoylan@chromium.org
-qjw@chromium.org
-
 per-file *.mojom=set noparent
 per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/components/ml/webnn/BUILD.gn b/components/ml/webnn/BUILD.gn
new file mode 100644
index 0000000..1f360e45
--- /dev/null
+++ b/components/ml/webnn/BUILD.gn
@@ -0,0 +1,11 @@
+# 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.
+
+static_library("webnn") {
+  sources = [
+    "graph_validation_utils.cc",
+    "graph_validation_utils.h",
+  ]
+  deps = [ "//base" ]
+}
diff --git a/components/ml/webnn/OWNERS b/components/ml/webnn/OWNERS
new file mode 100644
index 0000000..b141619
--- /dev/null
+++ b/components/ml/webnn/OWNERS
@@ -0,0 +1,3 @@
+qjw@chromium.org
+ningxin.hu@intel.com
+rafael.cintron@microsoft.com
diff --git a/components/ml/webnn/graph_validation_utils.cc b/components/ml/webnn/graph_validation_utils.cc
new file mode 100644
index 0000000..f5ed89e
--- /dev/null
+++ b/components/ml/webnn/graph_validation_utils.cc
@@ -0,0 +1,85 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/ml/webnn/graph_validation_utils.h"
+
+#include "base/check_op.h"
+#include "base/numerics/checked_math.h"
+
+namespace webnn {
+
+absl::optional<size_t> ValidateAndCalculateElementsNumber(
+    base::span<const uint32_t> dimensions,
+    std::string& error_message) {
+  if (dimensions.empty()) {
+    error_message = "The dimensions is empty.";
+    return absl::nullopt;
+  }
+  base::CheckedNumeric<size_t> checked_number_of_elements = 1;
+  for (auto& d : dimensions) {
+    if (d == 0) {
+      error_message = "All dimensions should be positive.";
+      return absl::nullopt;
+    }
+    checked_number_of_elements *= d;
+  }
+  if (!checked_number_of_elements.IsValid()) {
+    error_message = "The number of elements is too large.";
+    return absl::nullopt;
+  }
+  return checked_number_of_elements.ValueOrDie();
+}
+
+absl::optional<size_t> ValidateAndCalculateByteLength(
+    size_t type_bytes,
+    base::span<const uint32_t> dimensions,
+    std::string& error_message) {
+  absl::optional<size_t> elements_num =
+      ValidateAndCalculateElementsNumber(dimensions, error_message);
+  if (!elements_num) {
+    return absl::nullopt;
+  }
+  auto checked_byte_length =
+      base::MakeCheckedNum<size_t>(elements_num.value()) * type_bytes;
+  if (!checked_byte_length.IsValid()) {
+    error_message = "The byte length is too large.";
+    return absl::nullopt;
+  }
+  return checked_byte_length.ValueOrDie();
+}
+
+absl::optional<std::vector<uint32_t>> BroadcastShapes(
+    base::span<const uint32_t> dims_lhs,
+    base::span<const uint32_t> dims_rhs,
+    bool bidirectional) {
+  // If bidirectional is true, the rank of the output shape is the maximum rank
+  // of the input shapes. Otherwise it is as the same as the rhs' rank.
+  auto rank_lhs = dims_lhs.size(), rank_rhs = dims_rhs.size();
+  auto rank_output = bidirectional ? std::max(rank_lhs, rank_rhs) : rank_rhs;
+  std::vector<uint32_t> dims_output(rank_output);
+  for (size_t i = 0; i < rank_output; ++i) {
+    auto dim_lhs = i < rank_lhs ? dims_lhs[rank_lhs - i - 1] : 1;
+    DCHECK_GT(dim_lhs, static_cast<uint32_t>(0));
+    auto dim_rhs = i < rank_rhs ? dims_rhs[rank_rhs - i - 1] : 1;
+    DCHECK_GT(dim_rhs, static_cast<uint32_t>(0));
+    // If bidirectional is true, two dimensions are compatible when they are
+    // equal, or one of them is 1. Otherwise, two dimensions are compatible when
+    // they are equal, or the lhs dimension is 1.
+    if (bidirectional) {
+      if (dim_lhs != dim_rhs && dim_lhs != 1 && dim_rhs != 1) {
+        return absl::nullopt;
+      }
+    } else if (dim_lhs != dim_rhs && dim_lhs != 1) {
+      return absl::nullopt;
+    }
+    // If bidirectional is true, for each dimension of the output tensor, its
+    // size is the maximum size along that dimension of the input shapes.
+    // Otherwise, its size is the same as the rhs.
+    dims_output[rank_output - i - 1] =
+        bidirectional ? std::max(dim_lhs, dim_rhs) : dim_rhs;
+  }
+  return dims_output;
+}
+
+}  // namespace webnn
diff --git a/components/ml/webnn/graph_validation_utils.h b/components/ml/webnn/graph_validation_utils.h
new file mode 100644
index 0000000..90927b5b
--- /dev/null
+++ b/components/ml/webnn/graph_validation_utils.h
@@ -0,0 +1,35 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_ML_WEBNN_GRAPH_VALIDATION_UTILS_H_
+#define COMPONENTS_ML_WEBNN_GRAPH_VALIDATION_UTILS_H_
+
+#include <vector>
+
+#include "base/containers/span.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace webnn {
+
+absl::optional<size_t> ValidateAndCalculateElementsNumber(
+    base::span<const uint32_t> dimensions,
+    std::string& error_message);
+
+absl::optional<size_t> ValidateAndCalculateByteLength(
+    size_t type_bytes,
+    base::span<const uint32_t> dimensions,
+    std::string& error_message);
+
+// Broadcast the input shapes and return the output shape.
+// If bidirectional is true, its behavior follows the numpy-broadcasting-rule:
+// https://numpy.org/doc/stable/user/basics.broadcasting.html#general-broadcasting-rules.
+// Otherwise, it unidirectionally broadcasts the lhs to the rhs.
+absl::optional<std::vector<uint32_t>> BroadcastShapes(
+    base::span<const uint32_t> dims_lhs,
+    base::span<const uint32_t> dims_rhs,
+    bool bidirectional = true);
+
+}  // namespace webnn
+
+#endif  // COMPONENTS_ML_WEBNN_GRAPH_VALIDATION_UTILS_H_
diff --git a/components/segmentation_platform/internal/post_processor/post_processor.cc b/components/segmentation_platform/internal/post_processor/post_processor.cc
index 70e6c7e..18431b0c 100644
--- a/components/segmentation_platform/internal/post_processor/post_processor.cc
+++ b/components/segmentation_platform/internal/post_processor/post_processor.cc
@@ -193,20 +193,16 @@
   return base::TimeDelta();
 }
 
-AnnotatedNumericResult PostProcessor::GetAnnotatedNumericResult(
+RawResult PostProcessor::GetRawResult(
     const proto::PredictionResult& prediction_result,
     PredictionStatus status) {
   if (status != PredictionStatus::kSucceeded) {
-    return AnnotatedNumericResult(status);
+    return RawResult(status);
   }
   if (!IsValidResult(prediction_result)) {
-    return AnnotatedNumericResult(PredictionStatus::kFailed);
+    return RawResult(PredictionStatus::kFailed);
   }
-  DCHECK_EQ(prediction_result.result_size(), prediction_result.output_config()
-                                                 .predictor()
-                                                 .generic_predictor()
-                                                 .output_labels_size());
-  AnnotatedNumericResult result(status);
+  RawResult result(status);
   result.result = prediction_result;
   return result;
 }
diff --git a/components/segmentation_platform/internal/post_processor/post_processor.h b/components/segmentation_platform/internal/post_processor/post_processor.h
index 089e0b36..8eed724 100644
--- a/components/segmentation_platform/internal/post_processor/post_processor.h
+++ b/components/segmentation_platform/internal/post_processor/post_processor.h
@@ -51,11 +51,10 @@
   // Returns -2 for all kinds of invalid cases.
   int GetIndexOfTopLabel(const proto::PredictionResult& prediction_result);
 
-  // Converts the prediction result into AnnotatedNumericResult usable by
+  // Converts the prediction result into RawResult usable by
   // clients.
-  AnnotatedNumericResult GetAnnotatedNumericResult(
-      const proto::PredictionResult& prediction_result,
-      PredictionStatus status);
+  RawResult GetRawResult(const proto::PredictionResult& prediction_result,
+                         PredictionStatus status);
 
  private:
   std::vector<std::string> GetBinaryClassifierResults(
diff --git a/components/segmentation_platform/internal/post_processor/post_processor_unittest.cc b/components/segmentation_platform/internal/post_processor/post_processor_unittest.cc
index 23c556e0..51c6410 100644
--- a/components/segmentation_platform/internal/post_processor/post_processor_unittest.cc
+++ b/components/segmentation_platform/internal/post_processor/post_processor_unittest.cc
@@ -311,13 +311,13 @@
             post_processor.GetTTLForPredictedResult(pred_result));
 }
 
-TEST(PostProcessorTest, GetAnnotatedNumericResult) {
+TEST(PostProcessorTest, GetRawResult) {
   proto::PredictionResult pred_result = metadata_utils::CreatePredictionResult(
       /*model_scores=*/{0.1, 0.2, 0.3},
       GetTestOutputConfigForGenericClassifier(),
       /*timestamp=*/base::Time::Now());
-  AnnotatedNumericResult result = PostProcessor().GetAnnotatedNumericResult(
-      pred_result, PredictionStatus::kSucceeded);
+  RawResult result =
+      PostProcessor().GetRawResult(pred_result, PredictionStatus::kSucceeded);
   EXPECT_EQ(pred_result.SerializeAsString(), result.result.SerializeAsString());
   EXPECT_EQ(PredictionStatus::kSucceeded, result.status);
   EXPECT_NEAR(0.1, *result.GetResultForLabel("Output1"), 0.001);
diff --git a/components/segmentation_platform/internal/selection/request_dispatcher.cc b/components/segmentation_platform/internal/selection/request_dispatcher.cc
index 2325f71..68f1a469 100644
--- a/components/segmentation_platform/internal/selection/request_dispatcher.cc
+++ b/components/segmentation_platform/internal/selection/request_dispatcher.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "components/segmentation_platform/internal/selection/request_dispatcher.h"
+
 #include <set>
 #include <utility>
 
@@ -14,12 +15,15 @@
 #include "base/time/time.h"
 #include "components/segmentation_platform/internal/database/config_holder.h"
 #include "components/segmentation_platform/internal/metadata/metadata_utils.h"
+#include "components/segmentation_platform/internal/post_processor/post_processor.h"
 #include "components/segmentation_platform/internal/selection/request_handler.h"
 #include "components/segmentation_platform/internal/selection/segment_result_provider.h"
 #include "components/segmentation_platform/internal/stats.h"
 #include "components/segmentation_platform/public/config.h"
 #include "components/segmentation_platform/public/prediction_options.h"
+#include "components/segmentation_platform/public/proto/prediction_result.pb.h"
 #include "components/segmentation_platform/public/proto/segmentation_platform.pb.h"
+#include "components/segmentation_platform/public/result.h"
 
 namespace segmentation_platform {
 
@@ -32,23 +36,35 @@
 // OptimizationGuide.ModelHandler.HandlerCreatedToModelAvailable histogram).
 const int kModelInitializationTimeoutMs = 200;
 
+void PostProcess(const RawResult& raw_result, ClassificationResult& result) {
+  result = PostProcessor().GetPostProcessedClassificationResult(
+      std::move(raw_result.result), raw_result.status);
+  result.request_id = raw_result.request_id;
+}
+void PostProcess(const RawResult& raw_result, AnnotatedNumericResult& result) {
+  result = raw_result;
+}
+
 // Wrap callback to record metrics.
 template <typename ResultType>
-base::OnceCallback<void(const ResultType&)> GetWrappedCallback(
+base::OnceCallback<void(const RawResult&)> GetWrappedCallback(
     const std::string& segmentation_key,
     base::OnceCallback<void(const ResultType&)> callback) {
   auto wrapped_callback = base::BindOnce(
       [](const std::string& segmentation_key, base::Time start_time,
          base::OnceCallback<void(const ResultType&)> callback,
-         const ResultType& result) -> void {
+         const RawResult& raw_result) -> void {
         stats::RecordClassificationRequestTotalDuration(
             segmentation_key, base::Time::Now() - start_time);
+        ResultType result(PredictionStatus::kFailed);
+        PostProcess(std::move(raw_result), result);
         std::move(callback).Run(result);
       },
       segmentation_key, base::Time::Now(), std::move(callback));
 
   return wrapped_callback;
 }
+
 }  // namespace
 
 RequestDispatcher::RequestDispatcher(
@@ -133,17 +149,37 @@
   ExecuteAllPendingActions();
 }
 
-template <typename ResultType, typename Request>
 void RequestDispatcher::GetModelResult(
     const std::string& segmentation_key,
     const PredictionOptions& options,
     scoped_refptr<InputContext> input_context,
-    Request request,
-    base::OnceCallback<void(const ResultType&)> callback) {
+    RawResultCallback callback) {
   if (config_holder_->IsLegacySegmentationKey(segmentation_key)) {
     return;
   }
 
+  if (!options.on_demand_execution) {
+    // Returns result directly from prefs for non-ondemand models.
+    auto pred_result =
+        cached_result_provider_->GetPredictionResultForClient(segmentation_key);
+    RawResult raw_result(PredictionStatus::kFailed);
+    if (pred_result) {
+      raw_result = PostProcessor().GetRawResult(*pred_result,
+                                                PredictionStatus::kSucceeded);
+      stats::RecordSegmentSelectionFailure(
+          segmentation_key, stats::SegmentationSelectionFailureReason::
+                                kClassificationResultFromPrefs);
+    } else {
+      stats::RecordSegmentSelectionFailure(
+          segmentation_key, stats::SegmentationSelectionFailureReason::
+                                kClassificationResultNotAvailableInPrefs);
+    }
+
+    base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
+        FROM_HERE, base::BindOnce(std::move(callback), std::move(raw_result)));
+    return;
+  }
+
   // TODO(ssid): Support cached results for all APIs.
   DCHECK(options.on_demand_execution);
 
@@ -154,10 +190,10 @@
       uninitialized_segmentation_keys_.contains(segmentation_key)) {
     // If the platform isn't fully initialized, cache the input arguments to
     // run later.
-    pending_actions_[segmentation_key].push_back(base::BindOnce(
-        &RequestDispatcher::GetModelResult<ResultType, Request>,
-        weak_ptr_factory_.GetWeakPtr(), segmentation_key, options,
-        std::move(input_context), std::move(request), std::move(callback)));
+    pending_actions_[segmentation_key].push_back(
+        base::BindOnce(&RequestDispatcher::GetModelResult,
+                       weak_ptr_factory_.GetWeakPtr(), segmentation_key,
+                       options, std::move(input_context), std::move(callback)));
     return;
   }
 
@@ -169,17 +205,16 @@
         stats::SegmentationSelectionFailureReason::kDBInitFailure);
     base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
         FROM_HERE, base::BindOnce(std::move(callback),
-                                  ResultType(PredictionStatus::kFailed)));
+                                  RawResult(PredictionStatus::kFailed)));
     return;
   }
 
-  auto wrapped_callback =
-      GetWrappedCallback(segmentation_key, std::move(callback));
-
   auto iter = request_handlers_.find(segmentation_key);
   CHECK(iter != request_handlers_.end());
-  std::move(request).Run(iter->second.get(), options, input_context,
-                         std::move(wrapped_callback));
+  auto wrapped_callback =
+      GetWrappedCallback(segmentation_key, std::move(callback));
+  iter->second->GetPredictionResult(options, input_context,
+                                    std::move(wrapped_callback));
 }
 
 void RequestDispatcher::GetClassificationResult(
@@ -187,29 +222,10 @@
     const PredictionOptions& options,
     scoped_refptr<InputContext> input_context,
     ClassificationResultCallback callback) {
-  if (!options.on_demand_execution) {
-    auto wrapped_callback =
-        GetWrappedCallback(segmentation_key, std::move(callback));
-
-    // Returns result directly from prefs for non-ondemand models.
-    auto result =
-        cached_result_provider_->GetCachedResultForClient(segmentation_key);
-
-    stats::RecordSegmentSelectionFailure(
-        segmentation_key, result.status == PredictionStatus::kSucceeded
-                              ? stats::SegmentationSelectionFailureReason::
-                                    kClassificationResultFromPrefs
-                              : stats::SegmentationSelectionFailureReason::
-                                    kClassificationResultNotAvailableInPrefs);
-
-    base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
-        FROM_HERE, base::BindOnce(std::move(wrapped_callback), result));
-    return;
-  }
-
+  auto wrapped_callback =
+      GetWrappedCallback(segmentation_key, std::move(callback));
   GetModelResult(segmentation_key, options, input_context,
-                 base::BindOnce(&RequestHandler::GetClassificationResult),
-                 std::move(callback));
+                 std::move(wrapped_callback));
 }
 
 void RequestDispatcher::GetAnnotatedNumericResult(
@@ -217,9 +233,10 @@
     const PredictionOptions& options,
     scoped_refptr<InputContext> input_context,
     AnnotatedNumericResultCallback callback) {
+  auto wrapped_callback =
+      GetWrappedCallback(segmentation_key, std::move(callback));
   GetModelResult(segmentation_key, options, input_context,
-                 base::BindOnce(&RequestHandler::GetAnnotatedNumericResult),
-                 std::move(callback));
+                 std::move(wrapped_callback));
 }
 
 int RequestDispatcher::GetPendingActionCountForTesting() {
diff --git a/components/segmentation_platform/internal/selection/request_dispatcher.h b/components/segmentation_platform/internal/selection/request_dispatcher.h
index ffe1c37c..9e7ea94 100644
--- a/components/segmentation_platform/internal/selection/request_dispatcher.h
+++ b/components/segmentation_platform/internal/selection/request_dispatcher.h
@@ -56,6 +56,7 @@
                                scoped_refptr<InputContext> input_context,
                                ClassificationResultCallback callback);
 
+  // Client API. See `SegmentationPlatformService::GetAnnotatedNumericResult`.
   void GetAnnotatedNumericResult(const std::string& segmentation_key,
                                  const PredictionOptions& options,
                                  scoped_refptr<InputContext> input_context,
@@ -74,12 +75,10 @@
   void ExecuteAllPendingActions();
   void ExecutePendingActionsForKey(const std::string& segmentation_key);
 
-  template <typename ResultType, typename Request>
   void GetModelResult(const std::string& segmentation_key,
                       const PredictionOptions& options,
                       scoped_refptr<InputContext> input_context,
-                      Request request,
-                      base::OnceCallback<void(const ResultType&)> callback);
+                      AnnotatedNumericResultCallback callback);
 
   // Configs for all registered clients.
   const raw_ptr<const ConfigHolder> config_holder_;
diff --git a/components/segmentation_platform/internal/selection/request_dispatcher_unittest.cc b/components/segmentation_platform/internal/selection/request_dispatcher_unittest.cc
index 707e686..34e94ae 100644
--- a/components/segmentation_platform/internal/selection/request_dispatcher_unittest.cc
+++ b/components/segmentation_platform/internal/selection/request_dispatcher_unittest.cc
@@ -14,11 +14,13 @@
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
 #include "components/segmentation_platform/internal/database/config_holder.h"
+#include "components/segmentation_platform/internal/metadata/metadata_writer.h"
 #include "components/segmentation_platform/internal/post_processor/post_processing_test_utils.h"
 #include "components/segmentation_platform/internal/selection/request_handler.h"
 #include "components/segmentation_platform/internal/selection/segment_result_provider.h"
 #include "components/segmentation_platform/public/config.h"
 #include "components/segmentation_platform/public/prediction_options.h"
+#include "components/segmentation_platform/public/proto/prediction_result.pb.h"
 #include "components/segmentation_platform/public/result.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -32,20 +34,44 @@
 // Test clients.
 const char kDeviceSwitcherClient[] = "device_switcher";
 const char kAdaptiveToolbarClient[] = "adaptive_toolbar";
+const char kTestLabel1[] = "test_label1";
+const char kTestLabel2[] = "test_label2";
+
+proto::PredictionResult CreatePredictionResultWithBinaryClassifier(
+    const char* const label) {
+  proto::SegmentationModelMetadata model_metadata;
+  MetadataWriter writer(&model_metadata);
+  writer.AddOutputConfigForBinaryClassifier(0.5f, label, "unused");
+
+  proto::PredictionResult prediction_result;
+  prediction_result.add_result(0.8f);
+  prediction_result.mutable_output_config()->Swap(
+      model_metadata.mutable_output_config());
+  return prediction_result;
+}
+
+proto::PredictionResult CreatePredictionResultWithGenericPredictor() {
+  proto::SegmentationModelMetadata model_metadata;
+  MetadataWriter writer(&model_metadata);
+  writer.AddOutputConfigForGenericPredictor({"output1", "output2"});
+
+  proto::PredictionResult prediction_result;
+  prediction_result.add_result(0.8f);
+  prediction_result.add_result(0.2f);
+  prediction_result.mutable_output_config()->Swap(
+      model_metadata.mutable_output_config());
+  return prediction_result;
+}
 
 class MockRequestHandler : public RequestHandler {
  public:
   MockRequestHandler() = default;
   ~MockRequestHandler() override = default;
 
-  MOCK_METHOD3(GetClassificationResult,
-               void(const PredictionOptions& options,
-                    scoped_refptr<InputContext> input_context,
-                    ClassificationResultCallback callback));
-  MOCK_METHOD3(GetAnnotatedNumericResult,
+  MOCK_METHOD3(GetPredictionResult,
                void(const PredictionOptions& prediction_options,
                     scoped_refptr<InputContext> input_context,
-                    AnnotatedNumericResultCallback callback));
+                    RawResultCallback callback));
 };
 
 class RequestDispatcherTest : public testing::Test {
@@ -112,7 +138,7 @@
   EXPECT_EQ(0, request_dispatcher_->GetPendingActionCountForTesting());
 
   // Request handler will never be invoked if init fails.
-  EXPECT_CALL(*request_handler1_, GetClassificationResult(_, _, _)).Times(0);
+  EXPECT_CALL(*request_handler1_, GetPredictionResult(_, _, _)).Times(0);
 
   base::RunLoop loop;
   request_dispatcher_->GetClassificationResult(
@@ -143,15 +169,18 @@
   EXPECT_EQ(0, request_dispatcher_->GetPendingActionCountForTesting());
 
   // Request from client 1.
-  ClassificationResult result1(PredictionStatus::kSucceeded);
-  result1.ordered_labels.emplace_back("test_label1");
-  EXPECT_CALL(*request_handler1_, GetClassificationResult(_, _, _))
-      .WillRepeatedly(Invoke([&](const PredictionOptions& options,
-                                 scoped_refptr<InputContext> input_context,
-                                 ClassificationResultCallback callback) {
-        std::move(callback).Run(result1);
-      }));
+  RawResult raw_result1(PredictionStatus::kSucceeded);
+  raw_result1.result = CreatePredictionResultWithBinaryClassifier(kTestLabel1);
+  EXPECT_CALL(*request_handler1_, GetPredictionResult(_, _, _))
+      .WillRepeatedly(
+          Invoke([&raw_result1](const PredictionOptions& options,
+                                scoped_refptr<InputContext> input_context,
+                                RawResultCallback callback) {
+            std::move(callback).Run(raw_result1);
+          }));
 
+  ClassificationResult result1(PredictionStatus::kSucceeded);
+  result1.ordered_labels.emplace_back(kTestLabel1);
   request_dispatcher_->GetClassificationResult(
       kDeviceSwitcherClient, options, scoped_refptr<InputContext>(),
       base::BindOnce(&RequestDispatcherTest::OnGetClassificationResult,
@@ -160,15 +189,18 @@
   EXPECT_EQ(1, request_dispatcher_->GetPendingActionCountForTesting());
 
   // Request from client 2.
-  ClassificationResult result2(PredictionStatus::kSucceeded);
-  result2.ordered_labels.emplace_back("test_label2");
-  EXPECT_CALL(*request_handler2_, GetClassificationResult(_, _, _))
-      .WillRepeatedly(Invoke([&](const PredictionOptions& options,
-                                 scoped_refptr<InputContext> input_context,
-                                 ClassificationResultCallback callback) {
-        std::move(callback).Run(result2);
-      }));
+  RawResult raw_result2(PredictionStatus::kSucceeded);
+  raw_result2.result = CreatePredictionResultWithBinaryClassifier(kTestLabel2);
+  EXPECT_CALL(*request_handler2_, GetPredictionResult(_, _, _))
+      .WillRepeatedly(
+          Invoke([&raw_result2](const PredictionOptions& options,
+                                scoped_refptr<InputContext> input_context,
+                                RawResultCallback callback) {
+            std::move(callback).Run(raw_result2);
+          }));
 
+  ClassificationResult result2(PredictionStatus::kSucceeded);
+  result2.ordered_labels.emplace_back(kTestLabel2);
   request_dispatcher_->GetClassificationResult(
       kAdaptiveToolbarClient, options, scoped_refptr<InputContext>(),
       base::BindOnce(&RequestDispatcherTest::OnGetClassificationResult,
@@ -205,15 +237,18 @@
   EXPECT_EQ(0, request_dispatcher_->GetPendingActionCountForTesting());
 
   // Request from client 1.
-  ClassificationResult result1(PredictionStatus::kSucceeded);
-  result1.ordered_labels.emplace_back("test_label1");
-  EXPECT_CALL(*request_handler1_, GetClassificationResult(_, _, _))
-      .WillRepeatedly(Invoke([&](const PredictionOptions& options,
-                                 scoped_refptr<InputContext> input_context,
-                                 ClassificationResultCallback callback) {
-        std::move(callback).Run(result1);
-      }));
+  RawResult raw_result1(PredictionStatus::kSucceeded);
+  raw_result1.result = CreatePredictionResultWithBinaryClassifier(kTestLabel1);
+  EXPECT_CALL(*request_handler1_, GetPredictionResult(_, _, _))
+      .WillRepeatedly(
+          Invoke([&raw_result1](const PredictionOptions& options,
+                                scoped_refptr<InputContext> input_context,
+                                RawResultCallback callback) {
+            std::move(callback).Run(raw_result1);
+          }));
 
+  ClassificationResult result1(PredictionStatus::kSucceeded);
+  result1.ordered_labels.emplace_back(kTestLabel1);
   request_dispatcher_->GetClassificationResult(
       kDeviceSwitcherClient, options, scoped_refptr<InputContext>(),
       base::BindOnce(&RequestDispatcherTest::OnGetClassificationResult,
@@ -222,15 +257,18 @@
   EXPECT_EQ(1, request_dispatcher_->GetPendingActionCountForTesting());
 
   // Request from client 2.
+  RawResult raw_result2(PredictionStatus::kSucceeded);
+  raw_result2.result = CreatePredictionResultWithBinaryClassifier(kTestLabel2);
+  EXPECT_CALL(*request_handler2_, GetPredictionResult(_, _, _))
+      .WillRepeatedly(
+          Invoke([&raw_result2](const PredictionOptions& options,
+                                scoped_refptr<InputContext> input_context,
+                                RawResultCallback callback) {
+            std::move(callback).Run(raw_result2);
+          }));
+
   ClassificationResult result2(PredictionStatus::kSucceeded);
   result2.ordered_labels.emplace_back("test_label2");
-  EXPECT_CALL(*request_handler2_, GetClassificationResult(_, _, _))
-      .WillRepeatedly(Invoke([&](const PredictionOptions& options,
-                                 scoped_refptr<InputContext> input_context,
-                                 ClassificationResultCallback callback) {
-        std::move(callback).Run(result2);
-      }));
-
   request_dispatcher_->GetClassificationResult(
       kAdaptiveToolbarClient, options, scoped_refptr<InputContext>(),
       base::BindOnce(&RequestDispatcherTest::OnGetClassificationResult,
@@ -286,15 +324,18 @@
       SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_ADAPTIVE_TOOLBAR);
 
   // Request from client 1.
-  ClassificationResult result1(PredictionStatus::kSucceeded);
-  result1.ordered_labels.emplace_back("test_label1");
-  EXPECT_CALL(*request_handler1_, GetClassificationResult(_, _, _))
-      .WillRepeatedly(Invoke([&](const PredictionOptions& options,
-                                 scoped_refptr<InputContext> input_context,
-                                 ClassificationResultCallback callback) {
-        std::move(callback).Run(result1);
-      }));
+  RawResult raw_result1(PredictionStatus::kSucceeded);
+  raw_result1.result = CreatePredictionResultWithBinaryClassifier(kTestLabel1);
+  EXPECT_CALL(*request_handler1_, GetPredictionResult(_, _, _))
+      .WillRepeatedly(
+          Invoke([&raw_result1](const PredictionOptions& options,
+                                scoped_refptr<InputContext> input_context,
+                                RawResultCallback callback) {
+            std::move(callback).Run(raw_result1);
+          }));
 
+  ClassificationResult result1(PredictionStatus::kSucceeded);
+  result1.ordered_labels.emplace_back(kTestLabel1);
   request_dispatcher_->GetClassificationResult(
       kDeviceSwitcherClient, options, scoped_refptr<InputContext>(),
       base::BindOnce(&RequestDispatcherTest::OnGetClassificationResult,
@@ -302,15 +343,18 @@
   EXPECT_EQ(0, request_dispatcher_->GetPendingActionCountForTesting());
 
   // Request from client 2.
-  ClassificationResult result2(PredictionStatus::kSucceeded);
-  result2.ordered_labels.emplace_back("test_label2");
-  EXPECT_CALL(*request_handler2_, GetClassificationResult(_, _, _))
-      .WillRepeatedly(Invoke([&](const PredictionOptions& options,
-                                 scoped_refptr<InputContext> input_context,
-                                 ClassificationResultCallback callback) {
-        std::move(callback).Run(result2);
-      }));
+  RawResult raw_result2(PredictionStatus::kSucceeded);
+  raw_result2.result = CreatePredictionResultWithBinaryClassifier(kTestLabel2);
+  EXPECT_CALL(*request_handler2_, GetPredictionResult(_, _, _))
+      .WillRepeatedly(
+          Invoke([&raw_result2](const PredictionOptions& options,
+                                scoped_refptr<InputContext> input_context,
+                                RawResultCallback callback) {
+            std::move(callback).Run(raw_result2);
+          }));
 
+  ClassificationResult result2(PredictionStatus::kSucceeded);
+  result2.ordered_labels.emplace_back(kTestLabel2);
   request_dispatcher_->GetClassificationResult(
       kAdaptiveToolbarClient, options, scoped_refptr<InputContext>(),
       base::BindOnce(&RequestDispatcherTest::OnGetClassificationResult,
@@ -325,19 +369,20 @@
   options.on_demand_execution = true;
 
   // Request from client 1.
-  AnnotatedNumericResult result1(PredictionStatus::kSucceeded);
-  result1.result.add_result(1.0);
-  EXPECT_CALL(*request_handler1_, GetAnnotatedNumericResult(_, _, _))
-      .WillRepeatedly(Invoke([&](const PredictionOptions& options,
-                                 scoped_refptr<InputContext> input_context,
-                                 AnnotatedNumericResultCallback callback) {
-        std::move(callback).Run(result1);
-      }));
+  RawResult raw_result1(PredictionStatus::kSucceeded);
+  raw_result1.result = CreatePredictionResultWithGenericPredictor();
+  EXPECT_CALL(*request_handler1_, GetPredictionResult(_, _, _))
+      .WillRepeatedly(
+          Invoke([&raw_result1](const PredictionOptions& options,
+                                scoped_refptr<InputContext> input_context,
+                                RawResultCallback callback) {
+            std::move(callback).Run(raw_result1);
+          }));
 
   request_dispatcher_->GetAnnotatedNumericResult(
       kDeviceSwitcherClient, options, scoped_refptr<InputContext>(),
       base::BindOnce(&RequestDispatcherTest::OnGetAnnotatedNumericResult,
-                     base::Unretained(this), loop.QuitClosure(), result1));
+                     base::Unretained(this), loop.QuitClosure(), raw_result1));
   EXPECT_EQ(1, request_dispatcher_->GetPendingActionCountForTesting());
 
   // Init platform.
diff --git a/components/segmentation_platform/internal/selection/request_handler.cc b/components/segmentation_platform/internal/selection/request_handler.cc
index e88fbce..d808f90 100644
--- a/components/segmentation_platform/internal/selection/request_handler.cc
+++ b/components/segmentation_platform/internal/selection/request_handler.cc
@@ -46,27 +46,19 @@
   RequestHandlerImpl(const RequestHandlerImpl&) = delete;
   RequestHandlerImpl& operator=(const RequestHandlerImpl&) = delete;
 
-  // Client API. See `SegmentationPlatformService::GetClassificationResult`.
-  void GetClassificationResult(const PredictionOptions& options,
-                               scoped_refptr<InputContext> input_context,
-                               ClassificationResultCallback callback) override;
-  void GetAnnotatedNumericResult(
-      const PredictionOptions& options,
-      scoped_refptr<InputContext> input_context,
-      AnnotatedNumericResultCallback callback) override;
+  // RequestHandler impl.
+  void GetPredictionResult(const PredictionOptions& options,
+                           scoped_refptr<InputContext> input_context,
+                           RawResultCallback callback) override;
 
  private:
   void GetModelResult(const PredictionOptions& options,
                       scoped_refptr<InputContext> input_context,
                       SegmentResultProvider::SegmentResultCallback callback);
 
-  void OnGetModelResultForClassification(
+  void OnGetPredictionResult(
       scoped_refptr<InputContext> input_context,
-      ClassificationResultCallback classification_callback,
-      std::unique_ptr<SegmentResultProvider::SegmentResult> result);
-  void OnGetAnnotatedNumericResult(
-      scoped_refptr<InputContext> input_context,
-      AnnotatedNumericResultCallback callback,
+      RawResultCallback callback,
       std::unique_ptr<SegmentResultProvider::SegmentResult> result);
 
   TrainingRequestId CollectTrainingData(
@@ -95,27 +87,15 @@
 
 RequestHandlerImpl::~RequestHandlerImpl() = default;
 
-void RequestHandlerImpl::GetClassificationResult(
+void RequestHandlerImpl::GetPredictionResult(
     const PredictionOptions& options,
     scoped_refptr<InputContext> input_context,
-    ClassificationResultCallback callback) {
+    RawResultCallback callback) {
   DCHECK(options.on_demand_execution);
-  GetModelResult(
-      options, input_context,
-      base::BindOnce(&RequestHandlerImpl::OnGetModelResultForClassification,
-                     weak_ptr_factory_.GetWeakPtr(), input_context,
-                     std::move(callback)));
-}
-void RequestHandlerImpl::GetAnnotatedNumericResult(
-    const PredictionOptions& options,
-    scoped_refptr<InputContext> input_context,
-    AnnotatedNumericResultCallback callback) {
-  DCHECK(options.on_demand_execution);
-  GetModelResult(
-      options, input_context,
-      base::BindOnce(&RequestHandlerImpl::OnGetAnnotatedNumericResult,
-                     weak_ptr_factory_.GetWeakPtr(), input_context,
-                     std::move(callback)));
+  GetModelResult(options, input_context,
+                 base::BindOnce(&RequestHandlerImpl::OnGetPredictionResult,
+                                weak_ptr_factory_.GetWeakPtr(), input_context,
+                                std::move(callback)));
 }
 
 void RequestHandlerImpl::GetModelResult(
@@ -135,53 +115,25 @@
   result_provider_->GetSegmentResult(std::move(result_options));
 }
 
-void RequestHandlerImpl::OnGetModelResultForClassification(
+void RequestHandlerImpl::OnGetPredictionResult(
     scoped_refptr<InputContext> input_context,
-    ClassificationResultCallback classification_callback,
-    std::unique_ptr<SegmentResultProvider::SegmentResult> result) {
-  PostProcessor post_processor;
-  PredictionStatus status = PredictionStatus::kFailed;
-  proto::PredictionResult pred_result;
-  absl::optional<TrainingRequestId> request_id;
-  if (result) {
-    stats::RecordSegmentSelectionFailure(
-        *config_, stats::GetSuccessOrFailureReason(result->state));
-    status = ResultStateToPredictionStatus(result->state);
-    pred_result = result->result;
-    stats::RecordClassificationResultComputed(*config_, pred_result);
+    RawResultCallback callback,
+    std::unique_ptr<SegmentResultProvider::SegmentResult> segment_result) {
+  RawResult result(PredictionStatus::kFailed);
+  if (segment_result) {
+    result.request_id = CollectTrainingData(input_context);
 
-    request_id = CollectTrainingData(input_context);
+    auto status = ResultStateToPredictionStatus(segment_result->state);
+    result = PostProcessor().GetRawResult(segment_result->result, status);
+
+    stats::RecordSegmentSelectionFailure(
+        *config_, stats::GetSuccessOrFailureReason(segment_result->state));
+    stats::RecordClassificationResultComputed(*config_, segment_result->result);
   } else {
     stats::RecordSegmentSelectionFailure(
         *config_, stats::SegmentationSelectionFailureReason::
                       kOnDemandModelExecutionFailed);
   }
-  ClassificationResult classification_result =
-      post_processor.GetPostProcessedClassificationResult(pred_result, status);
-
-  if (request_id && !request_id.value().is_null()) {
-    classification_result.request_id = request_id.value();
-  }
-
-  base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
-      FROM_HERE, base::BindOnce(std::move(classification_callback),
-                                classification_result));
-}
-
-void RequestHandlerImpl::OnGetAnnotatedNumericResult(
-    scoped_refptr<InputContext> input_context,
-    AnnotatedNumericResultCallback callback,
-    std::unique_ptr<SegmentResultProvider::SegmentResult> segment_result) {
-  PredictionStatus status = PredictionStatus::kFailed;
-  AnnotatedNumericResult result(status);
-  absl::optional<TrainingRequestId> request_id;
-  if (segment_result) {
-    status = ResultStateToPredictionStatus(segment_result->state);
-    result = PostProcessor().GetAnnotatedNumericResult(segment_result->result,
-                                                       status);
-
-    request_id = CollectTrainingData(input_context);
-  }
   base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), std::move(result)));
 }
diff --git a/components/segmentation_platform/internal/selection/request_handler.h b/components/segmentation_platform/internal/selection/request_handler.h
index 5bdad01b..030da1f 100644
--- a/components/segmentation_platform/internal/selection/request_handler.h
+++ b/components/segmentation_platform/internal/selection/request_handler.h
@@ -11,6 +11,7 @@
 #include "components/segmentation_platform/internal/scheduler/execution_service.h"
 #include "components/segmentation_platform/internal/selection/segment_result_provider.h"
 #include "components/segmentation_platform/public/input_context.h"
+#include "components/segmentation_platform/public/proto/prediction_result.pb.h"
 #include "components/segmentation_platform/public/result.h"
 
 namespace segmentation_platform {
@@ -32,17 +33,10 @@
       std::unique_ptr<SegmentResultProvider> result_provider,
       ExecutionService* execution_service);
 
-  // Client API. See `SegmentationPlatformService::GetClassificationResult`.
-  virtual void GetClassificationResult(
-      const PredictionOptions& options,
-      scoped_refptr<InputContext> input_context,
-      ClassificationResultCallback callback) = 0;
-
-  // Client API. See SegmentationPlatformService::GetAnnotatedNumericResult`.
-  virtual void GetAnnotatedNumericResult(
-      const PredictionOptions& options,
-      scoped_refptr<InputContext> input_context,
-      AnnotatedNumericResultCallback callback) = 0;
+  // Fetches raw result for on demand executions.
+  virtual void GetPredictionResult(const PredictionOptions& options,
+                                   scoped_refptr<InputContext> input_context,
+                                   RawResultCallback callback) = 0;
 };
 
 }  // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/selection/request_handler_unittest.cc b/components/segmentation_platform/internal/selection/request_handler_unittest.cc
index 3c269dc..c31cfa5 100644
--- a/components/segmentation_platform/internal/selection/request_handler_unittest.cc
+++ b/components/segmentation_platform/internal/selection/request_handler_unittest.cc
@@ -14,6 +14,7 @@
 #include "components/segmentation_platform/internal/selection/segment_result_provider.h"
 #include "components/segmentation_platform/public/config.h"
 #include "components/segmentation_platform/public/prediction_options.h"
+#include "components/segmentation_platform/public/proto/prediction_result.pb.h"
 #include "components/segmentation_platform/public/result.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -42,24 +43,10 @@
   writer.AddOutputConfigForBinaryClassifier(0.5f, "positive_label",
                                             "negative_label");
 
-  proto::PredictionResult prediction_result;
-  prediction_result.add_result(0.8f);
-  prediction_result.mutable_output_config()->Swap(
-      model_metadata.mutable_output_config());
-  return prediction_result;
-}
-
-proto::PredictionResult CreatePredictionResultWithGenericPredictor() {
-  proto::SegmentationModelMetadata model_metadata;
-  MetadataWriter writer(&model_metadata);
-  writer.AddOutputConfigForGenericPredictor({"output1", "output2"});
-
-  proto::PredictionResult prediction_result;
-  prediction_result.add_result(0.8f);
-  prediction_result.add_result(0.2f);
-  prediction_result.mutable_output_config()->Swap(
-      model_metadata.mutable_output_config());
-  return prediction_result;
+  proto::PredictionResult result;
+  result.add_result(0.8f);
+  result.mutable_output_config()->Swap(model_metadata.mutable_output_config());
+  return result;
 }
 
 class RequestHandlerTest : public testing::Test {
@@ -77,19 +64,10 @@
                                               &execution_service_);
   }
 
-  void OnGetClassificationResult(base::RepeatingClosure closure,
-                                 const ClassificationResult& expected,
-                                 const ClassificationResult& actual) {
-    EXPECT_EQ(expected.ordered_labels, actual.ordered_labels);
-    EXPECT_EQ(expected.status, actual.status);
-    std::move(closure).Run();
-  }
-
-  void OnGetAnnotatedNumericResult(base::RepeatingClosure closure,
-                                   const AnnotatedNumericResult& result) {
+  void OnGetPredictionResult(base::RepeatingClosure closure,
+                             const RawResult& result) {
+    EXPECT_EQ(result.status, PredictionStatus::kSucceeded);
     EXPECT_NEAR(0.8, result.result.result(0), 0.001);
-    EXPECT_NEAR(0.2, result.result.result(1), 0.001);
-    EXPECT_EQ(PredictionStatus::kSucceeded, result.status);
     std::move(closure).Run();
   }
 
@@ -101,55 +79,28 @@
   ExecutionService execution_service_;
 };
 
-TEST_F(RequestHandlerTest, TestGetClassificationResult) {
+TEST_F(RequestHandlerTest, GetPredictionResult) {
   PredictionOptions options;
   options.on_demand_execution = true;
 
   EXPECT_CALL(*result_provider_, GetSegmentResult(_))
-      .Times(1)
-      .WillRepeatedly(Invoke(
+      .WillOnce(Invoke(
           [](std::unique_ptr<SegmentResultProvider::GetResultOptions> options) {
             EXPECT_TRUE(options->ignore_db_scores);
             EXPECT_EQ(options->segment_id, kSegmentId);
             auto result =
                 std::make_unique<SegmentResultProvider::SegmentResult>(
                     SegmentResultProvider::ResultState::kTfliteModelScoreUsed,
-                    CreatePredictionResultWithBinaryClassifier(), /*rank=*/2);
+                    CreatePredictionResultWithBinaryClassifier(),
+                    /*rank=*/2);
             std::move(options->callback).Run(std::move(result));
           }));
 
   base::RunLoop loop;
-  ClassificationResult expected(PredictionStatus::kSucceeded);
-  expected.ordered_labels.emplace_back("positive_label");
-  request_handler_->GetClassificationResult(
+  RawResult result(PredictionStatus::kFailed);
+  request_handler_->GetPredictionResult(
       options, scoped_refptr<InputContext>(),
-      base::BindOnce(&RequestHandlerTest::OnGetClassificationResult,
-                     base::Unretained(this), loop.QuitClosure(), expected));
-  loop.Run();
-}
-
-TEST_F(RequestHandlerTest, GetAnnotatedNumericResult) {
-  PredictionOptions options;
-  options.on_demand_execution = true;
-
-  EXPECT_CALL(*result_provider_, GetSegmentResult(_))
-      .Times(1)
-      .WillRepeatedly(Invoke(
-          [](std::unique_ptr<SegmentResultProvider::GetResultOptions> options) {
-            EXPECT_TRUE(options->ignore_db_scores);
-            EXPECT_EQ(options->segment_id, kSegmentId);
-            auto result =
-                std::make_unique<SegmentResultProvider::SegmentResult>(
-                    SegmentResultProvider::ResultState::kTfliteModelScoreUsed,
-                    CreatePredictionResultWithGenericPredictor(), /*rank=*/2);
-            std::move(options->callback).Run(std::move(result));
-          }));
-
-  base::RunLoop loop;
-  AnnotatedNumericResult result(PredictionStatus::kSucceeded);
-  request_handler_->GetAnnotatedNumericResult(
-      options, scoped_refptr<InputContext>(),
-      base::BindOnce(&RequestHandlerTest::OnGetAnnotatedNumericResult,
+      base::BindOnce(&RequestHandlerTest::OnGetPredictionResult,
                      base::Unretained(this), loop.QuitClosure()));
   loop.Run();
 }
diff --git a/components/segmentation_platform/public/result.h b/components/segmentation_platform/public/result.h
index b35fbe1..466f53d1 100644
--- a/components/segmentation_platform/public/result.h
+++ b/components/segmentation_platform/public/result.h
@@ -71,6 +71,10 @@
 
   // The result from the model.
   proto::PredictionResult result;
+
+  // The request ID used for identifying a specific training data inputs. Can be
+  // null if training data was not uploaded for that execution.
+  TrainingRequestId request_id;
 };
 
 using ClassificationResultCallback =
@@ -78,6 +82,9 @@
 using AnnotatedNumericResultCallback =
     base::OnceCallback<void(const AnnotatedNumericResult&)>;
 
+using RawResult = AnnotatedNumericResult;
+using RawResultCallback = base::OnceCallback<void(const RawResult&)>;
+
 }  // namespace segmentation_platform
 
 #endif  // COMPONENTS_SEGMENTATION_PLATFORM_PUBLIC_RESULT_H_
diff --git a/components/services/screen_ai/BUILD.gn b/components/services/screen_ai/BUILD.gn
index 374abbb..296dac04 100644
--- a/components/services/screen_ai/BUILD.gn
+++ b/components/services/screen_ai/BUILD.gn
@@ -79,7 +79,6 @@
   testonly = true
 
   sources = [
-    "public/cpp/screen_ai_install_state_unittest.cc",
     "screen_ai_ax_tree_serializer_unittest.cc",
     "screen_ai_service_impl_unittest.cc",
   ]
@@ -97,7 +96,6 @@
     ":screen_ai",
     "//base/test:test_support",
     "//components/services/screen_ai/proto",
-    "//components/services/screen_ai/public/cpp:screen_ai_install_state",
     "//components/ukm:test_support",
     "//testing/gtest",
     "//ui/accessibility:test_support",
diff --git a/components/services/screen_ai/public/cpp/BUILD.gn b/components/services/screen_ai/public/cpp/BUILD.gn
index 24613dd..d8b2b43 100644
--- a/components/services/screen_ai/public/cpp/BUILD.gn
+++ b/components/services/screen_ai/public/cpp/BUILD.gn
@@ -2,59 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/config/ui.gni")
-
-if (is_chromeos_ash) {
-  source_set("screen_ai_chromeos_installer") {
-    sources = [
-      "screen_ai_chromeos_installer.cc",
-      "screen_ai_chromeos_installer.h",
-    ]
-
-    deps = [
-      ":screen_ai_install_state",
-      ":utilities",
-      "//chromeos/ash/components/dbus/dlcservice",
-      "//chromeos/ash/components/dbus/dlcservice:dlcservice_proto",
-    ]
-  }
-}
-
-source_set("screen_ai_install_state") {
-  sources = [
-    "screen_ai_install_state.cc",
-    "screen_ai_install_state.h",
-  ]
-
-  deps = [
-    ":utilities",
-    "//base/",
-    "//components/prefs",
-    "//ui/accessibility:ax_base",
-  ]
-}
-
-source_set("screen_ai_service_router_factory") {
-  sources = [
-    "screen_ai_service_router.cc",
-    "screen_ai_service_router.h",
-    "screen_ai_service_router_factory.cc",
-    "screen_ai_service_router_factory.h",
-  ]
-
-  deps = [
-    ":screen_ai_install_state",
-    "//components/keyed_service/content",
-    "//components/keyed_service/core",
-    "//components/services/screen_ai/public/mojom",
-    "//content/public/browser",
-  ]
-}
-
 source_set("utilities") {
   sources = [
-    "pref_names.cc",
-    "pref_names.h",
     "utilities.cc",
     "utilities.h",
   ]
@@ -62,6 +11,5 @@
   deps = [
     "//base",
     "//components/component_updater",
-    "//components/prefs",
   ]
 }
diff --git a/components/services/screen_ai/public/cpp/DEPS b/components/services/screen_ai/public/cpp/DEPS
index 7e7224c5..905953f 100644
--- a/components/services/screen_ai/public/cpp/DEPS
+++ b/components/services/screen_ai/public/cpp/DEPS
@@ -1,7 +1,3 @@
 include_rules = [
-  "+components/keyed_service/core",
-  "+components/keyed_service/content",
-  "+components/prefs",
   "+components/component_updater",
-  "+chromeos/ash/components/dbus/dlcservice"
 ]
diff --git a/components/supervised_user/core/common/features.cc b/components/supervised_user/core/common/features.cc
index 4daa30c..c041cba 100644
--- a/components/supervised_user/core/common/features.cc
+++ b/components/supervised_user/core/common/features.cc
@@ -148,6 +148,21 @@
              "EnableExtensionsPermissionsForSupervisedUsersOnDesktop",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+// Whether to display a "Managed by your parent" or similar text for supervised
+// users in various UI surfaces.
+BASE_FEATURE(kEnableManagedByParentUi,
+             "EnableManagedByParentUi",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+// The URL which the "Managed by your parent" UI links to. This is defined as a
+// FeatureParam (but with the currently correct default) because:
+// * We expect to change this URL in the near-term, this allows us to gradually
+//   roll out that change
+// * If the exact URL needs changing this can be done without requiring a binary
+//   rollout
+constexpr base::FeatureParam<std::string> kManagedByParentUiMoreInfoUrl{
+    &kEnableManagedByParentUi, "more_info_url",
+    "https://familylink.google.com/setting/resource/94"};
+
 bool IsSynchronousSignInCheckingEnabled() {
   return base::FeatureList::IsEnabled(kSynchronousSignInChecking);
 }
diff --git a/components/supervised_user/core/common/features.h b/components/supervised_user/core/common/features.h
index be7f72c2..f6c9b012 100644
--- a/components/supervised_user/core/common/features.h
+++ b/components/supervised_user/core/common/features.h
@@ -6,6 +6,7 @@
 #define COMPONENTS_SUPERVISED_USER_CORE_COMMON_FEATURES_H_
 
 #include "base/feature_list.h"
+#include "base/metrics/field_trial_params.h"
 
 namespace supervised_user {
 
@@ -22,6 +23,8 @@
 BASE_DECLARE_FEATURE(kEnableSupervisionOnDesktopAndIOS);
 BASE_DECLARE_FEATURE(kFilterWebsitesForSupervisedUsersOnDesktopAndIOS);
 BASE_DECLARE_FEATURE(kEnableExtensionsPermissionsForSupervisedUsersOnDesktop);
+BASE_DECLARE_FEATURE(kEnableManagedByParentUi);
+extern const base::FeatureParam<std::string> kManagedByParentUiMoreInfoUrl;
 
 BASE_DECLARE_FEATURE(kLocalExtensionApprovalsV2);
 
diff --git a/components/sync/protocol/autofill_specifics.proto b/components/sync/protocol/autofill_specifics.proto
index ee40460..a1113563 100644
--- a/components/sync/protocol/autofill_specifics.proto
+++ b/components/sync/protocol/autofill_specifics.proto
@@ -152,11 +152,8 @@
   // Phone.
   repeated string phone_home_whole_number = 13;
 
-  // The state indicates if the profile qualifies to get merged with a
-  // profile observed in a form submission. If true, the profile can still be
-  // updated silently, but it should not be considered for merges that need to
-  // involve user interactions.
-  optional bool disallow_settings_visible_updates = 63;
+  reserved 63;
+  reserved "disallow_settings_visible_updates";
 
   // Birthdate fields.
   optional int32 birthdate_day = 64;
diff --git a/components/sync/protocol/proto_visitors.h b/components/sync/protocol/proto_visitors.h
index 3d1da88..a7cd902 100644
--- a/components/sync/protocol/proto_visitors.h
+++ b/components/sync/protocol/proto_visitors.h
@@ -254,7 +254,6 @@
   VISIT(address_home_language_code);
   VISIT_REP(phone_home_whole_number);
   VISIT(validity_state_bitfield);
-  VISIT(disallow_settings_visible_updates);
 
   VISIT(birthdate_day);
   VISIT(birthdate_month);
diff --git a/components/viz/service/display/dc_layer_overlay.cc b/components/viz/service/display/dc_layer_overlay.cc
index bc44bb7..c6ee9ca 100644
--- a/components/viz/service/display/dc_layer_overlay.cc
+++ b/components/viz/service/display/dc_layer_overlay.cc
@@ -661,16 +661,15 @@
 
 void DCLayerOverlayProcessor::RemoveClearVideoQuadCandidatesIfMoving(
     const QuadList* quad_list,
-    std::vector<size_t>* candidate_index_list) {
+    std::vector<QuadList::Iterator>& candidates) {
   // The number of frames all overlay candidates need to be stable before we
   // allow overlays again. This number was chosen experimentally.
   constexpr int kFramesOfStabilityForOverlayPromotion = 5;
 
   std::vector<gfx::Rect> current_frame_overlay_candidate_rects;
-  current_frame_overlay_candidate_rects.reserve(candidate_index_list->size());
+  current_frame_overlay_candidate_rects.reserve(candidates.size());
 
-  for (auto index : *candidate_index_list) {
-    auto candidate_it = std::next(quad_list->begin(), index);
+  for (const auto& candidate_it : candidates) {
     if (IsClearVideoQuad(candidate_it)) {
       gfx::Rect quad_rectangle_in_target_space =
           ClippedQuadRectangle(*candidate_it);
@@ -692,14 +691,14 @@
   if (frames_since_last_overlay_candidate_rects_change_ <=
       kFramesOfStabilityForOverlayPromotion) {
     // Remove all video quad candidates if any of them moved recently
-    auto candidate_index_it = candidate_index_list->begin();
-    while (candidate_index_it != candidate_index_list->end()) {
-      auto candidate_it = std::next(quad_list->begin(), *candidate_index_it);
-      if (IsClearVideoQuad(candidate_it)) {
-        candidate_index_it = candidate_index_list->erase(candidate_index_it);
-        RecordDCLayerResult(DC_LAYER_FAILED_YUV_VIDEO_QUAD_MOVED, candidate_it);
+    auto candidate_it = candidates.begin();
+    while (candidate_it != candidates.end()) {
+      if (IsClearVideoQuad(*candidate_it)) {
+        RecordDCLayerResult(DC_LAYER_FAILED_YUV_VIDEO_QUAD_MOVED,
+                            *candidate_it);
+        candidate_it = candidates.erase(candidate_it);
       } else {
-        candidate_index_it++;
+        candidate_it++;
       }
     }
   }
@@ -735,22 +734,15 @@
     return;
   }
 
-  // Used for generating the candidate index list.
-  std::vector<size_t> candidate_index_list;
-  size_t candidate = 0;
-
-  // Used for looping through candidate_index_list to UpdateDCLayerOverlays()
-  size_t prev_index = 0;
+  std::vector<QuadList::Iterator> candidates;
   QuadList* quad_list = &render_pass->quad_list;
-  auto prev_it = quad_list->begin();
 
   // Used for whether overlay should be skipped
   int yuv_quads_in_quad_list = 0;
   int damaged_yuv_quads_in_quad_list = 0;
   bool has_protected_video_or_texture_overlays = false;
 
-  for (auto it = quad_list->begin(); it != quad_list->end();
-       ++it, ++candidate) {
+  for (auto it = quad_list->begin(); it != quad_list->end(); ++it) {
     if (it->material == DrawQuad::Material::kAggregatedRenderPass) {
       const auto* rpdq = AggregatedRenderPassDrawQuad::MaterialCast(*it);
       auto render_pass_it =
@@ -846,12 +838,7 @@
     if (is_protected_video || is_texture_quad)
       has_protected_video_or_texture_overlays = true;
 
-    if (candidate_index_list.size() == 0) {
-      prev_index = candidate;
-      prev_it = it;
-    }
-
-    candidate_index_list.push_back(candidate);
+    candidates.push_back(it);
   }
 
   // We might not save power if there are more than one videos and only part of
@@ -886,16 +873,12 @@
   processed_yuv_overlay_count_ = 0;
 
   if (base::FeatureList::IsEnabled(features::kDisableVideoOverlayIfMoving)) {
-    RemoveClearVideoQuadCandidatesIfMoving(quad_list, &candidate_index_list);
+    RemoveClearVideoQuadCandidatesIfMoving(quad_list, candidates);
   }
 
   // Copy the overlay quad info to dc_layer_overlays and replace/delete overlay
   // quads in quad_list.
-  for (auto index : candidate_index_list) {
-    auto it = std::next(prev_it, index - prev_index);
-    prev_it = it;
-    prev_index = index;
-
+  for (auto& it : candidates) {
     if (reject_overlays) {
       RecordDCLayerResult(DC_LAYER_FAILED_TOO_MANY_OVERLAYS, it);
       continue;
@@ -954,9 +937,8 @@
                                quad_rectangle_in_root_space);
 
     UpdateDCLayerOverlays(resource_provider, display_rect, render_pass, it,
-                          quad_rectangle_in_root_space, is_overlay, &prev_it,
-                          &prev_index, damage_rect, dc_layer_overlays,
-                          is_page_fullscreen_mode);
+                          quad_rectangle_in_root_space, is_overlay, damage_rect,
+                          dc_layer_overlays, is_page_fullscreen_mode);
   }
 
   // Update previous frame state after processing root pass. If there is no
@@ -1040,8 +1022,6 @@
     const QuadList::Iterator& it,
     const gfx::Rect& quad_rectangle_in_root_space,
     bool is_overlay,
-    QuadList::Iterator* new_it,
-    size_t* new_index,
     gfx::Rect* damage_rect,
     OverlayCandidateList* dc_layer_overlays,
     bool is_page_fullscreen_mode) {
@@ -1078,8 +1058,7 @@
   // Underlays are less efficient, so attempt regular overlays first. We can
   // only check for occlusion within a render pass.
   if (is_overlay) {
-    *new_it = ProcessForOverlay(display_rect, render_pass, it);
-    (*new_index)++;
+    ProcessForOverlay(display_rect, render_pass, it);
   } else {
     ProcessForUnderlay(display_rect, render_pass, quad_rectangle_in_root_space,
                        it, dc_layer_overlays->size(), damage_rect, &dc_layer);
@@ -1087,14 +1066,13 @@
 
   current_frame_overlay_rects_.push_back(
       {quad_rectangle_in_root_space, is_overlay});
-
   dc_layer_overlays->push_back(dc_layer);
 
   // Recorded for each overlay.
   UMA_HISTOGRAM_BOOLEAN("GPU.DirectComposition.IsUnderlay", !is_overlay);
 }
 
-QuadList::Iterator DCLayerOverlayProcessor::ProcessForOverlay(
+void DCLayerOverlayProcessor::ProcessForOverlay(
     const gfx::RectF& display_rect,
     AggregatedRenderPass* render_pass,
     const QuadList::Iterator& it) {
@@ -1109,7 +1087,11 @@
     RemoveOverlayDamageRect(it);
   }
 
-  return render_pass->quad_list.EraseAndInvalidateAllPointers(it);
+  // Overlay quads should not be drawn. Removing the quads from the quad list
+  // creates extra complexity since we would be traversing the list while
+  // removing them. Instead, we can just make the visible rect empty, which
+  // would then be skipped by DirectRenderer::ShouldSkipQuad.
+  it->visible_rect = gfx::Rect();
 }
 
 void DCLayerOverlayProcessor::ProcessForUnderlay(
diff --git a/components/viz/service/display/dc_layer_overlay.h b/components/viz/service/display/dc_layer_overlay.h
index 9858e462..d89dfff 100644
--- a/components/viz/service/display/dc_layer_overlay.h
+++ b/components/viz/service/display/dc_layer_overlay.h
@@ -78,16 +78,14 @@
                              const QuadList::Iterator& it,
                              const gfx::Rect& quad_rectangle_in_root_space,
                              bool is_overlay,
-                             QuadList::Iterator* new_it,
-                             size_t* new_index,
                              gfx::Rect* damage_rect,
                              OverlayCandidateList* dc_layer_overlays,
                              bool is_page_fullscreen_mode);
 
   // Returns an iterator to the element after |it|.
-  QuadList::Iterator ProcessForOverlay(const gfx::RectF& display_rect,
-                                       AggregatedRenderPass* render_pass,
-                                       const QuadList::Iterator& it);
+  void ProcessForOverlay(const gfx::RectF& display_rect,
+                         AggregatedRenderPass* render_pass,
+                         const QuadList::Iterator& it);
   void ProcessForUnderlay(const gfx::RectF& display_rect,
                           AggregatedRenderPass* render_pass,
                           const gfx::Rect& quad_rectangle,
@@ -126,7 +124,7 @@
   // candidates.
   void RemoveClearVideoQuadCandidatesIfMoving(
       const QuadList* quad_list,
-      std::vector<size_t>* candidate_index_list);
+      std::vector<QuadList::Iterator>& candidates);
 
   bool has_overlay_support_;
   bool system_hdr_enabled_ = false;
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 e127aca..4fdcbd6 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl.cc
@@ -469,7 +469,8 @@
                           kPremul_SkAlphaType, sk_color_space_);
     skgpu::graphite::TextureInfo texture_info = gpu::GetGraphiteTextureInfo(
         dependency_->gr_context_type(), format_, /*plane_index=*/0,
-        /*mipmapped=*/false, /*root_surface=*/true);
+        /*mipmapped=*/false,
+        /*root_surface=*/!capabilities_.supports_surfaceless);
     CHECK(texture_info.isValid());
     current_paint_.emplace(graphite_recorder_, image_info, texture_info);
   } else {
diff --git a/content/browser/attribution_reporting/attribution_config.cc b/content/browser/attribution_reporting/attribution_config.cc
index 97e5800..e3729db 100644
--- a/content/browser/attribution_reporting/attribution_config.cc
+++ b/content/browser/attribution_reporting/attribution_config.cc
@@ -80,8 +80,15 @@
     return false;
   }
 
-  if (first_report_window_deadline < base::TimeDelta() ||
-      second_report_window_deadline <= first_report_window_deadline) {
+  if (first_navigation_report_window_deadline < base::TimeDelta() ||
+      second_navigation_report_window_deadline <=
+          first_navigation_report_window_deadline) {
+    return false;
+  }
+
+  if (first_event_report_window_deadline < base::TimeDelta() ||
+      second_event_report_window_deadline <=
+          first_event_report_window_deadline) {
     return false;
   }
 
@@ -122,4 +129,16 @@
   return true;
 }
 
+AttributionConfig::EventLevelLimit::EventLevelLimit() = default;
+AttributionConfig::EventLevelLimit::EventLevelLimit(const EventLevelLimit&) =
+    default;
+AttributionConfig::EventLevelLimit::EventLevelLimit(EventLevelLimit&&) =
+    default;
+AttributionConfig::EventLevelLimit::~EventLevelLimit() = default;
+
+AttributionConfig::EventLevelLimit&
+AttributionConfig::EventLevelLimit::operator=(const EventLevelLimit&) = default;
+AttributionConfig::EventLevelLimit&
+AttributionConfig::EventLevelLimit::operator=(EventLevelLimit&&) = default;
+
 }  // namespace content
diff --git a/content/browser/attribution_reporting/attribution_config.h b/content/browser/attribution_reporting/attribution_config.h
index 0638181..44a7bfe 100644
--- a/content/browser/attribution_reporting/attribution_config.h
+++ b/content/browser/attribution_reporting/attribution_config.h
@@ -40,7 +40,16 @@
     // should also be updated.
   };
 
-  struct EventLevelLimit {
+  struct CONTENT_EXPORT EventLevelLimit {
+    EventLevelLimit();
+
+    EventLevelLimit(const EventLevelLimit&);
+    EventLevelLimit(EventLevelLimit&&);
+    ~EventLevelLimit();
+
+    EventLevelLimit& operator=(const EventLevelLimit&);
+    EventLevelLimit& operator=(EventLevelLimit&&);
+
     // Returns true if this config is valid.
     [[nodiscard]] bool Validate() const;
 
@@ -70,10 +79,17 @@
     static constexpr base::TimeDelta kDefaultSecondReportWindowDeadline =
         base::Days(7);
 
-    // Controls the report window deadlines for scheduling report times.
-    base::TimeDelta first_report_window_deadline =
+    // Controls the report window deadlines for scheduling navigation report
+    // times.
+    base::TimeDelta first_navigation_report_window_deadline =
         kDefaultFirstReportWindowDeadline;
-    base::TimeDelta second_report_window_deadline =
+    base::TimeDelta second_navigation_report_window_deadline =
+        kDefaultSecondReportWindowDeadline;
+
+    // Controls the report window deadlines for scheduling event report times.
+    base::TimeDelta first_event_report_window_deadline =
+        kDefaultFirstReportWindowDeadline;
+    base::TimeDelta second_event_report_window_deadline =
         kDefaultSecondReportWindowDeadline;
 
     // When adding new members, the corresponding `Validate()` definition and
diff --git a/content/browser/attribution_reporting/attribution_interop_parser_unittest.cc b/content/browser/attribution_reporting/attribution_interop_parser_unittest.cc
index 241135a8..a2c68fc 100644
--- a/content/browser/attribution_reporting/attribution_interop_parser_unittest.cc
+++ b/content/browser/attribution_reporting/attribution_interop_parser_unittest.cc
@@ -65,8 +65,10 @@
                            config.max_reports_per_destination,
                            config.max_attributions_per_navigation_source,
                            config.max_attributions_per_event_source,
-                           config.first_report_window_deadline,
-                           config.second_report_window_deadline);
+                           config.first_navigation_report_window_deadline,
+                           config.second_navigation_report_window_deadline,
+                           config.first_event_report_window_deadline,
+                           config.second_event_report_window_deadline);
   };
   return tie(a) == tie(b);
 }
@@ -101,6 +103,13 @@
 
 using ::attribution_reporting::SuitableOrigin;
 
+AttributionConfig::EventLevelLimit EventLevelLimitWith(
+    base::FunctionRef<void(AttributionConfig::EventLevelLimit&)> f) {
+  AttributionConfig::EventLevelLimit limit;
+  f(limit);
+  return limit;
+}
+
 // Pick an arbitrary offset time to test correct handling.
 constexpr base::Time kOffsetTime = base::Time::UnixEpoch() + base::Days(5);
 
@@ -599,26 +608,37 @@
       {R"json({"rate_limit_max_attributions":"10"})json", false,
        AttributionConfig{.rate_limit = {.max_attributions = 10}}},
       {R"json({"navigation_source_trigger_data_cardinality":"10"})json", false,
-       AttributionConfig{
-           .event_level_limit = {.navigation_source_trigger_data_cardinality =
-                                     10}}},
+       AttributionConfig{.event_level_limit = EventLevelLimitWith(
+                             [](AttributionConfig::EventLevelLimit& e) {
+                               e.navigation_source_trigger_data_cardinality =
+                                   10;
+                             })}},
       {R"json({"event_source_trigger_data_cardinality":"10"})json", false,
-       AttributionConfig{
-           .event_level_limit = {.event_source_trigger_data_cardinality = 10}}},
+       AttributionConfig{.event_level_limit = EventLevelLimitWith(
+                             [](AttributionConfig::EventLevelLimit& e) {
+                               e.event_source_trigger_data_cardinality = 10;
+                             })}},
       {R"json({"randomized_response_epsilon":"inf"})json", false,
-       AttributionConfig{.event_level_limit =
-                             {.randomized_response_epsilon =
-                                  std ::numeric_limits<double>::infinity()}}},
+       AttributionConfig{.event_level_limit = EventLevelLimitWith(
+                             [](AttributionConfig::EventLevelLimit& e) {
+                               e.randomized_response_epsilon =
+                                   std::numeric_limits<double>::infinity();
+                             })}},
       {R"json({"max_event_level_reports_per_destination":"10"})json", false,
-       AttributionConfig{
-           .event_level_limit = {.max_reports_per_destination = 10}}},
+       AttributionConfig{.event_level_limit = EventLevelLimitWith(
+                             [](AttributionConfig::EventLevelLimit& e) {
+                               e.max_reports_per_destination = 10;
+                             })}},
       {R"json({"max_attributions_per_navigation_source":"10"})json", false,
-       AttributionConfig{
-           .event_level_limit = {.max_attributions_per_navigation_source =
-                                     10}}},
+       AttributionConfig{.event_level_limit = EventLevelLimitWith(
+                             [](AttributionConfig::EventLevelLimit& e) {
+                               e.max_attributions_per_navigation_source = 10;
+                             })}},
       {R"json({"max_attributions_per_event_source":"10"})json", false,
-       AttributionConfig{
-           .event_level_limit = {.max_attributions_per_event_source = 10}}},
+       AttributionConfig{.event_level_limit = EventLevelLimitWith(
+                             [](AttributionConfig::EventLevelLimit& e) {
+                               e.max_attributions_per_event_source = 10;
+                             })}},
       {R"json({"max_aggregatable_reports_per_destination":"10"})json", false,
        AttributionConfig{
            .aggregate_limit = {.max_reports_per_destination = 10}}},
@@ -655,13 +675,15 @@
                           .max_source_registration_reporting_origins = 20,
                           .max_attribution_reporting_origins = 15,
                           .max_attributions = 10},
-           .event_level_limit = {.navigation_source_trigger_data_cardinality =
-                                     100,
-                                 .event_source_trigger_data_cardinality = 10,
-                                 .randomized_response_epsilon = 0.2,
-                                 .max_reports_per_destination = 10,
-                                 .max_attributions_per_navigation_source = 5,
-                                 .max_attributions_per_event_source = 1},
+           .event_level_limit =
+               EventLevelLimitWith([](AttributionConfig::EventLevelLimit& e) {
+                 e.navigation_source_trigger_data_cardinality = 100;
+                 e.event_source_trigger_data_cardinality = 10;
+                 e.randomized_response_epsilon = 0.2;
+                 e.max_reports_per_destination = 10;
+                 e.max_attributions_per_navigation_source = 5;
+                 e.max_attributions_per_event_source = 1;
+               }),
            .aggregate_limit = {.max_reports_per_destination = 10,
                                .aggregatable_budget_per_source = 1000,
                                .min_delay = base::Minutes(10),
diff --git a/content/browser/attribution_reporting/attribution_storage_delegate_impl.cc b/content/browser/attribution_reporting/attribution_storage_delegate_impl.cc
index 45ac2e1..45a35e9a 100644
--- a/content/browser/attribution_reporting/attribution_storage_delegate_impl.cc
+++ b/content/browser/attribution_reporting/attribution_storage_delegate_impl.cc
@@ -43,14 +43,24 @@
 
 using ::attribution_reporting::mojom::SourceType;
 
-const base::FeatureParam<base::TimeDelta> kFirstReportWindowDeadline{
+const base::FeatureParam<base::TimeDelta> kFirstNavigationReportWindowDeadline{
     &blink::features::kConversionMeasurement, "first_report_window_deadline",
     AttributionConfig::EventLevelLimit::kDefaultFirstReportWindowDeadline};
 
-const base::FeatureParam<base::TimeDelta> kSecondReportWindowDeadline{
+const base::FeatureParam<base::TimeDelta> kSecondNavigationReportWindowDeadline{
     &blink::features::kConversionMeasurement, "second_report_window_deadline",
     AttributionConfig::EventLevelLimit::kDefaultSecondReportWindowDeadline};
 
+const base::FeatureParam<base::TimeDelta> kFirstEventReportWindowDeadline{
+    &blink::features::kConversionMeasurement,
+    "first_event_report_window_deadline",
+    AttributionConfig::EventLevelLimit::kDefaultFirstReportWindowDeadline};
+
+const base::FeatureParam<base::TimeDelta> kSecondEventReportWindowDeadline{
+    &blink::features::kConversionMeasurement,
+    "second_event_report_window_deadline",
+    AttributionConfig::EventLevelLimit::kDefaultSecondReportWindowDeadline};
+
 const base::FeatureParam<base::TimeDelta> kAggregateReportMinDelay{
     &blink::features::kConversionMeasurement, "aggregate_report_min_delay",
     AttributionConfig::AggregateLimit::kDefaultMinDelay};
@@ -59,6 +69,22 @@
     &blink::features::kConversionMeasurement, "aggregate_report_delay_span",
     AttributionConfig::AggregateLimit::kDefaultDelaySpan};
 
+const base::FeatureParam<bool> kVTCEarlyReportingWindows(
+    &blink::features::kConversionMeasurement,
+    "vtc_early_reporting_windows",
+    false);
+
+std::vector<base::TimeDelta> GetVtcEarlyDeadlines(
+    const AttributionConfig& config) {
+  if (!kVTCEarlyReportingWindows.Get()) {
+    return std::vector<base::TimeDelta>();
+  }
+
+  return std::vector<base::TimeDelta>{
+      config.event_level_limit.first_event_report_window_deadline,
+      config.event_level_limit.second_event_report_window_deadline};
+}
+
 base::Time GetClampedTime(base::TimeDelta time_delta, base::Time source_time) {
   constexpr base::TimeDelta kMinDeltaTime = base::Days(1);
   return source_time +
@@ -114,15 +140,38 @@
     : AttributionStorageDelegateImpl(noise_mode,
                                      delay_mode,
                                      AttributionConfig()) {
-  base::TimeDelta first_deadline = kFirstReportWindowDeadline.Get();
-  base::TimeDelta second_deadline = kSecondReportWindowDeadline.Get();
+  base::TimeDelta first_deadline = kFirstNavigationReportWindowDeadline.Get();
+  base::TimeDelta second_deadline = kSecondNavigationReportWindowDeadline.Get();
 
   if (!first_deadline.is_negative() && first_deadline < second_deadline) {
-    config_.event_level_limit.first_report_window_deadline = first_deadline;
-    config_.event_level_limit.second_report_window_deadline = second_deadline;
+    config_.event_level_limit.first_navigation_report_window_deadline =
+        first_deadline;
+    config_.event_level_limit.second_navigation_report_window_deadline =
+        second_deadline;
   } else {
     LOG(WARNING)
-        << "Invalid reporting window deadline value(s) - "
+        << "Invalid navigation reporting window deadline value(s) - "
+        << "Reporting window deadlines should be non-negative "
+        << "and the first deadline should be less than the second."
+        << "Using default values: ["
+        << AttributionConfig::EventLevelLimit::kDefaultFirstReportWindowDeadline
+        << ", "
+        << AttributionConfig::EventLevelLimit::
+               kDefaultSecondReportWindowDeadline
+        << "]";
+  }
+
+  first_deadline = kFirstEventReportWindowDeadline.Get();
+  second_deadline = kSecondEventReportWindowDeadline.Get();
+
+  if (!first_deadline.is_negative() && first_deadline < second_deadline) {
+    config_.event_level_limit.first_event_report_window_deadline =
+        first_deadline;
+    config_.event_level_limit.second_event_report_window_deadline =
+        second_deadline;
+  } else {
+    LOG(WARNING)
+        << "Invalid VTC reporting window deadline value(s) - "
         << "Reporting window deadlines should be non-negative "
         << "and the first deadline should be less than the second."
         << "Using default values: ["
@@ -413,10 +462,10 @@
   switch (source_type) {
     case SourceType::kNavigation:
       return std::vector<base::TimeDelta>{
-          config_.event_level_limit.first_report_window_deadline,
-          config_.event_level_limit.second_report_window_deadline};
+          config_.event_level_limit.first_navigation_report_window_deadline,
+          config_.event_level_limit.second_navigation_report_window_deadline};
     case SourceType::kEvent:
-      return std::vector<base::TimeDelta>();
+      return GetVtcEarlyDeadlines(config_);
   }
 }
 
diff --git a/content/browser/attribution_reporting/attribution_storage_delegate_impl_unittest.cc b/content/browser/attribution_reporting/attribution_storage_delegate_impl_unittest.cc
index 3ed3c3c2..26b13f1 100644
--- a/content/browser/attribution_reporting/attribution_storage_delegate_impl_unittest.cc
+++ b/content/browser/attribution_reporting/attribution_storage_delegate_impl_unittest.cc
@@ -564,14 +564,135 @@
                 declared_expiry, source_time));
 }
 
+class AttributionStorageDelegateImplTestEventFlagEnabled
+    : public testing::Test {
+ public:
+  AttributionStorageDelegateImplTestEventFlagEnabled() {
+    feature_list_.InitWithFeaturesAndParameters(
+        {{blink::features::kConversionMeasurement,
+          {{"vtc_early_reporting_windows", "true"}}}},
+        /*disabled_features=*/{});
+  }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+TEST_F(AttributionStorageDelegateImplTestEventFlagEnabled,
+       EventImmediateConversion_FirstWindowUsed) {
+  base::Time source_time = base::Time::Now();
+  const AttributionReport report =
+      GetReport(source_time, source_time,
+                /*expiry=*/base::Days(30),
+                /*report_window=*/base::Days(30), SourceType::kEvent);
+  EXPECT_EQ(source_time + base::Days(2) + base::Hours(1),
+            AttributionStorageDelegateImpl().GetEventLevelReportTime(
+                *report.GetStoredSource(), report.attribution_info().time));
+}
+
+TEST_F(AttributionStorageDelegateImplTestEventFlagEnabled,
+       EventConversionImmediatelyBeforeWindow_SameWindowUsed) {
+  base::Time source_time = base::Time::Now();
+  base::Time trigger_time = source_time + base::Days(2) - base::Minutes(1);
+  const AttributionReport report =
+      GetReport(source_time, trigger_time,
+                /*expiry=*/base::Days(30),
+                /*report_window=*/base::Days(30), SourceType::kEvent);
+  EXPECT_EQ(source_time + base::Days(2) + base::Hours(1),
+            AttributionStorageDelegateImpl().GetEventLevelReportTime(
+                *report.GetStoredSource(), report.attribution_info().time));
+}
+
+TEST_F(AttributionStorageDelegateImplTestEventFlagEnabled,
+       EventConversionImmediatelyAfterWindow_NextWindowUsed) {
+  base::Time source_time = base::Time::Now();
+
+  // The deadline for a window is 1 hour before the window. Use a time just
+  // after the deadline.
+  base::Time trigger_time = source_time + base::Days(2) + base::Minutes(1);
+  const AttributionReport report =
+      GetReport(source_time, trigger_time,
+                /*expiry=*/base::Days(30),
+                /*report_window=*/base::Days(30), SourceType::kEvent);
+  EXPECT_EQ(source_time + base::Days(7) + base::Hours(1),
+            AttributionStorageDelegateImpl().GetEventLevelReportTime(
+                *report.GetStoredSource(), report.attribution_info().time));
+}
+
+TEST_F(AttributionStorageDelegateImplTestEventFlagEnabled,
+       EventImpressionExpiryBeforeTwoDayWindow_ExpiryUsed) {
+  base::Time source_time = base::Time::Now();
+  base::Time trigger_time = source_time + base::Hours(1);
+
+  // Set the impression to expire before the two day window
+  const AttributionReport report =
+      GetReport(source_time, trigger_time,
+                /*expiry=*/base::Hours(2),
+                /*report_window=*/base::Hours(2), SourceType::kEvent);
+  EXPECT_EQ(source_time + base::Hours(3),
+            AttributionStorageDelegateImpl().GetEventLevelReportTime(
+                *report.GetStoredSource(), report.attribution_info().time));
+}
+
+TEST_F(AttributionStorageDelegateImplTestEventFlagEnabled,
+       EventImpressionExpiryBeforeSevenDayWindow_ExpiryWindowUsed) {
+  base::Time source_time = base::Time::Now();
+  base::Time trigger_time = source_time + base::Days(3);
+
+  // Set the impression to expire before the two day window.
+  const AttributionReport report =
+      GetReport(source_time, trigger_time,
+                /*expiry=*/base::Days(4),
+                /*report_window=*/base::Days(4), SourceType::kEvent);
+
+  EXPECT_EQ(source_time + base::Days(4) + base::Hours(1),
+            AttributionStorageDelegateImpl().GetEventLevelReportTime(
+                *report.GetStoredSource(), report.attribution_info().time));
+}
+
+TEST_F(AttributionStorageDelegateImplTestEventFlagEnabled,
+       EventImpressionExpiryAfterSevenDayWindow_ExpiryWindowUsed) {
+  base::Time source_time = base::Time::Now();
+  base::Time trigger_time = source_time + base::Days(7) + base::Hours(1);
+
+  // Set the impression to expire before the two day window.
+  const AttributionReport report =
+      GetReport(source_time, trigger_time,
+                /*expiry=*/base::Days(9),
+                /*report_window=*/base::Days(9), SourceType::kEvent);
+
+  // The expiry window is reported one hour after expiry time.
+  EXPECT_EQ(source_time + base::Days(9) + base::Hours(1),
+            AttributionStorageDelegateImpl().GetEventLevelReportTime(
+                *report.GetStoredSource(), report.attribution_info().time));
+}
+
+TEST_F(AttributionStorageDelegateImplTestEventFlagEnabled,
+       GetRandomFakeReports_Event_MatchesExpectedDistribution) {
+  // The probability that not all of the 3 states are seen after `num_samples`
+  // trials is at most ~1e-14476, which is 0 for all practical purposes, so the
+  // `expected_num_combinations` check should always pass.
+  //
+  // For the distribution check, the probability of failure with `tolerance` is
+  // at most 1e-9.
+  RunRandomFakeReportsTest(SourceType::kEvent,
+                           /*num_stars=*/1,
+                           /*num_bars=*/6,
+                           /*num_samples=*/100'000,
+                           /*tolerance=*/0.03);
+}
+
 class AttributionStorageDelegateImplTestFeatureConfigured
     : public testing::Test {
  public:
   AttributionStorageDelegateImplTestFeatureConfigured() {
     feature_list_.InitWithFeaturesAndParameters(
         {{blink::features::kConversionMeasurement,
-          {{"first_report_window_deadline", "1d"},
+          {{"vtc_early_reporting_windows", "true"},
+           {"first_report_window_deadline", "1d"},
            {"second_report_window_deadline", "5d"},
+           {"first_event_report_window_deadline", "1d"},
+           {"second_event_report_window_deadline", "5d"},
            {"aggregate_report_min_delay", "1m"},
            {"aggregate_report_delay_span", "29m"}}}},
         /*disabled_features=*/{});
@@ -584,11 +705,15 @@
 TEST_F(AttributionStorageDelegateImplTestFeatureConfigured,
        ImmediateConversion_FirstFeatureWindowUsed) {
   base::Time source_time = base::Time::Now();
-  const AttributionReport report =
-      GetReport(source_time, /*trigger_time=*/source_time);
-  EXPECT_EQ(source_time + base::Days(1) + base::Hours(1),
-            AttributionStorageDelegateImpl().GetEventLevelReportTime(
-                *report.GetStoredSource(), report.attribution_info().time));
+  for (auto source_type : kSourceTypes) {
+    const AttributionReport report =
+        GetReport(source_time, source_time,
+                  /*expiry=*/base::Days(30),
+                  /*report_window=*/base::Days(30), source_type);
+    EXPECT_EQ(source_time + base::Days(1) + base::Hours(1),
+              AttributionStorageDelegateImpl().GetEventLevelReportTime(
+                  *report.GetStoredSource(), report.attribution_info().time));
+  }
 }
 
 TEST_F(AttributionStorageDelegateImplTestFeatureConfigured,
@@ -598,10 +723,15 @@
   // The deadline for a window is 1 hour before the window. Use a time just
   // after the deadline.
   base::Time trigger_time = source_time + base::Days(1) + base::Minutes(1);
-  const AttributionReport report = GetReport(source_time, trigger_time);
-  EXPECT_EQ(source_time + base::Days(5) + base::Hours(1),
-            AttributionStorageDelegateImpl().GetEventLevelReportTime(
-                *report.GetStoredSource(), report.attribution_info().time));
+  for (auto source_type : kSourceTypes) {
+    const AttributionReport report =
+        GetReport(source_time, trigger_time,
+                  /*expiry=*/base::Days(30),
+                  /*report_window=*/base::Days(30), source_type);
+    EXPECT_EQ(source_time + base::Days(5) + base::Hours(1),
+              AttributionStorageDelegateImpl().GetEventLevelReportTime(
+                  *report.GetStoredSource(), report.attribution_info().time));
+  }
 }
 
 TEST_F(AttributionStorageDelegateImplTestFeatureConfigured,
@@ -620,8 +750,11 @@
   AttributionStorageDelegateImplTestInvalidFeatureConfigured() {
     feature_list_.InitWithFeaturesAndParameters(
         {{blink::features::kConversionMeasurement,
-          {{"first_report_window_deadline", "-1d"},
+          {{"vtc_early_reporting_windows", "true"},
+           {"first_report_window_deadline", "-1d"},
            {"second_report_window_deadline", "-5d"},
+           {"first_event_report_window_deadline", "-1d"},
+           {"second_event_report_window_deadline", "-5d"},
            {"aggregate_report_min_delay", "-1m"},
            {"aggregate_report_delay_span", "-29m"}}}},
         /*disabled_features=*/{});
@@ -634,21 +767,32 @@
 TEST_F(AttributionStorageDelegateImplTestInvalidFeatureConfigured,
        NegativeFirstWindow_DefaultUsed) {
   base::Time source_time = base::Time::Now();
-  const AttributionReport report =
-      GetReport(source_time, /*trigger_time=*/source_time);
-  EXPECT_EQ(source_time + base::Days(2) + base::Hours(1),
-            AttributionStorageDelegateImpl().GetEventLevelReportTime(
-                *report.GetStoredSource(), report.attribution_info().time));
+
+  for (auto source_type : kSourceTypes) {
+    const AttributionReport report =
+        GetReport(source_time, source_time,
+                  /*expiry=*/base::Days(30),
+                  /*report_window=*/base::Days(30), source_type);
+    EXPECT_EQ(source_time + base::Days(2) + base::Hours(1),
+              AttributionStorageDelegateImpl().GetEventLevelReportTime(
+                  *report.GetStoredSource(), report.attribution_info().time));
+  }
 }
 
 TEST_F(AttributionStorageDelegateImplTestInvalidFeatureConfigured,
        NegativeSecondWindow_DefaultUsed) {
   base::Time source_time = base::Time::Now();
   base::Time trigger_time = source_time + base::Days(2) + base::Minutes(1);
-  const AttributionReport report = GetReport(source_time, trigger_time);
-  EXPECT_EQ(source_time + base::Days(7) + base::Hours(1),
-            AttributionStorageDelegateImpl().GetEventLevelReportTime(
-                *report.GetStoredSource(), report.attribution_info().time));
+
+  for (auto source_type : kSourceTypes) {
+    const AttributionReport report =
+        GetReport(source_time, trigger_time,
+                  /*expiry=*/base::Days(30),
+                  /*report_window=*/base::Days(30), source_type);
+    EXPECT_EQ(source_time + base::Days(7) + base::Hours(1),
+              AttributionStorageDelegateImpl().GetEventLevelReportTime(
+                  *report.GetStoredSource(), report.attribution_info().time));
+  }
 }
 
 TEST_F(AttributionStorageDelegateImplTestInvalidFeatureConfigured,
diff --git a/content/browser/attribution_reporting/test/configurable_storage_delegate.cc b/content/browser/attribution_reporting/test/configurable_storage_delegate.cc
index dfead185..7ac9535f 100644
--- a/content/browser/attribution_reporting/test/configurable_storage_delegate.cc
+++ b/content/browser/attribution_reporting/test/configurable_storage_delegate.cc
@@ -24,6 +24,17 @@
 #include "content/browser/attribution_reporting/common_source_info.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
+namespace {
+
+content::AttributionConfig::EventLevelLimit EventLevelLimitWith(
+    base::FunctionRef<void(content::AttributionConfig::EventLevelLimit&)> f) {
+  content::AttributionConfig::EventLevelLimit limit;
+  f(limit);
+  return limit;
+}
+
+}  // namespace
+
 namespace content {
 
 ConfigurableStorageDelegate::ConfigurableStorageDelegate()
@@ -41,20 +52,19 @@
                   .max_attributions = std::numeric_limits<int64_t>::max(),
               },
           .event_level_limit =
-              {
-                  .navigation_source_trigger_data_cardinality =
-                      std::numeric_limits<uint64_t>::max(),
-                  .event_source_trigger_data_cardinality =
-                      std::numeric_limits<uint64_t>::max(),
-                  .randomized_response_epsilon =
-                      std::numeric_limits<double>::infinity(),
-                  .max_reports_per_destination =
-                      std::numeric_limits<int>::max(),
-                  .max_attributions_per_navigation_source =
-                      std::numeric_limits<int>::max(),
-                  .max_attributions_per_event_source =
-                      std::numeric_limits<int>::max(),
-              },
+              EventLevelLimitWith([](AttributionConfig::EventLevelLimit& e) {
+                e.navigation_source_trigger_data_cardinality =
+                    std::numeric_limits<uint64_t>::max();
+                e.event_source_trigger_data_cardinality =
+                    std::numeric_limits<uint64_t>::max();
+                e.randomized_response_epsilon =
+                    std::numeric_limits<double>::infinity();
+                e.max_reports_per_destination = std::numeric_limits<int>::max();
+                e.max_attributions_per_navigation_source =
+                    std::numeric_limits<int>::max();
+                e.max_attributions_per_event_source =
+                    std::numeric_limits<int>::max();
+              }),
           .aggregate_limit =
               {
                   .max_reports_per_destination =
diff --git a/content/browser/back_forward_cache_basics_browsertest.cc b/content/browser/back_forward_cache_basics_browsertest.cc
index 6e9f8ca..4f14061 100644
--- a/content/browser/back_forward_cache_basics_browsertest.cc
+++ b/content/browser/back_forward_cache_basics_browsertest.cc
@@ -5,6 +5,7 @@
 #include "content/browser/back_forward_cache_browsertest.h"
 
 #include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/content_navigation_policy.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/site_isolation_policy.h"
 #include "content/public/browser/web_contents.h"
@@ -202,13 +203,16 @@
   ASSERT_TRUE(embedded_test_server()->Start());
   GURL url_a(embedded_test_server()->GetURL("a.com", "/title1.html"));
   GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html"));
+  base::HistogramTester histograms;
 
   // 1) Navigate to A and open a popup.
   ASSERT_TRUE(NavigateToURL(shell(), url_a));
   RenderFrameHostImplWrapper rfh_a(current_frame_host());
   EXPECT_EQ(1u, rfh_a->GetSiteInstance()->GetRelatedActiveContentsCount());
+  EXPECT_EQ(1u, rfh_a->GetSiteInstance()->active_document_count());
   Shell* popup = OpenPopup(rfh_a.get(), url_a, "");
   EXPECT_EQ(2u, rfh_a->GetSiteInstance()->GetRelatedActiveContentsCount());
+  EXPECT_EQ(2u, rfh_a->GetSiteInstance()->active_document_count());
   rfh_a->GetBackForwardCacheMetrics()->SetObserverForTesting(this);
 
   // 2) Navigate to B. The previous document can't enter the BackForwardCache,
@@ -236,13 +240,27 @@
                               NotRestoredReason::kBrowsingInstanceNotSwapped}),
           BlockListedFeatures()));
 
+  // Make sure that histograms for related active contents are updated with info
+  // about A's related active contents.
+  histograms.ExpectUniqueSample(
+      "BackForwardCache.HistoryNavigationOutcome.RelatedActiveContents.Count",
+      2, 1);
+  histograms.ExpectUniqueSample(
+      "BackForwardCache.HistoryNavigationOutcome.RelatedActiveContents."
+      "IsPotentiallySyncAccessible",
+      BackForwardCacheMetrics::RelatedActiveContentsSyncAccessInfo::
+          kPotentiallySyncAccessibleNormalSiteInstance,
+      1);
+
   // 4) Make the popup drop the window.opener connection. It happens when the
   //    user does an omnibox-initiated navigation, which happens in a new
   //    BrowsingInstance.
   RenderFrameHostImplWrapper rfh_a_new(current_frame_host());
   EXPECT_EQ(2u, rfh_a_new->GetSiteInstance()->GetRelatedActiveContentsCount());
+  EXPECT_EQ(2u, rfh_a_new->GetSiteInstance()->active_document_count());
   ASSERT_TRUE(NavigateToURL(popup, url_b));
   EXPECT_EQ(1u, rfh_a_new->GetSiteInstance()->GetRelatedActiveContentsCount());
+  EXPECT_EQ(1u, rfh_a_new->GetSiteInstance()->active_document_count());
 
   // 5) Navigate to B again. As the scripting relationship with the popup is
   // now severed, the current page (|rfh_a_new|) can enter back-forward cache.
@@ -258,6 +276,275 @@
   ASSERT_TRUE(WaitForLoadStop(web_contents()));
   EXPECT_FALSE(rfh_b_new.IsRenderFrameDeleted());
   EXPECT_TRUE(rfh_b_new->IsInBackForwardCache());
+
+  // Expect the histograms aren't updated, since a BrowsingInstance swap
+  // happened.
+  histograms.ExpectTotalCount(
+      "BackForwardCache.HistoryNavigationOutcome.RelatedActiveContents.Count",
+      1);
+  histograms.ExpectTotalCount(
+      "BackForwardCache.HistoryNavigationOutcome.RelatedActiveContents."
+      "IsPotentiallySyncAccessible",
+      1);
+}
+
+// Similar with WindowOpen above, but open a cross-site page in the popup.
+IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest, WindowOpenCrossSite) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+  GURL url_a(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html"));
+  GURL url_c(embedded_test_server()->GetURL("c.com", "/title1.html"));
+  base::HistogramTester histograms;
+
+  // 1) Navigate to A and open a cross-site popup B.
+  ASSERT_TRUE(NavigateToURL(shell(), url_a));
+  RenderFrameHostImplWrapper rfh_a(current_frame_host());
+  EXPECT_EQ(1u, rfh_a->GetSiteInstance()->GetRelatedActiveContentsCount());
+  Shell* popup = OpenPopup(rfh_a.get(), url_b, "");
+  WebContentsImpl* popup_contents =
+      static_cast<WebContentsImpl*>(popup->web_contents());
+  EXPECT_TRUE(WaitForLoadStop(popup_contents));
+  FrameTreeNode* popup_root = popup_contents->GetPrimaryFrameTree().root();
+  EXPECT_EQ(popup_root->opener(), web_contents()->GetPrimaryFrameTree().root());
+
+  // The popup and the original tab are related active contents.
+  RenderFrameHostImplWrapper rfh_b(popup_root->current_frame_host());
+  EXPECT_EQ(2u, rfh_a->GetSiteInstance()->GetRelatedActiveContentsCount());
+  EXPECT_EQ(2u, rfh_b->GetSiteInstance()->GetRelatedActiveContentsCount());
+  // A and B use different SiteInstances if site isolation is turned on, and
+  // shares the same SiteInstance otherwise.
+  if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites()) {
+    EXPECT_EQ(1u, rfh_a->GetSiteInstance()->active_document_count());
+    EXPECT_EQ(1u, rfh_b->GetSiteInstance()->active_document_count());
+    EXPECT_NE(rfh_a->GetSiteInstance(), rfh_b->GetSiteInstance());
+  } else {
+    EXPECT_EQ(2u, rfh_a->GetSiteInstance()->active_document_count());
+    EXPECT_EQ(2u, rfh_b->GetSiteInstance()->active_document_count());
+    EXPECT_EQ(rfh_a->GetSiteInstance(), rfh_b->GetSiteInstance());
+  }
+  EXPECT_TRUE(rfh_a->GetSiteInstance()->IsRelatedSiteInstance(
+      rfh_b->GetSiteInstance()));
+
+  // 2) Navigate to C in the popup. The B document can't enter the
+  // BackForwardCache, because of the opener.
+  ASSERT_TRUE(NavigateToURLFromRenderer(rfh_b.get(), url_c));
+
+  if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites()) {
+    ASSERT_TRUE(rfh_b.WaitUntilRenderFrameDeleted());
+  } else {
+    ASSERT_FALSE(rfh_b->IsInBackForwardCache());
+  }
+  RenderFrameHostImplWrapper rfh_c(popup_root->current_frame_host());
+  EXPECT_EQ(2u, rfh_a->GetSiteInstance()->GetRelatedActiveContentsCount());
+  EXPECT_EQ(2u, rfh_c->GetSiteInstance()->GetRelatedActiveContentsCount());
+  EXPECT_TRUE(rfh_a->GetSiteInstance()->IsRelatedSiteInstance(
+      rfh_c->GetSiteInstance()));
+
+  // 3) Go back to B. It should not be restored from the back/forward cache.
+  ASSERT_TRUE(HistoryGoBack(popup_contents));
+  // Make sure that histograms for related active contents are updated with info
+  // about B's related active contents.
+  histograms.ExpectUniqueSample(
+      "BackForwardCache.HistoryNavigationOutcome.RelatedActiveContents.Count",
+      2, 1);
+
+  // When site isolation is turned on, A and B use different SiteInstances which
+  // means B doesn't share a SiteInstance with any other page, and thus can't be
+  // synchronously accessible by other pages. Meanwhile when site isolation is
+  // turned off, A and B will share the same SiteInstance and is marked as
+  // potentially synchronously accessible.
+  if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites()) {
+    histograms.ExpectUniqueSample(
+        "BackForwardCache.HistoryNavigationOutcome.RelatedActiveContents."
+        "IsPotentiallySyncAccessible",
+        BackForwardCacheMetrics::RelatedActiveContentsSyncAccessInfo::
+            kNoSyncAccess,
+        1);
+  } else {
+    histograms.ExpectUniqueSample(
+        "BackForwardCache.HistoryNavigationOutcome.RelatedActiveContents."
+        "IsPotentiallySyncAccessible",
+        BackForwardCacheMetrics::RelatedActiveContentsSyncAccessInfo::
+            kPotentiallySyncAccessibleDefaultSiteInstance,
+        1);
+  }
+}
+
+// Similar with WindowOpenCrossSite above, but navigate the popup same-site
+// instead of cross site.
+IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest,
+                       WindowOpenCrossSiteNavigateSameSite) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+  GURL url_a(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  GURL url_b1(embedded_test_server()->GetURL("b.com", "/title1.html"));
+  GURL url_b2(embedded_test_server()->GetURL("b.com", "/title2.html"));
+  base::HistogramTester histograms;
+
+  // 1) Navigate to A and open a cross-site popup B1.
+  ASSERT_TRUE(NavigateToURL(shell(), url_a));
+  RenderFrameHostImplWrapper rfh_a(current_frame_host());
+  EXPECT_EQ(1u, rfh_a->GetSiteInstance()->GetRelatedActiveContentsCount());
+  Shell* popup = OpenPopup(rfh_a.get(), url_b1, "");
+  WebContentsImpl* popup_contents =
+      static_cast<WebContentsImpl*>(popup->web_contents());
+  EXPECT_TRUE(WaitForLoadStop(popup_contents));
+  FrameTreeNode* popup_root = popup_contents->GetPrimaryFrameTree().root();
+  EXPECT_EQ(popup_root->opener(), web_contents()->GetPrimaryFrameTree().root());
+
+  // The popup and the original tab are related active contents.
+  RenderFrameHostImplWrapper rfh_b1(popup_root->current_frame_host());
+  EXPECT_EQ(2u, rfh_a->GetSiteInstance()->GetRelatedActiveContentsCount());
+  EXPECT_EQ(2u, rfh_b1->GetSiteInstance()->GetRelatedActiveContentsCount());
+  // A and B use different SiteInstances if site isolation is turned on, and
+  // shares the same SiteInstance otherwise.
+  if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites()) {
+    EXPECT_EQ(1u, rfh_a->GetSiteInstance()->active_document_count());
+    EXPECT_EQ(1u, rfh_b1->GetSiteInstance()->active_document_count());
+    EXPECT_NE(rfh_a->GetSiteInstance(), rfh_b1->GetSiteInstance());
+  } else {
+    EXPECT_EQ(2u, rfh_a->GetSiteInstance()->active_document_count());
+    EXPECT_EQ(2u, rfh_b1->GetSiteInstance()->active_document_count());
+    EXPECT_EQ(rfh_a->GetSiteInstance(), rfh_b1->GetSiteInstance());
+  }
+  EXPECT_TRUE(rfh_a->GetSiteInstance()->IsRelatedSiteInstance(
+      rfh_b1->GetSiteInstance()));
+
+  // 2) Navigate to B2 in the popup. The B1 document can't enter the
+  // BackForwardCache, because of the opener.
+  ASSERT_TRUE(NavigateToURLFromRenderer(rfh_b1.get(), url_b2));
+
+  if (ShouldCreateNewHostForAllFrames()) {
+    ASSERT_TRUE(rfh_b1.WaitUntilRenderFrameDeleted());
+  } else {
+    ASSERT_FALSE(rfh_b1->IsInBackForwardCache());
+  }
+
+  RenderFrameHostImplWrapper rfh_b2(popup_root->current_frame_host());
+  EXPECT_EQ(2u, rfh_a->GetSiteInstance()->GetRelatedActiveContentsCount());
+  EXPECT_EQ(2u, rfh_b2->GetSiteInstance()->GetRelatedActiveContentsCount());
+  EXPECT_TRUE(rfh_a->GetSiteInstance()->IsRelatedSiteInstance(
+      rfh_b2->GetSiteInstance()));
+
+  // 3) Go back to B1. It should not be restored from the back/forward cache.
+  ASSERT_TRUE(HistoryGoBack(popup_contents));
+  // Make sure that histograms for related active contents are updated with info
+  // about B1's related active contents.
+  histograms.ExpectUniqueSample(
+      "BackForwardCache.HistoryNavigationOutcome.RelatedActiveContents.Count",
+      2, 1);
+
+  // When site isolation is turned on, A and B1 use different SiteInstances
+  // which means B1 doesn't share a SiteInstance with any other page, and thus
+  // can't be synchronously accessible by other pages. Meanwhile when site
+  // isolation is turned off, A and B1 will share the same SiteInstance and is
+  // marked as potentially synchronously accessible. Note: Even though B1 and B2
+  // are same site and end up using the same SiteInstance and BrowsingInstance,
+  // the documents are not active at the same time (as B2 replaces B1), so those
+  // aren't counted as potentially having synchronous access to each other.
+  if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites()) {
+    histograms.ExpectUniqueSample(
+        "BackForwardCache.HistoryNavigationOutcome.RelatedActiveContents."
+        "IsPotentiallySyncAccessible",
+        BackForwardCacheMetrics::RelatedActiveContentsSyncAccessInfo::
+            kNoSyncAccess,
+        1);
+  } else {
+    histograms.ExpectUniqueSample(
+        "BackForwardCache.HistoryNavigationOutcome.RelatedActiveContents."
+        "IsPotentiallySyncAccessible",
+        BackForwardCacheMetrics::RelatedActiveContentsSyncAccessInfo::
+            kPotentiallySyncAccessibleDefaultSiteInstance,
+        1);
+  }
+}
+
+// Similar with WindowOpen above, but open a cross-site page that has an iframe
+// that is same-site with the opener.
+IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest,
+                       WindowOpenCrossSiteWithSameSiteChild) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+  GURL url_a(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  GURL url_b_with_a_iframe(embedded_test_server()->GetURL(
+      "b.com", "/cross_site_iframe_factory.html?b(a)"));
+  GURL url_c(embedded_test_server()->GetURL("c.com", "/title1.html"));
+  base::HistogramTester histograms;
+
+  // 1) Navigate to A and open a cross-site popup B.
+  ASSERT_TRUE(NavigateToURL(shell(), url_a));
+  RenderFrameHostImplWrapper rfh_a(current_frame_host());
+  EXPECT_EQ(1u, rfh_a->GetSiteInstance()->GetRelatedActiveContentsCount());
+  Shell* popup = OpenPopup(rfh_a.get(), url_b_with_a_iframe, "");
+  WebContentsImpl* popup_contents =
+      static_cast<WebContentsImpl*>(popup->web_contents());
+  EXPECT_TRUE(WaitForLoadStop(popup_contents));
+  FrameTreeNode* popup_root = popup_contents->GetPrimaryFrameTree().root();
+  EXPECT_EQ(popup_root->opener(), web_contents()->GetPrimaryFrameTree().root());
+
+  // The popup and the original tab are related active contents.
+  RenderFrameHostImplWrapper rfh_b(popup_root->current_frame_host());
+  EXPECT_EQ(2u, rfh_a->GetSiteInstance()->GetRelatedActiveContentsCount());
+  EXPECT_EQ(2u, rfh_b->GetSiteInstance()->GetRelatedActiveContentsCount());
+
+  // The opener A and the iframe A uses the same SiteInstance. Meanwhile, A and
+  // B use different SiteInstances if site isolation is turned on, and shares
+  // the same SiteInstance otherwise.
+  RenderFrameHostImplWrapper rfh_a_iframe(
+      rfh_b->child_at(0)->current_frame_host());
+  EXPECT_EQ(rfh_a->GetSiteInstance(), rfh_a_iframe->GetSiteInstance());
+  if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites()) {
+    EXPECT_EQ(2u, rfh_a->GetSiteInstance()->active_document_count());
+    EXPECT_EQ(2u, rfh_a_iframe->GetSiteInstance()->active_document_count());
+    EXPECT_EQ(1u, rfh_b->GetSiteInstance()->active_document_count());
+    EXPECT_NE(rfh_a->GetSiteInstance(), rfh_b->GetSiteInstance());
+  } else {
+    EXPECT_EQ(3u, rfh_a->GetSiteInstance()->active_document_count());
+    EXPECT_EQ(3u, rfh_a_iframe->GetSiteInstance()->active_document_count());
+    EXPECT_EQ(3u, rfh_b->GetSiteInstance()->active_document_count());
+    EXPECT_EQ(rfh_a->GetSiteInstance(), rfh_b->GetSiteInstance());
+  }
+  EXPECT_TRUE(rfh_a->GetSiteInstance()->IsRelatedSiteInstance(
+      rfh_b->GetSiteInstance()));
+
+  // 2) Navigate to C in the popup. The B document can't enter the
+  // BackForwardCache, because of the opener.
+  ASSERT_TRUE(NavigateToURLFromRenderer(rfh_b.get(), url_c));
+
+  if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites()) {
+    ASSERT_TRUE(rfh_b.WaitUntilRenderFrameDeleted());
+  } else {
+    ASSERT_FALSE(rfh_b->IsInBackForwardCache());
+  }
+  RenderFrameHostImplWrapper rfh_c(popup_root->current_frame_host());
+  EXPECT_EQ(2u, rfh_a->GetSiteInstance()->GetRelatedActiveContentsCount());
+  EXPECT_EQ(2u, rfh_c->GetSiteInstance()->GetRelatedActiveContentsCount());
+  EXPECT_TRUE(rfh_a->GetSiteInstance()->IsRelatedSiteInstance(
+      rfh_c->GetSiteInstance()));
+
+  // 3) Go back to B. It should not be restored from the back/forward cache.
+  ASSERT_TRUE(HistoryGoBack(popup_contents));
+  // Make sure that histograms for related active contents are updated with info
+  // about B's related active contents.
+  histograms.ExpectUniqueSample(
+      "BackForwardCache.HistoryNavigationOutcome.RelatedActiveContents.Count",
+      2, 1);
+
+  // As there is another document in another page that uses A's SiteInstance,
+  // A is marked as potentially synchronously accessible from another page.
+  if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites()) {
+    histograms.ExpectUniqueSample(
+        "BackForwardCache.HistoryNavigationOutcome.RelatedActiveContents."
+        "IsPotentiallySyncAccessible",
+        BackForwardCacheMetrics::RelatedActiveContentsSyncAccessInfo::
+            kPotentiallySyncAccessibleNormalSiteInstance,
+        1);
+  } else {
+    histograms.ExpectUniqueSample(
+        "BackForwardCache.HistoryNavigationOutcome.RelatedActiveContents."
+        "IsPotentiallySyncAccessible",
+        BackForwardCacheMetrics::RelatedActiveContentsSyncAccessInfo::
+            kPotentiallySyncAccessibleDefaultSiteInstance,
+        1);
+  }
 }
 
 // A popup will prevent a page from entering BFCache. Test that after closing a
@@ -269,15 +556,18 @@
   ASSERT_TRUE(embedded_test_server()->Start());
   GURL url_a(embedded_test_server()->GetURL("a.test", "/title1.html"));
   GURL url_b(embedded_test_server()->GetURL("b.test", "/title2.html"));
+  base::HistogramTester histograms;
 
   // Navigate to A.
   ASSERT_TRUE(NavigateToURL(shell(), url_a));
   RenderFrameHostImplWrapper rfh_a(current_frame_host());
   EXPECT_EQ(1u, rfh_a->GetSiteInstance()->GetRelatedActiveContentsCount());
+  EXPECT_EQ(1u, rfh_a->GetSiteInstance()->active_document_count());
 
   // Open a popup.
   Shell* popup = OpenPopup(rfh_a.get(), url_a, "");
   EXPECT_EQ(2u, rfh_a->GetSiteInstance()->GetRelatedActiveContentsCount());
+  EXPECT_EQ(2u, rfh_a->GetSiteInstance()->active_document_count());
 
   // Start navigating to B, the response will be delayed.
   TestNavigationObserver observer(web_contents());
@@ -291,6 +581,7 @@
   ASSERT_TRUE(rfh_popup.WaitUntilRenderFrameDeleted());
 
   EXPECT_EQ(1u, rfh_a->GetSiteInstance()->GetRelatedActiveContentsCount());
+  EXPECT_EQ(1u, rfh_a->GetSiteInstance()->active_document_count());
 
   // Send the response.
   response.Send(net::HTTP_OK, "text/html", "foo");
@@ -307,6 +598,15 @@
   // A is restored from BFCache.
   EXPECT_FALSE(rfh_a.IsRenderFrameDeleted());
   ExpectRestored(FROM_HERE);
+
+  // Expect no related active contents.
+  histograms.ExpectTotalCount(
+      "BackForwardCache.HistoryNavigationOutcome.RelatedActiveContents.Count",
+      0);
+  histograms.ExpectTotalCount(
+      "BackForwardCache.HistoryNavigationOutcome.RelatedActiveContents."
+      "IsPotentiallySyncAccessible",
+      0);
 }
 
 // Navigate from A(B) to C and go back.
diff --git a/content/browser/back_forward_cache_browsertest.cc b/content/browser/back_forward_cache_browsertest.cc
index aebc59d..d11f680 100644
--- a/content/browser/back_forward_cache_browsertest.cc
+++ b/content/browser/back_forward_cache_browsertest.cc
@@ -945,8 +945,9 @@
 // The test below tests that the brief period of time where two main frames are
 // alive in the same BrowsingInstance does not cause anything to blow up.
 
-// TODO(crbug.com/1127979): Flaky on Linux and Windows
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN)
+// TODO(crbug.com/1127979, crbug.com/1446206): Flaky on Linux, Windows and
+// ChromeOS
+#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_CHROMEOS)
 #define MAYBE_NavigateToTwoPagesOnSameSite DISABLED_NavigateToTwoPagesOnSameSite
 #else
 #define MAYBE_NavigateToTwoPagesOnSameSite NavigateToTwoPagesOnSameSite
diff --git a/content/browser/devtools/devtools_background_services_context_impl.h b/content/browser/devtools/devtools_background_services_context_impl.h
index d35278c..0197ceaf 100644
--- a/content/browser/devtools/devtools_background_services_context_impl.h
+++ b/content/browser/devtools/devtools_background_services_context_impl.h
@@ -117,7 +117,7 @@
 
   void OnRecordingTimeExpired(devtools::proto::BackgroundService service);
 
-  const raw_ref<BrowserContext> browser_context_;
+  const raw_ref<BrowserContext, DanglingUntriaged> browser_context_;
   scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
 
   // Maps from the background service to the time up until the events can be
diff --git a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
index 60746ef..9d47c50 100644
--- a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
+++ b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -1684,6 +1684,27 @@
   WaitForNotification("Inspector.targetReloadedAfterCrash", true);
 }
 
+IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, TargetGetTargetsAfterCrash) {
+  set_agent_host_can_close();
+  ASSERT_TRUE(embedded_test_server()->Start());
+  GURL url_a = embedded_test_server()->GetURL("a.com", "/title1.html");
+
+  NavigateToURLBlockUntilNavigationsComplete(shell(), url_a, 1);
+  Attach();
+  SendCommandSync("Inspector.enable");
+  SendCommandSync("Target.getTargets");
+  EXPECT_EQ(1u, result()->FindList("targetInfos")->size());
+
+  {
+    ScopedAllowRendererCrashes scoped_allow_renderer_crashes(shell());
+    shell()->LoadURL(GURL(blink::kChromeUICrashURL));
+    WaitForNotification("Inspector.targetCrashed");
+  }
+
+  SendCommandSync("Target.getTargets");
+  EXPECT_EQ(1u, result()->FindList("targetInfos")->size());
+}
+
 // Same as in DevToolsProtocolTest.InspectorTargetCrashedNavigate, but with a
 // cross-process navigation at the end.
 // Regression test for https://crbug.com/990315
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.cc b/content/browser/devtools/render_frame_devtools_agent_host.cc
index 9c48f63..c70240a 100644
--- a/content/browser/devtools/render_frame_devtools_agent_host.cc
+++ b/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -208,8 +208,6 @@
           FrameTreeNode* node = FrameTreeNode::From(render_frame_host);
           if (!ShouldCreateDevToolsForNode(node))
             return;
-          if (!render_frame_host->IsRenderFrameLive())
-            return;
           result->push_back(RenderFrameDevToolsAgentHost::GetOrCreateFor(node));
         });
   }
diff --git a/content/browser/loader/loader_browsertest.cc b/content/browser/loader/loader_browsertest.cc
index fd7f24a..dcf89eab 100644
--- a/content/browser/loader/loader_browsertest.cc
+++ b/content/browser/loader/loader_browsertest.cc
@@ -770,6 +770,7 @@
   url::Origin top_origin = url::Origin::Create(top_url);
 
   NavigateToURLBlockUntilNavigationsComplete(shell(), top_url, 1);
+  WaitForRequests(8u);
 
   auto requests = data();
   EXPECT_EQ(8u, requests.size());
@@ -877,6 +878,7 @@
   url::Origin top_origin = url::Origin::Create(top_url);
 
   NavigateToURLBlockUntilNavigationsComplete(shell(), top_url, 1);
+  WaitForRequests(3u);
 
   auto requests = data();
   EXPECT_EQ(3u, requests.size());
@@ -916,6 +918,7 @@
   EXPECT_EQ(true, EvalJs(shell(), "clickSameSiteNewWindowLink();"));
   Shell* new_shell = new_shell_observer.GetShell();
   EXPECT_TRUE(WaitForLoadStop(new_shell->web_contents()));
+  WaitForRequests(2u);
 
   auto requests = data();
   EXPECT_EQ(2u, requests.size());
@@ -1005,6 +1008,7 @@
   url::Origin nested_origin = url::Origin::Create(nested_url);
 
   NavigateToURLBlockUntilNavigationsComplete(shell(), top_url, 1);
+  WaitForRequests(4u);
 
   auto requests = data();
   EXPECT_EQ(4u, requests.size());
diff --git a/content/browser/renderer_host/back_forward_cache_metrics.cc b/content/browser/renderer_host/back_forward_cache_metrics.cc
index 20679118..fea2281a 100644
--- a/content/browser/renderer_host/back_forward_cache_metrics.cc
+++ b/content/browser/renderer_host/back_forward_cache_metrics.cc
@@ -457,6 +457,25 @@
     UMA_HISTOGRAM_ENUMERATION(
         "BackForwardCache.AllSites.EvictedAfterDocumentRestoredReason",
         EvictedAfterDocumentRestoredReason::kRestored);
+  } else {
+    if (back_forward_cache_allowed) {
+      base::UmaHistogramCounts100(
+          "BackForwardCache.HistoryNavigationOutcome.RelatedActiveContents."
+          "Count",
+          related_active_contents_count_);
+      base::UmaHistogramEnumeration(
+          "BackForwardCache.HistoryNavigationOutcome."
+          "RelatedActiveContents.IsPotentiallySyncAccessible",
+          related_active_contents_sync_access_info_);
+    }
+    base::UmaHistogramCounts100(
+        "BackForwardCache.AllSites.HistoryNavigationOutcome."
+        "RelatedActiveContents.Count",
+        related_active_contents_count_);
+    base::UmaHistogramEnumeration(
+        "BackForwardCache.AllSites.HistoryNavigationOutcome."
+        "RelatedActiveContents.IsPotentiallySyncAccessible",
+        related_active_contents_sync_access_info_);
   }
 
   if (back_forward_cache_allowed) {
@@ -586,8 +605,79 @@
 }
 
 void BackForwardCacheMetrics::SetBrowsingInstanceSwapResult(
-    absl::optional<ShouldSwapBrowsingInstance> reason) {
+    absl::optional<ShouldSwapBrowsingInstance> reason,
+    RenderFrameHostImpl* navigated_away_rfh) {
   browsing_instance_swap_result_ = reason;
+  if (navigated_away_rfh) {
+    SetRelatedActiveContentsInfo(navigated_away_rfh);
+  } else {
+    // The tracked reason is being reset as a result of prerender activation.
+    // Also reset `related_active_contents_count_` and
+    // `related_active_contents_sync_access_info_` as they are stale too.
+    CHECK(!reason.has_value());
+    related_active_contents_count_ = 1;
+    related_active_contents_sync_access_info_ =
+        RelatedActiveContentsSyncAccessInfo::kNoSyncAccess;
+  }
+}
+
+void BackForwardCacheMetrics::SetRelatedActiveContentsInfo(
+    RenderFrameHostImpl* navigated_away_rfh) {
+  CHECK(navigated_away_rfh->is_main_frame());
+  related_active_contents_count_ =
+      navigated_away_rfh->GetSiteInstance()->GetRelatedActiveContentsCount();
+
+  // Count how many documents in the navigating page uses each SiteInstance.
+  std::map<SiteInstanceId, int> doc_count_in_page;
+  navigated_away_rfh->ForEachRenderFrameHost(
+      [&doc_count_in_page](RenderFrameHost* rfh) {
+        auto id = rfh->GetSiteInstance()->GetId();
+        if (doc_count_in_page.contains(id)) {
+          doc_count_in_page[id]++;
+        } else {
+          doc_count_in_page[id] = 1;
+        }
+      });
+
+  // Determine if any document in the navigating page is potentially
+  // synchronously accessible by documents in other pages, by checking if there
+  // are documents in other pages that use the same SiteInstance as a document
+  // in the navigating page.
+  // Note that when site isolation is turned off, most sites will use the same
+  // SiteInstance (default SiteInstance), even when they come from unrelated
+  // origins & domains and can't synchronously access each other. In that case,
+  // we might overcount the potentially synchronously accessible pages, so
+  // handle those cases separately.
+  // TODO(https://crbug.com/1444759): Handle the default SiteInstance case in a
+  // better way.
+  related_active_contents_sync_access_info_ =
+      RelatedActiveContentsSyncAccessInfo::kNoSyncAccess;
+  navigated_away_rfh->ForEachRenderFrameHostWithAction(
+      [&doc_count_in_page, this](RenderFrameHost* rfh) {
+        auto* site_instance =
+            static_cast<SiteInstanceImpl*>(rfh->GetSiteInstance());
+        // `active_document_count()` counts the number of active documents in
+        // all pages that are in `site_instance`, including the navigating page.
+        // To get the number of active documents using `site_instance` in pages
+        // other than the navigating page, just subtract by the number of
+        // active document using `site_instance` in the navigating page.
+        int doc_in_other_pages_count =
+            site_instance->active_document_count() -
+            doc_count_in_page[site_instance->GetId()];
+        if (doc_in_other_pages_count > 0) {
+          if (site_instance->IsDefaultSiteInstance()) {
+            related_active_contents_sync_access_info_ =
+                RelatedActiveContentsSyncAccessInfo::
+                    kPotentiallySyncAccessibleDefaultSiteInstance;
+          } else {
+            related_active_contents_sync_access_info_ =
+                RelatedActiveContentsSyncAccessInfo::
+                    kPotentiallySyncAccessibleNormalSiteInstance;
+            return RenderFrameHost::FrameIterationAction::kStop;
+          }
+        }
+        return RenderFrameHost::FrameIterationAction::kContinue;
+      });
 }
 
 bool BackForwardCacheMetrics::DidSwapBrowsingInstance() const {
diff --git a/content/browser/renderer_host/back_forward_cache_metrics.h b/content/browser/renderer_host/back_forward_cache_metrics.h
index 0afc5e1..905b7542 100644
--- a/content/browser/renderer_host/back_forward_cache_metrics.h
+++ b/content/browser/renderer_host/back_forward_cache_metrics.h
@@ -196,10 +196,12 @@
   static void RecordEvictedAfterDocumentRestored(
       EvictedAfterDocumentRestoredReason reason);
 
-  // Sets the reason why the browsing instance is swapped/not swapped. Passing
-  // absl::nullopt resets the reason.
+  // Sets the reason why the browsing instance is swapped/not swapped when
+  // navigating away from `navigated_away_rfh`. Passing`reason` as absl::nullopt
+  // resets the reason and other tracked information.
   void SetBrowsingInstanceSwapResult(
-      absl::optional<ShouldSwapBrowsingInstance> reason);
+      absl::optional<ShouldSwapBrowsingInstance> reason,
+      RenderFrameHostImpl* navigated_away_rfh);
 
   absl::optional<ShouldSwapBrowsingInstance> browsing_instance_swap_result()
       const {
@@ -289,6 +291,15 @@
 
  private:
   friend class base::RefCounted<BackForwardCacheMetrics>;
+  FRIEND_TEST_ALL_PREFIXES(BackForwardCacheBrowserTest, WindowOpen);
+  FRIEND_TEST_ALL_PREFIXES(BackForwardCacheBrowserTest, WindowOpenCrossSite);
+  FRIEND_TEST_ALL_PREFIXES(BackForwardCacheBrowserTest,
+                           WindowOpenCrossSiteNavigateSameSite);
+  FRIEND_TEST_ALL_PREFIXES(BackForwardCacheBrowserTest,
+                           WindowOpenCrossSiteWithSameSiteChild);
+  FRIEND_TEST_ALL_PREFIXES(BackForwardCacheBrowserTest, WindowOpenThenClose);
+  FRIEND_TEST_ALL_PREFIXES(BackForwardCacheBrowserTest,
+                           WindowWithOpenerAndOpenee);
 
   ~BackForwardCacheMetrics();
 
@@ -318,6 +329,13 @@
   // (`browsing_instance_swap_result_` is not set).  Returns false otherwise.
   bool DidSwapBrowsingInstance() const;
 
+  // Sets information about `rfh`'s related active contents, whose existence
+  // make `rfh` ineligible for back/forward cache. This should be set at the
+  // same time as `browsing_instance_swap_result_` to reflect the condition of
+  // the related active contents at the time the BrowsingInstance swap decision
+  // was made when navigating away from `rfh`.
+  void SetRelatedActiveContentsInfo(RenderFrameHostImpl* rfh);
+
   // Main frame document sequence number that identifies all
   // NavigationEntries this metrics object is associated with.
   const int64_t document_sequence_number_;
@@ -369,6 +387,26 @@
   // didn't use a new BrowsingInstance.
   absl::optional<ShouldSwapBrowsingInstance> browsing_instance_swap_result_;
 
+  // The number of related active contents for the page.
+  int related_active_contents_count_ = 1;
+
+  // Whether any document in the page can potentially be accessed synchronously
+  // by another document in a different page, i.e. if there are any documents
+  // using the same SiteInstance as any document in the page. See also
+  // `SetRelatedActiveContentsInfo()`.
+  // Please keep in sync with BackForwardCacheReloadsAfterHistoryNavigation
+  // in tools/metrics/histograms/enums.xml. These values should not be
+  // renumbered.
+  enum class RelatedActiveContentsSyncAccessInfo {
+    kNoSyncAccess = 0,
+    kPotentiallySyncAccessibleDefaultSiteInstance = 1,
+    kPotentiallySyncAccessibleNormalSiteInstance = 2,
+    kMaxValue = kPotentiallySyncAccessibleNormalSiteInstance
+  };
+  RelatedActiveContentsSyncAccessInfo
+      related_active_contents_sync_access_info_ =
+          RelatedActiveContentsSyncAccessInfo::kNoSyncAccess;
+
   raw_ptr<TestObserver> test_observer_ = nullptr;
 };
 
diff --git a/content/browser/renderer_host/navigator.cc b/content/browser/renderer_host/navigator.cc
index 057902f8..0ace2920 100644
--- a/content/browser/renderer_host/navigator.cc
+++ b/content/browser/renderer_host/navigator.cc
@@ -612,7 +612,7 @@
             },
             controller_.GetLastCommittedEntryIndex(),
             controller_.GetEntryCount()),
-        site_instance);
+        site_instance->group());
   }
 
   // Store some information for recording WebPlatform security metrics. These
diff --git a/content/browser/renderer_host/render_frame_host_manager.cc b/content/browser/renderer_host/render_frame_host_manager.cc
index fea976a0..73b31e23 100644
--- a/content/browser/renderer_host/render_frame_host_manager.cc
+++ b/content/browser/renderer_host/render_frame_host_manager.cc
@@ -1125,7 +1125,8 @@
   BackForwardCacheMetrics* back_forward_cache_metrics =
       render_frame_host_->GetBackForwardCacheMetrics();
   if (back_forward_cache_metrics)
-    back_forward_cache_metrics->SetBrowsingInstanceSwapResult(absl::nullopt);
+    back_forward_cache_metrics->SetBrowsingInstanceSwapResult(absl::nullopt,
+                                                              nullptr);
 
   RestorePage(std::move(stored_page));
 }
@@ -2395,7 +2396,7 @@
     if (BackForwardCacheMetrics* back_forward_cache_metrics =
             render_frame_host_->GetBackForwardCacheMetrics()) {
       back_forward_cache_metrics->SetBrowsingInstanceSwapResult(
-          should_swap_result->reason());
+          should_swap_result->reason(), render_frame_host_.get());
     }
   }
 
@@ -4600,16 +4601,18 @@
     old_render_frame_host->SetHasPendingLifecycleStateUpdate();
   }
 
-  if (frame_tree_node_->IsMainFrame()) {
-    // Update the count of top-level frames using this SiteInstance.  All
-    // subframes are in the same BrowsingInstance as the main frame, so we only
-    // count top-level ones.  This makes the value easier for consumers to
-    // interpret.
-    if (render_frame_host_) {
+  // Update the count of active documents using this SiteInstance, both for
+  // active document tracking and related active contents tracking.
+  if (render_frame_host_) {
+    render_frame_host_->GetSiteInstance()->IncrementActiveDocumentCount();
+    if (frame_tree_node_->IsMainFrame()) {
       render_frame_host_->GetSiteInstance()
           ->IncrementRelatedActiveContentsCount();
     }
-    if (old_render_frame_host) {
+  }
+  if (old_render_frame_host) {
+    old_render_frame_host->GetSiteInstance()->DecrementActiveDocumentCount();
+    if (frame_tree_node_->IsMainFrame()) {
       old_render_frame_host->GetSiteInstance()
           ->DecrementRelatedActiveContentsCount();
     }
@@ -4784,7 +4787,7 @@
 
 void RenderFrameHostManager::ExecutePageBroadcastMethod(
     PageBroadcastMethodCallback callback,
-    SiteInstanceImpl* instance_to_skip) {
+    SiteInstanceGroup* group_to_skip) {
   DCHECK(!frame_tree_node_->parent());
 
   // When calling a PageBroadcast Mojo method for an inner WebContents, we don't
@@ -4795,17 +4798,19 @@
        render_frame_host_->browsing_context_state()->proxy_hosts()) {
     if (outer_delegate_proxy == pair.second.get())
       continue;
-    if (pair.second->GetSiteInstance() == instance_to_skip)
+    if (pair.second->site_instance_group() == group_to_skip) {
       continue;
+    }
     callback.Run(pair.second->GetRenderViewHost());
   }
 
   if (speculative_render_frame_host_ &&
-      speculative_render_frame_host_->GetSiteInstance() != instance_to_skip) {
+      speculative_render_frame_host_->GetSiteInstance()->group() !=
+          group_to_skip) {
     callback.Run(speculative_render_frame_host_->render_view_host());
   }
 
-  if (render_frame_host_->GetSiteInstance() != instance_to_skip) {
+  if (render_frame_host_->GetSiteInstance()->group() != group_to_skip) {
     callback.Run(render_frame_host_->render_view_host());
   }
 }
diff --git a/content/browser/renderer_host/render_frame_host_manager.h b/content/browser/renderer_host/render_frame_host_manager.h
index 1f8048e..ce554cbf 100644
--- a/content/browser/renderer_host/render_frame_host_manager.h
+++ b/content/browser/renderer_host/render_frame_host_manager.h
@@ -524,9 +524,9 @@
   // Executes a PageBroadcast Mojo method to every `blink::WebView` in the
   // FrameTree. This should only be called in the top-level
   // RenderFrameHostManager. The `callback` is called synchronously and the
-  // `instance_to_skip` won't be referenced after this method returns.
+  // `group_to_skip` won't be referenced after this method returns.
   void ExecutePageBroadcastMethod(PageBroadcastMethodCallback callback,
-                                  SiteInstanceImpl* instance_to_skip = nullptr);
+                                  SiteInstanceGroup* group_to_skip = nullptr);
 
   // Executes a RemoteMainFrame Mojo method to every instance in |proxy_hosts|.
   // This should only be called in the top-level RenderFrameHostManager.
diff --git a/content/browser/site_instance_impl.h b/content/browser/site_instance_impl.h
index a1d224e..f8e044fc 100644
--- a/content/browser/site_instance_impl.h
+++ b/content/browser/site_instance_impl.h
@@ -496,6 +496,22 @@
   // Sets the process for `this`, creating a SiteInstanceGroup if necessary.
   void SetProcessForTesting(RenderProcessHost* process);
 
+  // Returns the number of active documents using `this`, potentially spanning
+  // multiple pages/WebContents, but still within the same BrowsingInstance.
+  size_t active_document_count() const { return active_document_count_; }
+
+  // Increments the active document count after a new document that uses `this`
+  // finishes committing and becomes active.
+  void IncrementActiveDocumentCount() { active_document_count_++; }
+
+  // Decrement the active document count after a previously document that uses
+  // `this` got swapped out and becomes inactive due to another document
+  // committing in the same frame.
+  void DecrementActiveDocumentCount() {
+    CHECK_GT(active_document_count_, 0u);
+    active_document_count_--;
+  }
+
  private:
   friend class BrowsingInstance;
   friend class SiteInstanceGroupManager;
@@ -639,6 +655,9 @@
   // Keeps track of whether we need to verify that the StoragePartition
   // information does not change when `site_info_` is set.
   bool verify_storage_partition_info_ = false;
+
+  // Tracks the number of active documents currently in this SiteInstance.
+  size_t active_document_count_ = 0;
 };
 
 }  // namespace content
diff --git a/content/browser/smart_card/smart_card_browsertest.cc b/content/browser/smart_card/smart_card_browsertest.cc
index 356f256..2f93cc9 100644
--- a/content/browser/smart_card/smart_card_browsertest.cc
+++ b/content/browser/smart_card/smart_card_browsertest.cc
@@ -70,6 +70,11 @@
                const std::vector<uint8_t>& data,
                ControlCallback callback),
               (override));
+
+  MOCK_METHOD(void,
+              GetAttrib,
+              (uint32_t id, GetAttribCallback callback),
+              (override));
 };
 
 class FakeSmartCardDelegate : public SmartCardDelegate {
diff --git a/content/browser/webui/web_ui_managed_interface.h b/content/browser/webui/web_ui_managed_interface.h
index 7f01e7ca..176e4445 100644
--- a/content/browser/webui/web_ui_managed_interface.h
+++ b/content/browser/webui/web_ui_managed_interface.h
@@ -38,6 +38,8 @@
 
 }  // namespace internal
 
+using WebUIManagedInterfaceNoPageHandler = void;
+
 // WebUIManagedInterface is an optional base class for implementing classes
 // that interact with Mojo endpoints e.g. implement a Mojo interface or
 // communicate with a Mojo Remote.
@@ -61,30 +63,63 @@
 //                            BarObserver> { ... }
 //
 // TODO(crbug.com/1417272): provide helpers to retrieve InterfaceImpl objects.
-template <typename InterfaceImpl, typename... Interfaces>
-class WebUIManagedInterface;
-
-template <typename InterfaceImpl, typename PageHandler, typename Page>
-class WebUIManagedInterface<InterfaceImpl, PageHandler, Page>
-    : public PageHandler, public internal::WebUIManagedInterfaceBase {
+template <typename InterfaceImpl, typename PageHandler, typename Page = void>
+class WebUIManagedInterface : public internal::WebUIManagedInterfaceBase {
  public:
-  static void Create(content::WebUIController*,
-                     mojo::PendingReceiver<PageHandler>,
-                     mojo::PendingRemote<Page>);
+  template <typename T>
+  using EnableIfNotVoid = typename std::enable_if_t<!std::is_void_v<T>>;
+
+  // Method for when PageHandler is void.
+  static void Create(content::WebUIController* webui_controller,
+                     mojo::PendingRemote<Page> pending_remote) {
+    return WebUIManagedInterface::Create(webui_controller, mojo::NullReceiver(),
+                                         std::move(pending_remote));
+  }
+
+  static void Create(
+      content::WebUIController* webui_controller,
+      mojo::PendingReceiver<PageHandler> pending_receiver,
+      mojo::PendingRemote<Page> pending_remote = mojo::NullRemote()) {
+    static_assert(
+        !std::is_void_v<PageHandler> || !std::is_void_v<Page>,
+        "Either PageHandler must be non-void or Page must be non-void.");
+
+    auto interface_impl = std::make_unique<InterfaceImpl>();
+    auto* interface_impl_ptr = interface_impl.get();
+    interface_impl->webui_controller_ = webui_controller;
+
+    if constexpr (!std::is_void_v<PageHandler>) {
+      interface_impl->page_handler_receiver_.emplace(
+          interface_impl_ptr, std::move(pending_receiver));
+    }
+
+    if constexpr (!std::is_void_v<Page>) {
+      interface_impl->page_remote_.Bind(std::move(pending_remote));
+    }
+
+    internal::SaveWebUIManagedInterfaceInDocument(webui_controller,
+                                                  std::move(interface_impl));
+    interface_impl_ptr->ready_ = true;
+    interface_impl_ptr->OnReady();
+  }
 
   // Invoked when Mojo endpoints are bound and ready to use.
   // TODO(crbug.com/1417260): Remove this by saving endpoints in an external
   // storage before constructing `InterfaceImpl`.
   virtual void OnReady() {}
 
+  template <typename P = PageHandler, typename = EnableIfNotVoid<P>>
   mojo::Receiver<PageHandler>& receiver() {
     CHECK(ready_) << "Mojo endpoints are not ready. Please use OnReady().";
-    return page_handler_receiver_;
+    return page_handler_receiver_.value();
   }
+
+  template <typename P = Page, typename = EnableIfNotVoid<P>>
   mojo::Remote<Page>& remote() {
     CHECK(ready_) << "Mojo endpoints are not ready. Please use OnReady().";
     return page_remote_;
   }
+
   content::WebUIController* webui_controller() {
     CHECK(ready_) << "webui_controller() is not ready. Please use OnReady().";
     return webui_controller_;
@@ -92,111 +127,28 @@
 
  private:
   bool ready_ = false;
-  mojo::Receiver<PageHandler> page_handler_receiver_{this};
-  mojo::Remote<Page> page_remote_;
+
+  // When `PageHandler` is void, declare an unused bool member variable instead
+  // of a mojo::Receiver<PageHandler>. This allows us to share the same class
+  // instead of having three different specializations at the cost of an extra
+  // bool member.
+  using PageHandlerReceiverType =
+      std::conditional_t<std::is_void_v<PageHandler>,
+                         bool,
+                         mojo::Receiver<PageHandler>>;
+  absl::optional<PageHandlerReceiverType> page_handler_receiver_;
+
+  // When `Page` is void, declare a unused bool member variable instead of a
+  // mojo::Remote<PageHandler>. This allows us to share the same class
+  // instead of having three different specializations at the cost of an extra
+  // bool member.
+  using PageRemoteType =
+      std::conditional_t<std::is_void_v<Page>, bool, mojo::Remote<Page>>;
+  PageRemoteType page_remote_;
+
   raw_ptr<content::WebUIController> webui_controller_;
 };
 
-template <typename InterfaceImpl, typename PageHandler>
-class WebUIManagedInterface<InterfaceImpl, PageHandler>
-    : public PageHandler, public internal::WebUIManagedInterfaceBase {
- public:
-  static void Create(content::WebUIController*,
-                     mojo::PendingReceiver<PageHandler>);
-
-  // Invoked when Mojo endpoints are bound and ready to use.
-  // TODO(crbug.com/1417260): Remove this by saving endpoints in an external
-  // storage before constructing `InterfaceImpl`.
-  virtual void OnReady() {}
-
-  mojo::Receiver<PageHandler>& receiver() {
-    CHECK(ready_) << "Mojo endpoints are not ready. Please use OnReady().";
-    return page_handler_receiver_;
-  }
-  content::WebUIController* webui_controller() {
-    CHECK(ready_) << "webui_controller() is not ready. Please use OnReady().";
-    return webui_controller_;
-  }
-
- private:
-  bool ready_ = false;
-  mojo::Receiver<PageHandler> page_handler_receiver_{this};
-  raw_ptr<content::WebUIController> webui_controller_;
-};
-
-using WebUIManagedInterfaceNoPageHandler = void;
-
-template <typename InterfaceImpl, typename Page>
-class WebUIManagedInterface<InterfaceImpl,
-                            WebUIManagedInterfaceNoPageHandler,
-                            Page> : public internal::WebUIManagedInterfaceBase {
- public:
-  static void Create(content::WebUIController*, mojo::PendingRemote<Page>);
-
-  // Invoked when Mojo endpoints are bound and ready to use.
-  // TODO(crbug.com/1417260): Remove this by saving endpoints in an external
-  // storage before constructing `InterfaceImpl`.
-  virtual void OnReady() {}
-
-  mojo::Remote<Page>& remote() {
-    CHECK(ready_) << "Mojo endpoints are not ready. Please use OnReady().";
-    return page_remote_;
-  }
-  content::WebUIController* webui_controller() {
-    CHECK(ready_) << "webui_controller() is not ready. Please use OnReady().";
-    return webui_controller_;
-  }
-
- private:
-  bool ready_ = false;
-  mojo::Remote<Page> page_remote_;
-  raw_ptr<content::WebUIController> webui_controller_;
-};
-
-template <typename InterfaceImpl, typename PageHandler, typename Page>
-void WebUIManagedInterface<InterfaceImpl, PageHandler, Page>::Create(
-    content::WebUIController* webui_controller,
-    mojo::PendingReceiver<PageHandler> pending_receiver,
-    mojo::PendingRemote<Page> pending_remote) {
-  auto interface_impl = std::make_unique<InterfaceImpl>();
-  auto* interface_impl_ptr = interface_impl.get();
-  interface_impl->webui_controller_ = webui_controller;
-  interface_impl->page_handler_receiver_.Bind(std::move(pending_receiver));
-  interface_impl->page_remote_.Bind(std::move(pending_remote));
-  internal::SaveWebUIManagedInterfaceInDocument(webui_controller,
-                                                std::move(interface_impl));
-  interface_impl_ptr->ready_ = true;
-  interface_impl_ptr->OnReady();
-}
-
-template <typename InterfaceImpl, typename PageHandler>
-void WebUIManagedInterface<InterfaceImpl, PageHandler>::Create(
-    content::WebUIController* webui_controller,
-    mojo::PendingReceiver<PageHandler> pending_receiver) {
-  auto interface_impl = std::make_unique<InterfaceImpl>();
-  auto* interface_impl_ptr = interface_impl.get();
-  interface_impl->webui_controller_ = webui_controller;
-  interface_impl->page_handler_receiver_.Bind(std::move(pending_receiver));
-  internal::SaveWebUIManagedInterfaceInDocument(webui_controller,
-                                                std::move(interface_impl));
-  interface_impl_ptr->ready_ = true;
-  interface_impl_ptr->OnReady();
-}
-
-template <typename InterfaceImpl, typename Page>
-void WebUIManagedInterface<InterfaceImpl, void, Page>::Create(
-    content::WebUIController* webui_controller,
-    mojo::PendingRemote<Page> pending_remote) {
-  auto interface_impl = std::make_unique<InterfaceImpl>();
-  auto* interface_impl_ptr = interface_impl.get();
-  interface_impl->webui_controller_ = webui_controller;
-  interface_impl->page_remote_.Bind(std::move(pending_remote));
-  internal::SaveWebUIManagedInterfaceInDocument(webui_controller,
-                                                std::move(interface_impl));
-  interface_impl_ptr->ready_ = true;
-  interface_impl_ptr->OnReady();
-}
-
 }  // namespace content
 
 #endif  // CONTENT_BROWSER_WEBUI_WEB_UI_MANAGED_INTERFACE_H_
diff --git a/content/browser/webui/web_ui_managed_interface_browsertest.cc b/content/browser/webui/web_ui_managed_interface_browsertest.cc
index f7993062..3cc5fcc 100644
--- a/content/browser/webui/web_ui_managed_interface_browsertest.cc
+++ b/content/browser/webui/web_ui_managed_interface_browsertest.cc
@@ -66,7 +66,8 @@
 int InstanceCounter<Type>::count_ = 0;
 
 // FooImpl implements Foo.
-class FooImpl : public WebUIManagedInterface<FooImpl, mojom::Foo> {
+class FooImpl : public mojom::Foo,
+                public WebUIManagedInterface<FooImpl, mojom::Foo> {
  public:
   FooImpl() { InstanceCounter<FooImpl>::Increment(); }
 
@@ -80,7 +81,8 @@
 
 // FooImpl implements Foo and talks to a Bar remote.
 class FooBarImpl
-    : public WebUIManagedInterface<FooBarImpl, mojom::Foo, mojom::Bar> {
+    : public mojom::Foo,
+      public WebUIManagedInterface<FooBarImpl, mojom::Foo, mojom::Bar> {
  public:
   FooBarImpl() { InstanceCounter<FooBarImpl>::Increment(); }
 
diff --git a/extensions/browser/extension_event_histogram_value.h b/extensions/browser/extension_event_histogram_value.h
index 82c92a2f..59e4384 100644
--- a/extensions/browser/extension_event_histogram_value.h
+++ b/extensions/browser/extension_event_histogram_value.h
@@ -537,6 +537,7 @@
   SMART_CARD_PROVIDER_PRIVATE_ON_TRANSMIT_REQUESTED = 515,
   SMART_CARD_PROVIDER_PRIVATE_ON_CONTROL_REQUESTED = 516,
   OS_EVENTS_ON_POWER_EVENT = 517,
+  SMART_CARD_PROVIDER_PRIVATE_ON_GET_ATTRIB_REQUESTED = 518,
   // Last entry: Add new entries above, then run:
   // tools/metrics/histograms/update_extension_histograms.py
   ENUM_BOUNDARY
diff --git a/extensions/common/extension_features.cc b/extensions/common/extension_features.cc
index fdcccf5e..b72483c 100644
--- a/extensions/common/extension_features.cc
+++ b/extensions/common/extension_features.cc
@@ -109,6 +109,12 @@
              "ForceWebRequestProxyForTest",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+// Launches Native Host executables directly on Windows rather than using a
+// cmd.exe process as a proxy.
+BASE_FEATURE(kLaunchWindowsNativeHostsDirectly,
+             "LaunchWindowsNativeHostsDirectly",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 // Controls whether extensions can use the new favicon fetching in Manifest V3.
 BASE_FEATURE(kNewExtensionFaviconHandling,
              "ExtensionsNewFaviconHandling",
diff --git a/extensions/common/extension_features.h b/extensions/common/extension_features.h
index 9e63db2..eb88c937b 100644
--- a/extensions/common/extension_features.h
+++ b/extensions/common/extension_features.h
@@ -69,6 +69,8 @@
 
 BASE_DECLARE_FEATURE(kForceWebRequestProxyForTest);
 
+BASE_DECLARE_FEATURE(kLaunchWindowsNativeHostsDirectly);
+
 BASE_DECLARE_FEATURE(kNewExtensionFaviconHandling);
 
 BASE_DECLARE_FEATURE(kNewWebstoreDomain);
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd
index 2782445..74981423 100644
--- a/ios/chrome/app/strings/ios_strings.grd
+++ b/ios/chrome/app/strings/ios_strings.grd
@@ -432,6 +432,11 @@
       <message name="IDS_IOS_BOOKMARK_DELETE" desc="Title of button that deletes currently edited bookmark. [Length: 20em.]">
         Delete
       </message>
+      <message name="IDS_IOS_BOOKMARK_DELETED_BOOKMARKS" desc="This confirmation message is intended to help users understand that a bookmark has been deleted. The confirmation message appears at the bottom of the page after users choose to bookmark a page. The tone should be informative. [iOS only]">
+        {count, plural,
+        =1 {1 bookmark deleted}
+        other {{count} bookmarks deleted}}
+      </message>
       <message name="IDS_IOS_BOOKMARK_EDIT_PARENT_FOLDER_BUTTON_HINT" desc="The accessibility hint spoken when hovering over the parent folder of a bookmark in the editor. [iOS only]">
         Double tap to change the parent folder.
       </message>
@@ -536,10 +541,10 @@
         =1 {Bookmarked}
         other {Bookmarked}}
       </message>
-      <message name="IDS_IOS_BOOKMARK_PAGE_SAVED_FOLDER" desc="Presented in a snackbar when  bookmark are created. Specifies in which folder the bookmark was added. [Length: 30em.]">
+      <message name="IDS_IOS_BOOKMARK_PAGE_SAVED_FOLDER" desc="This confirmation message is intended to help users understand that a bookmark has been saved in Chrome. These users are not signed in to a Google Account and are not syncing their data, so we do not specify where the bookmark is saved. The confirmation message appears at the bottom of the page after users choose to bookmark a page. The tone should be informative.">
           {count, plural,
-          =1 {Bookmarked to "{title}"}
-          other {Bookmarked to "{title}"}}
+          =1 {Bookmark saved to "{title}"}
+          other {Bookmarks saved to "{title}"}}
       </message>
       <message name="IDS_IOS_BOOKMARK_PAGE_SAVED_INTO_ACCOUNT" desc="Presented in a snackbar when bookmarks are created in an account. Specifies in which folder the bookmark was added. ">
           {count, plural,
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_BOOKMARK_DELETED_BOOKMARKS.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_BOOKMARK_DELETED_BOOKMARKS.png.sha1
new file mode 100644
index 0000000..84463de
--- /dev/null
+++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_BOOKMARK_DELETED_BOOKMARKS.png.sha1
@@ -0,0 +1 @@
+8ee103670ca2f9551fc5cca6fa2cef887a3e0e9e
\ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_BOOKMARK_PAGE_SAVED_FOLDER.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_BOOKMARK_PAGE_SAVED_FOLDER.png.sha1
index 1719b802..fc1af53e 100644
--- a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_BOOKMARK_PAGE_SAVED_FOLDER.png.sha1
+++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_BOOKMARK_PAGE_SAVED_FOLDER.png.sha1
@@ -1 +1 @@
-83b6697941aa6e3b2ff341deb7fc92e109e2ba80
\ No newline at end of file
+5e2d22a6e8e804750ca7bb529601035cdfc8dd9a
\ No newline at end of file
diff --git a/ios/chrome/browser/bookmarks/bookmark_ios_unit_test_support.h b/ios/chrome/browser/bookmarks/bookmark_ios_unit_test_support.h
index ae573f9..a424663 100644
--- a/ios/chrome/browser/bookmarks/bookmark_ios_unit_test_support.h
+++ b/ios/chrome/browser/bookmarks/bookmark_ios_unit_test_support.h
@@ -21,6 +21,7 @@
 class ManagedBookmarkService;
 }  // namespace bookmarks
 class Browser;
+class GURL;
 class TestChromeBrowserState;
 
 // Provides common bookmark testing infrastructure.
@@ -34,6 +35,10 @@
   const bookmarks::BookmarkNode* AddBookmark(
       const bookmarks::BookmarkNode* parent,
       const std::u16string& title);
+  const bookmarks::BookmarkNode* AddBookmark(
+      const bookmarks::BookmarkNode* parent,
+      const std::u16string& title,
+      const GURL& url);
   const bookmarks::BookmarkNode* AddFolder(
       const bookmarks::BookmarkNode* parent,
       const std::u16string& title);
diff --git a/ios/chrome/browser/bookmarks/bookmark_ios_unit_test_support.mm b/ios/chrome/browser/bookmarks/bookmark_ios_unit_test_support.mm
index 47589cf..17f3463 100644
--- a/ios/chrome/browser/bookmarks/bookmark_ios_unit_test_support.mm
+++ b/ios/chrome/browser/bookmarks/bookmark_ios_unit_test_support.mm
@@ -17,6 +17,7 @@
 #import "ios/chrome/browser/shared/model/browser_state/test_chrome_browser_state.h"
 #import "ios/chrome/browser/signin/authentication_service_factory.h"
 #import "ios/chrome/browser/signin/fake_authentication_service_delegate.h"
+#import "url/gurl.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -64,8 +65,15 @@
 const BookmarkNode* BookmarkIOSUnitTestSupport::AddBookmark(
     const BookmarkNode* parent,
     const std::u16string& title) {
-  bookmarks::BookmarkModel* model = GetBookmarkModelForNode(parent);
   GURL url(u"http://example.com/bookmark" + title);
+  return AddBookmark(parent, title, url);
+}
+
+const BookmarkNode* BookmarkIOSUnitTestSupport::AddBookmark(
+    const BookmarkNode* parent,
+    const std::u16string& title,
+    const GURL& url) {
+  bookmarks::BookmarkModel* model = GetBookmarkModelForNode(parent);
   return model->AddURL(parent, parent->children().size(), title, url);
 }
 
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h b/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h
index 064bf756..eb645ff 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h
+++ b/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h
@@ -241,6 +241,16 @@
 // Converts NSString entered by the user to a GURL.
 GURL ConvertUserDataToGURL(NSString* urlString);
 
+// Uses `GetMostRecentlyAddedUserNodeForURL` to find the most recently added
+// bookmark node with the corresponding URL in both models. If both models
+// contain matching entries - compares them and returns the most recently added
+// entry. If only one model has a matching entry - returns that entry. If no
+// models contain matching entries - returns null.
+const bookmarks::BookmarkNode* GetMostRecentlyAddedUserNodeForURL(
+    const GURL& url,
+    bookmarks::BookmarkModel* local_model,
+    bookmarks::BookmarkModel* account_model);
+
 }  // namespace bookmark_utils_ios
 
 #endif  // IOS_CHROME_BROWSER_UI_BOOKMARKS_BOOKMARK_UTILS_IOS_H_
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.mm b/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.mm
index f8e3b54..9b28cddf 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.mm
+++ b/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.mm
@@ -443,7 +443,10 @@
   [wrapper resetUndoManagerChanged];
 
   NSString* text = nil;
-  if (node_count == 1) {
+  if (base::FeatureList::IsEnabled(bookmarks::kEnableBookmarksAccountStorage)) {
+    text = base::SysUTF16ToNSString(l10n_util::GetPluralStringFUTF16(
+        IDS_IOS_BOOKMARK_DELETED_BOOKMARKS, node_count));
+  } else if (node_count == 1) {
     text = l10n_util::GetNSString(IDS_IOS_BOOKMARK_NEW_SINGLE_BOOKMARK_DELETE);
   } else {
     text =
@@ -778,4 +781,24 @@
   }
 }
 
+const BookmarkNode* GetMostRecentlyAddedUserNodeForURL(
+    const GURL& url,
+    bookmarks::BookmarkModel* local_model,
+    bookmarks::BookmarkModel* account_model) {
+  const BookmarkNode* local_bookmark =
+      local_model->GetMostRecentlyAddedUserNodeForURL(url);
+  if (!account_model) {
+    return local_bookmark;
+  }
+  const BookmarkNode* account_bookmark =
+      account_model->GetMostRecentlyAddedUserNodeForURL(url);
+  if (local_bookmark && account_bookmark) {
+    // Found bookmarks in both models, return one that was added more recently.
+    return local_bookmark->date_added() > account_bookmark->date_added()
+               ? local_bookmark
+               : account_bookmark;
+  }
+  return local_bookmark ? local_bookmark : account_bookmark;
+}
+
 }  // namespace bookmark_utils_ios
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios_unittest.mm b/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios_unittest.mm
index 68402ca..8e25c86 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios_unittest.mm
+++ b/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios_unittest.mm
@@ -457,6 +457,115 @@
                 &sync_setup_service));
 }
 
+TEST_P(BookmarkIOSUtilsUnitTest, GetMostRecentlyAddedNoMatchingBookmarks) {
+  AddBookmark(profile_bookmark_model_->mobile_node(), u"a",
+              GURL("http://example.com/a"));
+  if (IsAccountStorageEnabled()) {
+    AddBookmark(account_bookmark_model_->mobile_node(), u"b",
+                GURL("http://example.com/b"));
+  }
+
+  const BookmarkNode* result =
+      bookmark_utils_ios::GetMostRecentlyAddedUserNodeForURL(
+          GURL("http://example.com/c"), profile_bookmark_model_,
+          account_bookmark_model_);
+  EXPECT_EQ(result, nullptr);
+}
+
+TEST_P(BookmarkIOSUtilsUnitTest, GetMostRecentlyAddedMatchingLocalBookmark) {
+  const BookmarkNode* local_bookmark =
+      AddBookmark(profile_bookmark_model_->mobile_node(), u"a",
+                  GURL("http://example.com/a"));
+  if (IsAccountStorageEnabled()) {
+    AddBookmark(account_bookmark_model_->mobile_node(), u"b",
+                GURL("http://example.com/b"));
+  }
+
+  const BookmarkNode* result =
+      bookmark_utils_ios::GetMostRecentlyAddedUserNodeForURL(
+          GURL("http://example.com/a"), profile_bookmark_model_,
+          account_bookmark_model_);
+  EXPECT_EQ(result, local_bookmark);
+}
+
+TEST_P(BookmarkIOSUtilsUnitTest, GetMostRecentlyAddedMatchingAccountBookmark) {
+  if (!IsAccountStorageEnabled()) {
+    GTEST_SKIP() << "Need account storage to test matches in that storage";
+  }
+
+  AddBookmark(profile_bookmark_model_->mobile_node(), u"a",
+              GURL("http://example.com/a"));
+  const BookmarkNode* account_bookmark =
+      AddBookmark(account_bookmark_model_->mobile_node(), u"b",
+                  GURL("http://example.com/b"));
+
+  const BookmarkNode* result =
+      bookmark_utils_ios::GetMostRecentlyAddedUserNodeForURL(
+          GURL("http://example.com/b"), profile_bookmark_model_,
+          account_bookmark_model_);
+  EXPECT_EQ(result, account_bookmark);
+}
+
+TEST_P(BookmarkIOSUtilsUnitTest,
+       GetMostRecentlyAddedMatchingBothStoragesLocalWins) {
+  if (!IsAccountStorageEnabled()) {
+    GTEST_SKIP() << "Need account storage to test matches in both storages";
+  }
+
+  const BookmarkNode* local_bookmark =
+      AddBookmark(profile_bookmark_model_->mobile_node(), u"a",
+                  GURL("http://example.com/a"));
+  const BookmarkNode* account_bookmark =
+      AddBookmark(account_bookmark_model_->mobile_node(), u"b",
+                  GURL("http://example.com/a"));
+
+  base::Time added_time_account_bookmark = base::Time::Now();
+  account_bookmark_model_->SetDateAdded(account_bookmark,
+                                        added_time_account_bookmark);
+  // Simulate local bookmark being added after the account one.
+  base::Time added_time_local_bookmark =
+      added_time_account_bookmark + base::Seconds(1);
+  profile_bookmark_model_->SetDateAdded(local_bookmark,
+                                        added_time_local_bookmark);
+
+  const BookmarkNode* result =
+      bookmark_utils_ios::GetMostRecentlyAddedUserNodeForURL(
+          GURL("http://example.com/a"), profile_bookmark_model_,
+          account_bookmark_model_);
+  // Local bookmark is more recent, so it should be returned.
+  EXPECT_EQ(result, local_bookmark);
+}
+
+TEST_P(BookmarkIOSUtilsUnitTest,
+       GetMostRecentlyAddedMatchingBothStoragesAccountWins) {
+  if (!IsAccountStorageEnabled()) {
+    GTEST_SKIP() << "Need account storage to test matches in both storages";
+  }
+
+  const BookmarkNode* local_bookmark =
+      AddBookmark(profile_bookmark_model_->mobile_node(), u"a",
+                  GURL("http://example.com/a"));
+  const BookmarkNode* account_bookmark =
+      AddBookmark(account_bookmark_model_->mobile_node(), u"b",
+                  GURL("http://example.com/a"));
+
+  base::Time added_time_local_bookmark = base::Time::Now();
+  profile_bookmark_model_->SetDateAdded(local_bookmark,
+                                        added_time_local_bookmark);
+  // Simulate account bookmark being added after the local one.
+  base::Time added_time_account_bookmark =
+      added_time_local_bookmark + base::Seconds(1);
+  account_bookmark_model_->SetDateAdded(account_bookmark,
+                                        added_time_account_bookmark);
+
+  const BookmarkNode* result =
+      bookmark_utils_ios::GetMostRecentlyAddedUserNodeForURL(
+          GURL("http://example.com/a"), profile_bookmark_model_,
+          account_bookmark_model_);
+  // Account bookmark is more recent, so it should be returned.
+  EXPECT_EQ(result, account_bookmark);
+}
+
 INSTANTIATE_TEST_SUITE_P(All, BookmarkIOSUtilsUnitTest, ::testing::Bool());
 
 }  // namespace
diff --git a/ios/chrome/browser/ui/bookmarks/bookmarks_coordinator.mm b/ios/chrome/browser/ui/bookmarks/bookmarks_coordinator.mm
index aedbcc0..b60769c 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmarks_coordinator.mm
+++ b/ios/chrome/browser/ui/bookmarks/bookmarks_coordinator.mm
@@ -227,7 +227,8 @@
 }
 
 - (void)createBookmarkURL:(const GURL&)URL title:(NSString*)title {
-  if (!_profileBookmarkModel->loaded()) {
+  if (!bookmark_utils_ios::AreAllAvailableBookmarkModelsLoaded(
+          _profileBookmarkModel.get(), _accountBookmarkModel.get())) {
     return;
   }
 
@@ -247,12 +248,14 @@
 }
 
 - (void)presentBookmarkEditorForURL:(const GURL&)URL {
-  if (!_profileBookmarkModel->loaded()) {
+  if (!bookmark_utils_ios::AreAllAvailableBookmarkModelsLoaded(
+          _profileBookmarkModel.get(), _accountBookmarkModel.get())) {
     return;
   }
 
   const BookmarkNode* bookmark =
-      _profileBookmarkModel->GetMostRecentlyAddedUserNodeForURL(URL);
+      bookmark_utils_ios::GetMostRecentlyAddedUserNodeForURL(
+          URL, _profileBookmarkModel.get(), _accountBookmarkModel.get());
   if (!bookmark) {
     return;
   }
@@ -552,13 +555,14 @@
   DCHECK(URLWithTitle) << [self description];
   NSString* title = URLWithTitle.title;
   GURL URL = URLWithTitle.URL;
-  if (!_profileBookmarkModel->loaded()) {
+  if (!bookmark_utils_ios::AreAllAvailableBookmarkModelsLoaded(
+          _profileBookmarkModel.get(), _accountBookmarkModel.get())) {
     return;
   }
 
   const BookmarkNode* existingBookmark =
-      _profileBookmarkModel->GetMostRecentlyAddedUserNodeForURL(URL);
-
+      bookmark_utils_ios::GetMostRecentlyAddedUserNodeForURL(
+          URL, _profileBookmarkModel.get(), _accountBookmarkModel.get());
   if (existingBookmark) {
     [self presentBookmarkEditorForURL:URL];
   } else {
@@ -569,7 +573,8 @@
 - (void)bookmarkWithFolderChooser:(NSArray<URLWithTitle*>*)URLs {
   DCHECK(URLs.count > 0) << "URLs are missing " << [self description];
 
-  if (!_profileBookmarkModel->loaded()) {
+  if (!bookmark_utils_ios::AreAllAvailableBookmarkModelsLoaded(
+          _profileBookmarkModel.get(), _accountBookmarkModel.get())) {
     return;
   }
 
@@ -578,12 +583,14 @@
 }
 
 - (void)openToExternalBookmark:(GURL)URL {
-  if (!_profileBookmarkModel->loaded()) {
+  if (!bookmark_utils_ios::AreAllAvailableBookmarkModelsLoaded(
+          _profileBookmarkModel.get(), _accountBookmarkModel.get())) {
     return;
   }
 
   const BookmarkNode* existingBookmark =
-      _profileBookmarkModel->GetMostRecentlyAddedUserNodeForURL(URL);
+      bookmark_utils_ios::GetMostRecentlyAddedUserNodeForURL(
+          URL, _profileBookmarkModel.get(), _accountBookmarkModel.get());
   [self
       presentBookmarksAtDisplayedFolderNode:_profileBookmarkModel->mobile_node()
                           selectingBookmark:existingBookmark];
@@ -695,7 +702,8 @@
   self.bookmarkBrowser.snackbarCommandsHandler = self.snackbarCommandsHandler;
 
   NSArray<BookmarksHomeViewController*>* replacementViewControllers = nil;
-  if (_profileBookmarkModel->loaded()) {
+  if (bookmark_utils_ios::AreAllAvailableBookmarkModelsLoaded(
+          _profileBookmarkModel.get(), _accountBookmarkModel.get())) {
     // Set the root node if the model has been loaded. If the model has not been
     // loaded yet, the root node will be set in BookmarksHomeViewController
     // after the model is finished loading.
diff --git a/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_mediator.mm b/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_mediator.mm
index 306bf475..ff5c130 100644
--- a/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_mediator.mm
+++ b/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_mediator.mm
@@ -237,17 +237,11 @@
     [self generateTableViewDataForModel:_profileBookmarkModel.get()
                               inSection:
                                   BookmarksHomeSectionIdentifierRootProfile];
-  } else {
-    [self.consumer.tableViewModel
-        removeSectionWithIdentifier:BookmarksHomeSectionIdentifierRootProfile];
   }
   if (showAccountSection) {
     [self generateTableViewDataForModel:_accountBookmarkModel.get()
                               inSection:
                                   BookmarksHomeSectionIdentifierRootAccount];
-  } else {
-    [self.consumer.tableViewModel
-        removeSectionWithIdentifier:BookmarksHomeSectionIdentifierRootAccount];
   }
   if (showProfileSection && showAccountSection) {
     // Headers are only shown if both sections are visible.
diff --git a/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_view_controller_unittest.mm b/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_view_controller_unittest.mm
index 39870f1d..2412040 100644
--- a/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_view_controller_unittest.mm
@@ -95,9 +95,8 @@
   }
 }
 
-// Tests with two empty bookmark model. None of them are shown.
 TEST_P(BookmarksHomeViewControllerTest,
-       TableViewPopulatedAfterBookmarkModelLoadedAtRootLevelWithNoModel) {
+       TableViewPopulatedAfterBookmarkModelLoadedAtRootLevel) {
   @autoreleasepool {
     id mockSnackbarCommandHandler =
         OCMProtocolMock(@protocol(SnackbarCommands));
@@ -124,68 +123,14 @@
     controller.applicationCommandsHandler = mockApplicationCommandHandler;
     controller.snackbarCommandsHandler = mockSnackbarCommandHandler;
 
-    // At root level `displayedFolderNode` is the root node of
-    // `profile_bookmark_model`.
-    controller.displayedFolderNode = profile_bookmark_model_->root_node();
-    // sections: Promo, Bookmarks, root profile or root account, message.
-    EXPECT_EQ(3, [controller numberOfSectionsInTableView:controller.tableView]);
-    EXPECT_EQ(1, [controller tableView:controller.tableView
-                     numberOfRowsInSection:
-                         [controller.tableViewModel
-                             sectionForSectionIdentifier:
-                                 BookmarksHomeSectionIdentifierPromo]]);
-    EXPECT_EQ(0, [controller tableView:controller.tableView
-                     numberOfRowsInSection:
-                         [controller.tableViewModel
-                             sectionForSectionIdentifier:
-                                 BookmarksHomeSectionIdentifierBookmarks]]);
-    EXPECT_EQ(0, [controller tableView:controller.tableView
-                     numberOfRowsInSection:
-                         [controller.tableViewModel
-                             sectionForSectionIdentifier:
-                                 BookmarksHomeSectionIdentifierMessages]]);
-  }
-}
-
-// Tests with one empty bookmark model and one non-empty bookmark model at
-// root level. The non-empty bookmark model is hidden.
-// TODO(crbug.com/14446777): Test with account bookmark model after refactoring
-// BookmarkIOSUnitTestSupport.
-TEST_P(BookmarksHomeViewControllerTest,
-       TableViewPopulatedAfterBookmarkModelLoadedAtRootLevelWithOneModel) {
-  @autoreleasepool {
-    id mockSnackbarCommandHandler =
-        OCMProtocolMock(@protocol(SnackbarCommands));
-
-    // Set up ApplicationCommands mock. Because ApplicationCommands conforms
-    // to ApplicationSettingsCommands, that needs to be mocked and dispatched
-    // as well.
-    id mockApplicationCommandHandler =
-        OCMProtocolMock(@protocol(ApplicationCommands));
-    id mockApplicationSettingsCommandHandler =
-        OCMProtocolMock(@protocol(ApplicationSettingsCommands));
-
-    CommandDispatcher* dispatcher = browser_->GetCommandDispatcher();
-    [dispatcher startDispatchingToTarget:mockSnackbarCommandHandler
-                             forProtocol:@protocol(SnackbarCommands)];
-    [dispatcher startDispatchingToTarget:mockApplicationCommandHandler
-                             forProtocol:@protocol(ApplicationCommands)];
-    [dispatcher
-        startDispatchingToTarget:mockApplicationSettingsCommandHandler
-                     forProtocol:@protocol(ApplicationSettingsCommands)];
-
-    BookmarksHomeViewController* controller =
-        [[BookmarksHomeViewController alloc] initWithBrowser:browser_.get()];
-    controller.applicationCommandsHandler = mockApplicationCommandHandler;
-    controller.snackbarCommandsHandler = mockSnackbarCommandHandler;
-
-    // Ensure there are bookmarks.
-    AddBookmark(profile_bookmark_model_->mobile_node(), u"foo");
-    // At root level `displayedFolderNode` is the root node of
-    // `profile_bookmark_model`.
-    controller.displayedFolderNode = profile_bookmark_model_->root_node();
-    // sections: Promo, Bookmarks, root profile or root account, message.
-    EXPECT_EQ(4, [controller numberOfSectionsInTableView:controller.tableView]);
+    const bookmarks::BookmarkNode* rootNode =
+        profile_bookmark_model_->root_node();
+    const bookmarks::BookmarkNode* mobileNode =
+        profile_bookmark_model_->mobile_node();
+    AddBookmark(mobileNode, u"foo");  // Ensure there are bookmarks
+    controller.displayedFolderNode = rootNode;
+    // sections: Promo, Bookmarks, root profile, root account, message.
+    EXPECT_EQ(5, [controller numberOfSectionsInTableView:controller.tableView]);
     EXPECT_EQ(1, [controller tableView:controller.tableView
                      numberOfRowsInSection:
                          [controller.tableViewModel
@@ -205,15 +150,15 @@
                      numberOfRowsInSection:
                          [controller.tableViewModel
                              sectionForSectionIdentifier:
+                                 BookmarksHomeSectionIdentifierRootAccount]]);
+    EXPECT_EQ(0, [controller tableView:controller.tableView
+                     numberOfRowsInSection:
+                         [controller.tableViewModel
+                             sectionForSectionIdentifier:
                                  BookmarksHomeSectionIdentifierMessages]]);
   }
 }
 
-// TODO(crbug.com/14446777): Write this test after account storage support is
-// available.
-// TEST_P(BookmarksHomeViewControllerTest,
-//       TableViewPopulatedAfterBookmarkModelLoadedAtRootLevelWithBothModel) {}
-
 // Checks that metrics are correctly reported.
 TEST_P(BookmarksHomeViewControllerTest, Metrics) {
   @autoreleasepool {
diff --git a/mojo/public/tools/bindings/generators/mojom_js_generator.py b/mojo/public/tools/bindings/generators/mojom_js_generator.py
index c65c93a..d222659 100644
--- a/mojo/public/tools/bindings/generators/mojom_js_generator.py
+++ b/mojo/public/tools/bindings/generators/mojom_js_generator.py
@@ -186,16 +186,27 @@
 
 _primitive_kind_to_fuzz_type = {
     mojom.BOOL: "Bool",
+    mojom.NULLABLE_BOOL: "Bool",
     mojom.INT8: "Int8",
+    mojom.NULLABLE_INT8: "Int8",
     mojom.UINT8: "Uint8",
+    mojom.NULLABLE_UINT8: "Uint8",
     mojom.INT16: "Int16",
+    mojom.NULLABLE_INT16: "Int16",
     mojom.UINT16: "Uint16",
+    mojom.NULLABLE_UINT16: "Uint16",
     mojom.INT32: "Int32",
+    mojom.NULLABLE_INT32: "Int32",
     mojom.UINT32: "Uint32",
+    mojom.NULLABLE_UINT32: "Uint32",
     mojom.FLOAT: "Float",
+    mojom.NULLABLE_FLOAT: "Float",
     mojom.INT64: "Int64",
+    mojom.NULLABLE_INT64: "Int64",
     mojom.UINT64: "Uint64",
+    mojom.NULLABLE_UINT64: "Uint64",
     mojom.DOUBLE: "Double",
+    mojom.NULLABLE_DOUBLE: "Double",
     mojom.STRING: "String",
     mojom.NULLABLE_STRING: "String",
     mojom.HANDLE: "Handle",
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc
index 971ad06..93e9154 100644
--- a/net/http/http_cache_transaction.cc
+++ b/net/http/http_cache_transaction.cc
@@ -3946,19 +3946,17 @@
 
   bool did_send_request = !send_request_since_.is_null();
 
-  // TODO(ricea): Understand why this DCHECK is failing in the wild, fix it, and
-  // remove it. See https://crbug.com/1409150.
-  if (did_send_request) {
-    DCHECK_NE(cache_entry_status_, CacheEntryStatus::ENTRY_USED);
-  }
-  // This DCHECK() should not fire, because the one above should catch all the
-  // erroneous cases.
+  // It's not clear why `did_send_request` can be true when status is
+  // ENTRY_USED. See https://crbug.com/1409150.
+  // TODO(ricea): Maybe remove ENTRY_USED from the `did_send_request` true
+  // branch once that issue is resolved.
   DCHECK(
       (did_send_request &&
        (cache_entry_status_ == CacheEntryStatus::ENTRY_NOT_IN_CACHE ||
         cache_entry_status_ == CacheEntryStatus::ENTRY_VALIDATED ||
         cache_entry_status_ == CacheEntryStatus::ENTRY_UPDATED ||
-        cache_entry_status_ == CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE)) ||
+        cache_entry_status_ == CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE ||
+        cache_entry_status_ == CacheEntryStatus::ENTRY_USED)) ||
       (!did_send_request &&
        (cache_entry_status_ == CacheEntryStatus::ENTRY_USED ||
         cache_entry_status_ == CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE)));
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc
index 3238470..e991c4b 100644
--- a/net/url_request/url_request.cc
+++ b/net/url_request/url_request.cc
@@ -539,8 +539,9 @@
   if (status_ != OK)
     return;
 
-  if (context_->require_network_isolation_key())
+  if (context_->require_network_anonymization_key()) {
     DCHECK(!isolation_info_.IsEmpty());
+  }
 
   // Some values can be NULL, but the job factory must not be.
   DCHECK(context_->job_factory());
diff --git a/net/url_request/url_request_context.h b/net/url_request/url_request_context.h
index cf7bdadb..d6b0633 100644
--- a/net/url_request/url_request_context.h
+++ b/net/url_request/url_request_context.h
@@ -222,8 +222,8 @@
   // Returns current value of the |check_cleartext_permitted| flag.
   bool check_cleartext_permitted() const { return check_cleartext_permitted_; }
 
-  bool require_network_isolation_key() const {
-    return require_network_isolation_key_;
+  bool require_network_anonymization_key() const {
+    return require_network_anonymization_key_;
   }
 
   // If != handles::kInvalidNetworkHandle, the network which this
@@ -291,8 +291,9 @@
   void set_check_cleartext_permitted(bool check_cleartext_permitted) {
     check_cleartext_permitted_ = check_cleartext_permitted;
   }
-  void set_require_network_isolation_key(bool require_network_isolation_key) {
-    require_network_isolation_key_ = require_network_isolation_key;
+  void set_require_network_anonymization_key(
+      bool require_network_anonymization_key) {
+    require_network_anonymization_key_ = require_network_anonymization_key;
   }
   void set_bound_network(handles::NetworkHandle network) {
     bound_network_ = network;
@@ -357,7 +358,7 @@
 
   // Triggers a DCHECK if a NetworkAnonymizationKey/IsolationInfo is not
   // provided to a request when true.
-  bool require_network_isolation_key_ = false;
+  bool require_network_anonymization_key_ = false;
 
   handles::NetworkHandle bound_network_;
 
diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/url_request_context_builder.cc
index 55a32f7..78b436c 100644
--- a/net/url_request/url_request_context_builder.cc
+++ b/net/url_request/url_request_context_builder.cc
@@ -275,7 +275,8 @@
 
   context->set_enable_brotli(enable_brotli_);
   context->set_check_cleartext_permitted(check_cleartext_permitted_);
-  context->set_require_network_isolation_key(require_network_isolation_key_);
+  context->set_require_network_anonymization_key(
+      require_network_anonymization_key_);
   context->set_network_quality_estimator(network_quality_estimator_);
 
   if (http_user_agent_settings_) {
diff --git a/net/url_request/url_request_context_builder.h b/net/url_request/url_request_context_builder.h
index e726346..ae211c1 100644
--- a/net/url_request/url_request_context_builder.h
+++ b/net/url_request/url_request_context_builder.h
@@ -150,8 +150,8 @@
     check_cleartext_permitted_ = value;
   }
 
-  void set_require_network_isolation_key(bool value) {
-    require_network_isolation_key_ = value;
+  void set_require_network_anonymization_key(bool value) {
+    require_network_anonymization_key_ = value;
   }
 
   // Unlike most other setters, the builder does not take ownership of the
@@ -402,7 +402,7 @@
 
   bool enable_brotli_ = false;
   bool check_cleartext_permitted_ = false;
-  bool require_network_isolation_key_ = false;
+  bool require_network_anonymization_key_ = false;
   raw_ptr<NetworkQualityEstimator> network_quality_estimator_ = nullptr;
 
   std::string accept_language_;
diff --git a/services/device/public/mojom/smart_card.mojom b/services/device/public/mojom/smart_card.mojom
index a60afee..cbec3a4 100644
--- a/services/device/public/mojom/smart_card.mojom
+++ b/services/device/public/mojom/smart_card.mojom
@@ -186,11 +186,13 @@
   Control(uint32 control_code, array<uint8> data)
       => (SmartCardDataResult result);
 
+  // Gets an attribute from the Interface Device Handler (reader driver).
+  GetAttrib(uint32 id) => (SmartCardDataResult result);
+
   // TODO(crbug.com/1386175): Add methods:
   // * BeginTransaction()
   // * EndTransaction()
   // * Status()
-  // * GetAttrib()
   // * SetAttrib()
 };
 
diff --git a/services/network/network_context.cc b/services/network/network_context.cc
index 479b87b..660df7d 100644
--- a/services/network/network_context.cc
+++ b/services/network/network_context.cc
@@ -1186,8 +1186,9 @@
 #if BUILDFLAG(ENABLE_REPORTING)
   // If |reporting_source| is provided, it must not be empty.
   DCHECK(!(reporting_source.has_value() && reporting_source->is_empty()));
-  if (require_network_isolation_key_)
+  if (require_network_anonymization_key_) {
     DCHECK(!network_anonymization_key.IsEmpty());
+  }
 
   // Get the ReportingService.
   net::URLRequestContext* request_context = url_request_context();
@@ -1215,8 +1216,9 @@
     mojom::SignedExchangeReportPtr report,
     const net::NetworkAnonymizationKey& network_anonymization_key) {
 #if BUILDFLAG(ENABLE_REPORTING)
-  if (require_network_isolation_key_)
+  if (require_network_anonymization_key_) {
     DCHECK(!network_anonymization_key.IsEmpty());
+  }
 
   net::NetworkErrorLoggingService* logging_service =
       url_request_context_->network_error_logging_service();
@@ -1738,8 +1740,9 @@
     const std::string& ocsp_result,
     const std::string& sct_list,
     VerifyCertForSignedExchangeCallback callback) {
-  if (require_network_isolation_key_)
+  if (require_network_anonymization_key_) {
     DCHECK(!network_anonymization_key.IsEmpty());
+  }
 
   uint64_t cert_verify_id = ++next_cert_verify_id_;
   CHECK_NE(0u, next_cert_verify_id_);  // The request ID should not wrap around.
@@ -1939,7 +1942,7 @@
     const GURL& original_url,
     bool allow_credentials,
     const net::NetworkAnonymizationKey& network_anonymization_key) {
-  DCHECK(!require_network_isolation_key_ ||
+  DCHECK(!require_network_anonymization_key_ ||
          !network_anonymization_key.IsEmpty());
 
   GURL url = GetHSTSRedirect(original_url);
@@ -2551,17 +2554,17 @@
             std::move(params_->socket_broker)));
   }
 
-  // If `require_network_isolation_key_` is true, but the features that can
-  // trigger another URLRequest are not set to respect NetworkIsolationKeys,
-  // the URLRequests that they create might not have a NIK, so only set the
+  // If `require_network_anonymization_key_` is true, but the features that can
+  // trigger another URLRequest are not set to respect NetworkAnonymizationKeys,
+  // the URLRequests that they create might not have a NAK, so only set the
   // corresponding value in the URLRequestContext to true at the URLRequest
-  // layer if all those features are set to respect NIK.
-  if (require_network_isolation_key_ &&
+  // layer if all those features are set to respect NAK.
+  if (require_network_anonymization_key_ &&
       net::NetworkAnonymizationKey::IsPartitioningEnabled() &&
       base::FeatureList::IsEnabled(
           domain_reliability::features::
               kPartitionDomainReliabilityByNetworkIsolationKey)) {
-    builder.set_require_network_isolation_key(true);
+    builder.set_require_network_anonymization_key(true);
   }
 
 #if BUILDFLAG(IS_ANDROID)
@@ -2574,7 +2577,8 @@
   auto result =
       URLRequestContextOwner(std::move(pref_service), builder.Build());
 
-  require_network_isolation_key_ = params_->require_network_isolation_key;
+  require_network_anonymization_key_ =
+      params_->require_network_anonymization_key;
 
   // Subscribe the CertVerifier to configuration changes that are exposed via
   // the mojom::SSLConfig, but which are not part of the
diff --git a/services/network/network_context.h b/services/network/network_context.h
index a314820..9fca958 100644
--- a/services/network/network_context.h
+++ b/services/network/network_context.h
@@ -607,8 +607,8 @@
     return cors_origin_access_list_;
   }
 
-  bool require_network_isolation_key() const {
-    return require_network_isolation_key_;
+  bool require_network_anonymization_key() const {
+    return require_network_anonymization_key_;
   }
 
   bool acam_preflight_spec_conformant() const {
@@ -918,7 +918,7 @@
   // Whether all external consumers are expected to provide a non-empty
   // NetworkAnonymizationKey with all requests. When set, enabled a variety of
   // DCHECKs on APIs used by external callers.
-  bool require_network_isolation_key_ = false;
+  bool require_network_anonymization_key_ = false;
 
   // Whether Access-Control-Allow-Methods matching in CORS preflight is done
   // according to the spec.
diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom
index 0d5fd16e..e11f45e 100644
--- a/services/network/public/mojom/network_context.mojom
+++ b/services/network/public/mojom/network_context.mojom
@@ -526,9 +526,9 @@
   // See comments on NetworkContext.SetSplitAuthCacheByNetworkAnonymizationKey.
   bool split_auth_cache_by_network_anonymization_key = false;
 
-  // If true, all requests that can take a NetworkIsolationKey or IsolationInfo
-  // must be given a non-empty one.
-  bool require_network_isolation_key = false;
+  // If true, all requests that can take a NetworkAnonymizationKey
+  // or IsolationInfo must be given a non-empty one.
+  bool require_network_anonymization_key = false;
 
   // If true, then the correct permissions have been set on the network service
   // files and sandbox can be enabled for this network context.
diff --git a/services/network/url_loader_factory.cc b/services/network/url_loader_factory.cc
index 53e0cb9..58719917 100644
--- a/services/network/url_loader_factory.cc
+++ b/services/network/url_loader_factory.cc
@@ -151,7 +151,7 @@
 }
 
 bool URLLoaderFactory::ShouldRequireNetworkIsolationKey() const {
-  return context_->require_network_isolation_key();
+  return context_->require_network_anonymization_key();
 }
 
 scoped_refptr<ResourceSchedulerClient>
diff --git a/services/network/websocket_factory.cc b/services/network/websocket_factory.cc
index 6bcf0e1..83412b2 100644
--- a/services/network/websocket_factory.cc
+++ b/services/network/websocket_factory.cc
@@ -23,7 +23,7 @@
 
 WebSocketFactory::~WebSocketFactory() {
   // Subtle: This is important to avoid WebSocketFactory::Remove calls during
-  // |connections_| destruction.
+  // `connections_` destruction.
   WebSocketSet connections = std::move(connections_);
 }
 
@@ -50,10 +50,11 @@
     return;
   }
 
-  // If |require_network_isolation_key| is set, |isolation_info| must not be
+  // If `require_network_anonymization_key` is set, `isolation_info` must not be
   // empty.
-  if (context_->require_network_isolation_key())
+  if (context_->require_network_anonymization_key()) {
     DCHECK(!isolation_info.IsEmpty());
+  }
 
   if (throttler_.HasTooManyPendingConnections(process_id)) {
     // Too many websockets!
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index cd5a1a6f..dc325b0 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -5698,9 +5698,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.beta.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.31/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5735.31",
+        "description": "Run with ash-chrome version 114.0.5735.37",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -5711,8 +5711,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5735.31",
-              "revision": "version:114.0.5735.31"
+              "location": "lacros_version_skew_tests_v114.0.5735.37",
+              "revision": "version:114.0.5735.37"
             }
           ],
           "dimension_sets": [
@@ -5730,9 +5730,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5787.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5788.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 115.0.5787.0",
+        "description": "Run with ash-chrome version 115.0.5788.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -5743,8 +5743,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v115.0.5787.0",
-              "revision": "version:115.0.5787.0"
+              "location": "lacros_version_skew_tests_v115.0.5788.0",
+              "revision": "version:115.0.5788.0"
             }
           ],
           "dimension_sets": [
@@ -5864,9 +5864,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.31/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5735.31",
+        "description": "Run with ash-chrome version 114.0.5735.37",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -5877,8 +5877,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5735.31",
-              "revision": "version:114.0.5735.31"
+              "location": "lacros_version_skew_tests_v114.0.5735.37",
+              "revision": "version:114.0.5735.37"
             }
           ],
           "dimension_sets": [
@@ -5895,9 +5895,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5787.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5788.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 115.0.5787.0",
+        "description": "Run with ash-chrome version 115.0.5788.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -5908,8 +5908,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v115.0.5787.0",
-              "revision": "version:115.0.5787.0"
+              "location": "lacros_version_skew_tests_v115.0.5788.0",
+              "revision": "version:115.0.5788.0"
             }
           ],
           "dimension_sets": [
@@ -6010,9 +6010,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.31/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5735.31",
+        "description": "Run with ash-chrome version 114.0.5735.37",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -6023,8 +6023,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5735.31",
-              "revision": "version:114.0.5735.31"
+              "location": "lacros_version_skew_tests_v114.0.5735.37",
+              "revision": "version:114.0.5735.37"
             }
           ],
           "dimension_sets": [
@@ -6042,9 +6042,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5787.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5788.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 115.0.5787.0",
+        "description": "Run with ash-chrome version 115.0.5788.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -6055,8 +6055,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v115.0.5787.0",
-              "revision": "version:115.0.5787.0"
+              "location": "lacros_version_skew_tests_v115.0.5788.0",
+              "revision": "version:115.0.5788.0"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.coverage.json b/testing/buildbot/chromium.coverage.json
index 14f593a..1ff02197 100644
--- a/testing/buildbot/chromium.coverage.json
+++ b/testing/buildbot/chromium.coverage.json
@@ -25459,9 +25459,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.beta.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.31/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5735.31",
+        "description": "Run with ash-chrome version 114.0.5735.37",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -25472,8 +25472,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5735.31",
-              "revision": "version:114.0.5735.31"
+              "location": "lacros_version_skew_tests_v114.0.5735.37",
+              "revision": "version:114.0.5735.37"
             }
           ],
           "dimension_sets": [
@@ -25491,9 +25491,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5787.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5788.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 115.0.5787.0",
+        "description": "Run with ash-chrome version 115.0.5788.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -25504,8 +25504,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v115.0.5787.0",
-              "revision": "version:115.0.5787.0"
+              "location": "lacros_version_skew_tests_v115.0.5788.0",
+              "revision": "version:115.0.5788.0"
             }
           ],
           "dimension_sets": [
@@ -25625,9 +25625,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.31/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5735.31",
+        "description": "Run with ash-chrome version 114.0.5735.37",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -25638,8 +25638,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5735.31",
-              "revision": "version:114.0.5735.31"
+              "location": "lacros_version_skew_tests_v114.0.5735.37",
+              "revision": "version:114.0.5735.37"
             }
           ],
           "dimension_sets": [
@@ -25656,9 +25656,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5787.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5788.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 115.0.5787.0",
+        "description": "Run with ash-chrome version 115.0.5788.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -25669,8 +25669,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v115.0.5787.0",
-              "revision": "version:115.0.5787.0"
+              "location": "lacros_version_skew_tests_v115.0.5788.0",
+              "revision": "version:115.0.5788.0"
             }
           ],
           "dimension_sets": [
@@ -25771,9 +25771,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.31/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5735.31",
+        "description": "Run with ash-chrome version 114.0.5735.37",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -25784,8 +25784,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5735.31",
-              "revision": "version:114.0.5735.31"
+              "location": "lacros_version_skew_tests_v114.0.5735.37",
+              "revision": "version:114.0.5735.37"
             }
           ],
           "dimension_sets": [
@@ -25803,9 +25803,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5787.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5788.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 115.0.5787.0",
+        "description": "Run with ash-chrome version 115.0.5788.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -25816,8 +25816,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v115.0.5787.0",
-              "revision": "version:115.0.5787.0"
+              "location": "lacros_version_skew_tests_v115.0.5788.0",
+              "revision": "version:115.0.5788.0"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 6760496..cfc79d90 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -40114,9 +40114,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.beta.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.31/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5735.31",
+        "description": "Run with ash-chrome version 114.0.5735.37",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -40126,8 +40126,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5735.31",
-              "revision": "version:114.0.5735.31"
+              "location": "lacros_version_skew_tests_v114.0.5735.37",
+              "revision": "version:114.0.5735.37"
             }
           ],
           "dimension_sets": [
@@ -40146,9 +40146,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5787.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5788.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 115.0.5787.0",
+        "description": "Run with ash-chrome version 115.0.5788.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -40158,8 +40158,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v115.0.5787.0",
-              "revision": "version:115.0.5787.0"
+              "location": "lacros_version_skew_tests_v115.0.5788.0",
+              "revision": "version:115.0.5788.0"
             }
           ],
           "dimension_sets": [
@@ -40280,9 +40280,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.31/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5735.31",
+        "description": "Run with ash-chrome version 114.0.5735.37",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -40292,8 +40292,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5735.31",
-              "revision": "version:114.0.5735.31"
+              "location": "lacros_version_skew_tests_v114.0.5735.37",
+              "revision": "version:114.0.5735.37"
             }
           ],
           "dimension_sets": [
@@ -40311,9 +40311,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5787.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5788.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 115.0.5787.0",
+        "description": "Run with ash-chrome version 115.0.5788.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -40323,8 +40323,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v115.0.5787.0",
-              "revision": "version:115.0.5787.0"
+              "location": "lacros_version_skew_tests_v115.0.5788.0",
+              "revision": "version:115.0.5788.0"
             }
           ],
           "dimension_sets": [
@@ -40426,9 +40426,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.31/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5735.31",
+        "description": "Run with ash-chrome version 114.0.5735.37",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -40438,8 +40438,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5735.31",
-              "revision": "version:114.0.5735.31"
+              "location": "lacros_version_skew_tests_v114.0.5735.37",
+              "revision": "version:114.0.5735.37"
             }
           ],
           "dimension_sets": [
@@ -40458,9 +40458,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5787.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5788.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 115.0.5787.0",
+        "description": "Run with ash-chrome version 115.0.5788.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -40470,8 +40470,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v115.0.5787.0",
-              "revision": "version:115.0.5787.0"
+              "location": "lacros_version_skew_tests_v115.0.5788.0",
+              "revision": "version:115.0.5788.0"
             }
           ],
           "dimension_sets": [
@@ -41903,9 +41903,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.beta.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.31/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5735.31",
+        "description": "Run with ash-chrome version 114.0.5735.37",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -41915,8 +41915,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5735.31",
-              "revision": "version:114.0.5735.31"
+              "location": "lacros_version_skew_tests_v114.0.5735.37",
+              "revision": "version:114.0.5735.37"
             }
           ],
           "dimension_sets": [
@@ -41935,9 +41935,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5787.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5788.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 115.0.5787.0",
+        "description": "Run with ash-chrome version 115.0.5788.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -41947,8 +41947,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v115.0.5787.0",
-              "revision": "version:115.0.5787.0"
+              "location": "lacros_version_skew_tests_v115.0.5788.0",
+              "revision": "version:115.0.5788.0"
             }
           ],
           "dimension_sets": [
@@ -42069,9 +42069,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.31/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5735.31",
+        "description": "Run with ash-chrome version 114.0.5735.37",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -42081,8 +42081,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5735.31",
-              "revision": "version:114.0.5735.31"
+              "location": "lacros_version_skew_tests_v114.0.5735.37",
+              "revision": "version:114.0.5735.37"
             }
           ],
           "dimension_sets": [
@@ -42100,9 +42100,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5787.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5788.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 115.0.5787.0",
+        "description": "Run with ash-chrome version 115.0.5788.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -42112,8 +42112,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v115.0.5787.0",
-              "revision": "version:115.0.5787.0"
+              "location": "lacros_version_skew_tests_v115.0.5788.0",
+              "revision": "version:115.0.5788.0"
             }
           ],
           "dimension_sets": [
@@ -42215,9 +42215,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.31/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5735.31",
+        "description": "Run with ash-chrome version 114.0.5735.37",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -42227,8 +42227,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5735.31",
-              "revision": "version:114.0.5735.31"
+              "location": "lacros_version_skew_tests_v114.0.5735.37",
+              "revision": "version:114.0.5735.37"
             }
           ],
           "dimension_sets": [
@@ -42247,9 +42247,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5787.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5788.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 115.0.5787.0",
+        "description": "Run with ash-chrome version 115.0.5788.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -42259,8 +42259,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v115.0.5787.0",
-              "revision": "version:115.0.5787.0"
+              "location": "lacros_version_skew_tests_v115.0.5788.0",
+              "revision": "version:115.0.5788.0"
             }
           ],
           "dimension_sets": [
@@ -42964,9 +42964,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.31/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 114.0.5735.31",
+        "description": "Run with ash-chrome version 114.0.5735.37",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -42976,8 +42976,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5735.31",
-              "revision": "version:114.0.5735.31"
+              "location": "lacros_version_skew_tests_v114.0.5735.37",
+              "revision": "version:114.0.5735.37"
             }
           ],
           "dimension_sets": [
@@ -42995,9 +42995,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5787.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5788.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 115.0.5787.0",
+        "description": "Run with ash-chrome version 115.0.5788.0",
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
@@ -43007,8 +43007,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v115.0.5787.0",
-              "revision": "version:115.0.5787.0"
+              "location": "lacros_version_skew_tests_v115.0.5788.0",
+              "revision": "version:115.0.5788.0"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index 38e1d506..05d541e 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -18045,12 +18045,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.beta.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.31/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 114.0.5735.31",
+        "description": "Run with ash-chrome version 114.0.5735.37",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -18061,8 +18061,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5735.31",
-              "revision": "version:114.0.5735.31"
+              "location": "lacros_version_skew_tests_v114.0.5735.37",
+              "revision": "version:114.0.5735.37"
             }
           ],
           "dimension_sets": [
@@ -18080,12 +18080,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5787.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5788.0/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 115.0.5787.0",
+        "description": "Run with ash-chrome version 115.0.5788.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -18096,8 +18096,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v115.0.5787.0",
-              "revision": "version:115.0.5787.0"
+              "location": "lacros_version_skew_tests_v115.0.5788.0",
+              "revision": "version:115.0.5788.0"
             }
           ],
           "dimension_sets": [
@@ -18231,12 +18231,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.31/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 114.0.5735.31",
+        "description": "Run with ash-chrome version 114.0.5735.37",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -18247,8 +18247,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5735.31",
-              "revision": "version:114.0.5735.31"
+              "location": "lacros_version_skew_tests_v114.0.5735.37",
+              "revision": "version:114.0.5735.37"
             }
           ],
           "dimension_sets": [
@@ -18265,12 +18265,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5787.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5788.0/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 115.0.5787.0",
+        "description": "Run with ash-chrome version 115.0.5788.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -18281,8 +18281,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v115.0.5787.0",
-              "revision": "version:115.0.5787.0"
+              "location": "lacros_version_skew_tests_v115.0.5788.0",
+              "revision": "version:115.0.5788.0"
             }
           ],
           "dimension_sets": [
@@ -18392,12 +18392,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.31/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 114.0.5735.31",
+        "description": "Run with ash-chrome version 114.0.5735.37",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -18408,8 +18408,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v114.0.5735.31",
-              "revision": "version:114.0.5735.31"
+              "location": "lacros_version_skew_tests_v114.0.5735.37",
+              "revision": "version:114.0.5735.37"
             }
           ],
           "dimension_sets": [
@@ -18427,12 +18427,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5787.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5788.0/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 115.0.5787.0",
+        "description": "Run with ash-chrome version 115.0.5788.0",
         "isolate_profile_data": true,
         "merge": {
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -18443,8 +18443,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v115.0.5787.0",
-              "revision": "version:115.0.5787.0"
+              "location": "lacros_version_skew_tests_v115.0.5788.0",
+              "revision": "version:115.0.5788.0"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index 0b866e4..ada6274b 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -22,16 +22,16 @@
   },
   'LACROS_VERSION_SKEW_CANARY': {
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5787.0/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v115.0.5788.0/test_ash_chrome',
     ],
-    'description': 'Run with ash-chrome version 115.0.5787.0',
+    'description': 'Run with ash-chrome version 115.0.5788.0',
     'identifier': 'Lacros version skew testing ash canary',
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v115.0.5787.0',
-          'revision': 'version:115.0.5787.0',
+          'location': 'lacros_version_skew_tests_v115.0.5788.0',
+          'revision': 'version:115.0.5788.0',
         },
       ],
     },
@@ -54,16 +54,16 @@
   },
   'LACROS_VERSION_SKEW_BETA': {
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.31/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome',
     ],
-    'description': 'Run with ash-chrome version 114.0.5735.31',
+    'description': 'Run with ash-chrome version 114.0.5735.37',
     'identifier': 'Lacros version skew testing ash beta',
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v114.0.5735.31',
-          'revision': 'version:114.0.5735.31',
+          'location': 'lacros_version_skew_tests_v114.0.5735.37',
+          'revision': 'version:114.0.5735.37',
         },
       ],
     },
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 25cdb94..300096f 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -1472,6 +1472,31 @@
             ]
         }
     ],
+    "AutofillStreetNameOrHouseNumberPrecedenceOverAutocomplete": [
+        {
+            "platforms": [
+                "android",
+                "chromeos",
+                "chromeos_lacros",
+                "ios",
+                "linux",
+                "mac",
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled_Heuristic_AddressLine_1_And_2_1",
+                    "params": {
+                        "AutofillHeuristicPrecedenceOverAutocompleteScope": "address_line_1_and_2",
+                        "AutofillServerPrecedenceOverAutocompleteScope": "none"
+                    },
+                    "enable_features": [
+                        "AutofillStreetNameOrHouseNumberPrecedenceOverAutocomplete"
+                    ]
+                }
+            ]
+        }
+    ],
     "AutofillSurveys": [
         {
             "platforms": [
@@ -4910,21 +4935,6 @@
             ]
         }
     ],
-    "DriveFsChromeNetworking": [
-        {
-            "platforms": [
-                "chromeos"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled_20230127",
-                    "enable_features": [
-                        "DriveFsChromeNetworking"
-                    ]
-                }
-            ]
-        }
-    ],
     "EcheNetworkConnectionState": [
         {
             "platforms": [
@@ -11284,7 +11294,6 @@
                 "android",
                 "chromeos",
                 "chromeos_lacros",
-                "ios",
                 "linux",
                 "mac",
                 "windows"
@@ -11299,6 +11308,22 @@
             ]
         }
     ],
+    "ReadingListEnableDualReadingListModelAndOptInFlow": [
+        {
+            "platforms": [
+                "ios"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "ReadingListEnableDualReadingListModel",
+                        "ReadingListEnableSyncTransportModeUponSignIn"
+                    ]
+                }
+            ]
+        }
+    ],
     "RecordPermissionExpirationTimestamps": [
         {
             "platforms": [
@@ -12839,6 +12864,21 @@
             ]
         }
     ],
+    "StructuredMetricsService": [
+        {
+            "platforms": [
+                "chromeos"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "EnableStructuredMetricsService"
+                    ]
+                }
+            ]
+        }
+    ],
     "StylusPointerAdjustment": [
         {
             "platforms": [
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index 4ed5fd6..f4d48a7 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -352,7 +352,7 @@
 
 BASE_FEATURE(kSharedStorageSelectURLLimit,
              "SharedStorageSelectURLLimit",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+             base::FEATURE_ENABLED_BY_DEFAULT);
 const base::FeatureParam<int> kSharedStorageSelectURLBitBudgetPerPageLoad = {
     &kSharedStorageSelectURLLimit, "SharedStorageSelectURLBitBudgetPerPageLoad",
     12};
diff --git a/third_party/blink/public/common/privacy_budget/identifiable_surface.h b/third_party/blink/public/common/privacy_budget/identifiable_surface.h
index 68ddf5e..8ad570b 100644
--- a/third_party/blink/public/common/privacy_budget/identifiable_surface.h
+++ b/third_party/blink/public/common/privacy_budget/identifiable_surface.h
@@ -260,6 +260,12 @@
     // sampled in the browser.
     kFontFamilyAvailable = 38,
 
+    // Represents determining that a local font exists or does not, based on a
+    // name lookup that is allowed to match either a unique name or a family
+    // name. This occurs when a font-family CSS rule doesn't match any
+    // @font-face rule. Input is the lookup name. Output is a bool.
+    kLocalFontExistenceByUniqueOrFamilyName = 39,
+
     // We can use values up to and including |kMax|.
     kMax = (1 << kTypeBits) - 1
   };
diff --git a/third_party/blink/renderer/core/css/style_property_serializer.cc b/third_party/blink/renderer/core/css/style_property_serializer.cc
index a0968e1..61c925ce 100644
--- a/third_party/blink/renderer/core/css/style_property_serializer.cc
+++ b/third_party/blink/renderer/core/css/style_property_serializer.cc
@@ -560,7 +560,7 @@
     case CSSPropertyID::kBorderStyle:
       return Get4Values(borderStyleShorthand());
     case CSSPropertyID::kColumnRule:
-      return GetShorthandValue(columnRuleShorthand());
+      return GetShorthandValueForColumnRule(columnRuleShorthand());
     case CSSPropertyID::kColumns:
       return GetShorthandValueForColumns(columnsShorthand());
     case CSSPropertyID::kContainIntrinsicSize:
@@ -1740,6 +1740,56 @@
   return result.ReleaseString();
 }
 
+String StylePropertySerializer::GetShorthandValueForColumnRule(
+    const StylePropertyShorthand& shorthand) const {
+  DCHECK_EQ(shorthand.length(), 3u);
+
+  const CSSValue* column_rule_width =
+      property_set_.GetPropertyCSSValue(*shorthand.properties()[0]);
+  const CSSValue* column_rule_style =
+      property_set_.GetPropertyCSSValue(*shorthand.properties()[1]);
+  const CSSValue* column_rule_color =
+      property_set_.GetPropertyCSSValue(*shorthand.properties()[2]);
+
+  StringBuilder result;
+  if (!(IsA<CSSIdentifierValue>(column_rule_width) &&
+        To<CSSIdentifierValue>(column_rule_width)->GetValueID() ==
+            CSSValueID::kMedium) &&
+      !column_rule_width->IsInitialValue()) {
+    String column_rule_width_text = column_rule_width->CssText();
+    result.Append(column_rule_width_text);
+  }
+
+  if (!(IsA<CSSIdentifierValue>(column_rule_style) &&
+        To<CSSIdentifierValue>(column_rule_style)->GetValueID() ==
+            CSSValueID::kNone) &&
+      !column_rule_style->IsInitialValue()) {
+    String column_rule_style_text = column_rule_style->CssText();
+    if (!result.empty()) {
+      result.Append(" ");
+    }
+
+    result.Append(column_rule_style_text);
+  }
+  if (!(IsA<CSSIdentifierValue>(column_rule_color) &&
+        To<CSSIdentifierValue>(column_rule_color)->GetValueID() ==
+            CSSValueID::kCurrentcolor) &&
+      !column_rule_color->IsInitialValue()) {
+    String column_rule_color_text = column_rule_color->CssText();
+    if (!result.empty()) {
+      result.Append(" ");
+    }
+
+    result.Append(column_rule_color_text);
+  }
+
+  if (result.empty()) {
+    return "medium";
+  }
+
+  return result.ReleaseString();
+}
+
 String StylePropertySerializer::GetShorthandValueForColumns(
     const StylePropertyShorthand& shorthand) const {
   DCHECK_EQ(shorthand.length(), 2u);
diff --git a/third_party/blink/renderer/core/css/style_property_serializer.h b/third_party/blink/renderer/core/css/style_property_serializer.h
index 3a12f55..2f47dec 100644
--- a/third_party/blink/renderer/core/css/style_property_serializer.h
+++ b/third_party/blink/renderer/core/css/style_property_serializer.h
@@ -60,6 +60,7 @@
   String PageBreakPropertyValue(const StylePropertyShorthand&) const;
   String GetShorthandValue(const StylePropertyShorthand&,
                            String separator = " ") const;
+  String GetShorthandValueForColumnRule(const StylePropertyShorthand&) const;
   String GetShorthandValueForColumns(const StylePropertyShorthand&) const;
   // foo || bar || ... || baz
   // https://drafts.csswg.org/css-values-4/#component-combinators
diff --git a/third_party/blink/renderer/core/frame/font_matching_metrics.cc b/third_party/blink/renderer/core/frame/font_matching_metrics.cc
index c978210..4e2f285 100644
--- a/third_party/blink/renderer/core/frame/font_matching_metrics.cc
+++ b/third_party/blink/renderer/core/frame/font_matching_metrics.cc
@@ -50,6 +50,7 @@
       IdentifiableSurface::Type::kGenericFontLookup,
       IdentifiableSurface::Type::kLocalFontLoadPostScriptName,
       IdentifiableSurface::Type::kLocalFontExistenceByUniqueNameOnly,
+      IdentifiableSurface::Type::kLocalFontExistenceByUniqueOrFamilyName,
   });
 }
 
@@ -97,6 +98,8 @@
     return;
   }
   successful_font_families_.insert(font_family_name);
+  ReportLocalFontExistenceByUniqueOrFamilyName(font_family_name,
+                                               /*font_exists=*/true);
 }
 
 void FontMatchingMetrics::ReportFailedFontFamilyMatch(
@@ -105,6 +108,8 @@
     return;
   }
   failed_font_families_.insert(font_family_name);
+  ReportLocalFontExistenceByUniqueOrFamilyName(font_family_name,
+                                               /*font_exists=*/false);
 }
 
 void FontMatchingMetrics::ReportSystemFontFamily(
@@ -141,6 +146,21 @@
   ReportLocalFontExistenceByUniqueNameOnly(font_name, /*font_exists=*/false);
 }
 
+void FontMatchingMetrics::ReportLocalFontExistenceByUniqueOrFamilyName(
+    const AtomicString& font_name,
+    bool font_exists) {
+  if (font_name.IsNull()) {
+    return;
+  }
+  if (!IdentifiabilityStudySettings::Get()->ShouldSampleType(
+          IdentifiableSurface::Type::kLocalFontExistenceByUniqueOrFamilyName)) {
+    return;
+  }
+  IdentifiableTokenKey input_key(
+      IdentifiabilityBenignCaseFoldingStringToken(font_name));
+  local_font_existence_by_unique_or_family_name_.insert(input_key, font_exists);
+}
+
 void FontMatchingMetrics::ReportLocalFontExistenceByUniqueNameOnly(
     const AtomicString& font_name,
     bool font_exists) {
@@ -343,6 +363,8 @@
            IdentifiableSurface::Type::kGenericFontLookup},
           {&font_load_postscript_name_,
            IdentifiableSurface::Type::kLocalFontLoadPostScriptName},
+          {&local_font_existence_by_unique_or_family_name_,
+           IdentifiableSurface::Type::kLocalFontExistenceByUniqueOrFamilyName},
           {&local_font_existence_by_unique_name_only_,
            IdentifiableSurface::Type::kLocalFontExistenceByUniqueNameOnly},
       };
diff --git a/third_party/blink/renderer/core/frame/font_matching_metrics.h b/third_party/blink/renderer/core/frame/font_matching_metrics.h
index 9cac07b2..67fadb1b 100644
--- a/third_party/blink/renderer/core/frame/font_matching_metrics.h
+++ b/third_party/blink/renderer/core/frame/font_matching_metrics.h
@@ -194,6 +194,13 @@
   void ReportLocalFontExistenceByUniqueNameOnly(const AtomicString& font_name,
                                                 bool font_exists);
 
+  // Reports a local font's existence was looked up by a name, but its actual
+  // font data may or may not have been loaded. This includes lookups where the
+  // name is allowed to match full font names or family names.
+  void ReportLocalFontExistenceByUniqueOrFamilyName(
+      const AtomicString& font_name,
+      bool font_exists);
+
   // Constructs a builder with a hash of the FontSelectionRequest already added.
   IdentifiableTokenBuilder GetTokenBuilderWithFontSelectionRequest(
       const FontDescription& font_description);
@@ -237,6 +244,7 @@
   TokenToTokenHashMap font_lookups_as_last_resort_;
   TokenToTokenHashMap generic_font_lookups_;
   TokenToTokenHashMap font_load_postscript_name_;
+  TokenToTokenHashMap local_font_existence_by_unique_or_family_name_;
   TokenToTokenHashMap local_font_existence_by_unique_name_only_;
 
   uint64_t total_emoji_clusters_shaped_ = 0;
diff --git a/third_party/blink/renderer/core/layout/ng/inline/README.md b/third_party/blink/renderer/core/layout/ng/inline/README.md
index 2833bbdd..5b5ffca 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/README.md
+++ b/third_party/blink/renderer/core/layout/ng/inline/README.md
@@ -146,8 +146,8 @@
 
 [CSS Calculating widths and margins]: https://drafts.csswg.org/css2/#Computing_widths_and_margins
 
-### <a name="create-line">Line Box Construction</a> ###
-[line Box Construction]: #create-line
+### <a name="line-box-construction">Line Box Construction</a> ###
+[line Box Construction]: #line-box-construction
 
 `NGInlineLayoutAlgorithm::CreateLine()` takes a list of [NGInlineItemResult] and
 produces a list of [NGLogicalLineItem].
@@ -369,7 +369,7 @@
 [UAX#9 Resolving Embedding Levels]: http://www.unicode.org/reports/tr9/#Resolving_Embedding_Levels
 [UAX#9 Reordering Resolved Levels]: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels
 
-[FontBaseline]: ../../../platform/fonts/font_baseline.h
+[FontBaseline]: ../../../../platform/fonts/font_baseline.h
 [NGBaselineAlgorithmType]: ng_baseline.h
 [NGBaselineRequest]: ng_baseline.h
 [NGBidiParagraph]: ng_bidi_paragraph.h
@@ -394,5 +394,5 @@
 [NGPhysicalFragment]: ../ng_physical_fragment.h
 [NGPhysicalLineBoxFragment]: ng_physical_line_box_fragment.h
 [NGPhysicalTextFragment]: ng_physical_text_fragment.h
-[ShapeResult]: ../../../platform/fonts/shaping/shape_result.h
-[ShapingLineBreaker]: ../../../platform/fonts/shaping/shaping_line_breaker.h
+[ShapeResult]: ../../../../platform/fonts/shaping/shape_result.h
+[ShapingLineBreaker]: ../../../../platform/fonts/shaping/shaping_line_breaker.h
diff --git a/third_party/blink/renderer/modules/ml/BUILD.gn b/third_party/blink/renderer/modules/ml/BUILD.gn
index 2391625..6d33320 100644
--- a/third_party/blink/renderer/modules/ml/BUILD.gn
+++ b/third_party/blink/renderer/modules/ml/BUILD.gn
@@ -43,6 +43,7 @@
   deps = [
     ":buildflags",
     "//components/ml/mojom:mojom_blink",
+    "//components/ml/webnn",
     "//services/webnn/public/mojom:mojom_blink",
   ]
 
diff --git a/third_party/blink/renderer/modules/ml/DEPS b/third_party/blink/renderer/modules/ml/DEPS
index 41b4e49..9a2f4bb 100644
--- a/third_party/blink/renderer/modules/ml/DEPS
+++ b/third_party/blink/renderer/modules/ml/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
-    "+components/ml/mojom",
-    "+services/webnn/public/mojom",
+  "+components/ml/mojom",
+  "+components/ml/webnn",
+  "+services/webnn/public/mojom",
 ]
\ No newline at end of file
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.cc b/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.cc
index 88d75c926..6bca3c4 100644
--- a/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.cc
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 
 #include "base/numerics/checked_math.h"
+#include "components/ml/webnn/graph_validation_utils.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_ml_clamp_options.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_ml_conv_2d_options.h"
@@ -77,41 +78,16 @@
   return true;
 }
 
-// Broadcast the input shapes and return the output shape.
-// If bidirectional is true, its behavior follows the numpy-broadcasting-rule:
-// https://numpy.org/doc/stable/user/basics.broadcasting.html#general-broadcasting-rules.
-// Otherwise, it unidirectionally broadcasts the lhs to the rhs.
 absl::optional<Vector<uint32_t>> BroadcastShapes(
     const Vector<uint32_t>& dims_lhs,
     const Vector<uint32_t>& dims_rhs,
     bool bidirectional = true) {
-  // If bidirectional is true, the rank of the output shape is the maximum rank
-  // of the input shapes. Otherwise it is as the same as the rhs' rank.
-  auto rank_lhs = dims_lhs.size(), rank_rhs = dims_rhs.size();
-  auto rank_output = bidirectional ? std::max(rank_lhs, rank_rhs) : rank_rhs;
-  Vector<uint32_t> dims_output(rank_output);
-  for (wtf_size_t i = 0; i < rank_output; ++i) {
-    auto dim_lhs = i < rank_lhs ? dims_lhs[rank_lhs - i - 1] : 1;
-    DCHECK_GT(dim_lhs, uint32_t(0));
-    auto dim_rhs = i < rank_rhs ? dims_rhs[rank_rhs - i - 1] : 1;
-    DCHECK_GT(dim_rhs, uint32_t(0));
-    // If bidirectional is true, two dimensions are compatible when they are
-    // equal, or one of them is 1. Otherwise, two dimensions are compatible when
-    // they are equal, or the lhs dimension is 1.
-    if (bidirectional) {
-      if (dim_lhs != dim_rhs && dim_lhs != 1 && dim_rhs != 1) {
-        return absl::nullopt;
-      }
-    } else if (dim_lhs != dim_rhs && dim_lhs != 1) {
-      return absl::nullopt;
-    }
-    // If bidirectional is true, for each dimension of the output tensor, its
-    // size is the maximum size along that dimension of the input shapes.
-    // Otherwise, its size is the same as the rhs.
-    dims_output[rank_output - i - 1] =
-        bidirectional ? std::max(dim_lhs, dim_rhs) : dim_rhs;
+  auto output_shape = webnn::BroadcastShapes(
+      base::make_span(dims_lhs), base::make_span(dims_rhs), bidirectional);
+  if (!output_shape) {
+    return absl::nullopt;
   }
-  return dims_output;
+  return Vector<uint32_t>(output_shape.value());
 }
 
 MLOperand* BuildElementWiseBinary(MLGraphBuilder* builder,
@@ -1879,6 +1855,77 @@
                                             MLOperator::OperatorKind::kSigmoid);
 }
 
+MLOperand* MLGraphBuilder::slice(const MLOperand* input,
+                                 const Vector<uint32_t>& starts,
+                                 const Vector<uint32_t>& sizes,
+                                 ExceptionState& exception_state) {
+  const auto input_rank = input->Dimensions().size();
+  if (starts.size() != input_rank) {
+    exception_state.ThrowDOMException(DOMExceptionCode::kDataError,
+                                      "The length of starts must be "
+                                      "equal to the rank of the input tensor.");
+    return nullptr;
+  }
+  if (sizes.size() != input_rank) {
+    exception_state.ThrowDOMException(DOMExceptionCode::kDataError,
+                                      "The length of sizes must be "
+                                      "equal to the rank of the input tensor.");
+    return nullptr;
+  }
+
+  for (wtf_size_t i = 0; i < input_rank; i++) {
+    if (starts[i] >= input->Dimensions()[i]) {
+      exception_state.ThrowDOMException(
+          DOMExceptionCode::kDataError,
+          String::Format("For dimension (%u): the starting index to slice must "
+                         "be less than input size (%u).",
+                         i, input->Dimensions()[i]));
+      return nullptr;
+    }
+    // WebNN plans to allow 0 size dimensions and an issue has been filed to
+    // track it: https://github.com/webmachinelearning/webnn/issues/391.
+    if (sizes[i] == 0) {
+      exception_state.ThrowDOMException(
+          DOMExceptionCode::kDataError,
+          String::Format("For dimension (%u): the number of elements to slice "
+                         "must not be 0.",
+                         i));
+      return nullptr;
+    }
+    auto checked_ending_index =
+        base::MakeCheckedNum<uint32_t>(starts[i]) + sizes[i];
+    if (!checked_ending_index.IsValid<uint32_t>()) {
+      exception_state.ThrowDOMException(
+          DOMExceptionCode::kDataError,
+          String::Format(
+              "For dimension (%u): the ending index to slice is too large.",
+              i));
+      return nullptr;
+    }
+    if (checked_ending_index.ValueOrDie() > input->Dimensions()[i]) {
+      exception_state.ThrowDOMException(
+          DOMExceptionCode::kDataError,
+          String::Format("For dimension (%u): the ending index to slice must "
+                         "not be greater "
+                         "than input size (%u).",
+                         i, input->Dimensions()[i]));
+      return nullptr;
+    }
+  }
+
+  auto* slice = MakeGarbageCollected<MLSliceOperator>(this, starts, sizes);
+  String error_message;
+  auto* output = MLOperand::ValidateAndCreateOutput(this, input->Type(), sizes,
+                                                    slice, error_message);
+  if (!output) {
+    exception_state.ThrowDOMException(DOMExceptionCode::kDataError,
+                                      error_message);
+    return nullptr;
+  }
+  slice->Connect({input}, {output});
+  return output;
+}
+
 MLOperand* MLGraphBuilder::softmax(const MLOperand* input,
                                    ExceptionState& exception_state) {
   // According to WebNN spec:
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.h b/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.h
index aea83c9..aa65f41 100644
--- a/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.h
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.h
@@ -214,6 +214,11 @@
   MLOperand* sigmoid(const MLOperand* input, ExceptionState& exception_state);
   MLActivation* sigmoid(ExceptionState& exception_state);
 
+  MLOperand* slice(const MLOperand* input,
+                   const Vector<uint32_t>& starts,
+                   const Vector<uint32_t>& sizes,
+                   ExceptionState& exception_state);
+
   MLOperand* softmax(const MLOperand* input, ExceptionState& exception_state);
 
   MLOperand* transpose(const MLOperand* input,
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.idl b/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.idl
index c7cf217..65d4393 100644
--- a/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.idl
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.idl
@@ -164,6 +164,8 @@
   [RaisesException] MLOperand sigmoid(MLOperand input);
   [RaisesException] MLActivation sigmoid();
 
+  [RaisesException] MLOperand slice(MLOperand input, sequence<[EnforceRange] unsigned long> starts, sequence<[EnforceRange] unsigned long> sizes);
+
   [RaisesException] MLOperand transpose(MLOperand input, optional MLTransposeOptions options = {});
 
   [RaisesException] MLOperand softmax(MLOperand input);
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder_test.cc b/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder_test.cc
index 7ce20c8..eefa65c 100644
--- a/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder_test.cc
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder_test.cc
@@ -3850,6 +3850,119 @@
   }
 }
 
+TEST_F(MLGraphBuilderTest, SliceTest) {
+  V8TestingScope scope;
+  auto* builder = CreateMLGraphBuilder(scope.GetExecutionContext());
+  {
+    // Test building slice with starts = {0, 1, 2} and sizes = {1, 2, 3}.
+    Vector<uint32_t> input_shape({3, 4, 5});
+    auto* input =
+        BuildInput(builder, "input", input_shape,
+                   V8MLOperandType::Enum::kFloat32, scope.GetExceptionState());
+    auto* output =
+        builder->slice(input, {0, 1, 2}, {1, 2, 3}, scope.GetExceptionState());
+    EXPECT_NE(output, nullptr);
+    EXPECT_EQ(output->Kind(), MLOperand::OperandKind::kOutput);
+    EXPECT_EQ(output->Type(), V8MLOperandType::Enum::kFloat32);
+    EXPECT_EQ(output->Dimensions(), Vector<uint32_t>({1, 2, 3}));
+    const MLOperator* slice = output->Operator();
+    EXPECT_NE(slice, nullptr);
+    EXPECT_EQ(slice->Kind(), MLOperator::OperatorKind::kSlice);
+    EXPECT_EQ(slice->IsConnected(), true);
+    EXPECT_EQ(slice->Options(), nullptr);
+  }
+  {
+    // Test throwing error when the length of sizes is not equal to the rank of
+    // the input tensor.
+    Vector<uint32_t> input_shape({3, 4, 5});
+    auto* input =
+        BuildInput(builder, "input", input_shape,
+                   V8MLOperandType::Enum::kFloat32, scope.GetExceptionState());
+    const Vector<uint32_t> starts = {1, 2, 3};
+    const Vector<uint32_t> sizes = {1, 1};
+    auto* output =
+        builder->slice(input, starts, sizes, scope.GetExceptionState());
+    EXPECT_EQ(output, nullptr);
+    EXPECT_EQ(scope.GetExceptionState().CodeAs<DOMExceptionCode>(),
+              DOMExceptionCode::kDataError);
+    EXPECT_EQ(
+        scope.GetExceptionState().Message(),
+        "The length of sizes must be equal to the rank of the input tensor.");
+  }
+  {
+    // Test throwing error when the length of starts is not equal to the rank
+    // of the input tensor.
+    Vector<uint32_t> input_shape({3, 4, 5});
+    auto* input =
+        BuildInput(builder, "input", input_shape,
+                   V8MLOperandType::Enum::kFloat32, scope.GetExceptionState());
+    const Vector<uint32_t> starts = {1, 2, 1, 3};
+    const Vector<uint32_t> sizes = {1, 1, 1};
+    auto* output =
+        builder->slice(input, starts, sizes, scope.GetExceptionState());
+    EXPECT_EQ(output, nullptr);
+    EXPECT_EQ(scope.GetExceptionState().CodeAs<DOMExceptionCode>(),
+              DOMExceptionCode::kDataError);
+    EXPECT_EQ(
+        scope.GetExceptionState().Message(),
+        "The length of starts must be equal to the rank of the input tensor.");
+  }
+  {
+    // Test throwing error when the starting index is equal to or greater than
+    // input size in the same dimension.
+    Vector<uint32_t> input_shape({3, 4, 5});
+    auto* input =
+        BuildInput(builder, "input", input_shape,
+                   V8MLOperandType::Enum::kFloat32, scope.GetExceptionState());
+    const Vector<uint32_t> starts = {0, 4, 4};
+    const Vector<uint32_t> sizes = {1, 1, 1};
+    auto* output =
+        builder->slice(input, starts, sizes, scope.GetExceptionState());
+    EXPECT_EQ(output, nullptr);
+    EXPECT_EQ(scope.GetExceptionState().CodeAs<DOMExceptionCode>(),
+              DOMExceptionCode::kDataError);
+    EXPECT_EQ(scope.GetExceptionState().Message(),
+              "For dimension (1): the starting index to slice must be less "
+              "than input size (4).");
+  }
+  {
+    // Test throwing error when the number of elements to slice is equal to 0.
+    Vector<uint32_t> input_shape({3, 4, 5});
+    auto* input =
+        BuildInput(builder, "input", input_shape,
+                   V8MLOperandType::Enum::kFloat32, scope.GetExceptionState());
+    const Vector<uint32_t> starts = {1, 2, 3};
+    const Vector<uint32_t> sizes = {1, 0, 1};
+    auto* output =
+        builder->slice(input, starts, sizes, scope.GetExceptionState());
+    EXPECT_EQ(output, nullptr);
+    EXPECT_EQ(scope.GetExceptionState().CodeAs<DOMExceptionCode>(),
+              DOMExceptionCode::kDataError);
+    EXPECT_EQ(
+        scope.GetExceptionState().Message(),
+        "For dimension (1): the number of elements to slice must not be 0.");
+  }
+  {
+    // Test throwing error when the ending index to slice is greater than input
+    // size in the same dimension.
+    Vector<uint32_t> input_shape({3, 4, 5});
+    auto* input =
+        BuildInput(builder, "input", input_shape,
+                   V8MLOperandType::Enum::kFloat32, scope.GetExceptionState());
+    const Vector<uint32_t> starts = {0, 1, 2};
+    const Vector<uint32_t> sizes = {3, 4, 1};
+    auto* output =
+        builder->slice(input, starts, sizes, scope.GetExceptionState());
+    EXPECT_EQ(output, nullptr);
+    EXPECT_EQ(scope.GetExceptionState().CodeAs<DOMExceptionCode>(),
+              DOMExceptionCode::kDataError);
+    EXPECT_EQ(scope.GetExceptionState().Message(),
+              "For dimension (1): the ending index to slice must not be "
+              "greater than input "
+              "size (4).");
+  }
+}
+
 class FakeMLGraphBackend final : public MLGraph {
  public:
   // Create and build a FakeMLGraphBackend object. Resolve the promise with
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_operand.cc b/third_party/blink/renderer/modules/ml/webnn/ml_operand.cc
index 64b56c895..d1026269 100644
--- a/third_party/blink/renderer/modules/ml/webnn/ml_operand.cc
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_operand.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/modules/ml/webnn/ml_operand.h"
 
+#include "components/ml/webnn/graph_validation_utils.h"
 #include "third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.h"
 #include "third_party/blink/renderer/modules/ml/webnn/ml_operator.h"
 
@@ -32,43 +33,23 @@
 
 absl::optional<size_t> ValidateAndCalculateElementsNumber(
     const Vector<uint32_t>& dimensions,
-    String& error_message) {
-  if (dimensions.empty()) {
-    error_message = "The dimensions is empty.";
-    return absl::nullopt;
-  }
-  base::CheckedNumeric<size_t> checked_number_of_elements = 1;
-  for (auto& d : dimensions) {
-    if (d == 0) {
-      error_message = "All dimensions should be positive.";
-      return absl::nullopt;
-    }
-    checked_number_of_elements *= d;
-  }
-  if (!checked_number_of_elements.IsValid()) {
-    error_message = "The number of elements is too large.";
-    return absl::nullopt;
-  }
-  return checked_number_of_elements.ValueOrDie();
+    String& error_message_blink) {
+  std::string error_message;
+  auto number_of_elements = webnn::ValidateAndCalculateElementsNumber(
+      base::make_span(dimensions), error_message);
+  error_message_blink = WTF::String::FromUTF8(error_message);
+  return number_of_elements;
 }
 
 absl::optional<size_t> ValidateAndCalculateByteLength(
     V8MLOperandType::Enum type,
     const Vector<uint32_t>& dimensions,
-    String& error_message) {
-  absl::optional<size_t> elements_num =
-      ValidateAndCalculateElementsNumber(dimensions, error_message);
-  if (!elements_num) {
-    return absl::nullopt;
-  }
-  auto checked_byte_length =
-      base::MakeCheckedNum<size_t>(elements_num.value()) *
-      GetBytesPerElement(type);
-  if (!checked_byte_length.IsValid()) {
-    error_message = "The byte length is too large.";
-    return absl::nullopt;
-  }
-  return checked_byte_length.ValueOrDie();
+    String& error_message_blink) {
+  std::string error_message;
+  auto byte_length = webnn::ValidateAndCalculateByteLength(
+      GetBytesPerElement(type), base::make_span(dimensions), error_message);
+  error_message_blink = WTF::String::FromUTF8(error_message);
+  return byte_length;
 }
 
 }  // namespace
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_operator.cc b/third_party/blink/renderer/modules/ml/webnn/ml_operator.cc
index 99467e1..99d8b2f1 100644
--- a/third_party/blink/renderer/modules/ml/webnn/ml_operator.cc
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_operator.cc
@@ -62,10 +62,12 @@
       return "reshape";
     case MLOperator::OperatorKind::kResample2d:
       return "resample2d";
-    case MLOperator::OperatorKind::kSoftmax:
-      return "softmax";
     case MLOperator::OperatorKind::kSigmoid:
       return "sigmoid";
+    case MLOperator::OperatorKind::kSlice:
+      return "slice";
+    case MLOperator::OperatorKind::kSoftmax:
+      return "softmax";
     case MLOperator::OperatorKind::kTranspose:
       return "transpose";
   }
@@ -132,4 +134,21 @@
 const Vector<uint32_t>& MLPadOperator::EndingPadding() const {
   return ending_padding_;
 }
+
+MLSliceOperator::MLSliceOperator(MLGraphBuilder* builder,
+                                 const Vector<uint32_t>& starts,
+                                 const Vector<uint32_t>& sizes)
+    : MLOperator(builder, MLOperator::OperatorKind::kSlice, nullptr),
+      starts_(starts),
+      sizes_(sizes) {}
+
+MLSliceOperator::~MLSliceOperator() = default;
+
+const Vector<uint32_t>& MLSliceOperator::Starts() const {
+  return starts_;
+}
+
+const Vector<uint32_t>& MLSliceOperator::Sizes() const {
+  return sizes_;
+}
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_operator.h b/third_party/blink/renderer/modules/ml/webnn/ml_operator.h
index 8d1c618..b368755 100644
--- a/third_party/blink/renderer/modules/ml/webnn/ml_operator.h
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_operator.h
@@ -46,8 +46,9 @@
     kRelu,
     kReshape,
     kResample2d,
-    kSoftmax,
     kSigmoid,
+    kSlice,
+    kSoftmax,
     kTranspose
   };
 
@@ -124,6 +125,25 @@
   Vector<uint32_t> beginning_padding_;
   Vector<uint32_t> ending_padding_;
 };
+
+class MODULES_EXPORT MLSliceOperator : public MLOperator {
+ public:
+  MLSliceOperator(MLGraphBuilder* builder,
+                  const Vector<uint32_t>& beginning_padding,
+                  const Vector<uint32_t>& ending_padding);
+
+  MLSliceOperator(const MLSliceOperator&) = delete;
+  MLSliceOperator& operator=(const MLSliceOperator&) = delete;
+
+  ~MLSliceOperator();
+
+  const Vector<uint32_t>& Starts() const;
+  const Vector<uint32_t>& Sizes() const;
+
+ private:
+  Vector<uint32_t> starts_;
+  Vector<uint32_t> sizes_;
+};
 }  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_ML_WEBNN_ML_OPERATOR_H_
diff --git a/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.cc b/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.cc
index 03b3f7ad..7d2aa75 100644
--- a/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.cc
+++ b/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.cc
@@ -84,12 +84,6 @@
   DEFINE_THREAD_SAFE_STATIC_LOCAL(
       CustomCountHistogram, jpeg_density_histogram,
       ("Blink.DecodedImage.JpegDensity.KiBWeighted", 1, 1000, 100));
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(
-      CustomCountHistogram, webp_density_histogram,
-      ("Blink.DecodedImage.WebPDensity.KiBWeighted", 1, 1000, 100));
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(
-      CustomCountHistogram, avif_density_histogram,
-      ("Blink.DecodedImage.AvifDensity.KiBWeighted", 1, 1000, 100));
 
   CustomCountHistogram* density_histogram = nullptr;
   BitmapImageMetrics::DecodedImageType decoded_image_type =
@@ -98,12 +92,6 @@
     case BitmapImageMetrics::DecodedImageType::kJPEG:
       density_histogram = &jpeg_density_histogram;
       break;
-    case BitmapImageMetrics::DecodedImageType::kWebP:
-      density_histogram = &webp_density_histogram;
-      break;
-    case BitmapImageMetrics::DecodedImageType::kAVIF:
-      density_histogram = &avif_density_histogram;
-      break;
     default:
       // All other formats are not reported.
       return;
diff --git a/third_party/blink/renderer/platform/graphics/bitmap_image_test.cc b/third_party/blink/renderer/platform/graphics/bitmap_image_test.cc
index e58d9d2..fc4c0db 100644
--- a/third_party/blink/renderer/platform/graphics/bitmap_image_test.cc
+++ b/third_party/blink/renderer/platform/graphics/bitmap_image_test.cc
@@ -841,10 +841,6 @@
     LoadImage("animated-10color.gif");       // 100x100 but GIF is not reported.
     histogram_tester.ExpectTotalCount(
         "Blink.DecodedImage.JpegDensity.KiBWeighted", 0);
-    histogram_tester.ExpectTotalCount(
-        "Blink.DecodedImage.WebPDensity.KiBWeighted", 0);
-    histogram_tester.ExpectTotalCount(
-        "Blink.DecodedImage.AvifDensity.KiBWeighted", 0);
   }
 
   // 439x154, 23220 bytes --> 2.74 bpp, 23 KiB (rounded up)
@@ -856,11 +852,6 @@
   ExpectImageRecordsSample("blue-wheel-srgb-color-profile.jpg",
                            "Blink.DecodedImage.JpegDensity.KiBWeighted", 578,
                            72);
-
-  // 800x800, 19436 bytes --> 0.24, 19 KiB
-  ExpectImageRecordsSample("webp-color-profile-lossy.webp",
-                           "Blink.DecodedImage.WebPDensity.KiBWeighted", 24,
-                           19);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/web_tests/SmokeTests/Mac.txt b/third_party/blink/web_tests/SmokeTests/Mac.txt
index d041588..3b10840 100644
--- a/third_party/blink/web_tests/SmokeTests/Mac.txt
+++ b/third_party/blink/web_tests/SmokeTests/Mac.txt
@@ -1884,7 +1884,6 @@
 virtual/threaded/external/wpt/scroll-animations/css/at-scroll-timeline-default-descriptors-iframe.html
 virtual/threaded/external/wpt/scroll-animations/scroll-timelines/current-time-nan.html
 virtual/threaded/external/wpt/web-animations/timing-model/animations/updating-the-finished-state.html
-virtual/threaded/http/tests/devtools/tracing/timeline-misc/timeline-event-causes.js
 virtual/threaded/http/tests/devtools/tracing/timeline-paint/paint-profiler-update.js
 virtual/threaded/printing/absolute-position-headers-and-footers.html
 virtual/threaded/printing/fixed-positioned-headers-and-footers-inside-transform.html
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index b525b725..840380a8 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -2897,10 +2897,14 @@
 crbug.com/626703 [ Win ] virtual/partitioned-cookies/http/tests/inspector-protocol/network/disabled-cache-navigation.js [ Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 [ Mac13 ] external/wpt/html/semantics/links/hyperlink-auditing/headers.optional.html [ Timeout ]
+crbug.com/626703 [ Mac13 ] virtual/threaded-prefer-compositing/external/wpt/scroll-animations/scroll-timelines/effect-updateTiming.html [ Timeout ]
+crbug.com/626703 [ Mac13 ] virtual/threaded-prefer-compositing/external/wpt/scroll-animations/view-timelines/view-timeline-range.html [ Timeout ]
+crbug.com/626703 [ Mac13 ] virtual/threaded/external/wpt/scroll-animations/scroll-timelines/effect-updateTiming.html [ Timeout ]
+crbug.com/626703 [ Mac13 ] virtual/threaded/external/wpt/scroll-animations/view-timelines/view-timeline-inset.html [ Timeout ]
 crbug.com/626703 external/wpt/css/css-images/image-set/image-set-negative-resolution-rendering-3.html [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/video-rvfc/request-video-frame-callback-webrtc.https.html [ Timeout ]
 crbug.com/626703 [ Mac13-arm64 ] external/wpt/webrtc-encoded-transform/RTCPeerConnection-insertable-streams-simulcast.https.html [ Timeout ]
-crbug.com/626703 [ Mac13 ] virtual/threaded-prefer-compositing/external/wpt/scroll-animations/css/scroll-timeline-dynamic.tentative.html [ Timeout ]
 crbug.com/626703 [ Mac11-arm64 ] virtual/threaded-prefer-compositing/external/wpt/scroll-animations/css/view-timeline-range-animation.html [ Timeout ]
 crbug.com/626703 [ Mac12 ] virtual/threaded/external/wpt/scroll-animations/css/animation-timeline-view-functional-notation.tentative.html [ Timeout ]
 crbug.com/626703 [ Mac10.15 ] virtual/threaded-prefer-compositing/external/wpt/scroll-animations/css/view-timeline-range-animation.html [ Timeout ]
@@ -2910,7 +2914,6 @@
 crbug.com/626703 [ Mac13 ] virtual/threaded-prefer-compositing/external/wpt/scroll-animations/css/view-timeline-range-animation.html [ Timeout ]
 crbug.com/626703 [ Mac13-arm64 ] virtual/threaded-prefer-compositing/external/wpt/scroll-animations/css/view-timeline-range-animation.html [ Timeout ]
 crbug.com/626703 [ Mac12 ] virtual/threaded-prefer-compositing/external/wpt/scroll-animations/css/animation-timeline-view-functional-notation.tentative.html [ Timeout ]
-crbug.com/626703 [ Mac12 ] virtual/threaded-prefer-compositing/external/wpt/scroll-animations/css/scroll-timeline-dynamic.tentative.html [ Timeout ]
 crbug.com/626703 [ Mac13 ] external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-video.html [ Failure ]
 crbug.com/626703 [ Mac13 ] external/wpt/html/semantics/embedded-content/media-elements/ready-states/autoplay-hidden.optional.html [ Timeout ]
 crbug.com/626703 [ Mac13-arm64 ] external/wpt/html/semantics/embedded-content/media-elements/ready-states/autoplay-hidden.optional.html [ Timeout ]
@@ -4575,7 +4578,6 @@
 
 # Failing on Webkit Linux Leak
 crbug.com/1046784 [ Linux ] http/tests/devtools/tracing/timeline-paint/timeline-paint.js [ Failure Pass ]
-crbug.com/1046784 [ Linux ] http/tests/devtools/tracing/timeline-misc/timeline-event-causes.js [ Failure Pass ]
 
 # Sheriff 2020-07-23
 
@@ -6831,3 +6833,8 @@
 crbug.com/1447531 [ Mac10.13 ] virtual/threaded-prefer-compositing/external/wpt/scroll-animations/css/view-timeline-range-animation.html [ Failure Pass Timeout ]
 crbug.com/1447531 [ Mac10.14 ] virtual/threaded-prefer-compositing/external/wpt/scroll-animations/css/view-timeline-range-animation.html [ Failure Pass ]
 crbug.com/1447244 [ Mac ] virtual/threaded/external/wpt/scroll-animations/css/animation-range-visual-test.html [ Failure Pass ]
+
+crbug.com/1377004 [ Mac ] external/wpt/video-rvfc/request-video-frame-callback-webrtc.https.html [ Failure Pass Timeout ]
+
+# Sheriff 2023-05-23
+crbug.com/1376679 [ Mac ] virtual/threaded-prefer-compositing/external/wpt/scroll-animations/css/scroll-timeline-dynamic.tentative.html [ Pass 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 126b556..6a29b3d 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
@@ -40958,7 +40958,7 @@
        ]
       ],
       "float-root.html": [
-       "ee7f70e7844d9db7c247a4c7bc14be4634fbdba4",
+       "944ae7ad5f46296d1ce65088421e25b79eed40af",
        [
         null,
         [
@@ -84660,7 +84660,7 @@
       ]
      ],
      "inner-border-non-renderable.html": [
-      "46fbcc6c920eec3d95c56cf8b85fb8a1699942d2",
+      "7c3cff798819b7cc592b807a172a0bbebae32c9b",
       [
        null,
        [
@@ -97597,7 +97597,7 @@
       ]
      ],
      "lab-l-over-100-1.html": [
-      "fdb3955e96ee4fc00e33db85134fc78adb84002b",
+      "7d6e0387700ac3226ed87402c5e26f4e9341e763",
       [
        null,
        [
@@ -97610,7 +97610,7 @@
       ]
      ],
      "lab-l-over-100-2.html": [
-      "f62f9e0559b0c23106a29848bcf3e5515e16ff04",
+      "6674c41ae9667c7f30ce1e7b743abb21e6a398e0",
       [
        null,
        [
@@ -97753,7 +97753,7 @@
       ]
      ],
      "lch-l-over-100-1.html": [
-      "9711956242df6e903d8ebcd3eebe2820c7b8b1e6",
+      "6e0c62330c39d329bb71323caf393e8d4426e535",
       [
        null,
        [
@@ -97766,7 +97766,7 @@
       ]
      ],
      "lch-l-over-100-2.html": [
-      "a909a49f0c2344e3b8934a9b4d9b80a77ddac8fc",
+      "7752d0dc0eb4d59cbb12364441b59732d025fd1d",
       [
        null,
        [
@@ -127296,7 +127296,7 @@
        ]
       ],
       "slnt-backslant-variable.html": [
-       "4bbe2b157f5cf07c7aacca0d4c2d94afb98dfaec",
+       "36a4305da72590c01280bee49ba08825cd3bcb59",
        [
         null,
         [
@@ -127309,7 +127309,7 @@
        ]
       ],
       "slnt-variable.html": [
-       "d81df09c19d1bac0175d0e3e9e095f63165bfb6d",
+       "ae937037940b4533442777853dd43d76c241ce3f",
        [
         null,
         [
@@ -165039,7 +165039,7 @@
       ]
      ],
      "marker-variable.html": [
-      "3d0a7c8596e0bc51b0421224696925997bc02561",
+      "eb349c98dfb26fec5917fe1be3c01e404cce5a65",
       [
        null,
        [
@@ -175043,7 +175043,7 @@
       ]
      ],
      "fit-content-block-size-abspos.html": [
-      "d8ce91f9f626f8569bd9452c9fd90ead9a75ee4e",
+      "8ed6771483d220665d73f2667bf698f01d249994",
       [
        null,
        [
@@ -175056,7 +175056,7 @@
       ]
      ],
      "fit-content-block-size-fixedpos.html": [
-      "1f08c6ab9f20747a3ab166a12654e106b5d51efd",
+      "052435ba93771f146c3875ce868a9b4ae366b2a8",
       [
        null,
        [
@@ -175290,7 +175290,7 @@
       ]
      ],
      "grid-item-image-percentage-min-height-computes-as-0.html": [
-      "3b5dd2aedd0ce81d771130a7d8b905c75a9a7485",
+      "ef3da03100229a846ca77156bdf34e5e37c92508",
       [
        null,
        [
@@ -175836,7 +175836,7 @@
       ]
      ],
      "nested-flexbox-image-percentage-max-height-computes-as-none.html": [
-      "afac4641477a6d7c39c0c682da6d4f3abc461e90",
+      "06b70f18e3d4e89299281024048f7984ba39a469",
       [
        null,
        [
@@ -186340,7 +186340,7 @@
        ]
       ],
       "text-indent-min-max-content-001.html": [
-       "99592df5c5ba4fe751f9d21d2c2364847f04598f",
+       "93ddac50d6b6c8a7f272f208fdec6057d52a383b",
        [
         null,
         [
@@ -190874,7 +190874,7 @@
        ]
       ],
       "text-wrap-balance-002.html": [
-       "7366c6ac0f10ada47f67c7ad35fc073016bccf96",
+       "cae9d54de0e60c42047f7bffafe729f8aae2b740",
        [
         null,
         [
@@ -190887,7 +190887,7 @@
        ]
       ],
       "text-wrap-balance-align-001.html": [
-       "b4659613c8552a90bb210292774fab7271a2b6c8",
+       "b27823b72a4dfec983e0e0eae7a5436d9f958b74",
        [
         null,
         [
@@ -190900,7 +190900,7 @@
        ]
       ],
       "text-wrap-balance-dynamic-001.html": [
-       "8c7d27d1a347407c82f0602bba105982764729e3",
+       "76b4cbbb433568b7cc25f7b1fb6e419b9a9570be",
        [
         null,
         [
@@ -190913,7 +190913,7 @@
        ]
       ],
       "text-wrap-balance-line-clamp-001.html": [
-       "292e655464b750a3c0426fb6c63df8ebdbac5ffe",
+       "f104a5261bc9837ad0f9af675ba44de28421b824",
        [
         null,
         [
@@ -190926,7 +190926,7 @@
        ]
       ],
       "text-wrap-balance-text-indent-001.html": [
-       "e06d91e599e6e137d3c178d3553ca82ff370eae6",
+       "0fe4447acfb0f3a9a0c445723c99071959ff6d6c",
        [
         null,
         [
@@ -247658,7 +247658,7 @@
        ]
       ],
       "nth-child-containing-ancestor.html": [
-       "7266cd5a2518bb533e2729859f43d21ac59f1279",
+       "a7f246328c8f5f48c7f32822ea8dfdecde474022",
        [
         null,
         [
@@ -247684,7 +247684,7 @@
        ]
       ],
       "nth-child-of-attr-largedom.html": [
-       "76bc4542dae30ec1d7cbd4856875dc63def90015",
+       "07d87d2d4b4ae7448725890cc27f8ac0bc334c88",
        [
         null,
         [
@@ -247697,7 +247697,7 @@
        ]
       ],
       "nth-child-of-attr.html": [
-       "d929d6a50db02d3e34d024d83200649573ca20a4",
+       "d4e82ff78c01832f2531d0b0e0a720b7fb9115fc",
        [
         null,
         [
@@ -247710,7 +247710,7 @@
        ]
       ],
       "nth-child-of-class-prefix.html": [
-       "ac7757db3eb03bbc11e01911d857baca63b1b4a8",
+       "2ea57c099f815399ec1d2f1a7839b08901e00f54",
        [
         null,
         [
@@ -247723,7 +247723,7 @@
        ]
       ],
       "nth-child-of-class.html": [
-       "dc1e8cec82ed334d75c51351775fa001b3cddb4e",
+       "1171f25c0a448a233580e7552fa5bb06ef721ec3",
        [
         null,
         [
@@ -247736,7 +247736,7 @@
        ]
       ],
       "nth-child-of-has.html": [
-       "1a548315cc09c49bf3c5177172adf771ec0a350c",
+       "8473828973def17ad8859fd1167ba364c5c4b41b",
        [
         null,
         [
@@ -247749,7 +247749,7 @@
        ]
       ],
       "nth-child-of-id-prefix.html": [
-       "fadb8f38514e1cf2c143a5bdd586687a28c64537",
+       "b07b1cfc411c3b002f991ef5e13021880d225969",
        [
         null,
         [
@@ -247762,7 +247762,7 @@
        ]
       ],
       "nth-child-of-ids.html": [
-       "033205283c46d43bc1f6f7f8f3dd79991e1a8b82",
+       "8e94aa3e22c68e2fdb8c4787949dab8bd999ef59",
        [
         null,
         [
@@ -247775,7 +247775,7 @@
        ]
       ],
       "nth-child-of-in-ancestor.html": [
-       "7311c3e301155620b05cde7ffecd9d829d20618a",
+       "2ae80061b05deff92ae2805634530ee4e2b212d0",
        [
         null,
         [
@@ -247788,7 +247788,7 @@
        ]
       ],
       "nth-child-of-in-is.html": [
-       "31276e6ef9eb0bf9990d548d576ab30b82b14e48",
+       "f004195c83e226c02fe87c0b70a0a8e74d59eaa1",
        [
         null,
         [
@@ -247801,7 +247801,7 @@
        ]
       ],
       "nth-child-of-in-shadow-root.html": [
-       "1e949a3bd0e991d97d3ae87fc7420c81047477e6",
+       "4195a14a3ed80583ace772854fcbbf6e84388614",
        [
         null,
         [
@@ -247814,7 +247814,7 @@
        ]
       ],
       "nth-child-of-is.html": [
-       "e230a30d177627139a327f09f93c3e66319f5fc8",
+       "4473845a7a09d97acd5dacd1fbc51e50b679222c",
        [
         null,
         [
@@ -247840,7 +247840,7 @@
        ]
       ],
       "nth-child-of-sibling.html": [
-       "5beaad6a58108dde8607e9940c4fb017e4056ab2",
+       "68e46518ec2bf1bb82b56572b58bde61377120b4",
        [
         null,
         [
@@ -247853,7 +247853,7 @@
        ]
       ],
       "nth-child-when-ancestor-changes.html": [
-       "4d2b4fbce076a1ea1d651e4a86afdd0da0decf07",
+       "c4a97ee7e805c24e74874c330a9ed1f260229267",
        [
         null,
         [
@@ -247866,7 +247866,7 @@
        ]
       ],
       "nth-child-when-sibling-changes.html": [
-       "a0025be95a2bcab29d77e4a9e1b789304fa31055",
+       "43374df917423e7ec9860011b2ce6e1915e52289",
        [
         null,
         [
@@ -247918,7 +247918,7 @@
        ]
       ],
       "nth-last-child-of-class-prefix.html": [
-       "f9fc196c2136e600e84c0116aa58ffa3938ea316",
+       "da12246926d72293893330a041592130ddd4663c",
        [
         null,
         [
@@ -247957,7 +247957,7 @@
        ]
       ],
       "nth-last-child-of-id-prefix.html": [
-       "1a9e6a9aa319b6d690771e1b9fae96fa3db9bb37",
+       "747236aca0b8818bce370626f359c779dcf4a0ac",
        [
         null,
         [
@@ -247970,7 +247970,7 @@
        ]
       ],
       "nth-last-child-of-ids.html": [
-       "cd682ed5fb547b2238b1eaa591b67d103f60999b",
+       "def336119a5c2143a3330afc265325f3cfb46c1d",
        [
         null,
         [
@@ -247996,7 +247996,7 @@
        ]
       ],
       "nth-last-child-of-in-is.html": [
-       "90c8860c87f5028cf5f5cea5988dd66cc6ef147d",
+       "370883ecf1c44412f8978980296ad30c0f547977",
        [
         null,
         [
@@ -248022,7 +248022,7 @@
        ]
       ],
       "nth-last-child-of-is.html": [
-       "ac1ec316c74c8bea13f668804c290e7a1548f91f",
+       "0db7347698db341f4c11adf2203efd909410ed39",
        [
         null,
         [
@@ -248218,7 +248218,7 @@
       ]
      ],
      "nth-child-and-nth-last-child.html": [
-      "455063f916013a47b7034dfff7b553fd8bb0f036",
+      "1379b4c706de2e3353f0ecc4bb5e2bbe00e24b25",
       [
        null,
        [
@@ -248257,7 +248257,7 @@
       ]
      ],
      "nth-child-of-classname.html": [
-      "8ec3f43f7f481e4f3c65d03f6dfd2e12f6f59961",
+      "1cfb01056c96390771aa07c1e704113f689188fd",
       [
        null,
        [
@@ -248283,7 +248283,7 @@
       ]
      ],
      "nth-child-of-complex-selector-many-children.html": [
-      "72f58cd93a0476cec88dad5c4b79cdc36f949437",
+      "ab958c9d8844c485cb78401051840dba688d224e",
       [
        null,
        [
@@ -248296,7 +248296,7 @@
       ]
      ],
      "nth-child-of-complex-selector.html": [
-      "b751d83de2228ccfe6ed25e53d80b34be76732b2",
+      "f06680a57f7260b275b8205d878b9febd6b37fb1",
       [
        null,
        [
@@ -248309,7 +248309,7 @@
       ]
      ],
      "nth-child-of-compound-selector.html": [
-      "5efefe6eadfedfe3b2c670a31a26d1268ddfb8eb",
+      "50bdba0b83ee53ff6b6c8e5e7d6f8b2ea37b333a",
       [
        null,
        [
@@ -248335,7 +248335,7 @@
       ]
      ],
      "nth-child-of-nesting.html": [
-      "851260623d6d402016070b5081994ca6474c00c0",
+      "78c5cde1cc6e359ef45cb7d2f2505944c0e7a5c4",
       [
        null,
        [
@@ -248348,7 +248348,7 @@
       ]
      ],
      "nth-child-of-no-space-after-of.html": [
-      "613593ce668db7a97220d08932dbd2281c2bca4d",
+      "997b07c27dc52c12ec5e279a2f1b19aae09682bd",
       [
        null,
        [
@@ -248387,7 +248387,7 @@
       ]
      ],
      "nth-child-of-tagname.html": [
-      "107e834296f7b457afda9394fdbb7838e3591594",
+      "cc92ad6df99c532d69e788710a756b4533a52cc4",
       [
        null,
        [
@@ -248413,7 +248413,7 @@
       ]
      ],
      "nth-child-specificity-1.html": [
-      "d0b084a719daf95d8a94ad34e6d1c58c557a089f",
+      "64d9eb27c0e34feda152a613dc8d20894ec20a76",
       [
        null,
        [
@@ -248426,7 +248426,7 @@
       ]
      ],
      "nth-child-specificity-2.html": [
-      "a467e5e056a2daceb5f0a814416334e1e1d53f39",
+      "10467e7408ffcd42586982c89fb0b1443295aedc",
       [
        null,
        [
@@ -248439,7 +248439,7 @@
       ]
      ],
      "nth-child-specificity-3.html": [
-      "f9c23b27ca17105380cba780644cf2b933050f2b",
+      "8649f4fc4a058ad452a7cb4abf613a4b044dcde1",
       [
        null,
        [
@@ -248452,7 +248452,7 @@
       ]
      ],
      "nth-child-specificity-4.html": [
-      "6286b01f7ea7f6932eb24431a769add3db075ca2",
+      "de856c28249de80672b577835461d727457dc601",
       [
        null,
        [
@@ -248465,7 +248465,7 @@
       ]
      ],
      "nth-last-child-of-classname.html": [
-      "770fda381f0c5f27806c17cc2caec1b6d939c350",
+      "80770b08a60b006a391331ab6bc46b59170d359a",
       [
        null,
        [
@@ -248478,7 +248478,7 @@
       ]
      ],
      "nth-last-child-of-complex-selector.html": [
-      "0f1262c746f7341c1e59dfdbb9866e753eb03bb4",
+      "ae8fc6ebfad500c13ec77d39b9440980e87b9ca6",
       [
        null,
        [
@@ -248491,7 +248491,7 @@
       ]
      ],
      "nth-last-child-of-compound-selector.html": [
-      "a7aa40f50a28e09a36481a2c565d9c75c66a0341",
+      "df1d58347b73bb277b64fdc221217106147833cf",
       [
        null,
        [
@@ -248504,7 +248504,7 @@
       ]
      ],
      "nth-last-child-of-nesting.html": [
-      "0dd18f2c4b99396bdb34c75551a8aca512d53e99",
+      "e1ce3ce2038f33640c32bf11d7064273bd922e4b",
       [
        null,
        [
@@ -248517,7 +248517,7 @@
       ]
      ],
      "nth-last-child-of-no-space-after-of.html": [
-      "d79d5733a5c3986e0c3560420471a24dba313052",
+      "5ce99119b91c0df63ac1d1360e6bd7684ce9e3ee",
       [
        null,
        [
@@ -248530,7 +248530,7 @@
       ]
      ],
      "nth-last-child-of-style-sharing-1.html": [
-      "de3e26325619a06406fca1db96e1a9fd38987739",
+      "17ea008b2d8da04d709b2bba11041b9fa91a368e",
       [
        null,
        [
@@ -248543,7 +248543,7 @@
       ]
      ],
      "nth-last-child-of-style-sharing-2.html": [
-      "19fc9af414eb5e7745e333af9ab1eb9baeaf724d",
+      "2c586956b4a5afd38608fe4a98828f3797daee1e",
       [
        null,
        [
@@ -248556,7 +248556,7 @@
       ]
      ],
      "nth-last-child-of-tagname.html": [
-      "ddfd6528cc5c51d1e2afaea578473a947da769de",
+      "385d12948c011365717342494cef0f24a49230ff",
       [
        null,
        [
@@ -248569,7 +248569,7 @@
       ]
      ],
      "nth-last-child-specificity-1.html": [
-      "cc4f542fff3ed8397a1c9f605a591f0964d022e1",
+      "18e00f1ca57dbe6be1f1af10650023f8f3e8e020",
       [
        null,
        [
@@ -248582,7 +248582,7 @@
       ]
      ],
      "nth-last-child-specificity-2.html": [
-      "3ddb43b62bd65a53f86ad1e73bd32182196d3bf1",
+      "3c3c8739f37b8190b0f0745b23395223d9a18e37",
       [
        null,
        [
@@ -248595,7 +248595,7 @@
       ]
      ],
      "nth-last-child-specificity-3.html": [
-      "673b4350443b50c1cd0d53683a32ffc722c54678",
+      "93a7007a48bf114a51ff4f05f88d9b2ac7e190d0",
       [
        null,
        [
@@ -248608,7 +248608,7 @@
       ]
      ],
      "nth-last-child-specificity-4.html": [
-      "b690ea2b01714bfb6ee042dcbac728f77005cc4e",
+      "f556b994b06b894e1b9cf68854f5e87b0283630d",
       [
        null,
        [
@@ -272683,11 +272683,11 @@
   "support": {
    ".cache": {
     "gitignore2.json": [
-     "7a4c5864cf625d778c12ec29330e76d6e501665f",
+     "9bfa643620d616c02802e0526a993d3b696d306f",
      []
     ],
     "mtime.json": [
-     "3240bac2772db37e71b159f51107a0e8a514f4a1",
+     "b6e9b103d6db900a54f917ead330b82cd72af5eb",
      []
     ]
    },
@@ -289890,7 +289890,7 @@
       ]
      },
      "inner-border-non-renderable-ref.html": [
-      "e4e3d3455f2086121be013d317bf36bd05d90518",
+      "b88cf1547afef62e5947d432b1528a1815b7d19c",
       []
      ],
      "inset-box-shadow-scroll-ref.html": [
@@ -316546,7 +316546,7 @@
       []
      ],
      "marker-variable-ref.html": [
-      "d966437560d2599544dd500fac76fa03fa10b314",
+      "d2ea847faf6fd14a86c5395ddc2d989804bd2db3",
       []
      ],
      "marker-word-break-ref.html": [
@@ -319410,7 +319410,7 @@
       []
      ],
      "grid-item-image-percentage-min-height-computes-as-0-ref.html": [
-      "296cc59331946d45a56b0813afdc44c060747ed7",
+      "7a8319d65460ea4b16d6ce06b107aa074e83607b",
       []
      ],
      "hori-block-size-small-or-larger-than-container-with-min-or-max-content-1-ref.html": [
@@ -319474,7 +319474,7 @@
       []
      ],
      "nested-flexbox-image-percentage-max-height-computes-as-none-ref.html": [
-      "6a290b23a80155f7989c148a3cca4a68df51012e",
+      "34e2ed01e5221369db8669548ec732099bef43e8",
       []
      ],
      "parsing": {
@@ -327141,6 +327141,10 @@
       "bea389ab47fc6b9eecde572a252149dc294f63e1",
       []
      ],
+     "perspective-zero.html.ini": [
+      "5e1862fe6dd97bede4cadf4783e34177bdcffb62",
+      []
+     ],
      "preserve-3d-flat-grouping-properties-containing-block-inline-ref.html": [
       "7ca006cc5de2b459aa5133af11618f7b6cb8195e",
       []
@@ -330351,7 +330355,7 @@
        []
       ],
       "kind-of-widget-fallback-input-search-text-border-top-style-001.html.ini": [
-       "b8989649989330670d42de6c6dde8435a7c8b401",
+       "94e2ba4fbdd57e43d78800ff983923b915f9d6b9",
        []
       ],
       "kind-of-widget-fallback-input-submit-background-attachment-001.html.ini": [
@@ -337592,7 +337596,7 @@
       []
      ],
      "backdrop-filters-opacity.html.ini": [
-      "07002e42106132c80e38d42a5666411f0147edab",
+      "9b23d738a343d8334c35d9bed08c69578c395907",
       []
      ],
      "backdrop-filters-saturate-ref.html": [
@@ -339221,7 +339225,7 @@
        []
       ],
       "nth-child-containing-ancestor-ref.html": [
-       "4dc7247e41ef83e0640828bdb6887f29c3c8ee98",
+       "6e6680d8c3f63b0539a62c7eb0bb010d48bc4409",
        []
       ],
       "nth-child-in-shadow-root-ref.html": [
@@ -339229,27 +339233,27 @@
        []
       ],
       "nth-child-of-attr-largedom-ref.html": [
-       "6ddc204b83aa8e21d2275352a3aac238bb3baa62",
+       "07617c53ad183adbd4d3f6633b3178d16f820536",
        []
       ],
       "nth-child-of-attr-ref.html": [
-       "41205174eb0ad5bfca3189f6e03912530c990f9e",
+       "5207cc987d10203bbc7ef282e519462abf0a15fc",
        []
       ],
       "nth-child-of-class-ref.html": [
-       "7a8247c469ea86fd4e8ea32a961d4e1b0741c986",
+       "d4e2dfb71d9847329e84388377f201c17bbc63b5",
        []
       ],
       "nth-child-of-has-ref.html": [
-       "ab3931d6ef46532ca1aa4e5d25683e9d5e12ed8e",
+       "39f0501b826126898a0552c538feed305d3f7b54",
        []
       ],
       "nth-child-of-in-ancestor-ref.html": [
-       "a4e4b7fd9fc44bd189aba0423d536dcb82201a9f",
+       "bc7ecb9ff7c1f7b16f13f2e062b378de24ff613a",
        []
       ],
       "nth-child-of-in-shadow-root-ref.html": [
-       "f28d358cdc53d71501fd35c0c6dc2db41e042b2b",
+       "060c07decac51542a483c4c8206070fd1cbf4933",
        []
       ],
       "nth-child-of-pseudo-class-ref.html": [
@@ -339257,15 +339261,15 @@
        []
       ],
       "nth-child-of-sibling-ref.html": [
-       "0388fc7c5ab112271e3b2d54293765c8ad87eff0",
+       "ed7fefc59fe20e9453f64d47b1e14de7a613f944",
        []
       ],
       "nth-child-when-ancestor-changes-ref.html": [
-       "8b7d32906d9c2766bc2c6d60451b84246e355d5c",
+       "7e3f7f0c98ae3b05dbab44da655b2533d6b16868",
        []
       ],
       "nth-child-when-sibling-changes-ref.html": [
-       "9a397529900cbb8e6248d94dccd1e52670f83ec5",
+       "f30a853cae7e4fe735099422fd192e6a930d12c1",
        []
       ],
       "nth-last-child-in-shadow-root-ref.html": [
@@ -380489,7 +380493,7 @@
      []
     ],
     "modulepreload-as.html.ini": [
-     "2825c72b987dff72f3b8bb673c7ed3cb2e695486",
+     "fc248ee27bd3a94dd5ea1fdcc2de64dcd162a5e8",
      []
     ],
     "modulepreload-expected.txt": [
@@ -393815,7 +393819,7 @@
        []
       ],
       "property-list.js": [
-       "d8896e77f0f2d700f5963888e990590a149c7ea6",
+       "24ad547bb59f040eac6a011b22d1c0c4e0ca974c",
        []
       ],
       "property-types.js": [
@@ -428001,6 +428005,105 @@
       }
      ]
     ],
+    "compression-large-flush-output.any.js": [
+     "c7455807fb2b2acc6d74d2ebf9540a81cf09647c",
+     [
+      "compression/compression-large-flush-output.any.html",
+      {
+       "script_metadata": [
+        [
+         "global",
+         "window,worker"
+        ],
+        [
+         "script",
+         "third_party/pako/pako_inflate.min.js"
+        ],
+        [
+         "script",
+         "resources/concatenate-stream.js"
+        ],
+        [
+         "timeout",
+         "long"
+        ]
+       ],
+       "timeout": "long"
+      }
+     ],
+     [
+      "compression/compression-large-flush-output.any.serviceworker.html",
+      {
+       "script_metadata": [
+        [
+         "global",
+         "window,worker"
+        ],
+        [
+         "script",
+         "third_party/pako/pako_inflate.min.js"
+        ],
+        [
+         "script",
+         "resources/concatenate-stream.js"
+        ],
+        [
+         "timeout",
+         "long"
+        ]
+       ],
+       "timeout": "long"
+      }
+     ],
+     [
+      "compression/compression-large-flush-output.any.sharedworker.html",
+      {
+       "script_metadata": [
+        [
+         "global",
+         "window,worker"
+        ],
+        [
+         "script",
+         "third_party/pako/pako_inflate.min.js"
+        ],
+        [
+         "script",
+         "resources/concatenate-stream.js"
+        ],
+        [
+         "timeout",
+         "long"
+        ]
+       ],
+       "timeout": "long"
+      }
+     ],
+     [
+      "compression/compression-large-flush-output.any.worker.html",
+      {
+       "script_metadata": [
+        [
+         "global",
+         "window,worker"
+        ],
+        [
+         "script",
+         "third_party/pako/pako_inflate.min.js"
+        ],
+        [
+         "script",
+         "resources/concatenate-stream.js"
+        ],
+        [
+         "timeout",
+         "long"
+        ]
+       ],
+       "timeout": "long"
+      }
+     ]
+    ],
     "compression-multiple-chunks.tentative.any.js": [
      "f43f13b5411033e53884017d7de70608017be854",
      [
@@ -439104,7 +439207,7 @@
        ]
       ],
       "justify-no-interpolation.html": [
-       "a242fb73e901d2a2bc933b9cf0b6a57afef70090",
+       "b72ccdc435513d93750d3c690ecb4ba2e9a6cf8b",
        [
         null,
         {}
@@ -439980,7 +440083,7 @@
       ]
      ],
      "anchor-getComputedStyle.html": [
-      "cce571c4d0d395073449981dceb1aaffe071c3ea",
+      "6d77cf9a9d4cc34f5b2c787502f0d7753ff41c94",
       [
        null,
        {}
@@ -440308,6 +440411,13 @@
        {}
       ]
      ],
+     "anchor-scroll-003.html": [
+      "87d8153e7e37d845196dc0c3b6d58e92abf95a56",
+      [
+       null,
+       {}
+      ]
+     ],
      "anchor-scroll-basics.html": [
       "6b2d96708bd44808f0cb7ce10a1b52e708e09eba",
       [
@@ -440442,21 +440552,21 @@
       ]
      ],
      "anchor-transition-001.html": [
-      "b5849510e838b47fd5ddcf30489842e755225d5b",
+      "e69a38820518289b769864fd6c85b30c0df3ce12",
       [
        null,
        {}
       ]
      ],
      "anchor-transition-002.html": [
-      "b6a1ff4511ac9ddfb20a531086137741b137b36b",
+      "b0fddc4943a8665ead1ea5844774b77735e27486",
       [
        null,
        {}
       ]
      ],
      "anchor-transition-003.html": [
-      "e7441275141176078e14fc16aadf134bf9b65a37",
+      "e7624575da56a47983f1a3aa17de3fb89a0e057f",
       [
        null,
        {}
@@ -440740,14 +440850,14 @@
       ]
      ],
      "animation-composition-keyframes.html": [
-      "86a27a2b526a1ff28a77927177b2eb648c7d8d56",
+      "7051186f8b265452e5a74d4ca4cbc9b8c4d88d52",
       [
        null,
        {}
       ]
      ],
      "animation-composition.html": [
-      "48e757c59818d317762c3ed4d9308fc5c0707785",
+      "c46d55a877eb22f580e329d65a08294e6772138f",
       [
        null,
        {}
@@ -442220,21 +442330,21 @@
      "margin-trim": {
       "computed-margin-values": {
        "block-container-block-end-nested-child.html": [
-        "2d36e75c2637d96428fbce5df86a8351f3d63a34",
+        "8a3b03c2e502c1f92ba43ac49ae0f4a304f60538",
         [
          null,
          {}
         ]
        ],
        "block-container-block-end-with-self-collapsing-children.html": [
-        "d03c2fe1422d55345839fb513b2c57c8d000533f",
+        "26d46628effdf6bcfcef7191a2f01d6623940606",
         [
          null,
          {}
         ]
        ],
        "block-container-block-end.html": [
-        "dcf8ba6fe2ef54dde882709b0304b371ad872cc1",
+        "6cd0cce2634d5d966d2f73277ad967afc2c6840a",
         [
          null,
          {}
@@ -442402,35 +442512,35 @@
         ]
        ],
        "grid-block-end-column-auto-flow.html": [
-        "c491301c8a6eaf987f60192d43c85ad85e7f296e",
+        "f49f036a639b993b539e7e598d6d4aadc401c399",
         [
          null,
          {}
         ]
        ],
        "grid-block-end-item-spans-multiple-rows.html": [
-        "4ae597760b3228673e84912574ba830227d5ed9c",
+        "d44085ed8a47bf70af5f81c3be7b16618fdca473",
         [
          null,
          {}
         ]
        ],
        "grid-block-end.html": [
-        "a0143364aab48c43c2cb8d9138b8976cf604f9d0",
+        "a7d5f44f377d18ecd7b18084daf09ad60f2ce098",
         [
          null,
          {}
         ]
        ],
        "grid-inline-start-item-negative-span.html": [
-        "4dc553e15b2c679fdf7de9d3144d1d2b34149733",
+        "80b97e9cd0d10526c713e58887733e51bad62ffb",
         [
          null,
          {}
         ]
        ],
        "grid-inline-start.html": [
-        "7d4157acfed5d1592b0bb80d29dd42eeb46187ea",
+        "380090f3a9f0de6f491229b6d52814021dd1da5e",
         [
          null,
          {}
@@ -443710,14 +443820,14 @@
     "css-color-adjust": {
      "animation": {
       "color-scheme-no-interpolation.html": [
-       "306b4b3da1241b724573bb7d968c664598534210",
+       "c2f7f91b68a9a2bda6d6fbd3b583bb19bb9120c1",
        [
         null,
         {}
        ]
       ],
       "forced-color-adjust-no-interpolation.html": [
-       "bcd2bdf223a98cb9635af1fa2059bb35594b7f5e",
+       "3e1fcc22b977f54e0895b28257da6721003aadfd",
        [
         null,
         {}
@@ -450860,7 +450970,7 @@
      },
      "animation": {
       "grid-no-interpolation.html": [
-       "1293cdb9d5d6807f8483dd4cdc723b0d93088d74",
+       "33806b85860241b7a6f26519c9d4d67ed8e346e8",
        [
         null,
         {}
@@ -452346,7 +452456,7 @@
     "css-images": {
      "animation": {
       "image-no-interpolation.html": [
-       "1f9faf7fbb512e76f5c938b8ea927f44e8b053db",
+       "1f7f68ade2646ca746739e23412f5d8a3c127fd8",
        [
         null,
         {}
@@ -452582,21 +452692,21 @@
     "css-inline": {
      "animation": {
       "alignment-baseline-no-interpolation.html": [
-       "8cbe0c98d814bdf86a6004ea82fdd6e1cbcd4120",
+       "8cacf54ff996022e2e26930016fd74924656f63b",
        [
         null,
         {}
        ]
       ],
       "dominant-baseline-no-interpolation.html": [
-       "7f6be5aac2bf47a1f66047ef91e5a6a4e0929fa7",
+       "19266dc168db52d509db017a44e9c125581c2c98",
        [
         null,
         {}
        ]
       ],
       "initial-letter-no-interpolation.html": [
-       "1efc4123ca2e983d1b9bf4ed1a2c251ea05989e8",
+       "2d57ce2aa4438255f8491eb3a08d7733c3b59761",
        [
         null,
         {}
@@ -452691,21 +452801,21 @@
      ],
      "initial-letter": {
       "initial-letter-computed.html": [
-       "e46306259a7088c3637597907a4b9f6d76933717",
+       "eae4aad9fb98fa69fec234233bdeb17a811f63f2",
        [
         null,
         {}
        ]
       ],
       "initial-letter-invalid.html": [
-       "574a347bda88b5bf6084bbd6485131ff1a3e8ae4",
+       "645372c0a95faa8616291013c1b5ed5e18f2555c",
        [
         null,
         {}
        ]
       ],
       "initial-letter-valid.html": [
-       "3c1e32811d80927b0e4017bfec3f98ef55f22fee",
+       "b02c564504f4fcbea363c6780b27b0be2353ac68",
        [
         null,
         {}
@@ -456517,7 +456627,7 @@
       ]
      ],
      "marker-variable-computed-style.html": [
-      "c50ee33ae91863704eeab8d5c7ac89d804ed7d25",
+      "c706edc02fc9253b2a26fdd537e7544c311d509c",
       [
        null,
        {}
@@ -459080,7 +459190,7 @@
        ]
       ],
       "height-no-interpolation.html": [
-       "902fe2e22f876db4ae989033cf9a467fc239a335",
+       "5738ae0301122b0a10347e47ef5ce0d08ff367d8",
        [
         null,
         {}
@@ -459382,7 +459492,7 @@
        ]
       ],
       "contain-intrinsic-size-033.html": [
-       "68192a837909bbdab267ab860630d69cfb3a7ba6",
+       "f98a48a0a973f942a24341713ab6f89b678ca616",
        [
         null,
         {}
@@ -460841,7 +460951,7 @@
     "css-text": {
      "animations": {
       "hyphen-no-interpolation.html": [
-       "e1e89d1772382aed394fb0217397546764a31d70",
+       "95a3ff5ee5639061a73b54822b098e5d323687e4",
        [
         null,
         {}
@@ -460862,7 +460972,7 @@
        ]
       ],
       "line-break-no-interpolation.html": [
-       "937b2483662f008cce6ab51fe131d6fc5f922d52",
+       "b6fc5f932ec0b1c1324315d66005714ac756a117",
        [
         null,
         {}
@@ -462390,21 +462500,21 @@
        ]
       ],
       "hyphenate-limit-chars-computed.html": [
-       "cf18f25ba74800327dd590cd6192552936aee06d",
+       "bc265c8e81ea82dba6725bc5f8d4ec44963cb394",
        [
         null,
         {}
        ]
       ],
       "hyphenate-limit-chars-invalid.html": [
-       "5a797fa8181d1ca16280067b6ed7031b2796d881",
+       "db68f403c111211c387cb4a98e0d56357d1f4f7d",
        [
         null,
         {}
        ]
       ],
       "hyphenate-limit-chars-valid.html": [
-       "699ddd4ab0724095b5ab7ac80aeaba906051b84d",
+       "2f10e33f1dec9994ed7489decd98bb3cce62248e",
        [
         null,
         {}
@@ -462705,14 +462815,14 @@
        ]
       ],
       "white-space-shorthand-text-wrap.html": [
-       "0600b8249e5c17e3feee30eebe854043c60ccb49",
+       "de6d9f5145d558397bea8e37caeb5a9b897723eb",
        [
         null,
         {}
        ]
       ],
       "white-space-shorthand.html": [
-       "518f81fdbf268d20e78b9f226391ecc9be46b69d",
+       "a7788f74ae30f930de4865aaa07d0806973394c4",
        [
         null,
         {}
@@ -463030,7 +463140,7 @@
        ]
       ],
       "text-wrap-balance-001.html": [
-       "3360681d0fc771e30730479fdf3262f4565dcd32",
+       "4e1829f49997aac964e3bc62ff5b514ae0882e86",
        [
         null,
         {}
@@ -467882,7 +467992,7 @@
       ]
      ],
      "user-select-inheritance.html": [
-      "38a57e0285698475fefe208cc8a71ca7d04226f3",
+      "28bf2abc3b2c04c88c39d1296c75fc8210adbc65",
       [
        null,
        {}
@@ -470755,7 +470865,7 @@
       ]
      ],
      "xml-stylesheet-pi-in-doctype.xhtml": [
-      "d25ca1765617f1457b90d31451925adc9817a084",
+      "59911eb52c2d6f646e985e7680fa08c0b937b0b3",
       [
        null,
        {}
@@ -473843,7 +473953,7 @@
        ]
       ],
       "media-loading-pseudo-classes-in-has.html": [
-       "62b18c1e0efbee8d87919e7abc91237dc7cda939",
+       "07ab6083e092220b5aadad3d9e852dce071dbf59",
        [
         null,
         {
@@ -473852,7 +473962,7 @@
        ]
       ],
       "media-pseudo-classes-in-has.html": [
-       "f0df71534aef8b63743d1874c59980f82031900c",
+       "881ba8f30ee822250e89aff4944b9ca161e52957",
        [
         null,
         {}
@@ -474033,7 +474143,7 @@
      ],
      "media": {
       "media-loading-state.html": [
-       "b48cfc13fb7a3c2cedcaa6de250c04a4bec5f790",
+       "6bead20a98aefb5453e6ad5c3687c0463772b65a",
        [
         null,
         {
@@ -474042,14 +474152,14 @@
        ]
       ],
       "media-playback-state.html": [
-       "628daa25214231570affc02f47f5f0d2078a50fd",
+       "c034dbbdc08bda87832c36c57b0db4cd6cfc0c73",
        [
         null,
         {}
        ]
       ],
       "sound-state.html": [
-       "d9eb86a5ebe3935359040b6478046a2dd4ffee0b",
+       "527bb30b97c63cccc2a907bab71bb9c06ffc1f78",
        [
         null,
         {}
@@ -474087,7 +474197,7 @@
       ]
      ],
      "nth-of-type-namespace.html": [
-      "aa67afd00a4347a0d651a6fc93573d0b4553478b",
+      "f5d81a5df3ac1380749a075cb5588897d6816c58",
       [
        null,
        {}
@@ -548557,7 +548667,7 @@
         ]
        ],
        "video-intrinsic-width-height.html": [
-        "ad5b69db21ef30fd7444eccd3d82f9bdae67221c",
+        "74989be5213d31dd6eef9c913163d370ffe722f4",
         [
          null,
          {}
@@ -602744,7 +602854,7 @@
       ]
      ],
      "animation-timeline-view-functional-notation.tentative.html": [
-      "42f4e7a3ca19e93b4d9eabc7cabecb8d02508435",
+      "3ac94478e5955b09d2625c5cc8785514d8cee76f",
       [
        null,
        {}
@@ -602961,7 +603071,7 @@
       ]
      ],
      "timeline-range-name-offset-in-keyframes.tentative.html": [
-      "4ab2e9cb802f4b5a65fec6afc880c34f7d9da95c",
+      "6fab0025dac324bf5f0af79e37af8e832d4d36b6",
       [
        null,
        {}
diff --git a/third_party/blink/web_tests/external/wpt/compression/compression-large-flush-output.any.js b/third_party/blink/web_tests/external/wpt/compression/compression-large-flush-output.any.js
new file mode 100644
index 0000000..c745580
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/compression/compression-large-flush-output.any.js
@@ -0,0 +1,41 @@
+// META: global=window,worker
+// META: script=third_party/pako/pako_inflate.min.js
+// META: script=resources/concatenate-stream.js
+// META: timeout=long
+
+'use strict';
+
+// This test verifies that a large flush output will not truncate the
+// final results.
+
+async function compressData(chunk, format) {
+  const cs = new CompressionStream(format);
+  const writer = cs.writable.getWriter();
+  writer.write(chunk);
+  writer.close();
+  return await concatenateStream(cs.readable);
+}
+
+// JSON-encoded array of 10 thousands numbers ("[0,1,2,...]"). This produces 48_891 bytes of data.
+const fullData = new TextEncoder().encode(JSON.stringify(Array.from({ length: 10_000 }, (_, i) => i)));
+const data = fullData.subarray(0, 35_579);
+const expectedValue = data;
+
+promise_test(async t => {
+  const compressedData = await compressData(data, 'deflate');
+  // decompress with pako, and check that we got the same result as our original string
+  assert_array_equals(expectedValue, pako.inflate(compressedData), 'value should match');
+}, `deflate compression with large flush output`);
+
+promise_test(async t => {
+  const compressedData = await compressData(data, 'gzip');
+  // decompress with pako, and check that we got the same result as our original string
+  assert_array_equals(expectedValue, pako.inflate(compressedData), 'value should match');
+}, `gzip compression with large flush output`);
+
+promise_test(async t => {
+  const compressedData = await compressData(data, 'deflate-raw');
+  // decompress with pako, and check that we got the same result as our original string
+  assert_array_equals(expectedValue, pako.inflateRaw(compressedData), 'value should match');
+}, `deflate-raw compression with large flush output`);
+
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/floats/float-root.html b/third_party/blink/web_tests/external/wpt/css/CSS2/floats/float-root.html
index ee7f70e..944ae7a 100644
--- a/third_party/blink/web_tests/external/wpt/css/CSS2/floats/float-root.html
+++ b/third_party/blink/web_tests/external/wpt/css/CSS2/floats/float-root.html
@@ -1,5 +1,5 @@
 <!DOCTYPe html>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css2/#propdef-float">
+<link rel="help" href="https://drafts.csswg.org/css2/#propdef-float">
 <link rel="match" href="float-root-ref.html">
 
 <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-align/animation/justify-no-interpolation.html b/third_party/blink/web_tests/external/wpt/css/css-align/animation/justify-no-interpolation.html
index a242fb7..b72ccdc 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-align/animation/justify-no-interpolation.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-align/animation/justify-no-interpolation.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <link rel=author href="mailto:jarhar@chromium.org">
-<link rel=help href="https://w3c.github.io/csswg-drafts/css-align/#justify-items-property">
-<link rel=help href="https://w3c.github.io/csswg-drafts/css-align/#justify-self-property">
+<link rel=help href="https://drafts.csswg.org/css-align/#justify-items-property">
+<link rel=help href="https://drafts.csswg.org/css-align/#justify-self-property">
 <link rel=help href="https://github.com/w3c/csswg-drafts/issues/4441">
 <link rel=help href="https://drafts.csswg.org/css-transitions-2/#transition-property-property">
 <script src="/resources/testharness.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-anchor-position/anchor-getComputedStyle.html b/third_party/blink/web_tests/external/wpt/css/css-anchor-position/anchor-getComputedStyle.html
index cce571c..6d77cf9a9 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-anchor-position/anchor-getComputedStyle.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-anchor-position/anchor-getComputedStyle.html
@@ -2,7 +2,7 @@
 <meta charset="utf-8">
 <title>Tests that getComputedStyle() resolves anchor functions</title>
 <link rel="help" href="https://drafts4.csswg.org/css-anchor-position-1">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/cssom/#resolved-value">
+<link rel="help" href="https://drafts.csswg.org/cssom/#resolved-value">
 <link rel="author" href="mailto:xiaochengh@chromium.org">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-anchor-position/anchor-transition-001.html b/third_party/blink/web_tests/external/wpt/css/css-anchor-position/anchor-transition-001.html
index b584951..e69a3882 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-anchor-position/anchor-transition-001.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-anchor-position/anchor-transition-001.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <title>Tests CSS transition of anchor() and anchor-size() functions</title>
-<link rel="help" href="https://drafts4.csswg.org/css-anchor-1/">
+<link rel="help" href="https://drafts4.csswg.org/css-anchor-position-1/">
 <link rel="help" href="https://github.com/w3c/csswg-drafts/issues/8180"></script>
 <link rel="author" href="mailto:xiaochengh@chromium.org">
 <script src="/resources/testharness.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-anchor-position/anchor-transition-002.html b/third_party/blink/web_tests/external/wpt/css/css-anchor-position/anchor-transition-002.html
index b6a1ff45..b0fddc4 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-anchor-position/anchor-transition-002.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-anchor-position/anchor-transition-002.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <title>Tests CSS transition of anchor() across tree scopes</title>
-<link rel="help" href="https://drafts4.csswg.org/css-anchor-1/">
+<link rel="help" href="https://drafts4.csswg.org/css-anchor-position-1/">
 <link rel="help" href="https://github.com/w3c/csswg-drafts/issues/8180"></script>
 <link rel="author" href="mailto:xiaochengh@chromium.org">
 <script src="/resources/testharness.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-anchor-position/anchor-transition-003.html b/third_party/blink/web_tests/external/wpt/css/css-anchor-position/anchor-transition-003.html
index e7441275..e762457 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-anchor-position/anchor-transition-003.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-anchor-position/anchor-transition-003.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <title>Tests CSS transition of anchor() across three tree scopes</title>
-<link rel="help" href="https://drafts4.csswg.org/css-anchor-1/">
+<link rel="help" href="https://drafts4.csswg.org/css-anchor-position-1/">
 <link rel="help" href="https://github.com/w3c/csswg-drafts/issues/8180"></script>
 <link rel="author" href="mailto:xiaochengh@chromium.org">
 <script src="/resources/testharness.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-animations/animation-composition-keyframes.html b/third_party/blink/web_tests/external/wpt/css/css-animations/animation-composition-keyframes.html
index 86a27a2b..7051186f 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-animations/animation-composition-keyframes.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-animations/animation-composition-keyframes.html
@@ -1,7 +1,7 @@
 <!doctype html>
 <meta charset=utf-8>
 <title>animation-composition test in keyframes</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-animations-2/#animation-composition">
+<link rel="help" href="https://drafts.csswg.org/css-animations-2/#animation-composition">
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
 <script src="support/testcommon.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-animations/animation-composition.html b/third_party/blink/web_tests/external/wpt/css/css-animations/animation-composition.html
index 48e757c..c46d55a8 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-animations/animation-composition.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-animations/animation-composition.html
@@ -1,7 +1,7 @@
 <!doctype html>
 <meta charset=utf-8>
 <title>animation-composition test</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-animations-2/#animation-composition">
+<link rel="help" href="https://drafts.csswg.org/css-animations-2/#animation-composition">
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
 <script src="support/testcommon.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/inner-border-non-renderable-ref.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/inner-border-non-renderable-ref.html
index e4e3d34..b88cf15 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/inner-border-non-renderable-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/inner-border-non-renderable-ref.html
@@ -2,7 +2,7 @@
 <html>
 <head>
     <title>Testing that child-background doesn't bleed through its parent border for a inner-border-radius that is larger than the content rect</title>
-    <link rel="help" href="https://w3c.github.io/csswg-drafts/css-backgrounds/#border-radius">
+    <link rel="help" href="https://drafts.csswg.org/css-backgrounds/#border-radius">
     <link rel="assert" content="Testing that child-background doesn't bleed through its parent border for a inner-border-radius that is larger than the content rect">
     <style>
         body {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/inner-border-non-renderable.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/inner-border-non-renderable.html
index 46fbcc6..7c3cff79 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/inner-border-non-renderable.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/inner-border-non-renderable.html
@@ -3,7 +3,7 @@
 <head>
     <title>Testing that child-background doesn't bleed through its parent border for a inner-border-radius that is larger than the content rect</title>
     <link rel="match" href="inner-border-non-renderable-ref.html">
-    <link rel="help" href="https://w3c.github.io/csswg-drafts/css-backgrounds/#border-radius">
+    <link rel="help" href="https://drafts.csswg.org/css-backgrounds/#border-radius">
     <link rel="assert" content="Testing that child-background doesn't bleed through its parent border for a inner-border-radius that is larger than the content rect">
     <style>
         body {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/block-container-block-end-nested-child.html b/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/block-container-block-end-nested-child.html
index 2d36e75c..8a3b03c2 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/block-container-block-end-nested-child.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/block-container-block-end-nested-child.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <link rel="author" href="mailto:sammy.gill@apple.com">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-box-4/#margin-trim-block">
+<link rel="help" href="https://drafts.csswg.org/css-box-4/#margin-trim-block">
 <meta name="assert" content="Items, including self-collapsing ones, at the block-end of the container should have their margins trimmed">
 <style>
 container {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/block-container-block-end-with-self-collapsing-children.html b/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/block-container-block-end-with-self-collapsing-children.html
index d03c2fe1..26d4662 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/block-container-block-end-with-self-collapsing-children.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/block-container-block-end-with-self-collapsing-children.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <link rel="author" href="mailto:sammy.gill@apple.com">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-box-4/#margin-trim-block">
+<link rel="help" href="https://drafts.csswg.org/css-box-4/#margin-trim-block">
 <meta name="assert" content="Second item and all self-collapsing children at block-end should have margins trimmed">
 <style>
 container {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/block-container-block-end.html b/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/block-container-block-end.html
index dcf8ba6..6cd0cce 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/block-container-block-end.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/block-container-block-end.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <link rel="author" href="mailto:sammy.gill@apple.com">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-box-4/#margin-trim-block">
+<link rel="help" href="https://drafts.csswg.org/css-box-4/#margin-trim-block">
 <meta name="assert" content="block-end margin of item should be trimmed">
 <style>
 container {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/grid-block-end-column-auto-flow.html b/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/grid-block-end-column-auto-flow.html
index c491301..f49f036a 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/grid-block-end-column-auto-flow.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/grid-block-end-column-auto-flow.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <link rel="author" href="mailto:sammy.gill@apple.com">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-box-4/#margin-trim-grid">
+<link rel="help" href="https://drafts.csswg.org/css-box-4/#margin-trim-grid">
 <meta name="assert" content="Trimmed block-end margins for grid items should be reflected in computed style">
 </head>
 <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/grid-block-end-item-spans-multiple-rows.html b/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/grid-block-end-item-spans-multiple-rows.html
index 4ae5977..d44085ed 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/grid-block-end-item-spans-multiple-rows.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/grid-block-end-item-spans-multiple-rows.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <link rel="author" href="mailto:sammy.gill@apple.com">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-box-4/#margin-trim-grid">
+<link rel="help" href="https://drafts.csswg.org/css-box-4/#margin-trim-grid">
 <meta name="assert" content="item that spans into last row should have block-end margin trimmed">
 </head>
 <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/grid-block-end.html b/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/grid-block-end.html
index a0143364a..a7d5f44f 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/grid-block-end.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/grid-block-end.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <link rel="author" href="mailto:sammy.gill@apple.com">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-box-4/#margin-trim-grid">
+<link rel="help" href="https://drafts.csswg.org/css-box-4/#margin-trim-grid">
 <meta name="assert" content="Trimmed block-end margins for grid items should be reflected in computed style">
 </head>
 <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/grid-inline-start-item-negative-span.html b/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/grid-inline-start-item-negative-span.html
index 4dc553e..80b97e9c 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/grid-inline-start-item-negative-span.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/grid-inline-start-item-negative-span.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <link rel="author" href="mailto:sammy.gill@apple.com">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-box-4/#margin-trim-grid">
+<link rel="help" href="https://drafts.csswg.org/css-box-4/#margin-trim-grid">
 <meta name="assert" content="trimmed inline-start margins in grid should be reflected in computed style">
 </head>
 <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/grid-inline-start.html b/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/grid-inline-start.html
index 7d4157a..380090f3a 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/grid-inline-start.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-box/margin-trim/computed-margin-values/grid-inline-start.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <link rel="author" href="mailto:sammy.gill@apple.com">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-box-4/#margin-trim-grid">
+<link rel="help" href="https://drafts.csswg.org/css-box-4/#margin-trim-grid">
 <meta name="assert" content="trimmed inline-start margins in grid should be reflected in computed style">
 </head>
 <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color-adjust/animation/color-scheme-no-interpolation.html b/third_party/blink/web_tests/external/wpt/css/css-color-adjust/animation/color-scheme-no-interpolation.html
index 306b4b3..c2f7f91 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-color-adjust/animation/color-scheme-no-interpolation.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-color-adjust/animation/color-scheme-no-interpolation.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <link rel=author href="mailto:jarhar@chromium.org">
 <link rel=help href="https://github.com/w3c/csswg-drafts/issues/4441">
-<link rel=help href="https://w3c.github.io/csswg-drafts/css-color-adjust/#color-scheme-prop">
+<link rel=help href="https://drafts.csswg.org/css-color-adjust/#color-scheme-prop">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/css/support/interpolation-testcommon.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color-adjust/animation/forced-color-adjust-no-interpolation.html b/third_party/blink/web_tests/external/wpt/css/css-color-adjust/animation/forced-color-adjust-no-interpolation.html
index bcd2bdf2..3e1fcc22 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-color-adjust/animation/forced-color-adjust-no-interpolation.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-color-adjust/animation/forced-color-adjust-no-interpolation.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <link rel=author href="mailto:jarhar@chromium.org">
 <link rel=help href="https://github.com/w3c/csswg-drafts/issues/4441">
-<link rel=help href="https://w3c.github.io/csswg-drafts/css-color-adjust/#forced-color-adjust-prop">
+<link rel=help href="https://drafts.csswg.org/css-color-adjust/#forced-color-adjust-prop">
 <link rel=help href="https://drafts.csswg.org/css-transitions-2/#transition-property-property">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/lab-l-over-100-1.html b/third_party/blink/web_tests/external/wpt/css/css-color/lab-l-over-100-1.html
index fdb3955..7d6e038 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-color/lab-l-over-100-1.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-color/lab-l-over-100-1.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <meta charset="utf-8">
 <title>CSS Color 4: Verify lightness in Lab is always clamped to a value between 0 to 100</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-color/#ok-lab">
+<link rel="help" href="https://drafts.csswg.org/css-color/#ok-lab">
 <link rel="match" href="lab-l-over-100-ref.html">
 <meta name="assert" content="lab() with lightness greater than 100">
 <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/lab-l-over-100-2.html b/third_party/blink/web_tests/external/wpt/css/css-color/lab-l-over-100-2.html
index f62f9e0..6674c41a 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-color/lab-l-over-100-2.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-color/lab-l-over-100-2.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <meta charset="utf-8">
 <title>CSS Color 4: Verify lightness in Lab is always clamped to a value between 0% to 100%</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-color/#ok-lab">
+<link rel="help" href="https://drafts.csswg.org/css-color/#ok-lab">
 <link rel="match" href="lab-l-over-100-ref.html">
 <meta name="assert" content="lab() with lightness greater than 100%">
 <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/lch-l-over-100-1.html b/third_party/blink/web_tests/external/wpt/css/css-color/lch-l-over-100-1.html
index 9711956..6e0c623 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-color/lch-l-over-100-1.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-color/lch-l-over-100-1.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <meta charset="utf-8">
 <title>CSS Color 4: Verify lightness in LCH is always clamped to a value between 0 to 100</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-color/#cie-lab">
+<link rel="help" href="https://drafts.csswg.org/css-color/#cie-lab">
 <link rel="match" href="lch-l-over-100-ref.html">
 <meta name="assert" content="lch() with lightness greater than 100">
 <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/lch-l-over-100-2.html b/third_party/blink/web_tests/external/wpt/css/css-color/lch-l-over-100-2.html
index a909a49f..7752d0d 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-color/lch-l-over-100-2.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-color/lch-l-over-100-2.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <meta charset="utf-8">
 <title>CSS Color 4: Verify lightness in LCH is always clamped to a value between 0% to 100%</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-color/#cie-lab">
+<link rel="help" href="https://drafts.csswg.org/css-color/#cie-lab">
 <link rel="match" href="lch-l-over-100-ref.html">
 <meta name="assert" content="lch() with lightness graeter than 100%">
 <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/variations/slnt-backslant-variable.html b/third_party/blink/web_tests/external/wpt/css/css-fonts/variations/slnt-backslant-variable.html
index 4bbe2b15..36a4305 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-fonts/variations/slnt-backslant-variable.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/variations/slnt-backslant-variable.html
@@ -3,7 +3,7 @@
 <meta charset="utf-8" />
 <title>CSS Test: Variable fonts with slant axis</title>
 <link rel="help" href="https://www.w3.org/TR/css-fonts-4/#descdef-font-face-font-variation-settings" />
-<link rel="help" href="http://w3c.github.io/csswg-drafts/css-fonts-4/#valdef-font-style-oblique-angle-90deg-90deg" />
+<link rel="help" href="http://drafts.csswg.org/css-fonts-4/#valdef-font-style-oblique-angle-90deg-90deg" />
 <link rel="match" href="slnt-backslant-variable-ref.html">
 <meta name="assert"
   content="For variable fonts, setting font-style to oblique or italic should apply forward and backward slant to variable axis.">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/variations/slnt-variable.html b/third_party/blink/web_tests/external/wpt/css/css-fonts/variations/slnt-variable.html
index d81df09..ae93703 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-fonts/variations/slnt-variable.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/variations/slnt-variable.html
@@ -3,7 +3,7 @@
 <meta charset="utf-8" />
 <title>CSS Test: Variable fonts with slant axis</title>
 <link rel="help" href="https://www.w3.org/TR/css-fonts-4/#descdef-font-face-font-variation-settings" />
-<link rel="help" href="http://w3c.github.io/csswg-drafts/css-fonts-4/#valdef-font-style-oblique-angle-90deg-90deg" />
+<link rel="help" href="http://drafts.csswg.org/css-fonts-4/#valdef-font-style-oblique-angle-90deg-90deg" />
 <link rel="match" href="slnt-variable-ref.html">
 <meta name="assert"
   content="For variable fonts, 'oblique' and 'italic' keywords should work equivalent to 14 degrees of slant">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/animation/grid-no-interpolation.html b/third_party/blink/web_tests/external/wpt/css/css-grid/animation/grid-no-interpolation.html
index 1293cdb..33806b85 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/animation/grid-no-interpolation.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/animation/grid-no-interpolation.html
@@ -2,10 +2,10 @@
 <link rel=author href="mailto:jarhar@chromium.org">
 <link rel=help href="https://github.com/w3c/csswg-drafts/issues/4441">
 <link rel=help href="https://drafts.csswg.org/css-transitions-2/#transition-property-property">
-<link rel=help href="https://w3c.github.io/csswg-drafts/css-grid/#auto-tracks">
-<link rel=help href="https://w3c.github.io/csswg-drafts/css-grid/#grid-auto-flow-property">
-<link rel=help href="https://w3c.github.io/csswg-drafts/css-grid/#line-placement">
-<link rel=help href="https://w3c.github.io/csswg-drafts/css-grid/#propdef-grid-template-areas">
+<link rel=help href="https://drafts.csswg.org/css-grid/#auto-tracks">
+<link rel=help href="https://drafts.csswg.org/css-grid/#grid-auto-flow-property">
+<link rel=help href="https://drafts.csswg.org/css-grid/#line-placement">
+<link rel=help href="https://drafts.csswg.org/css-grid/#propdef-grid-template-areas">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/css/support/interpolation-testcommon.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/animation/image-no-interpolation.html b/third_party/blink/web_tests/external/wpt/css/css-images/animation/image-no-interpolation.html
index 1f9faf7..1f7f68ade 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-images/animation/image-no-interpolation.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-images/animation/image-no-interpolation.html
@@ -2,8 +2,8 @@
 <link rel=author href="mailto:jarhar@chromium.org">
 <link rel=help href="https://github.com/w3c/csswg-drafts/issues/4441">
 <link rel=help href="https://drafts.csswg.org/css-transitions-2/#transition-property-property">
-<link rel=help href="https://w3c.github.io/csswg-drafts/css-images/#the-image-rendering">
-<link rel=help href="https://w3c.github.io/csswg-drafts/css-images/#the-image-orientation">
+<link rel=help href="https://drafts.csswg.org/css-images/#the-image-rendering">
+<link rel=help href="https://drafts.csswg.org/css-images/#the-image-orientation">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/css/support/interpolation-testcommon.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/animation/alignment-baseline-no-interpolation.html b/third_party/blink/web_tests/external/wpt/css/css-inline/animation/alignment-baseline-no-interpolation.html
index 8cbe0c9..8cacf54 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/animation/alignment-baseline-no-interpolation.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/animation/alignment-baseline-no-interpolation.html
@@ -2,7 +2,7 @@
 <link rel=author href="mailto:jarhar@chromium.org">
 <link rel=help href="https://github.com/w3c/csswg-drafts/issues/4441">
 <link rel=help href="https://drafts.csswg.org/css-transitions-2/#transition-property-property">
-<link rel=help href="https://w3c.github.io/csswg-drafts/css-inline/#alignment-baseline-property">
+<link rel=help href="https://drafts.csswg.org/css-inline/#alignment-baseline-property">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/css/support/interpolation-testcommon.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/animation/dominant-baseline-no-interpolation.html b/third_party/blink/web_tests/external/wpt/css/css-inline/animation/dominant-baseline-no-interpolation.html
index 7f6be5a..19266dc 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/animation/dominant-baseline-no-interpolation.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/animation/dominant-baseline-no-interpolation.html
@@ -2,7 +2,7 @@
 <link rel=author href="mailto:jarhar@chromium.org">
 <link rel=help href="https://github.com/w3c/csswg-drafts/issues/4441">
 <link rel=help href="https://drafts.csswg.org/css-transitions-2/#transition-property-property">
-<link rel=help href="https://w3c.github.io/csswg-drafts/css-inline/#dominant-baseline-property">
+<link rel=help href="https://drafts.csswg.org/css-inline/#dominant-baseline-property">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/css/support/interpolation-testcommon.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/animation/initial-letter-no-interpolation.html b/third_party/blink/web_tests/external/wpt/css/css-inline/animation/initial-letter-no-interpolation.html
index 1efc412..2d57ce2 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/animation/initial-letter-no-interpolation.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/animation/initial-letter-no-interpolation.html
@@ -2,7 +2,7 @@
 <link rel=author href="mailto:jarhar@chromium.org">
 <link rel=help href="https://github.com/w3c/csswg-drafts/issues/4441">
 <link rel=help href="https://drafts.csswg.org/css-transitions-2/#transition-property-property">
-<link rel=help href="https://w3c.github.io/csswg-drafts/css-inline/#sizing-drop-initials">
+<link rel=help href="https://drafts.csswg.org/css-inline/#sizing-drop-initials">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/css/support/interpolation-testcommon.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-computed.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-computed.html
index e463062..eae4aad9 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-computed.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-computed.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <title>Tests parsing of the initial-letter property</title>
 <link rel="author" title="Google LLC" href="https://www.google.com/">
-<link rel="help" href="https://https://w3c.github.io/csswg-drafts/css-inline-3/#sizing-drop-initials">
+<link rel="help" href="https://drafts.csswg.org/css-inline-3/#sizing-drop-initials">
 <meta name="assert" content="initial-letter supports the full grammar 'normal | <number [1,∞]> <integer [1,∞]> | <number [1,∞]> && [ drop | raise ]?'.">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-invalid.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-invalid.html
index 574a347..645372c 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-invalid.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-invalid.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <title>Tests parsing of the initial-letter property</title>
 <link rel="author" title="Google LLC" href="https://www.google.com/">
-<link rel="help" href="https://https://w3c.github.io/csswg-drafts/css-inline-3/#sizing-drop-initials">
+<link rel="help" href="https://drafts.csswg.org/css-inline-3/#sizing-drop-initials">
 <meta name="assert" content="initial-letter supports the full grammar 'normal | <number [1,∞]> <integer [1,∞]> | <number [1,∞]> && [ drop | raise ]?'.">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-valid.html b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-valid.html
index 3c1e3281..b02c564 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-valid.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-valid.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <title>Tests parsing of the initial-letter property</title>
 <link rel="author" title="Google LLC" href="https://www.google.com/">
-<link rel="help" href="https://https://w3c.github.io/csswg-drafts/css-inline-3/#sizing-drop-initials">
+<link rel="help" href="https://drafts.csswg.org/css-inline-3/#sizing-drop-initials">
 <meta name="assert" content="initial-letter supports the full grammar 'normal | <number [1,∞]> <integer [1,∞]> | <number [1,∞]> && [ drop | raise ]?'.">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-multicol/parsing/column-rule-valid-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-multicol/parsing/column-rule-valid-expected.txt
deleted file mode 100644
index 19e2f661..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-multicol/parsing/column-rule-valid-expected.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-This is a testharness.js-based test.
-PASS e.style['column-rule'] = "10px" should set the property value
-PASS e.style['column-rule'] = "dotted" should set the property value
-PASS e.style['column-rule'] = "red" should set the property value
-FAIL e.style['column-rule'] = "currentcolor hidden medium" should set the property value assert_equals: serialization should be canonical expected "hidden" but got "medium hidden currentcolor"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-multicol/parsing/column-rule-valid.html b/third_party/blink/web_tests/external/wpt/css/css-multicol/parsing/column-rule-valid.html
index 4743988f..30da638 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-multicol/parsing/column-rule-valid.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-multicol/parsing/column-rule-valid.html
@@ -16,6 +16,7 @@
 test_valid_value("column-rule", "red");
 
 test_valid_value("column-rule", "currentcolor hidden medium", "hidden");
+test_valid_value("column-rule", "currentcolor none medium", "medium");
 </script>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-pseudo/marker-variable-computed-style.html b/third_party/blink/web_tests/external/wpt/css/css-pseudo/marker-variable-computed-style.html
index c50ee33..c706edc 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-pseudo/marker-variable-computed-style.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-pseudo/marker-variable-computed-style.html
@@ -4,8 +4,8 @@
 <head>
     <meta charset="UTF-8" />
     <link rel="author" title="Karl Dubost" href="https://github.com/karlcow" />
-    <link rel="help" href="https://w3c.github.io/csswg-drafts/css-pseudo/#marker-pseudo" />
-    <link rel="help" href="https://w3c.github.io/csswg-drafts/css-variables/#defining-variables" />
+    <link rel="help" href="https://drafts.csswg.org/css-pseudo/#marker-pseudo" />
+    <link rel="help" href="https://drafts.csswg.org/css-variables/#defining-variables" />
     <script src="/resources/testharness.js"></script>
     <script src="/resources/testharnessreport.js"></script>
     <title>::marker with variables</title>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-pseudo/marker-variable-ref.html b/third_party/blink/web_tests/external/wpt/css/css-pseudo/marker-variable-ref.html
index d9664375..d2ea847 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-pseudo/marker-variable-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-pseudo/marker-variable-ref.html
@@ -5,11 +5,11 @@
     <link rel="author" title="Karl Dubost" href="https://github.com/karlcow" />
     <link
       rel="help"
-      href="https://w3c.github.io/csswg-drafts/css-pseudo/#marker-pseudo"
+      href="https://drafts.csswg.org/css-pseudo/#marker-pseudo"
     />
     <link
       rel="help"
-      href="https://w3c.github.io/csswg-drafts/css-variables/#defining-variables"
+      href="https://drafts.csswg.org/css-variables/#defining-variables"
     />
     <title>::marker with variables</title>
     <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-pseudo/marker-variable.html b/third_party/blink/web_tests/external/wpt/css/css-pseudo/marker-variable.html
index 3d0a7c8..eb349c9 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-pseudo/marker-variable.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-pseudo/marker-variable.html
@@ -3,8 +3,8 @@
 <head>
   <meta charset="UTF-8" />
   <link rel="author" title="Karl Dubost" href="https://github.com/karlcow" />
-  <link rel="help" href="https://w3c.github.io/csswg-drafts/css-pseudo/#marker-pseudo" />
-  <link rel="help" href="https://w3c.github.io/csswg-drafts/css-variables/#defining-variables" />
+  <link rel="help" href="https://drafts.csswg.org/css-pseudo/#marker-pseudo" />
+  <link rel="help" href="https://drafts.csswg.org/css-variables/#defining-variables" />
   <link rel="match" href="marker-variable-ref.html">
   <title>::marker with variables</title>
   <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/animation/height-no-interpolation.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/animation/height-no-interpolation.html
index 902fe2e..5738ae0 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-sizing/animation/height-no-interpolation.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/animation/height-no-interpolation.html
@@ -2,7 +2,7 @@
 <link rel=author href="mailto:jarhar@chromium.org">
 <link rel=help href="https://github.com/w3c/csswg-drafts/issues/4441">
 <link rel=help href="https://drafts.csswg.org/css-transitions-2/#transition-property-property">
-<link rel=help href="https://w3c.github.io/csswg-drafts/css-sizing/#preferred-size-properties">
+<link rel=help href="https://drafts.csswg.org/css-sizing/#preferred-size-properties">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/css/support/interpolation-testcommon.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/contain-intrinsic-size/contain-intrinsic-size-033.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/contain-intrinsic-size/contain-intrinsic-size-033.html
index 68192a8..f98a48a0 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-sizing/contain-intrinsic-size/contain-intrinsic-size-033.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/contain-intrinsic-size/contain-intrinsic-size-033.html
@@ -1,9 +1,9 @@
 <!DOCTYPE html>
 <meta charset="utf-8">
 <title>CIS + content-visibility:hidden and contain:size</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-sizing-4/#explicit-intrinsic-inner-size">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-contain-2/#size-containment">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-contain-2/#using-cv-hidden">
+<link rel="help" href="https://drafts.csswg.org/css-sizing-4/#explicit-intrinsic-inner-size">
+<link rel="help" href="https://drafts.csswg.org/css-contain-2/#size-containment">
+<link rel="help" href="https://drafts.csswg.org/css-contain-2/#using-cv-hidden">
 <meta name="assert"
     content="Tests that CIS + content-visibility:hidden should be same to CIS + contain:size" />
 
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/fit-content-block-size-abspos.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/fit-content-block-size-abspos.html
index d8ce91f9..8ed6771 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-sizing/fit-content-block-size-abspos.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/fit-content-block-size-abspos.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <link rel="author" title="Tim Nguyen" href="https://github.com/nt1m">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-sizing-4/#valdef-width-fit-content">
+<link rel="help" href="https://drafts.csswg.org/css-sizing-4/#valdef-width-fit-content">
 <link rel="match" href="fit-content-block-size-fixedpos-ref.html">
 <style>
 body {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/fit-content-block-size-fixedpos.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/fit-content-block-size-fixedpos.html
index 1f08c6ab..052435b 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-sizing/fit-content-block-size-fixedpos.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/fit-content-block-size-fixedpos.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <link rel="author" title="Tim Nguyen" href="https://github.com/nt1m">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-sizing-4/#valdef-width-fit-content">
+<link rel="help" href="https://drafts.csswg.org/css-sizing-4/#valdef-width-fit-content">
 <link rel="match" href="fit-content-block-size-fixedpos-ref.html">
 <style>
 #container {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/grid-item-image-percentage-min-height-computes-as-0-ref.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/grid-item-image-percentage-min-height-computes-as-0-ref.html
index 296cc59..7a8319d6 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-sizing/grid-item-image-percentage-min-height-computes-as-0-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/grid-item-image-percentage-min-height-computes-as-0-ref.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <link rel="author" title="Sammy Gill" href="mailto:sammy.gill@apple.com">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css2/#propdef-min-height">
+<link rel="help" href="https://drafts.csswg.org/css2/#propdef-min-height">
 <meta name="assert" content="Image percentage min-height cannot be resolved and used value should be 0">
 </head>
 <body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/grid-item-image-percentage-min-height-computes-as-0.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/grid-item-image-percentage-min-height-computes-as-0.html
index 3b5dd2a..ef3da031 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-sizing/grid-item-image-percentage-min-height-computes-as-0.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/grid-item-image-percentage-min-height-computes-as-0.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <link rel="author" title="Sammy Gill" href="mailto:sammy.gill@apple.com">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css2/#propdef-min-height">
+<link rel="help" href="https://drafts.csswg.org/css2/#propdef-min-height">
 <link rel="match" href="grid-item-image-percentage-min-height-computes-as-0-ref.html">
 <meta name="assert" content="Image percentage min-height cannot be resolved and used value should be 0">
 <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/nested-flexbox-image-percentage-max-height-computes-as-none-ref.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/nested-flexbox-image-percentage-max-height-computes-as-none-ref.html
index 6a290b23..34e2ed01 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-sizing/nested-flexbox-image-percentage-max-height-computes-as-none-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/nested-flexbox-image-percentage-max-height-computes-as-none-ref.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <link rel="author" title="Sammy Gill" href="mailto:sammy.gill@apple.com">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css2/#propdef-max-height">
+<link rel="help" href="https://drafts.csswg.org/css2/#propdef-max-height">
 <meta name="assert" content="Image percentage max-height cannot be resolved and used value should be none">
 </head>
 <body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/nested-flexbox-image-percentage-max-height-computes-as-none.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/nested-flexbox-image-percentage-max-height-computes-as-none.html
index afac464..06b70f1 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-sizing/nested-flexbox-image-percentage-max-height-computes-as-none.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/nested-flexbox-image-percentage-max-height-computes-as-none.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <link rel="author" title="Sammy Gill" href="mailto:sammy.gill@apple.com">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css2/#propdef-max-height">
+<link rel="help" href="https://drafts.csswg.org/css2/#propdef-max-height">
 <link rel="match" href="nested-flexbox-image-percentage-max-height-computes-as-none-ref.html">
 <meta name="assert" content="Image percentage max-height cannot be resolved and used value should be none">
 <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/animations/hyphen-no-interpolation.html b/third_party/blink/web_tests/external/wpt/css/css-text/animations/hyphen-no-interpolation.html
index e1e89d17..95a3ff5 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-text/animations/hyphen-no-interpolation.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/animations/hyphen-no-interpolation.html
@@ -1,9 +1,9 @@
 <!DOCTYPE html>
 <link rel=author href="mailto:jarhar@chromium.org">
 <link rel=help href="https://github.com/w3c/csswg-drafts/issues/4441">
-<link rel=help href="https://w3c.github.io/csswg-drafts/css-text-4/#propdef-hyphenate-character">
-<link rel=help href="https://w3c.github.io/csswg-drafts/css-text-4/#propdef-hyphenate-limit-chars">
-<link rel=help href="https://w3c.github.io/csswg-drafts/css-text/#hyphens-property">
+<link rel=help href="https://drafts.csswg.org/css-text-4/#propdef-hyphenate-character">
+<link rel=help href="https://drafts.csswg.org/css-text-4/#propdef-hyphenate-limit-chars">
+<link rel=help href="https://drafts.csswg.org/css-text/#hyphens-property">
 <link rel=help href="https://drafts.csswg.org/css-transitions-2/#transition-property-property">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/animations/line-break-no-interpolation.html b/third_party/blink/web_tests/external/wpt/css/css-text/animations/line-break-no-interpolation.html
index 937b248..b6fc5f9 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-text/animations/line-break-no-interpolation.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/animations/line-break-no-interpolation.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <link rel=author href="mailto:jarhar@chromium.org">
 <link rel=help href="https://github.com/w3c/csswg-drafts/issues/4441">
-<link rel=help href="https://w3c.github.io/csswg-drafts/css-text/#line-break-property">
+<link rel=help href="https://drafts.csswg.org/css-text/#line-break-property">
 <link rel=help href="https://drafts.csswg.org/css-transitions-2/#transition-property-property">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/parsing/hyphenate-limit-chars-computed.html b/third_party/blink/web_tests/external/wpt/css/css-text/parsing/hyphenate-limit-chars-computed.html
index cf18f25..bc265c8 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-text/parsing/hyphenate-limit-chars-computed.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/parsing/hyphenate-limit-chars-computed.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <title>CSS Text: hyphenate-limit-chars with computed values</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-text-4/#propdef-hyphenate-limit-chars">
+<link rel="help" href="https://drafts.csswg.org/css-text-4/#propdef-hyphenate-limit-chars">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/css/support/computed-testcommon.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/parsing/hyphenate-limit-chars-invalid.html b/third_party/blink/web_tests/external/wpt/css/css-text/parsing/hyphenate-limit-chars-invalid.html
index 5a797fa..db68f40 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-text/parsing/hyphenate-limit-chars-invalid.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/parsing/hyphenate-limit-chars-invalid.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <title>CSS Text: parsing hyphenate-limit-chars with invalid values</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-text-4/#propdef-hyphenate-limit-chars">
+<link rel="help" href="https://drafts.csswg.org/css-text-4/#propdef-hyphenate-limit-chars">
 <meta name="assert" content="hyphenate-character supports only the grammar 'none | manual | auto'.">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/parsing/hyphenate-limit-chars-valid.html b/third_party/blink/web_tests/external/wpt/css/css-text/parsing/hyphenate-limit-chars-valid.html
index 699ddd4..2f10e33 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-text/parsing/hyphenate-limit-chars-valid.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/parsing/hyphenate-limit-chars-valid.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <title>CSS Text: parsing hyphenate-limit-chars with valid values</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-text-4/#propdef-hyphenate-limit-chars">
+<link rel="help" href="https://drafts.csswg.org/css-text-4/#propdef-hyphenate-limit-chars">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/css/support/parsing-testcommon.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/parsing/white-space-shorthand-text-wrap.html b/third_party/blink/web_tests/external/wpt/css/css-text/parsing/white-space-shorthand-text-wrap.html
index 0600b82..de6d9f5 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-text/parsing/white-space-shorthand-text-wrap.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/parsing/white-space-shorthand-text-wrap.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-text-4/#propdef-white-space">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-text-4/#propdef-text-wrap">
+<link rel="help" href="https://drafts.csswg.org/css-text-4/#propdef-white-space">
+<link rel="help" href="https://drafts.csswg.org/css-text-4/#propdef-text-wrap">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/parsing/white-space-shorthand.html b/third_party/blink/web_tests/external/wpt/css/css-text/parsing/white-space-shorthand.html
index 518f81fd..a7788f7 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-text/parsing/white-space-shorthand.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/parsing/white-space-shorthand.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <title>CSS Text Module Test: parsing white-space as a shorthand</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-text-4/#propdef-white-space">
+<link rel="help" href="https://drafts.csswg.org/css-text-4/#propdef-white-space">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/css/support/parsing-testcommon.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/text-indent/text-indent-min-max-content-001.html b/third_party/blink/web_tests/external/wpt/css/css-text/text-indent/text-indent-min-max-content-001.html
index 99592df5..93ddac50 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-text/text-indent/text-indent-min-max-content-001.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/text-indent/text-indent-min-max-content-001.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-text-3/#text-indent-property">
+<link rel="help" href="https://drafts.csswg.org/css-text-3/#text-indent-property">
 <link rel="match" href="reference/text-indent-min-max-content-001-ref.html">
 <link rel="stylesheet" type="text/css" href="/fonts/ahem.css">
 <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/white-space/text-wrap-balance-001.html b/third_party/blink/web_tests/external/wpt/css/css-text/white-space/text-wrap-balance-001.html
index 3360681..4e1829f 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-text/white-space/text-wrap-balance-001.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/white-space/text-wrap-balance-001.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-text-4/#text-wrap">
+<link rel="help" href="https://drafts.csswg.org/css-text-4/#text-wrap">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/white-space/text-wrap-balance-002.html b/third_party/blink/web_tests/external/wpt/css/css-text/white-space/text-wrap-balance-002.html
index 7366c6ac0..cae9d54 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-text/white-space/text-wrap-balance-002.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/white-space/text-wrap-balance-002.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-text-4/#valdef-text-wrap-balance">
+<link rel="help" href="https://drafts.csswg.org/css-text-4/#valdef-text-wrap-balance">
 <link rel="mismatch" href="reference/text-wrap-balance-002-ref.html">
 <link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
 <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/white-space/text-wrap-balance-align-001.html b/third_party/blink/web_tests/external/wpt/css/css-text/white-space/text-wrap-balance-align-001.html
index b465961..b27823b 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-text/white-space/text-wrap-balance-align-001.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/white-space/text-wrap-balance-align-001.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-text-4/#valdef-text-wrap-balance">
+<link rel="help" href="https://drafts.csswg.org/css-text-4/#valdef-text-wrap-balance">
 <link rel="match" href="reference/text-wrap-balance-align-001-ref.html">
 <style>
 .container {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/white-space/text-wrap-balance-dynamic-001.html b/third_party/blink/web_tests/external/wpt/css/css-text/white-space/text-wrap-balance-dynamic-001.html
index 8c7d27d1..76b4cbbb 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-text/white-space/text-wrap-balance-dynamic-001.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/white-space/text-wrap-balance-dynamic-001.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-text-4/#valdef-text-wrap-balance">
+<link rel="help" href="https://drafts.csswg.org/css-text-4/#valdef-text-wrap-balance">
 <link rel="match" href="reference/text-wrap-balance-dynamic-001-ref.html">
 <style>
 #container {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/white-space/text-wrap-balance-line-clamp-001.html b/third_party/blink/web_tests/external/wpt/css/css-text/white-space/text-wrap-balance-line-clamp-001.html
index 292e6554..f104a526 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-text/white-space/text-wrap-balance-line-clamp-001.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/white-space/text-wrap-balance-line-clamp-001.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-text-4/#valdef-text-wrap-balance">
+<link rel="help" href="https://drafts.csswg.org/css-text-4/#valdef-text-wrap-balance">
 <link rel="match" href="reference/text-wrap-balance-line-clamp-001-ref.html">
 <style>
 .container {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/white-space/text-wrap-balance-text-indent-001.html b/third_party/blink/web_tests/external/wpt/css/css-text/white-space/text-wrap-balance-text-indent-001.html
index e06d91e..0fe4447 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-text/white-space/text-wrap-balance-text-indent-001.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/white-space/text-wrap-balance-text-indent-001.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-text-4/#valdef-text-wrap-balance">
+<link rel="help" href="https://drafts.csswg.org/css-text-4/#valdef-text-wrap-balance">
 <link rel="match" href="reference/text-wrap-balance-text-indent-001-ref.html">
 <link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
 <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/perspective-zero.html.ini b/third_party/blink/web_tests/external/wpt/css/css-transforms/perspective-zero.html.ini
new file mode 100644
index 0000000..5e1862f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/perspective-zero.html.ini
@@ -0,0 +1,3 @@
+[perspective-zero.html]
+  expected:
+    if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-search-text-border-top-style-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-search-text-border-top-style-001.html.ini
index b898964..94e2ba4 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-search-text-border-top-style-001.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-search-text-border-top-style-001.html.ini
@@ -1,3 +1,4 @@
 [kind-of-widget-fallback-input-search-text-border-top-style-001.html]
   expected:
     if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL
+    if (product == "content_shell") and (os == "linux"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/user-select-inheritance.html b/third_party/blink/web_tests/external/wpt/css/css-ui/user-select-inheritance.html
index 38a57e02..28bf2ab 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-ui/user-select-inheritance.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-ui/user-select-inheritance.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <title>Tests inheritance of CSS user-select property</title>
 <link rel="author" title="Google LLC" href="https://www.google.com/">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/css-ui/#content-selection">
+<link rel="help" href="https://drafts.csswg.org/css-ui/#content-selection">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <div id="container">abc<div id="target">xyz</div>def</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom/xml-stylesheet-pi-in-doctype.xhtml b/third_party/blink/web_tests/external/wpt/css/cssom/xml-stylesheet-pi-in-doctype.xhtml
index d25ca17..59911eb 100644
--- a/third_party/blink/web_tests/external/wpt/css/cssom/xml-stylesheet-pi-in-doctype.xhtml
+++ b/third_party/blink/web_tests/external/wpt/css/cssom/xml-stylesheet-pi-in-doctype.xhtml
@@ -2,7 +2,7 @@
 <html xmlns="http://www.w3.org/1999/xhtml">
   <head>
     <title>xml-stylesheet processing instruction in doctype internal subset</title>
-    <link rel="help" href="https://w3c.github.io/csswg-drafts/cssom/#prolog"/>
+    <link rel="help" href="https://drafts.csswg.org/cssom/#prolog"/>
     <script src="/resources/testharness.js"></script>
     <script src="/resources/testharnessreport.js"></script>
   </head>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-opacity.html.ini b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-opacity.html.ini
index 07002e42..9b23d73 100644
--- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-opacity.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filters-opacity.html.ini
@@ -1,3 +1,4 @@
 [backdrop-filters-opacity.html]
   expected:
+    if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
     if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/media-loading-pseudo-classes-in-has.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/media-loading-pseudo-classes-in-has.html
index 62b18c1..07ab608 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/media-loading-pseudo-classes-in-has.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/media-loading-pseudo-classes-in-has.html
@@ -3,7 +3,7 @@
 <title>:has() invalidation with :buffering & :stalled pseudo-classes</title>
 <link rel="author" title="Tim Nguyen" href="https://github.com/nt1m">
 <link rel="help" href="https://drafts.csswg.org/selectors/#relational">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors/#media-loading-state">
+<link rel="help" href="https://drafts.csswg.org/selectors/#media-loading-state">
 
 <style>
 #subject:has(video:buffering) {
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/media-pseudo-classes-in-has.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/media-pseudo-classes-in-has.html
index f0df715..881ba8f3 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/media-pseudo-classes-in-has.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/media-pseudo-classes-in-has.html
@@ -2,7 +2,7 @@
 <title>:has() invalidation with :playing, :paused, :seeking and :muted pseudo-classes</title>
 <link rel="author" title="Tim Nguyen" href="https://github.com/nt1m">
 <link rel="help" href="https://drafts.csswg.org/selectors/#relational">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors/#video-state">
+<link rel="help" href="https://drafts.csswg.org/selectors/#video-state">
 <style>
   #subject {
     background-color: black;
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-containing-ancestor-ref.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-containing-ancestor-ref.html
index 4dc7247e..6e6680d 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-containing-ancestor-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-containing-ancestor-ref.html
@@ -2,7 +2,7 @@
 <meta charset="utf-8" />
 <title>CSS Selectors Invalidation: :nth-child(... of S) with ancestor in S</title>
 <link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <div>
   <div>
     <div>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-containing-ancestor.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-containing-ancestor.html
index 7266cd5..a7f2463 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-containing-ancestor.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-containing-ancestor.html
@@ -3,7 +3,7 @@
 <title>CSS Selectors Invalidation: :nth-child(... of S) with ancestor in S</title>
 <link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
 <link rel="match" href="nth-child-containing-ancestor-ref.html">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <style>
   div:nth-child(odd of .a .b) {
     color: green;
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-attr-largedom-ref.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-attr-largedom-ref.html
index 6ddc204b..07617c5 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-attr-largedom-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-attr-largedom-ref.html
@@ -2,7 +2,7 @@
 <meta charset="utf-8" />
 <title>CSS Selectors Invalidation: :nth-child(... of attribute) with a large DOM</title>
 <link rel="author" title="Bramus" href="https://www.bram.us/">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <table border="1">
   <thead>
     <tr>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-attr-largedom.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-attr-largedom.html
index 76bc4542..07d87d2 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-attr-largedom.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-attr-largedom.html
@@ -3,7 +3,7 @@
 <title>CSS Selectors Invalidation: :nth-child(... of attribute) with a large DOM</title>
 <link rel="author" title="Bramus" href="https://www.bram.us/">
 <link rel="match" href="nth-child-of-attr-largedom-ref.html">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <style>
   tr:nth-child(even of :not([hidden])){
     background: lightgrey;
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-attr-ref.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-attr-ref.html
index 4120517..5207cc9 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-attr-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-attr-ref.html
@@ -2,7 +2,7 @@
 <meta charset="utf-8" />
 <title>CSS Selectors Invalidation: :nth-child(... of attribute)</title>
 <link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <div>
   <p>Ignored</p>
   <p>Ignored</p>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-attr.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-attr.html
index d929d6a..d4e82ff 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-attr.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-attr.html
@@ -3,7 +3,7 @@
 <title>CSS Selectors Invalidation: :nth-child(... of attribute)</title>
 <link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
 <link rel="match" href="nth-child-of-attr-ref.html">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <style>
   p:nth-child(even of [attr="yes"]) {
     color: green;
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-class-prefix.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-class-prefix.html
index ac7757db..2ea57c09 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-class-prefix.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-class-prefix.html
@@ -3,7 +3,7 @@
 <title>CSS Selectors Invalidation: :nth-child(... of class prefix)</title>
 <link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
 <link rel="match" href="nth-child-of-class-ref.html">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <style>
   p:nth-child(even of [class^=t]) {
     color: green;
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-class-ref.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-class-ref.html
index 7a8247c..d4e2dfb 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-class-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-class-ref.html
@@ -2,7 +2,7 @@
 <meta charset="utf-8" />
 <title>CSS Selectors Invalidation: :nth-child(... of class)</title>
 <link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <div>
   <p>Ignored</p>
   <p>Ignored</p>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-class.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-class.html
index dc1e8cec..1171f25 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-class.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-class.html
@@ -3,7 +3,7 @@
 <title>CSS Selectors Invalidation: :nth-child(... of class)</title>
 <link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
 <link rel="match" href="nth-child-of-class-ref.html">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <style>
   p:nth-child(even of .c) {
     color: green;
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-has-ref.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-has-ref.html
index ab3931d..39f0501 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-has-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-has-ref.html
@@ -2,7 +2,7 @@
 <meta charset="utf-8" />
 <title>CSS Selectors Invalidation: :nth-child(... of :has(...))</title>
 <link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <div>
   <p>Ignored</p>
   <p>Ignored</p>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-has.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-has.html
index 1a54831..8473828 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-has.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-has.html
@@ -3,7 +3,7 @@
 <title>CSS Selectors Invalidation: :nth-child(... of :has(...))</title>
 <link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
 <link rel="match" href="nth-child-of-has-ref.html">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <style>
   p:nth-child(even of :has(.c)) {
     color: green;
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-id-prefix.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-id-prefix.html
index fadb8f38..b07b1cfc 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-id-prefix.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-id-prefix.html
@@ -3,7 +3,7 @@
 <title>CSS Selectors Invalidation: :nth-child(... of ID prefix)</title>
 <link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
 <link rel="match" href="nth-child-of-class-ref.html">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <style>
   p:nth-child(even of [id^=t]) {
     color: green;
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-ids.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-ids.html
index 0332052..8e94aa3 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-ids.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-ids.html
@@ -3,7 +3,7 @@
 <title>CSS Selectors Invalidation: :nth-child(... of IDs)</title>
 <link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
 <link rel="match" href="nth-child-of-class-ref.html">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <style>
   p:nth-child(even of #t1, #t2, #t3, #t4, #t5) {
     color: green;
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-in-ancestor-ref.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-in-ancestor-ref.html
index a4e4b7f..bc7ecb9 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-in-ancestor-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-in-ancestor-ref.html
@@ -2,7 +2,7 @@
 <meta charset="utf-8" />
 <title>CSS Selectors Invalidation: :nth-child(... of class) as ancestor</title>
 <link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <div>
   <p>Not <span style="color: green">ignored</span></p>
   <p>Selectively <span>ignored<span></p>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-in-ancestor.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-in-ancestor.html
index 7311c3e..2ae8006 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-in-ancestor.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-in-ancestor.html
@@ -3,7 +3,7 @@
 <title>CSS Selectors Invalidation: :nth-child(... of class) as ancestor</title>
 <link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
 <link rel="match" href="nth-child-of-in-ancestor-ref.html">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <style>
   p:nth-child(odd of .c) span {
     color: green;
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-in-is.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-in-is.html
index 31276e6..f004195c 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-in-is.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-in-is.html
@@ -3,7 +3,7 @@
 <title>CSS Selectors Invalidation: :is(:nth-child(... of class))</title>
 <link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
 <link rel="match" href="nth-child-of-class-ref.html">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <style>
   p:is(:nth-child(even of .c)) {
     color: green;
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-in-shadow-root-ref.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-in-shadow-root-ref.html
index f28d358..060c07d 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-in-shadow-root-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-in-shadow-root-ref.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <title>CSS Selectors Invalidation: :nth-child(... of class) within shadow root</title>
 <link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <div>
   <div>No green</div>
   <div>No green</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-in-shadow-root.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-in-shadow-root.html
index 1e949a3..4195a14 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-in-shadow-root.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-in-shadow-root.html
@@ -2,7 +2,7 @@
 <title>CSS Selectors Invalidation: :nth-child(... of class) within shadow root</title>
 <link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
 <link rel="match" href="nth-child-of-in-shadow-root-ref.html">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <script src="/resources/declarative-shadow-dom-polyfill.js"></script>
 <div id="host">
   <template shadowrootmode="open">
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-is.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-is.html
index e230a30d..4473845 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-is.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-is.html
@@ -3,7 +3,7 @@
 <title>CSS Selectors Invalidation: :nth-child(... of :is)</title>
 <link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
 <link rel="match" href="nth-child-of-class-ref.html">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <style>
   p:nth-child(even of :is(.c)) {
     color: green;
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-sibling-ref.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-sibling-ref.html
index 0388fc7..ed7fefc 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-sibling-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-sibling-ref.html
@@ -2,7 +2,7 @@
 <meta charset="utf-8" />
 <title>CSS Selectors Invalidation: :nth-child(... of sibling)</title>
 <link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <div>
   <p>Ignored</p>
   <p>Ignored</p>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-sibling.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-sibling.html
index 5beaad6..68e4651 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-sibling.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-of-sibling.html
@@ -3,7 +3,7 @@
 <title>CSS Selectors Invalidation: :nth-child(... of sibling)</title>
 <link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
 <link rel="match" href="nth-child-of-sibling-ref.html">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <style>
   p:nth-child(even of .a + .b) {
     color: green;
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-when-ancestor-changes-ref.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-when-ancestor-changes-ref.html
index 8b7d329..7e3f7f0 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-when-ancestor-changes-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-when-ancestor-changes-ref.html
@@ -2,7 +2,7 @@
 <meta charset="utf-8" />
 <title>CSS Selectors Invalidation: :nth-child(... of class) when ancestor changes</title>
 <link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <div id="toggler">
   <p>Ignored</p>
   <p>Not ignored</p>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-when-ancestor-changes.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-when-ancestor-changes.html
index 4d2b4fb..c4a97ee 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-when-ancestor-changes.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-when-ancestor-changes.html
@@ -3,7 +3,7 @@
 <title>CSS Selectors Invalidation: :nth-child(... of class) when ancestor changes</title>
 <link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
 <link rel="match" href="nth-child-when-ancestor-changes-ref.html">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <style>
   .ancestor :nth-child(even of .c) {
     color: green;
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-when-sibling-changes-ref.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-when-sibling-changes-ref.html
index 9a397529..f30a853 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-when-sibling-changes-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-when-sibling-changes-ref.html
@@ -2,7 +2,7 @@
 <meta charset="utf-8" />
 <title>CSS Selectors Invalidation: :nth-child(... of class) when sibling changes</title>
 <link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <div>
   <p>Ignored</p>
   <p>Odd; used to be green, should not be since no sibling</p>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-when-sibling-changes.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-when-sibling-changes.html
index a0025be..43374df9 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-when-sibling-changes.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-child-when-sibling-changes.html
@@ -3,7 +3,7 @@
 <title>CSS Selectors Invalidation: :nth-child(... of class) when sibling changes</title>
 <link rel="author" title="Steinar H. Gunderson" href="sesse@chromium.org">
 <link rel="match" href="nth-child-when-sibling-changes-ref.html">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <style>
   .sibling + :nth-child(odd of .c) {
     color: green;
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-last-child-of-class-prefix.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-last-child-of-class-prefix.html
index f9fc196c..da12246 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-last-child-of-class-prefix.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-last-child-of-class-prefix.html
@@ -3,7 +3,7 @@
 <title>CSS Selectors Invalidation: :nth-last-child(... of class prefix)</title>
 <link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
 <link rel="match" href="nth-last-child-of-class-ref.html">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <style>
   p:nth-last-child(even of [class^=t]) {
     color: green;
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-last-child-of-id-prefix.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-last-child-of-id-prefix.html
index 1a9e6a9..747236a 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-last-child-of-id-prefix.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-last-child-of-id-prefix.html
@@ -3,7 +3,7 @@
 <title>CSS Selectors Invalidation: :nth-last-child(... of ID prefix)</title>
 <link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
 <link rel="match" href="nth-last-child-of-class-ref.html">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <style>
   p:nth-last-child(even of [id^=t]) {
     color: green;
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-last-child-of-ids.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-last-child-of-ids.html
index cd682ed..def33611 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-last-child-of-ids.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-last-child-of-ids.html
@@ -3,7 +3,7 @@
 <title>CSS Selectors Invalidation: :nth-last-child(... of IDs)</title>
 <link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
 <link rel="match" href="nth-last-child-of-class-ref.html">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <style>
   p:nth-last-child(even of #t1, #t2, #t3, #t4, #t5) {
     color: green;
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-last-child-of-in-is.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-last-child-of-in-is.html
index 90c8860..370883e 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-last-child-of-in-is.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-last-child-of-in-is.html
@@ -3,7 +3,7 @@
 <title>CSS Selectors Invalidation: :is(:nth-last-child(... of class))</title>
 <link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
 <link rel="match" href="nth-last-child-of-class-ref.html">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <style>
   p:is(:nth-last-child(even of .c)) {
     color: green;
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-last-child-of-is.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-last-child-of-is.html
index ac1ec31..0db7347 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-last-child-of-is.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/nth-last-child-of-is.html
@@ -3,7 +3,7 @@
 <title>CSS Selectors Invalidation: :nth-last-child(... of :is)</title>
 <link rel="author" title="Zach Hoffman" href="mailto:zach@zrhoffman.net">
 <link rel="match" href="nth-last-child-of-class-ref.html">
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <style>
   p:nth-last-child(even of :is(.c)) {
     color: green;
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/media/media-loading-state.html b/third_party/blink/web_tests/external/wpt/css/selectors/media/media-loading-state.html
index b48cfc1..6bead20a 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/media/media-loading-state.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/media/media-loading-state.html
@@ -3,7 +3,7 @@
 <title>Media Loading State: the :buffering and :stalled pseudo-classes</title>
 <link
   rel="help"
-  href="https://w3c.github.io/csswg-drafts/selectors/#media-loading-state"
+  href="https://drafts.csswg.org/selectors/#media-loading-state"
 />
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/media/media-playback-state.html b/third_party/blink/web_tests/external/wpt/css/selectors/media/media-playback-state.html
index 628daa2..c034dbb 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/media/media-playback-state.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/media/media-playback-state.html
@@ -4,7 +4,7 @@
 </title>
 <link
   rel="help"
-  href="https://w3c.github.io/csswg-drafts/selectors/#video-state"
+  href="https://drafts.csswg.org/selectors/#video-state"
 />
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/media/sound-state.html b/third_party/blink/web_tests/external/wpt/css/selectors/media/sound-state.html
index d9eb86a5..527bb30 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/media/sound-state.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/media/sound-state.html
@@ -2,7 +2,7 @@
 <title>Sound State: the :muted and :volume-locked pseudo-classes</title>
 <link
   rel="help"
-  href="https://w3c.github.io/csswg-drafts/selectors/#sound-state"
+  href="https://drafts.csswg.org/selectors/#sound-state"
 />
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-and-nth-last-child.html b/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-and-nth-last-child.html
index 455063f..1379b4c 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-and-nth-last-child.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-and-nth-last-child.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <title>:nth-child and :nth-last-child with selector list argument chained together</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <link rel="match" href="nth-child-and-nth-last-child-ref.html">
 <style>
     target1 {
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-of-classname.html b/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-of-classname.html
index 8ec3f43..1cfb010 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-of-classname.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-of-classname.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <title>:nth-child with .className selector list argument</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <link rel="match" href="nth-child-of-classname-ref.html">
 <style>
 p:nth-child(even of .webkit, .fast) {
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-of-complex-selector-many-children.html b/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-of-complex-selector-many-children.html
index 72f58cd..ab958c9 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-of-complex-selector-many-children.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-of-complex-selector-many-children.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <title>:nth-child with complex selector list argument and more than 32 elements</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <link rel="match" href="nth-child-of-complex-selector-many-children-ref.html">
 <style>
 /* At least 4 pair of <p> above, can be overlapping. The other selectors of the list are useless. */
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-of-complex-selector.html b/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-of-complex-selector.html
index b751d83..f06680a5 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-of-complex-selector.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-of-complex-selector.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <title>:nth-child with complex selector list argument</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <link rel="match" href="nth-child-of-complex-selector-ref.html">
 <style>
 /* At least 4 pair of <p> above, can be overlapping. The other selectors of the list are useless. */
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-of-compound-selector.html b/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-of-compound-selector.html
index 5efefe6..50bdba0 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-of-compound-selector.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-of-compound-selector.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <title>:nth-child with compound selector argument</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <link rel="match" href="nth-child-of-compound-selector-ref.html">
 <style>
 /* 3n of paragraph with the class foobar but for which foobar is not the only class. */
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-of-nesting.html b/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-of-nesting.html
index 8512606..78c5cde 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-of-nesting.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-of-nesting.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <title>:nth-last-child nesting</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <link rel=author href="mailto:zach@zrhoffman.net" title="Zach Hoffman">
 <link rel="match" href="nth-child-of-nesting-ref.html">
 <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-of-no-space-after-of.html b/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-of-no-space-after-of.html
index 613593c..997b07c 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-of-no-space-after-of.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-of-no-space-after-of.html
@@ -3,7 +3,7 @@
 <head>
 <meta charset="utf-8">
 <title>:nth-child with no space between "of" and the selector list</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <link rel=author href="mailto:zach@zrhoffman.net" title="Zach Hoffman">
 <link rel="match" href="nth-child-of-no-space-after-of-ref.html">
 <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-of-tagname.html b/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-of-tagname.html
index 107e834..cc92ad6d 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-of-tagname.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-of-tagname.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <title>:nth-child with tagname selector list argument</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <link rel="match" href="nth-child-of-tagname-ref.html">
 <style>
 :nth-child(odd of webkit, fast) {
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-specificity-1.html b/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-specificity-1.html
index d0b084a7..64d9eb2 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-specificity-1.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-specificity-1.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <title>:nth-child with selector list specificity</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <link rel="match" href="nth-child-specificity-1-ref.html">
 <style>
     /* The following 3 rules should all have the same specificity when matching <target>. They should be be applied in order. */
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-specificity-2.html b/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-specificity-2.html
index a467e5e0..10467e740 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-specificity-2.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-specificity-2.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <title>:nth-child with selector list specificity</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <link rel="match" href="nth-child-specificity-2-ref.html">
 <style>
     /* (1, 1, 0) */
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-specificity-3.html b/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-specificity-3.html
index f9c23b27..8649f4f 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-specificity-3.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-specificity-3.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <title>:nth-child with selector list specificity</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <link rel="match" href="nth-child-specificity-3-ref.html">
 <style>
     /* (1, 2, 1) */
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-specificity-4.html b/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-specificity-4.html
index 6286b01..de856c2 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-specificity-4.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/nth-child-specificity-4.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <title>:nth-child with selector list specificity</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <link rel="match" href="nth-child-specificity-4-ref.html">
 <style>
     /* (1, 2, 1) */
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-classname.html b/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-classname.html
index 770fda3..80770b08 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-classname.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-classname.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <title>:nth-last-child with .className selector list argument</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <link rel="match" href="nth-last-child-of-classname-ref.html">
 <style>
 p:nth-last-child(even of .webkit, .fast) {
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-complex-selector.html b/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-complex-selector.html
index 0f1262c..ae8fc6eb 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-complex-selector.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-complex-selector.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <title>:nth-last-child with complex selector list argument</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <link rel="match" href="nth-last-child-of-complex-selector-ref.html">
 <style>
 p:nth-last-child(4n of html:root>body>p+p:not(empty), :not(*), p:not(p), span, .notthere) {
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-compound-selector.html b/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-compound-selector.html
index a7aa40f..df1d583 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-compound-selector.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-compound-selector.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <title>:nth-last-child with compound selector argument</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <link rel="match" href="nth-last-child-of-compound-selector-ref.html">
 <style>
 p:nth-last-child(3n+1 of p.foobar:not([class=foobar])) {
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-nesting.html b/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-nesting.html
index 0dd18f2c..e1ce3ce 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-nesting.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-nesting.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <title>:nth-last-child nesting</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <link rel=author href="mailto:zach@zrhoffman.net" title="Zach Hoffman">
 <link rel="match" href="nth-child-of-nesting-ref.html">
 <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-no-space-after-of.html b/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-no-space-after-of.html
index d79d573..5ce99119 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-no-space-after-of.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-no-space-after-of.html
@@ -3,7 +3,7 @@
 <head>
 <meta charset="utf-8">
 <title>:nth-last-child with no space between "of" and the selector list</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <link rel=author href="mailto:zach@zrhoffman.net" title="Zach Hoffman">
 <link rel="match" href="nth-child-of-no-space-after-of-ref.html">
 <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-style-sharing-1.html b/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-style-sharing-1.html
index de3e263..17ea008 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-style-sharing-1.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-style-sharing-1.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <title>:nth-last-child correct style-sharing</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <link rel="match" href="nth-last-child-of-style-sharing-1-ref.html">
 <style>
 :nth-last-child(3n+1 of .target) {
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-style-sharing-2.html b/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-style-sharing-2.html
index 19fc9af..2c586956 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-style-sharing-2.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-style-sharing-2.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <title>:nth-last-child correct style-sharing</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <link rel="match" href="nth-last-child-of-style-sharing-2-ref.html">
 <style>
 :nth-last-child(3n+1 of .target) {
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-tagname.html b/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-tagname.html
index ddfd6528c..385d1294 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-tagname.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-of-tagname.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <title>:nth-last-child with tagname selector list argument</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <link rel="match" href="nth-last-child-of-tagname-ref.html">
 <style>
 :nth-last-child(odd of webkit, fast) {
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-specificity-1.html b/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-specificity-1.html
index cc4f542..18e00f1 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-specificity-1.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-specificity-1.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <title>:nth-last-child with selector list specificity</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <link rel="match" href="nth-last-child-specificity-1-ref.html">
 <style>
     /* The following 3 rules should all have the same specificity when matching <target>. They should be be applied in order. */
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-specificity-2.html b/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-specificity-2.html
index 3ddb43b6..3c3c873 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-specificity-2.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-specificity-2.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <title>:nth-last-child with selector list specificity</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <link rel="match" href="nth-last-child-specificity-2-ref.html">
 <style>
     /* (1, 1, 0) */
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-specificity-3.html b/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-specificity-3.html
index 673b435..93a7007 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-specificity-3.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-specificity-3.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <title>:nth-last-child with selector list specificity</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <link rel="match" href="nth-last-child-specificity-3-ref.html">
 <style>
     /* (1, 2, 1) */
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-specificity-4.html b/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-specificity-4.html
index b690ea2..f556b99 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-specificity-4.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/nth-last-child-specificity-4.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <title>:nth-last-child with selector list specificity</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors-4/#child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#child-index">
 <link rel="match" href="nth-last-child-specificity-4-ref.html">
 <style>
     /* (1, 2, 1) */
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/nth-of-type-namespace.html b/third_party/blink/web_tests/external/wpt/css/selectors/nth-of-type-namespace.html
index aa67afd0..f5d81a5 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/nth-of-type-namespace.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/nth-of-type-namespace.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <title>CSS Selectors Test: :*-of-type with namespace</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/selectors/#typed-child-index">
+<link rel="help" href="https://drafts.csswg.org/selectors/#typed-child-index">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <style>
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/video-intrinsic-width-height.html b/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/video-intrinsic-width-height.html
index ad5b69d..74989be 100644
--- a/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/video-intrinsic-width-height.html
+++ b/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/video-intrinsic-width-height.html
@@ -5,7 +5,7 @@
         <link rel="author" title="Sammy Gill" href="sammy.gill@apple.com" />
         <link rel="help" href="https://github.com/w3c/csswg-drafts/issues/7524" />
         <link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#replaced-elements" />
-        <link rel="help" href="https://w3c.github.io/csswg-drafts/css-sizing-4/#aspect-ratio" />
+        <link rel="help" href="https://drafts.csswg.org/css-sizing-4/#aspect-ratio" />
         <script src="/resources/testharness.js"></script>
         <script src="/resources/testharnessreport.js"></script>
     </head>
diff --git a/third_party/blink/web_tests/external/wpt/preload/modulepreload-as.html.ini b/third_party/blink/web_tests/external/wpt/preload/modulepreload-as.html.ini
index 2825c72..fc248ee2 100644
--- a/third_party/blink/web_tests/external/wpt/preload/modulepreload-as.html.ini
+++ b/third_party/blink/web_tests/external/wpt/preload/modulepreload-as.html.ini
@@ -1,7 +1,8 @@
 [modulepreload-as.html]
   expected:
-    if (product == "content_shell") and (os == "mac") and (port == "mac11"): OK
+    if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [ERROR, OK]
     if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): OK
+    if (product == "content_shell") and (os == "mac") and (port == "mac11"): OK
     if (product == "content_shell") and (os == "mac") and (port == "mac12"): OK
     if (product == "content_shell") and (os == "win"): TIMEOUT
     ERROR
@@ -12,14 +13,19 @@
     expected: FAIL
 
   [Modulepreload with as="document"]
-    expected: FAIL
+    expected:
+      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
+      FAIL
 
   [Modulepreload with as="embed"]
-    expected: FAIL
+    expected:
+      if (product == "content_shell") and (os == "linux") and (flag_specific == ""): PASS
+      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
+      FAIL
 
   [Modulepreload with as="fetch"]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [PASS, FAIL]
       if (product == "content_shell") and (os == "win") and (port == "win11"): PASS
       if (product == "content_shell") and (os == "linux"): PASS
       if product == "chrome": PASS
@@ -27,44 +33,44 @@
 
   [Modulepreload with as="font"]
     expected:
+      if (product == "content_shell") and (os == "linux") and (flag_specific == ""): PASS
       if (product == "content_shell") and (os == "win") and (port == "win11"): PASS
-      if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): PASS
       if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
       FAIL
 
   [Modulepreload with as="frame"]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL
-      if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL
-      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
-      if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL
-      if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL
+      if (product == "content_shell") and (os == "linux") and (flag_specific == ""): PASS
       if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "win"): PASS
+      if product == "chrome": PASS
+      FAIL
 
   [Modulepreload with as="iMaGe"]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [PASS, FAIL]
       if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL
-      if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL
       if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [PASS, FAIL]
+      if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
 
   [Modulepreload with as="iframe"]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
-      if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
-      if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL
       if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
       if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [PASS, FAIL]
 
   [Modulepreload with as="image"]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
       if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL
       if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL
       if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
       if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL
 
   [Modulepreload with as="invalid-dest"]
@@ -72,29 +78,30 @@
 
   [Modulepreload with as="manifest"]
     expected:
-      if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL
-      if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
-      if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL
       if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL
       if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL
 
   [Modulepreload with as="object"]
     expected:
       if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL
-      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [PASS, FAIL]
       if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
       if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [PASS, FAIL]
 
   [Modulepreload with as="paintworklet"]
     expected: FAIL
 
   [Modulepreload with as="report"]
     expected:
+      if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL
+      if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL
       if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [PASS, FAIL]
       if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL
-      if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL
-      if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL
 
   [Modulepreload with as="serviceworker"]
     expected: FAIL
@@ -104,14 +111,15 @@
 
   [Modulepreload with as="style"]
     expected:
+      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
       if (product == "content_shell") and (os == "linux") and (flag_specific == ""): PASS
-      if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): PASS
       if product == "chrome": PASS
       FAIL
 
   [Modulepreload with as="track"]
     expected:
-      if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): PASS
+      if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
+      if (product == "content_shell") and (os == "linux") and (flag_specific == ""): PASS
       if product == "chrome": PASS
       FAIL
 
@@ -126,8 +134,8 @@
   [Modulepreload with as="webidentity"]
     expected:
       if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
-      if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): PASS
       if (product == "content_shell") and (os == "linux") and (flag_specific == ""): PASS
+      if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): PASS
       if product == "chrome": PASS
       FAIL
 
@@ -136,7 +144,8 @@
 
   [Modulepreload with as="xslt"]
     expected:
+      if (product == "content_shell") and (os == "linux") and (flag_specific == ""): PASS
+      if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): PASS
       if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS]
-      if (product == "content_shell") and (os == "linux"): PASS
       if product == "chrome": PASS
       FAIL
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/css/animation-timeline-view-functional-notation.tentative.html b/third_party/blink/web_tests/external/wpt/scroll-animations/css/animation-timeline-view-functional-notation.tentative.html
index 42f4e7a..3ac94478 100644
--- a/third_party/blink/web_tests/external/wpt/scroll-animations/css/animation-timeline-view-functional-notation.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/scroll-animations/css/animation-timeline-view-functional-notation.tentative.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <title>The animation-timeline: view() notation</title>
 <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1">
-<link rel="help" src="https://w3c.github.io/csswg-drafts/scroll-animations-1/#view-notation">
+<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#view-notation">
 <link rel="help" src="https://github.com/w3c/csswg-drafts/issues/7587">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/css/timeline-range-name-offset-in-keyframes.tentative.html b/third_party/blink/web_tests/external/wpt/scroll-animations/css/timeline-range-name-offset-in-keyframes.tentative.html
index 4ab2e9c..6fab0025 100644
--- a/third_party/blink/web_tests/external/wpt/scroll-animations/css/timeline-range-name-offset-in-keyframes.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/scroll-animations/css/timeline-range-name-offset-in-keyframes.tentative.html
@@ -2,7 +2,7 @@
 <html>
 <meta charset="utf-8">
 <title>Timeline offset in Animation Keyframes</title>
-<link rel="help" href="https://w3c.github.io/csswg-drafts/scroll-animations-1/#named-range-keyframes">
+<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#named-range-keyframes">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/web-animations/testcommon.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/property-list.js b/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/property-list.js
index d8896e7..24ad547b 100644
--- a/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/property-list.js
+++ b/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/property-list.js
@@ -747,7 +747,7 @@
     types: [ 'color' ]
   },
   'line-height': {
-    // https://w3c.github.io/csswg-drafts/css-inline/#line-height-property
+    // https://drafts.csswg.org/css-inline/#line-height-property
     types: [
         { type: 'discrete', options: [ [ 'normal', '10px' ],
                                        [ 'normal', '10', 'normal', '100px' ] ] }
diff --git a/third_party/blink/web_tests/external/wpt/webnn/slice.https.any-expected.txt b/third_party/blink/web_tests/external/wpt/webnn/slice.https.any-expected.txt
deleted file mode 100644
index 7652a09..0000000
--- a/third_party/blink/web_tests/external/wpt/webnn/slice.https.any-expected.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-This is a testharness.js-based test.
-FAIL slice float32 1D tensor / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL slice float32 2D tensor / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL slice float32 3D tensor / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL slice float32 4D tensor / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL slice float32 5D tensor / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/webnn/slice.https.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/webnn/slice.https.any.worker-expected.txt
deleted file mode 100644
index 493e9b0..0000000
--- a/third_party/blink/web_tests/external/wpt/webnn/slice.https.any.worker-expected.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-This is a testharness.js-based test.
-FAIL slice float32 1D tensor / sync builder[operationName] is not a function
-FAIL slice float32 2D tensor / sync builder[operationName] is not a function
-FAIL slice float32 3D tensor / sync builder[operationName] is not a function
-FAIL slice float32 4D tensor / sync builder[operationName] is not a function
-FAIL slice float32 5D tensor / sync builder[operationName] is not a function
-FAIL slice float32 1D tensor / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL slice float32 2D tensor / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL slice float32 3D tensor / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL slice float32 4D tensor / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-FAIL slice float32 5D tensor / async promise_test: Unhandled rejection with value: object "TypeError: builder[operationName] is not a function"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/http/tests/devtools/quick-open/command-menu.js b/third_party/blink/web_tests/http/tests/devtools/quick-open/command-menu.js
index 2579e263..5de70da 100644
--- a/third_party/blink/web_tests/http/tests/devtools/quick-open/command-menu.js
+++ b/third_party/blink/web_tests/http/tests/devtools/quick-open/command-menu.js
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+
 (async function() {
   TestRunner.addResult(`Test that the command menu is properly filled.\n`);
   await TestRunner.loadLegacyModule('quick_open');
diff --git a/third_party/blink/web_tests/http/tests/devtools/resource-tree/iframe-main-resource.js b/third_party/blink/web_tests/http/tests/devtools/resource-tree/iframe-main-resource.js
index 6a3cc54..66db142cc 100644
--- a/third_party/blink/web_tests/http/tests/devtools/resource-tree/iframe-main-resource.js
+++ b/third_party/blink/web_tests/http/tests/devtools/resource-tree/iframe-main-resource.js
@@ -2,9 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {ApplicationTestRunner} from 'application_test_runner';
+
 (async function() {
   TestRunner.addResult(`Verify that iframe's main resource is reported only once.\n`);
-  await TestRunner.loadLegacyModule('console'); await TestRunner.loadTestModule('application_test_runner');
+  await TestRunner.loadLegacyModule('console');
   await TestRunner.showPanel('resources');
   await TestRunner.evaluateInPageAsync(`
       (function createIframe() {
diff --git a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-metadata.js b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-metadata.js
index 1e6b6603..e7b2fbb 100644
--- a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-metadata.js
+++ b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-metadata.js
@@ -2,9 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {NetworkTestRunner} from 'network_test_runner';
+
 (async function() {
   TestRunner.addResult(`Verify that dynamically added resource has metadata.\n`);
-  await TestRunner.loadTestModule('network_test_runner');
   await TestRunner.showPanel('resources');
   var url = TestRunner.url('resources/script-with-constant-last-modified.php');
   await TestRunner.evaluateInPageAsync(`
diff --git a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-request-content-after-loading-and-clearing-cache.js b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-request-content-after-loading-and-clearing-cache.js
index 96fde46..4de8d83a 100644
--- a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-request-content-after-loading-and-clearing-cache.js
+++ b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-request-content-after-loading-and-clearing-cache.js
@@ -2,10 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {ApplicationTestRunner} from 'application_test_runner';
+
 (async function() {
   TestRunner.addResult(
       `Tests resource content is correctly loaded if Resource.requestContent was called before network request was finished. https://bugs.webkit.org/show_bug.cgi?id=90153\n`);
-  await TestRunner.loadLegacyModule('console'); await TestRunner.loadTestModule('application_test_runner');
+  await TestRunner.loadLegacyModule('console');
   await TestRunner.showPanel('resources');
   await TestRunner.addStylesheetTag('resources/styles-initial.css');
   TestRunner.addResult('Adding dynamic script: ');
diff --git a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-request-content-while-loading.js b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-request-content-while-loading.js
index 93f4b772..a7dd30468 100644
--- a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-request-content-while-loading.js
+++ b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-request-content-while-loading.js
@@ -2,10 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {ApplicationTestRunner} from 'application_test_runner';
+
 (async function() {
   TestRunner.addResult(
       `Tests resource content is correctly loaded if Resource.requestContent was called before network request was finished. https://bugs.webkit.org/show_bug.cgi?id=90153\n`);
-  await TestRunner.loadLegacyModule('console'); await TestRunner.loadTestModule('application_test_runner');
+  await TestRunner.loadLegacyModule('console');
   await TestRunner.showPanel('resources');
 
   TestRunner.addSniffer(SDK.ResourceTreeFrame.prototype, 'addRequest', requestAdded, true);
diff --git a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-crafted-frame-add.js b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-crafted-frame-add.js
index 66e77fe2..3bcac8b 100644
--- a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-crafted-frame-add.js
+++ b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-crafted-frame-add.js
@@ -2,9 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {ApplicationTestRunner} from 'application_test_runner';
+
 (async function() {
   TestRunner.addResult(`Tests resource tree model on crafted iframe addition (will time out on failure).\n`);
-  await TestRunner.loadLegacyModule('console'); await TestRunner.loadTestModule('application_test_runner');
+  await TestRunner.loadLegacyModule('console');
   await TestRunner.showPanel('resources');
   TestRunner.addSniffer(TestRunner.resourceTreeModel, 'frameAttached', TestRunner.completeTest);
   TestRunner.evaluateInPage(`
diff --git a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-document-url.js b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-document-url.js
index 359359bf..21cdfd7 100644
--- a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-document-url.js
+++ b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-document-url.js
@@ -2,9 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {ApplicationTestRunner} from 'application_test_runner';
+
 (async function() {
   TestRunner.addResult(`Tests that resources have proper documentURL set in the tree model.\n`);
-  await TestRunner.loadLegacyModule('console'); await TestRunner.loadTestModule('application_test_runner');
+  await TestRunner.loadLegacyModule('console');
   await TestRunner.showPanel('resources');
 
   TestRunner.resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.FrameNavigated, waitForResources);
diff --git a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-events.js b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-events.js
index d6ad672..5bc7251 100644
--- a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-events.js
+++ b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-events.js
@@ -2,9 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {ApplicationTestRunner} from 'application_test_runner';
+
 (async function() {
   TestRunner.addResult(`Tests top frame navigation events.\n`);
-  await TestRunner.loadLegacyModule('console'); await TestRunner.loadTestModule('application_test_runner');
+  await TestRunner.loadLegacyModule('console');
   await TestRunner.showPanel('resources');
 
   // Reset resourceTreeModel.
diff --git a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-frame-add.js b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-frame-add.js
index ace96ca..2dae283 100644
--- a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-frame-add.js
+++ b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-frame-add.js
@@ -2,12 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {ApplicationTestRunner} from 'application_test_runner';
+import {ConsoleTestRunner} from 'console_test_runner';
+
 (async function() {
   TestRunner.addResult(
       `Tests resource tree model on iframe addition, compares resource tree against golden. Every line is important.\n`);
-  await TestRunner.loadLegacyModule('sources'); await TestRunner.loadTestModule('sources_test_runner');
-  await TestRunner.loadLegacyModule('console'); await TestRunner.loadTestModule('application_test_runner');
-  await TestRunner.loadLegacyModule('console'); await TestRunner.loadTestModule('console_test_runner');
+  await TestRunner.loadLegacyModule('sources');
+  await TestRunner.loadLegacyModule('console');
   await TestRunner.showPanel('resources');
   await TestRunner.addStylesheetTag('resources/styles-initial.css');
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-frame-in-crafted-frame.js b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-frame-in-crafted-frame.js
index 4126dda..c20543d 100644
--- a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-frame-in-crafted-frame.js
+++ b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-frame-in-crafted-frame.js
@@ -2,10 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {ApplicationTestRunner} from 'application_test_runner';
+
 (async function() {
   TestRunner.addResult(
       `Tests that frame inside crafted frame doesn't cause 'MainFrameNavigated' event and correctly attaches to frame tree. crbug/259036\n`);
-  await TestRunner.loadLegacyModule('console'); await TestRunner.loadTestModule('application_test_runner');
+  await TestRunner.loadLegacyModule('console');
   await TestRunner.showPanel('resources');
 
   var frameId = Symbol('frameId');
diff --git a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-frame-navigate.js b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-frame-navigate.js
index 3331333a..e4bf54e 100644
--- a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-frame-navigate.js
+++ b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-frame-navigate.js
@@ -2,11 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {SourcesTestRunner} from 'sources_test_runner';
+import {ApplicationTestRunner} from 'application_test_runner';
+
 (async function() {
   TestRunner.addResult(
       `Tests resource tree model on iframe navigation, compares resource tree against golden. Every line is important.\n`);
-  await TestRunner.loadLegacyModule('sources'); await TestRunner.loadTestModule('sources_test_runner');
-  await TestRunner.loadLegacyModule('console'); await TestRunner.loadTestModule('application_test_runner');
+  await TestRunner.loadLegacyModule('sources');
+  await TestRunner.loadLegacyModule('console');
   await TestRunner.showPanel('resources');
   await TestRunner.loadHTML(`
     <iframe id="iframe"></iframe>
diff --git a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-invalid-mime-type-css-content.js b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-invalid-mime-type-css-content.js
index fbe2737..87b081f 100644
--- a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-invalid-mime-type-css-content.js
+++ b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-invalid-mime-type-css-content.js
@@ -2,10 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {ApplicationTestRunner} from 'application_test_runner';
+
 (async function() {
   TestRunner.addResult(
       `Tests that content is correctly shown for css loaded with invalid mime type in quirks mode. https://bugs.webkit.org/show_bug.cgi?id=80528\n`);
-  await TestRunner.loadLegacyModule('console'); await TestRunner.loadTestModule('application_test_runner');
+  await TestRunner.loadLegacyModule('console');
   await TestRunner.showPanel('resources');
   await TestRunner.addStylesheetTag('resources/stylesheet-text-plain.php');
   await TestRunner.waitForUISourceCode('stylesheet-text-plain.php');
diff --git a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-no-xhrs.js b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-no-xhrs.js
index a117cd1..f8b80bb 100644
--- a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-no-xhrs.js
+++ b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-no-xhrs.js
@@ -2,10 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {NetworkTestRunner} from 'network_test_runner';
+
 (async function() {
   TestRunner.addResult(
       `Tests that XHRs are not added to resourceTreeModel. https://bugs.webkit.org/show_bug.cgi?id=60321\n`);
-  await TestRunner.loadTestModule('network_test_runner');
   await TestRunner.showPanel('resources');
 
   NetworkTestRunner.makeSimpleXHR('GET', 'resources/resource.php', false, step2);
diff --git a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-non-unique-url.js b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-non-unique-url.js
index 71c3097c..0ed0158 100644
--- a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-non-unique-url.js
+++ b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-non-unique-url.js
@@ -2,11 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {SourcesTestRunner} from 'sources_test_runner';
+import {ApplicationTestRunner} from 'application_test_runner';
+
 (async function() {
   TestRunner.addResult(
       `Tests resources panel shows several resources with the same url if they were loaded with inspector already opened.\n`);
-  await TestRunner.loadLegacyModule('sources'); await TestRunner.loadTestModule('sources_test_runner');
-  await TestRunner.loadLegacyModule('console'); await TestRunner.loadTestModule('application_test_runner');
+  await TestRunner.loadLegacyModule('sources');
+  await TestRunner.loadLegacyModule('console');
   await TestRunner.showPanel('resources');
   TestRunner.addSniffer(Resources.FrameTreeElement.prototype, 'appendResource', onResource, true);
   TestRunner.evaluateInPageAnonymously(`
diff --git a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-reload.js b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-reload.js
index e4f988e1..de707d4 100644
--- a/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-reload.js
+++ b/third_party/blink/web_tests/http/tests/devtools/resource-tree/resource-tree-reload.js
@@ -2,10 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {ApplicationTestRunner} from 'application_test_runner';
+
 (async function() {
   TestRunner.addResult(
       `Tests resource tree model on page reload, compares resource tree against golden. Every line is important.\n`);
-  await TestRunner.loadLegacyModule('console'); await TestRunner.loadTestModule('application_test_runner');
+  await TestRunner.loadLegacyModule('console');
   await TestRunner.showPanel('resources');
   await TestRunner.navigatePromise(TestRunner.url('resources/resource-tree-reload.html'));
   await TestRunner.reloadPagePromise();
diff --git a/third_party/blink/web_tests/http/tests/devtools/runtime/evaluate-timeout.js b/third_party/blink/web_tests/http/tests/devtools/runtime/evaluate-timeout.js
index dd38bbe8..e6bc0f36 100644
--- a/third_party/blink/web_tests/http/tests/devtools/runtime/evaluate-timeout.js
+++ b/third_party/blink/web_tests/http/tests/devtools/runtime/evaluate-timeout.js
@@ -2,8 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {SourcesTestRunner} from 'sources_test_runner';
+
 (async function() {
-  await TestRunner.loadLegacyModule('sources'); await TestRunner.loadTestModule('sources_test_runner');
+  await TestRunner.loadLegacyModule('sources');
   TestRunner.addResult("Test frontend's timeout support.\n");
 
   const executionContext = UI.context.flavor(SDK.ExecutionContext);
diff --git a/third_party/blink/web_tests/http/tests/devtools/runtime/evaluate-without-side-effects.js b/third_party/blink/web_tests/http/tests/devtools/runtime/evaluate-without-side-effects.js
index 7e625595..4a6be195 100644
--- a/third_party/blink/web_tests/http/tests/devtools/runtime/evaluate-without-side-effects.js
+++ b/third_party/blink/web_tests/http/tests/devtools/runtime/evaluate-without-side-effects.js
@@ -2,8 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {SourcesTestRunner} from 'sources_test_runner';
+
 (async function() {
-  await TestRunner.loadLegacyModule('sources'); await TestRunner.loadTestModule('sources_test_runner');
+  await TestRunner.loadLegacyModule('sources');
   TestRunner.addResult("Test frontend's side-effect support check for compatibility.\n");
 
   const executionContext = UI.context.flavor(SDK.ExecutionContext);
diff --git a/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-callFunctionOn.js b/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-callFunctionOn.js
index 62dde2f..40aaf4b 100644
--- a/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-callFunctionOn.js
+++ b/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-callFunctionOn.js
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+
 (async function() {
   TestRunner.addResult(`Tests TestRunner.RuntimeAgent.callFunctionOn usages.\n`);
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-es6-setSymbolPropertyValue-expected.txt b/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-es6-setSymbolPropertyValue-expected.txt
index 3917cce..8fac52b 100644
--- a/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-es6-setSymbolPropertyValue-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-es6-setSymbolPropertyValue-expected.txt
@@ -2,17 +2,17 @@
 
 
 Running: testSetUp
-runtime-es6-setSymbolPropertyValue.js:15 ===== Initial =====
-runtime-es6-setSymbolPropertyValue.js:16 2
-runtime-es6-setSymbolPropertyValue.js:17 
+runtime-es6-setSymbolPropertyValue.js:18 ===== Initial =====
+runtime-es6-setSymbolPropertyValue.js:19 2
+runtime-es6-setSymbolPropertyValue.js:20 
 
 Running: testSetSymbolPropertyValue
-runtime-es6-setSymbolPropertyValue.js:15 ===== Set property =====
-runtime-es6-setSymbolPropertyValue.js:16 3
-runtime-es6-setSymbolPropertyValue.js:17 
+runtime-es6-setSymbolPropertyValue.js:18 ===== Set property =====
+runtime-es6-setSymbolPropertyValue.js:19 3
+runtime-es6-setSymbolPropertyValue.js:20 
 
 Running: testDeleteSymbolProperty
-runtime-es6-setSymbolPropertyValue.js:15 ===== Delete property =====
-runtime-es6-setSymbolPropertyValue.js:16 undefined
-runtime-es6-setSymbolPropertyValue.js:17 
+runtime-es6-setSymbolPropertyValue.js:18 ===== Delete property =====
+runtime-es6-setSymbolPropertyValue.js:19 undefined
+runtime-es6-setSymbolPropertyValue.js:20 
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-es6-setSymbolPropertyValue.js b/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-es6-setSymbolPropertyValue.js
index 1793907..48a0657 100644
--- a/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-es6-setSymbolPropertyValue.js
+++ b/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-es6-setSymbolPropertyValue.js
@@ -2,9 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {ConsoleTestRunner} from 'console_test_runner';
+
 (async function() {
   TestRunner.addResult(`Tests editing Symbol properties.\n`);
-  await TestRunner.loadLegacyModule('console'); await TestRunner.loadTestModule('console_test_runner');
+  await TestRunner.loadLegacyModule('console');
   await TestRunner.evaluateInPagePromise(`
       var object1 = { foo: 1 };
       var symbol1 = Symbol("a");
diff --git a/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-evaluate-bad-unicode.js b/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-evaluate-bad-unicode.js
index 58cdd32e..7f5807a4 100644
--- a/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-evaluate-bad-unicode.js
+++ b/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-evaluate-bad-unicode.js
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+
 (async function() {
   TestRunner.addResult(`Tests TestRunner.RuntimeAgent.evaluate can handle invalid Unicode code points and non-characters.\n`);
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-getProperties-isOwnProperty.js b/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-getProperties-isOwnProperty.js
index 0898fecf..6c1a26d 100644
--- a/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-getProperties-isOwnProperty.js
+++ b/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-getProperties-isOwnProperty.js
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+
 (async function() {
   TestRunner.addResult(`Tests RemoteObject.getProperties.\n`);
   await TestRunner.evaluateInPagePromise(`
diff --git a/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-getProperties.js b/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-getProperties.js
index d36b65c..1171a0f 100644
--- a/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-getProperties.js
+++ b/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-getProperties.js
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+
 (async function() {
   TestRunner.addResult(`Tests RemoteObject.getProperties.\n`);
   await TestRunner.evaluateInPagePromise(`
diff --git a/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-localStorage-getProperties.js b/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-localStorage-getProperties.js
index 43d3cd5..dde4d5f 100644
--- a/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-localStorage-getProperties.js
+++ b/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-localStorage-getProperties.js
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+
 (async function() {
   TestRunner.addResult(`Tests RemoteObject.getProperties on localStorage object. 66215\n`);
   await TestRunner.evaluateInPagePromise(`
diff --git a/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-setPropertyValue-expected.txt b/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-setPropertyValue-expected.txt
index 4a0e645..cc623a92 100644
--- a/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-setPropertyValue-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-setPropertyValue-expected.txt
@@ -23,33 +23,33 @@
 Running: testNegativeZero
 
 Running: testReleaseObjectIsCalled
-runtime-setPropertyValue.js:14 ===== Initial =====
-runtime-setPropertyValue.js:15 {"foo":1}
-runtime-setPropertyValue.js:16 
-runtime-setPropertyValue.js:14 ===== Set primitive =====
-runtime-setPropertyValue.js:15 {"foo":2}
-runtime-setPropertyValue.js:16 
-runtime-setPropertyValue.js:14 ===== Set handle =====
-runtime-setPropertyValue.js:15 {"foo":{"bar":2}}
-runtime-setPropertyValue.js:16 
-runtime-setPropertyValue.js:14 ===== Set undefined =====
-runtime-setPropertyValue.js:15 {}
-runtime-setPropertyValue.js:16 
-runtime-setPropertyValue.js:14 ===== Set zero =====
-runtime-setPropertyValue.js:15 {"foo":0}
-runtime-setPropertyValue.js:16 
-runtime-setPropertyValue.js:14 ===== Set null =====
-runtime-setPropertyValue.js:15 {"foo":null}
-runtime-setPropertyValue.js:16 
-runtime-setPropertyValue.js:14 ===== Set empty string =====
-runtime-setPropertyValue.js:15 {"foo":""}
-runtime-setPropertyValue.js:16 
-runtime-setPropertyValue.js:14 ===== Set exception =====
-runtime-setPropertyValue.js:15 {"foo":""}
-runtime-setPropertyValue.js:16 
-runtime-setPropertyValue.js:14 ===== Set non-finite numbers =====
-runtime-setPropertyValue.js:15 {"foo":"NaN","foo1":"Infinity","foo2":"-Infinity"}
-runtime-setPropertyValue.js:16 
-runtime-setPropertyValue.js:28 ===== Checking negative zero =====
-runtime-setPropertyValue.js:29 1/-0 = -Infinity
+runtime-setPropertyValue.js:17 ===== Initial =====
+runtime-setPropertyValue.js:18 {"foo":1}
+runtime-setPropertyValue.js:19 
+runtime-setPropertyValue.js:17 ===== Set primitive =====
+runtime-setPropertyValue.js:18 {"foo":2}
+runtime-setPropertyValue.js:19 
+runtime-setPropertyValue.js:17 ===== Set handle =====
+runtime-setPropertyValue.js:18 {"foo":{"bar":2}}
+runtime-setPropertyValue.js:19 
+runtime-setPropertyValue.js:17 ===== Set undefined =====
+runtime-setPropertyValue.js:18 {}
+runtime-setPropertyValue.js:19 
+runtime-setPropertyValue.js:17 ===== Set zero =====
+runtime-setPropertyValue.js:18 {"foo":0}
+runtime-setPropertyValue.js:19 
+runtime-setPropertyValue.js:17 ===== Set null =====
+runtime-setPropertyValue.js:18 {"foo":null}
+runtime-setPropertyValue.js:19 
+runtime-setPropertyValue.js:17 ===== Set empty string =====
+runtime-setPropertyValue.js:18 {"foo":""}
+runtime-setPropertyValue.js:19 
+runtime-setPropertyValue.js:17 ===== Set exception =====
+runtime-setPropertyValue.js:18 {"foo":""}
+runtime-setPropertyValue.js:19 
+runtime-setPropertyValue.js:17 ===== Set non-finite numbers =====
+runtime-setPropertyValue.js:18 {"foo":"NaN","foo1":"Infinity","foo2":"-Infinity"}
+runtime-setPropertyValue.js:19 
+runtime-setPropertyValue.js:31 ===== Checking negative zero =====
+runtime-setPropertyValue.js:32 1/-0 = -Infinity
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-setPropertyValue.js b/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-setPropertyValue.js
index 9352f82..2e88972 100644
--- a/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-setPropertyValue.js
+++ b/third_party/blink/web_tests/http/tests/devtools/runtime/runtime-setPropertyValue.js
@@ -2,9 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {ConsoleTestRunner} from 'console_test_runner';
+
 (async function() {
   TestRunner.addResult(`Tests WebInspector.RemoveObject.setPropertyValue implementation.\n`);
-  await TestRunner.loadLegacyModule('console'); await TestRunner.loadTestModule('console_test_runner');
+  await TestRunner.loadLegacyModule('console');
   await TestRunner.evaluateInPagePromise(`
       var object1 = { foo: 1 };
       var object2 = { bar: 2 };
diff --git a/third_party/blink/web_tests/http/tests/devtools/sdk/network-interception-wildcard-pattern-matching.js b/third_party/blink/web_tests/http/tests/devtools/sdk/network-interception-wildcard-pattern-matching.js
index 8cb624f5..4d18588d 100644
--- a/third_party/blink/web_tests/http/tests/devtools/sdk/network-interception-wildcard-pattern-matching.js
+++ b/third_party/blink/web_tests/http/tests/devtools/sdk/network-interception-wildcard-pattern-matching.js
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+
 (async function() {
   TestRunner.addResult("Test to ensure the consistency of front-end patterns vs backend patterns for request interception.\n");
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/search/search-ignore-binary-files-expected.txt b/third_party/blink/web_tests/http/tests/devtools/search/search-ignore-binary-files-expected.txt
index f58d853b..4b414293 100644
--- a/third_party/blink/web_tests/http/tests/devtools/search/search-ignore-binary-files-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/search/search-ignore-binary-files-expected.txt
@@ -1,5 +1,5 @@
 Verify that search doesn't search in binary resources.
 
 Search result #1: uiSourceCode.url = http://127.0.0.1:8000/devtools/search/search-ignore-binary-files.js
-  search match #1: lineNumber = 18, lineContent = '    var searchConfig = new Search.SearchConfig('sources.search-in-files', 'AAAAAAA', true, false);'
+  search match #1: lineNumber = 21, lineContent = '    var searchConfig = new Search.SearchConfig('sources.search-in-files', 'AAAAAAA', true, false);'
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/search/search-ignore-binary-files.js b/third_party/blink/web_tests/http/tests/devtools/search/search-ignore-binary-files.js
index 5929a17..bb4d758 100644
--- a/third_party/blink/web_tests/http/tests/devtools/search/search-ignore-binary-files.js
+++ b/third_party/blink/web_tests/http/tests/devtools/search/search-ignore-binary-files.js
@@ -2,9 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {SourcesTestRunner} from 'sources_test_runner';
+
 (async function() {
   TestRunner.addResult(`Verify that search doesn't search in binary resources.\n`);
-  await TestRunner.loadLegacyModule('sources'); await TestRunner.loadTestModule('sources_test_runner');
+  await TestRunner.loadLegacyModule('sources');
   await TestRunner.loadLegacyModule('search');
   await TestRunner.showPanel('sources');
   await TestRunner.loadHTML(`
diff --git a/third_party/blink/web_tests/http/tests/devtools/search/search-in-non-existing-resource.js b/third_party/blink/web_tests/http/tests/devtools/search/search-in-non-existing-resource.js
index 6c11f14b..22f10218 100644
--- a/third_party/blink/web_tests/http/tests/devtools/search/search-in-non-existing-resource.js
+++ b/third_party/blink/web_tests/http/tests/devtools/search/search-in-non-existing-resource.js
@@ -2,11 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {ApplicationTestRunner} from 'application_test_runner';
+import {SourcesTestRunner} from 'sources_test_runner';
+
 (async function() {
   TestRunner.addResult(
       `Tests single resource search in inspector page agent with non existing resource url does not cause a crash.\n`);
-  await TestRunner.loadLegacyModule('console'); await TestRunner.loadTestModule('application_test_runner');
-  await TestRunner.loadLegacyModule('sources'); await TestRunner.loadTestModule('sources_test_runner');
+  await TestRunner.loadLegacyModule('console');
+  await TestRunner.loadLegacyModule('sources');
   await TestRunner.showPanel('sources');
   await TestRunner.addIframe('resources/search.html');
   await TestRunner
diff --git a/third_party/blink/web_tests/http/tests/devtools/search/search-in-resource.js b/third_party/blink/web_tests/http/tests/devtools/search/search-in-resource.js
index c58f14d7..a3c0821 100644
--- a/third_party/blink/web_tests/http/tests/devtools/search/search-in-resource.js
+++ b/third_party/blink/web_tests/http/tests/devtools/search/search-in-resource.js
@@ -2,10 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {ApplicationTestRunner} from 'application_test_runner';
+import {SourcesTestRunner} from 'sources_test_runner';
+
 (async function() {
   TestRunner.addResult(`Tests single resource search in inspector page agent.\n`);
-  await TestRunner.loadLegacyModule('console'); await TestRunner.loadTestModule('application_test_runner');
-  await TestRunner.loadLegacyModule('sources'); await TestRunner.loadTestModule('sources_test_runner');
+  await TestRunner.loadLegacyModule('console');
+  await TestRunner.loadLegacyModule('sources');
   await TestRunner.showPanel('sources');
 
   await TestRunner.addIframe('resources/search.html');
diff --git a/third_party/blink/web_tests/http/tests/devtools/search/search-in-script.js b/third_party/blink/web_tests/http/tests/devtools/search/search-in-script.js
index 665a40c9..ec47b43 100644
--- a/third_party/blink/web_tests/http/tests/devtools/search/search-in-script.js
+++ b/third_party/blink/web_tests/http/tests/devtools/search/search-in-script.js
@@ -2,10 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {ApplicationTestRunner} from 'application_test_runner';
+import {SourcesTestRunner} from 'sources_test_runner';
+
 (async function() {
   TestRunner.addResult(`Tests script search in inspector debugger agent.\n`);
-  await TestRunner.loadLegacyModule('console'); await TestRunner.loadTestModule('application_test_runner');
-  await TestRunner.loadLegacyModule('sources'); await TestRunner.loadTestModule('sources_test_runner');
+  await TestRunner.loadLegacyModule('console');
+  await TestRunner.loadLegacyModule('sources');
   await TestRunner.showPanel('sources');
 
   await TestRunner.addIframe('resources/search.html');
diff --git a/third_party/blink/web_tests/http/tests/devtools/search/search-in-sourcemap.js b/third_party/blink/web_tests/http/tests/devtools/search/search-in-sourcemap.js
index 125282a..bc11032 100644
--- a/third_party/blink/web_tests/http/tests/devtools/search/search-in-sourcemap.js
+++ b/third_party/blink/web_tests/http/tests/devtools/search/search-in-sourcemap.js
@@ -2,10 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {ApplicationTestRunner} from 'application_test_runner';
+import {SourcesTestRunner} from 'sources_test_runner';
+
 (async function() {
   TestRunner.addResult(`Tests single resource search in inspector page agent.\n`);
-  await TestRunner.loadLegacyModule('console'); await TestRunner.loadTestModule('application_test_runner');
-  await TestRunner.loadLegacyModule('sources'); await TestRunner.loadTestModule('sources_test_runner');
+  await TestRunner.loadLegacyModule('console');
+  await TestRunner.loadLegacyModule('sources');
   await TestRunner.loadLegacyModule('search');
   await TestRunner.showPanel('sources');
   await TestRunner.navigate('resources/sourcemap-page.html');
diff --git a/third_party/blink/web_tests/http/tests/devtools/search/search-in-static.js b/third_party/blink/web_tests/http/tests/devtools/search/search-in-static.js
index c6149a38..d05bec9a 100644
--- a/third_party/blink/web_tests/http/tests/devtools/search/search-in-static.js
+++ b/third_party/blink/web_tests/http/tests/devtools/search/search-in-static.js
@@ -2,10 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {ApplicationTestRunner} from 'application_test_runner';
+import {SourcesTestRunner} from 'sources_test_runner';
+
 (async function() {
   TestRunner.addResult(`Tests static content provider search.\n`);
-  await TestRunner.loadLegacyModule('console'); await TestRunner.loadTestModule('application_test_runner');
-  await TestRunner.loadLegacyModule('sources'); await TestRunner.loadTestModule('sources_test_runner');
+  await TestRunner.loadLegacyModule('console');
+  await TestRunner.loadLegacyModule('sources');
   await TestRunner.showPanel('sources');
 
   await TestRunner.addIframe('resources/search.html');
diff --git a/third_party/blink/web_tests/http/tests/devtools/search/sources-search-scope-in-files.js b/third_party/blink/web_tests/http/tests/devtools/search/sources-search-scope-in-files.js
index 6bf16ac..151b6b9 100644
--- a/third_party/blink/web_tests/http/tests/devtools/search/sources-search-scope-in-files.js
+++ b/third_party/blink/web_tests/http/tests/devtools/search/sources-search-scope-in-files.js
@@ -2,10 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {BindingsTestRunner} from 'bindings_test_runner';
+import {SourcesTestRunner} from 'sources_test_runner';
+
 (async function() {
   TestRunner.addResult(`Tests that ScriptSearchScope performs search across all sources correctly.\n`);
-  await TestRunner.loadTestModule('bindings_test_runner');
-  await TestRunner.loadLegacyModule('sources'); await TestRunner.loadTestModule('sources_test_runner');
+  await TestRunner.loadLegacyModule('sources');
   await TestRunner.loadLegacyModule('search');
   await TestRunner.showPanel('sources');
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/search/sources-search-scope-many-projects.js b/third_party/blink/web_tests/http/tests/devtools/search/sources-search-scope-many-projects.js
index 6ea2097..b81f8244 100644
--- a/third_party/blink/web_tests/http/tests/devtools/search/sources-search-scope-many-projects.js
+++ b/third_party/blink/web_tests/http/tests/devtools/search/sources-search-scope-many-projects.js
@@ -2,10 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {BindingsTestRunner} from 'bindings_test_runner';
+import {SourcesTestRunner} from 'sources_test_runner';
+
 (async function() {
   TestRunner.addResult(`Tests that ScriptSearchScope sorts network and dirty results correctly.\n`);
-  await TestRunner.loadTestModule('bindings_test_runner');
-  await TestRunner.loadLegacyModule('sources'); await TestRunner.loadTestModule('sources_test_runner');
+  await TestRunner.loadLegacyModule('sources');
   await TestRunner.loadLegacyModule('search');
   await TestRunner.showPanel('sources');
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/security/blank-origins-not-shown.js b/third_party/blink/web_tests/http/tests/devtools/security/blank-origins-not-shown.js
index a98595f..fd2d09e 100644
--- a/third_party/blink/web_tests/http/tests/devtools/security/blank-origins-not-shown.js
+++ b/third_party/blink/web_tests/http/tests/devtools/security/blank-origins-not-shown.js
@@ -2,9 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {SecurityTestRunner} from 'security_test_runner';
+
 (async function() {
   TestRunner.addResult(`Tests that blank origins aren't shown in the security panel origins list.\n`);
-  await TestRunner.loadTestModule('security_test_runner');
   await TestRunner.showPanel('security');
 
   var request1 = SDK.NetworkRequest.create(
diff --git a/third_party/blink/web_tests/http/tests/devtools/security/blocked-mixed-content.js b/third_party/blink/web_tests/http/tests/devtools/security/blocked-mixed-content.js
index feda31d..29cd666 100644
--- a/third_party/blink/web_tests/http/tests/devtools/security/blocked-mixed-content.js
+++ b/third_party/blink/web_tests/http/tests/devtools/security/blocked-mixed-content.js
@@ -2,9 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {SecurityTestRunner} from 'security_test_runner';
+
 (async function() {
   TestRunner.addResult(`Tests active mixed content blocking in the security panel.\n`);
-  await TestRunner.loadTestModule('security_test_runner');
   await TestRunner.showPanel('security');
 
   TestRunner.mainTarget.model(Security.SecurityModel)
diff --git a/third_party/blink/web_tests/http/tests/devtools/security/failed-request.js b/third_party/blink/web_tests/http/tests/devtools/security/failed-request.js
index 281841f..23e1c47 100644
--- a/third_party/blink/web_tests/http/tests/devtools/security/failed-request.js
+++ b/third_party/blink/web_tests/http/tests/devtools/security/failed-request.js
@@ -2,10 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {SecurityTestRunner} from 'security_test_runner';
+
 (async function() {
   TestRunner.addResult(
       `Tests that origins with failed requests are shown correctly in the security panel origins list.\n`);
-  await TestRunner.loadTestModule('security_test_runner');
   await TestRunner.showPanel('security');
 
   var request1 = SDK.NetworkRequest.create(
diff --git a/third_party/blink/web_tests/http/tests/devtools/security/interstitial-sidebar.js b/third_party/blink/web_tests/http/tests/devtools/security/interstitial-sidebar.js
index 9cd3b41..73cdce9 100644
--- a/third_party/blink/web_tests/http/tests/devtools/security/interstitial-sidebar.js
+++ b/third_party/blink/web_tests/http/tests/devtools/security/interstitial-sidebar.js
@@ -2,10 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {SecurityTestRunner} from 'security_test_runner';
+
 (async function() {
   TestRunner.addResult(
       `Tests that the sidebar origin list disappears and appers when an interstitial is shown or hidden.\n`);
-  await TestRunner.loadTestModule('security_test_runner');
   await TestRunner.showPanel('security');
 
   var request1 = SDK.NetworkRequest.create(
diff --git a/third_party/blink/web_tests/http/tests/devtools/security/main-origin-assigned-despite-request-missing.js b/third_party/blink/web_tests/http/tests/devtools/security/main-origin-assigned-despite-request-missing.js
index 858b436..0c35ee9 100644
--- a/third_party/blink/web_tests/http/tests/devtools/security/main-origin-assigned-despite-request-missing.js
+++ b/third_party/blink/web_tests/http/tests/devtools/security/main-origin-assigned-despite-request-missing.js
@@ -2,9 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {SecurityTestRunner} from 'security_test_runner';
+
 (async function() {
   TestRunner.addResult(`Tests that the Main Origin is assigned even if there is no matching Request.\n`);
-  await TestRunner.loadTestModule('security_test_runner');
   await TestRunner.showPanel('security');
 
   TestRunner.mainTarget.model(Security.SecurityModel)
diff --git a/third_party/blink/web_tests/http/tests/devtools/security/mixed-content-active-and-passive-reload.js b/third_party/blink/web_tests/http/tests/devtools/security/mixed-content-active-and-passive-reload.js
index 31b13a0b..26ea69e3 100644
--- a/third_party/blink/web_tests/http/tests/devtools/security/mixed-content-active-and-passive-reload.js
+++ b/third_party/blink/web_tests/http/tests/devtools/security/mixed-content-active-and-passive-reload.js
@@ -2,10 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {SecurityTestRunner} from 'security_test_runner';
+
 (async function() {
   TestRunner.addResult(
       `Tests that the active and passive mixed content explanations prompt the user to refresh when there are no recorded requests, and link to the network panel when there are recorded requests.\n`);
-  await TestRunner.loadTestModule('security_test_runner');
   await TestRunner.showPanel('security');
 
   TestRunner.addResult('\nBefore Refresh --------------');
diff --git a/third_party/blink/web_tests/http/tests/devtools/security/mixed-content-reload.js b/third_party/blink/web_tests/http/tests/devtools/security/mixed-content-reload.js
index 669187d..e27b24f 100644
--- a/third_party/blink/web_tests/http/tests/devtools/security/mixed-content-reload.js
+++ b/third_party/blink/web_tests/http/tests/devtools/security/mixed-content-reload.js
@@ -2,10 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {SecurityTestRunner} from 'security_test_runner';
+
 (async function() {
   TestRunner.addResult(
       `Tests that the mixed content explanation prompts the user to refresh when there are no recorded requests, and links to the network panel when there are recorded requests.\n`);
-  await TestRunner.loadTestModule('security_test_runner');
   await TestRunner.showPanel('security');
 
   TestRunner.addResult('\nBefore Refresh --------------');
diff --git a/third_party/blink/web_tests/http/tests/devtools/security/mixed-content-sidebar.js b/third_party/blink/web_tests/http/tests/devtools/security/mixed-content-sidebar.js
index 3287953..77a897fc 100644
--- a/third_party/blink/web_tests/http/tests/devtools/security/mixed-content-sidebar.js
+++ b/third_party/blink/web_tests/http/tests/devtools/security/mixed-content-sidebar.js
@@ -2,10 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {SecurityTestRunner} from 'security_test_runner';
+
 (async function() {
   TestRunner.addResult(
       `Tests that the sidebar uses the correct styling for mixed content subresources.\n`);
-  await TestRunner.loadTestModule('security_test_runner');
   await TestRunner.showPanel('security');
 
   const pageVisibleSecurityState = new Security.PageVisibleSecurityState(
diff --git a/third_party/blink/web_tests/http/tests/devtools/security/origin-group-names-unique.js b/third_party/blink/web_tests/http/tests/devtools/security/origin-group-names-unique.js
index 25fd631..0c3e21c6 100644
--- a/third_party/blink/web_tests/http/tests/devtools/security/origin-group-names-unique.js
+++ b/third_party/blink/web_tests/http/tests/devtools/security/origin-group-names-unique.js
@@ -2,9 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {SecurityTestRunner} from 'security_test_runner';
+
 (async function() {
   TestRunner.addResult(`Tests that origin group names in the Security panel are distinct.\n`);
-  await TestRunner.loadTestModule('security_test_runner');
   await TestRunner.showPanel('security');
 
   var originGroupNameSize = Object.keys(Security.SecurityPanelSidebarTree.OriginGroup).length;
diff --git a/third_party/blink/web_tests/http/tests/devtools/security/origin-view-ct-compliance.js b/third_party/blink/web_tests/http/tests/devtools/security/origin-view-ct-compliance.js
index ee9b66f..c2af8d9 100644
--- a/third_party/blink/web_tests/http/tests/devtools/security/origin-view-ct-compliance.js
+++ b/third_party/blink/web_tests/http/tests/devtools/security/origin-view-ct-compliance.js
@@ -2,10 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {SecurityTestRunner} from 'security_test_runner';
+
 (async function() {
   TestRunner.addResult(
       `Tests that the panel includes Certificate Transparency compliance status\n`);
-  await TestRunner.loadTestModule('security_test_runner');
   await TestRunner.showPanel('security');
 
   var request1 = SDK.NetworkRequest.create(
diff --git a/third_party/blink/web_tests/http/tests/devtools/security/origin-view-noncryptographic-secure-origin.js b/third_party/blink/web_tests/http/tests/devtools/security/origin-view-noncryptographic-secure-origin.js
index 4acb309..b76300a 100644
--- a/third_party/blink/web_tests/http/tests/devtools/security/origin-view-noncryptographic-secure-origin.js
+++ b/third_party/blink/web_tests/http/tests/devtools/security/origin-view-noncryptographic-secure-origin.js
@@ -2,10 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {SecurityTestRunner} from 'security_test_runner';
+
 (async function() {
   TestRunner.addResult(
       `Tests that the panel shows the correct text for non-cryptographic secure origins\n`);
-  await TestRunner.loadTestModule('security_test_runner');
   await TestRunner.showPanel('security');
 
   var request1 = SDK.NetworkRequest.create(
diff --git a/third_party/blink/web_tests/http/tests/devtools/security/origin-view-then-interstitial.js b/third_party/blink/web_tests/http/tests/devtools/security/origin-view-then-interstitial.js
index 346fe3c4..5f91868 100644
--- a/third_party/blink/web_tests/http/tests/devtools/security/origin-view-then-interstitial.js
+++ b/third_party/blink/web_tests/http/tests/devtools/security/origin-view-then-interstitial.js
@@ -2,10 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {SecurityTestRunner} from 'security_test_runner';
+
 (async function() {
   TestRunner.addResult(
       `Tests that the panel transitions to the overview view when navigating to an interstitial. Regression test for https://crbug.com/638601\n`);
-  await TestRunner.loadTestModule('security_test_runner');
   await TestRunner.showPanel('security');
 
   var request1 = SDK.NetworkRequest.create(
diff --git a/third_party/blink/web_tests/http/tests/devtools/security/security-blocked-mixed-content.js b/third_party/blink/web_tests/http/tests/devtools/security/security-blocked-mixed-content.js
index 89dbcae..a28e4a1 100644
--- a/third_party/blink/web_tests/http/tests/devtools/security/security-blocked-mixed-content.js
+++ b/third_party/blink/web_tests/http/tests/devtools/security/security-blocked-mixed-content.js
@@ -2,9 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {SecurityTestRunner} from 'security_test_runner';
+
 (async function() {
   TestRunner.addResult(`Tests active mixed content blocking in the security panel.\n`);
-  await TestRunner.loadTestModule('security_test_runner');
   await TestRunner.showPanel('security');
 
   TestRunner.mainTarget.model(Security.SecurityModel)
diff --git a/third_party/blink/web_tests/http/tests/devtools/security/security-details-updated-with-security-state.js b/third_party/blink/web_tests/http/tests/devtools/security/security-details-updated-with-security-state.js
index 3060889c..869773b 100644
--- a/third_party/blink/web_tests/http/tests/devtools/security/security-details-updated-with-security-state.js
+++ b/third_party/blink/web_tests/http/tests/devtools/security/security-details-updated-with-security-state.js
@@ -2,9 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {SecurityTestRunner} from 'security_test_runner';
+
 (async function() {
   TestRunner.addResult(`Tests that the security details for an origin are updated if its security state changes.\n`);
-  await TestRunner.loadTestModule('security_test_runner');
   await TestRunner.showPanel('security');
 
   // Add a request without security details.
diff --git a/third_party/blink/web_tests/http/tests/devtools/security/security-explanation-ordering.js b/third_party/blink/web_tests/http/tests/devtools/security/security-explanation-ordering.js
index b13d8719..750a392 100644
--- a/third_party/blink/web_tests/http/tests/devtools/security/security-explanation-ordering.js
+++ b/third_party/blink/web_tests/http/tests/devtools/security/security-explanation-ordering.js
@@ -2,9 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {SecurityTestRunner} from 'security_test_runner';
+
 (async function() {
   TestRunner.addResult(`Tests that info explanations are placed after regular explanations.\n`);
-  await TestRunner.loadTestModule('security_test_runner');
   await TestRunner.showPanel('security');
 
   const pageVisibleSecurityState = new Security.PageVisibleSecurityState(
diff --git a/third_party/blink/web_tests/http/tests/devtools/security/security-state-comparator.js b/third_party/blink/web_tests/http/tests/devtools/security/security-state-comparator.js
index 678cb20..2e48aa6a 100644
--- a/third_party/blink/web_tests/http/tests/devtools/security/security-state-comparator.js
+++ b/third_party/blink/web_tests/http/tests/devtools/security/security-state-comparator.js
@@ -2,9 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {SecurityTestRunner} from 'security_test_runner';
+
 (async function() {
   TestRunner.addResult(`Tests that SecurityStateComparator correctly compares the severity of security states.\n`);
-  await TestRunner.loadTestModule('security_test_runner');
   await TestRunner.showPanel('security');
 
   var ordering = [
diff --git a/third_party/blink/web_tests/http/tests/devtools/security/security-unknown-resource.js b/third_party/blink/web_tests/http/tests/devtools/security/security-unknown-resource.js
index bed7cba7..3432c92c 100644
--- a/third_party/blink/web_tests/http/tests/devtools/security/security-unknown-resource.js
+++ b/third_party/blink/web_tests/http/tests/devtools/security/security-unknown-resource.js
@@ -2,10 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {TestRunner} from 'test_runner';
+import {SecurityTestRunner} from 'security_test_runner';
+
 (async function() {
   TestRunner.addResult(
       `Tests that requests to unresolved origins result in unknown security state and show up in the sidebar origin list.\n`);
-  await TestRunner.loadTestModule('security_test_runner');
   await TestRunner.showPanel('security');
 
   var request = SDK.NetworkRequest.create(
diff --git a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-misc/timeline-event-causes-expected.txt b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-misc/timeline-event-causes-expected.txt
deleted file mode 100644
index 10a83aa..0000000
--- a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-misc/timeline-event-causes-expected.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-Test that causes are correctly generated for various types of events.
-
-
-Running: testTimerInstall
-PASS - record contained Timer Installed
-(anonymous) @ setTimeoutFunction.js:
-
-Running: testRequestAnimationFrame
-PASS - record contained Animation Frame Requested
-(anonymous) @ requestAnimationFrameFunction.js:
-
-Running: testStyleRecalc
-PASS - record contained First Invalidated
-styleRecalcFunction @ styleRecalcFunction.js:
-
-Running: testLayout
-PASS - record contained Layout Forced
-layoutFunction @ layoutFunction.js:
-PASS - record contained First Layout Invalidation
-layoutFunction @ layoutFunction.js:
-
diff --git a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-misc/timeline-event-causes.js b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-misc/timeline-event-causes.js
deleted file mode 100644
index 82ce221..0000000
--- a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-misc/timeline-event-causes.js
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright 2017 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-(async function() {
-  TestRunner.addResult(`Test that causes are correctly generated for various types of events.\n`);
-  await TestRunner.loadLegacyModule('timeline'); await TestRunner.loadTestModule('performance_test_runner');
-  await TestRunner.loadLegacyModule('components');
-  await TestRunner.showPanel('timeline');
-  await TestRunner.loadHTML(`
-      <div id="testElement"></div>
-    `);
-
-  function checkStringContains(string, contains) {
-    var doesContain = string.indexOf(contains) >= 0;
-    TestRunner.check(doesContain, contains + ' should be present in ' + string);
-    TestRunner.addResult('PASS - record contained ' + contains);
-  }
-
-  TestRunner.runTestSuite([
-    async function testTimerInstall(next) {
-      function setTimeoutFunction() {
-        return new Promise((fulfill) => setTimeout(fulfill, 0));
-      }
-
-      var source = setTimeoutFunction.toString();
-      source += '\n//# sourceURL=setTimeoutFunction.js';
-      TestRunner.evaluateInPage(source);
-
-      await PerformanceTestRunner.invokeAsyncWithTimeline('setTimeoutFunction');
-
-      var linkifier = new Components.Linkifier();
-      var event = PerformanceTestRunner.findTimelineEvent('TimerFire');
-      TestRunner.check(event, 'Should receive a TimerFire event.');
-      var contentHelper = new Timeline.TimelineDetailsContentHelper(
-          PerformanceTestRunner.timelineModel().targetByEvent(event), linkifier, true);
-      Timeline.TimelineUIUtils.generateCauses(
-          event, PerformanceTestRunner.timelineModel().targetByEvent(event), null, contentHelper);
-      await TestRunner.waitForPendingLiveLocationUpdates();
-      var causes = contentHelper.element.deepTextContent();
-      TestRunner.check(causes, 'Should generate causes');
-      checkStringContains(causes, 'Timer Installed\n(anonymous) @ setTimeoutFunction.js:');
-      next();
-    },
-
-    async function testRequestAnimationFrame(next) {
-      function requestAnimationFrameFunction(callback) {
-        return new Promise((fulfill) => requestAnimationFrame(fulfill));
-      }
-
-      var source = requestAnimationFrameFunction.toString();
-      source += '\n//# sourceURL=requestAnimationFrameFunction.js';
-      TestRunner.evaluateInPage(source);
-
-      await PerformanceTestRunner.invokeAsyncWithTimeline('requestAnimationFrameFunction');
-      var linkifier = new Components.Linkifier();
-      var event = PerformanceTestRunner.findTimelineEvent('FireAnimationFrame');
-      TestRunner.check(event, 'Should receive a FireAnimationFrame event.');
-      var contentHelper = new Timeline.TimelineDetailsContentHelper(
-          PerformanceTestRunner.timelineModel().targetByEvent(event), linkifier, true);
-      Timeline.TimelineUIUtils.generateCauses(
-          event, PerformanceTestRunner.timelineModel().targetByEvent(event), null, contentHelper);
-      await TestRunner.waitForPendingLiveLocationUpdates();
-      var causes = contentHelper.element.deepTextContent();
-      TestRunner.check(causes, 'Should generate causes');
-      checkStringContains(causes, 'Animation Frame Requested\n(anonymous) @ requestAnimationFrameFunction.js:');
-      next();
-    },
-
-    async function testStyleRecalc(next) {
-      function styleRecalcFunction() {
-        var element = document.getElementById('testElement');
-        element.style.backgroundColor = 'papayawhip';
-        var forceLayout = element.offsetWidth;
-      }
-
-      var source = styleRecalcFunction.toString();
-      source += '\n//# sourceURL=styleRecalcFunction.js';
-      TestRunner.evaluateInPage(source);
-
-      await PerformanceTestRunner.evaluateWithTimeline('styleRecalcFunction()');
-      var linkifier = new Components.Linkifier();
-      var event = PerformanceTestRunner.findTimelineEvent('UpdateLayoutTree');
-      TestRunner.check(event, 'Should receive a UpdateLayoutTree event.');
-      var contentHelper = new Timeline.TimelineDetailsContentHelper(
-          PerformanceTestRunner.timelineModel().targetByEvent(event), linkifier, true);
-      Timeline.TimelineUIUtils.generateCauses(
-          event, PerformanceTestRunner.timelineModel().targetByEvent(event), null, contentHelper);
-      await TestRunner.waitForPendingLiveLocationUpdates();
-      var causes = contentHelper.element.deepTextContent();
-      TestRunner.check(causes, 'Should generate causes');
-      checkStringContains(causes, 'First Invalidated\nstyleRecalcFunction @ styleRecalcFunction.js:');
-      next();
-    },
-
-    async function testLayout(next) {
-      function layoutFunction() {
-        var element = document.getElementById('testElement');
-        element.style.width = '200px';
-        var forceLayout = element.offsetWidth;
-      }
-
-      var source = layoutFunction.toString();
-      source += '\n//# sourceURL=layoutFunction.js';
-      TestRunner.evaluateInPage(source);
-
-      await PerformanceTestRunner.evaluateWithTimeline('layoutFunction()');
-      var linkifier = new Components.Linkifier();
-      var event = PerformanceTestRunner.findTimelineEvent('Layout');
-      TestRunner.check(event, 'Should receive a Layout event.');
-      var contentHelper = new Timeline.TimelineDetailsContentHelper(
-          PerformanceTestRunner.timelineModel().targetByEvent(event), linkifier, true);
-      Timeline.TimelineUIUtils.generateCauses(
-          event, PerformanceTestRunner.timelineModel().targetByEvent(event), null, contentHelper);
-      await TestRunner.waitForPendingLiveLocationUpdates();
-      var causes = contentHelper.element.deepTextContent();
-      TestRunner.check(causes, 'Should generate causes');
-      checkStringContains(causes, 'Layout Forced\nlayoutFunction @ layoutFunction.js:');
-      checkStringContains(causes, 'First Layout Invalidation\nlayoutFunction @ layoutFunction.js:');
-      next();
-    }
-  ]);
-})();
diff --git a/third_party/blink/web_tests/http/tests/security/cross-origin-OffscreenCanvas2D-createPattern-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-origin-OffscreenCanvas2D-createPattern-expected.txt
index 3356d98a..ccaf0c6 100644
--- a/third_party/blink/web_tests/http/tests/security/cross-origin-OffscreenCanvas2D-createPattern-expected.txt
+++ b/third_party/blink/web_tests/http/tests/security/cross-origin-OffscreenCanvas2D-createPattern-expected.txt
@@ -2,8 +2,8 @@
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
+PASS ImageBitmap is tainted. Threw error: SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.
 PASS successfullyParsed is true
 
 TEST COMPLETE
 
-PASS ImageBitmap is tainted. Threw error: SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.
diff --git a/third_party/blink/web_tests/http/tests/security/cross-origin-OffscreenCanvas2D-createPattern.html b/third_party/blink/web_tests/http/tests/security/cross-origin-OffscreenCanvas2D-createPattern.html
index 230f2952..49f59ec7 100644
--- a/third_party/blink/web_tests/http/tests/security/cross-origin-OffscreenCanvas2D-createPattern.html
+++ b/third_party/blink/web_tests/http/tests/security/cross-origin-OffscreenCanvas2D-createPattern.html
@@ -3,6 +3,7 @@
 <body>
 <script src="/js-test-resources/js-test.js"></script>
 <script>
+jsTestIsAsync = true;
 description("The pattern created by OffscreenCanvas2D from cross-origin image must be tainted.");
 
 function shouldBeTainted(pattern) {
@@ -28,7 +29,8 @@
     var offscreenContext = offscreenCanvas.getContext("2d");
     var pat = offscreenContext.createPattern(image, "no-repeat");
     shouldBeTainted(pat);
- });
+    finishJSTest();
+});
 
 </script>
 </body>
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/webnn/idlharness.https.any-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/webnn/idlharness.https.any-expected.txt
index 97c2898..cf97c09 100644
--- a/third_party/blink/web_tests/platform/mac/external/wpt/webnn/idlharness.https.any-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/external/wpt/webnn/idlharness.https.any-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 408 tests; 279 PASS, 129 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 408 tests; 282 PASS, 126 FAIL, 0 TIMEOUT, 0 NOTRUN.
 FAIL idl_test setup promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
 PASS idl_test validation
 PASS Partial interface MLContext: original interface defined
@@ -245,7 +245,7 @@
 PASS MLGraphBuilder interface: operation reshape(MLOperand, sequence<unsigned long?>)
 PASS MLGraphBuilder interface: operation sigmoid(MLOperand)
 PASS MLGraphBuilder interface: operation sigmoid()
-FAIL MLGraphBuilder interface: operation slice(MLOperand, sequence<unsigned long>, sequence<unsigned long>) assert_own_property: interface prototype object missing non-static operation expected property "slice" missing
+PASS MLGraphBuilder interface: operation slice(MLOperand, sequence<unsigned long>, sequence<unsigned long>)
 FAIL MLGraphBuilder interface: operation softmax(MLOperand) assert_equals: property has wrong .length expected 0 but got 1
 FAIL MLGraphBuilder interface: operation softmax() assert_equals: property has wrong .length expected 0 but got 1
 FAIL MLGraphBuilder interface: operation softplus(MLOperand, optional MLSoftplusOptions) assert_own_property: interface prototype object missing non-static operation expected property "softplus" missing
@@ -385,8 +385,8 @@
 PASS MLGraphBuilder interface: builder must inherit property "sigmoid(MLOperand)" with the proper type
 PASS MLGraphBuilder interface: calling sigmoid(MLOperand) on builder with too few arguments must throw TypeError
 PASS MLGraphBuilder interface: builder must inherit property "sigmoid()" with the proper type
-FAIL MLGraphBuilder interface: builder must inherit property "slice(MLOperand, sequence<unsigned long>, sequence<unsigned long>)" with the proper type assert_inherits: property "slice" not found in prototype chain
-FAIL MLGraphBuilder interface: calling slice(MLOperand, sequence<unsigned long>, sequence<unsigned long>) on builder with too few arguments must throw TypeError assert_inherits: property "slice" not found in prototype chain
+PASS MLGraphBuilder interface: builder must inherit property "slice(MLOperand, sequence<unsigned long>, sequence<unsigned long>)" with the proper type
+PASS MLGraphBuilder interface: calling slice(MLOperand, sequence<unsigned long>, sequence<unsigned long>) on builder with too few arguments must throw TypeError
 PASS MLGraphBuilder interface: builder must inherit property "softmax(MLOperand)" with the proper type
 PASS MLGraphBuilder interface: calling softmax(MLOperand) on builder with too few arguments must throw TypeError
 PASS MLGraphBuilder interface: builder must inherit property "softmax()" with the proper type
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/webnn/idlharness.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/webnn/idlharness.https.any.worker-expected.txt
index b080058..230c9eb 100644
--- a/third_party/blink/web_tests/platform/mac/external/wpt/webnn/idlharness.https.any.worker-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/external/wpt/webnn/idlharness.https.any.worker-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 414 tests; 278 PASS, 136 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 414 tests; 281 PASS, 133 FAIL, 0 TIMEOUT, 0 NOTRUN.
 FAIL idl_test setup promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented"
 PASS idl_test validation
 PASS Partial interface MLContext: original interface defined
@@ -250,7 +250,7 @@
 PASS MLGraphBuilder interface: operation reshape(MLOperand, sequence<unsigned long?>)
 PASS MLGraphBuilder interface: operation sigmoid(MLOperand)
 PASS MLGraphBuilder interface: operation sigmoid()
-FAIL MLGraphBuilder interface: operation slice(MLOperand, sequence<unsigned long>, sequence<unsigned long>) assert_own_property: interface prototype object missing non-static operation expected property "slice" missing
+PASS MLGraphBuilder interface: operation slice(MLOperand, sequence<unsigned long>, sequence<unsigned long>)
 FAIL MLGraphBuilder interface: operation softmax(MLOperand) assert_equals: property has wrong .length expected 0 but got 1
 FAIL MLGraphBuilder interface: operation softmax() assert_equals: property has wrong .length expected 0 but got 1
 FAIL MLGraphBuilder interface: operation softplus(MLOperand, optional MLSoftplusOptions) assert_own_property: interface prototype object missing non-static operation expected property "softplus" missing
@@ -391,8 +391,8 @@
 PASS MLGraphBuilder interface: builder must inherit property "sigmoid(MLOperand)" with the proper type
 PASS MLGraphBuilder interface: calling sigmoid(MLOperand) on builder with too few arguments must throw TypeError
 PASS MLGraphBuilder interface: builder must inherit property "sigmoid()" with the proper type
-FAIL MLGraphBuilder interface: builder must inherit property "slice(MLOperand, sequence<unsigned long>, sequence<unsigned long>)" with the proper type assert_inherits: property "slice" not found in prototype chain
-FAIL MLGraphBuilder interface: calling slice(MLOperand, sequence<unsigned long>, sequence<unsigned long>) on builder with too few arguments must throw TypeError assert_inherits: property "slice" not found in prototype chain
+PASS MLGraphBuilder interface: builder must inherit property "slice(MLOperand, sequence<unsigned long>, sequence<unsigned long>)" with the proper type
+PASS MLGraphBuilder interface: calling slice(MLOperand, sequence<unsigned long>, sequence<unsigned long>) on builder with too few arguments must throw TypeError
 PASS MLGraphBuilder interface: builder must inherit property "softmax(MLOperand)" with the proper type
 PASS MLGraphBuilder interface: calling softmax(MLOperand) on builder with too few arguments must throw TypeError
 PASS MLGraphBuilder interface: builder must inherit property "softmax()" with the proper type
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/webnn/slice.https.any-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/webnn/slice.https.any-expected.txt
new file mode 100644
index 0000000..957db29
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/external/wpt/webnn/slice.https.any-expected.txt
@@ -0,0 +1,8 @@
+This is a testharness.js-based test.
+FAIL slice float32 1D tensor / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
+FAIL slice float32 2D tensor / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
+FAIL slice float32 3D tensor / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
+FAIL slice float32 4D tensor / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
+FAIL slice float32 5D tensor / async promise_test: Unhandled rejection with value: object "NotSupportedError: Not implemented"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/webnn/slice.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/webnn/slice.https.any.worker-expected.txt
new file mode 100644
index 0000000..88d0a79
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/external/wpt/webnn/slice.https.any.worker-expected.txt
@@ -0,0 +1,13 @@
+This is a testharness.js-based test.
+FAIL slice float32 1D tensor / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
+FAIL slice float32 2D tensor / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
+FAIL slice float32 3D tensor / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
+FAIL slice float32 4D tensor / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
+FAIL slice float32 5D tensor / sync Failed to execute 'buildSync' on 'MLGraphBuilder': Not implemented
+FAIL slice float32 1D tensor / async promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function"
+FAIL slice float32 2D tensor / async promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function"
+FAIL slice float32 3D tensor / async promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function"
+FAIL slice float32 4D tensor / async promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function"
+FAIL slice float32 5D tensor / async promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/webnn/idlharness.https.any-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/webnn/idlharness.https.any-expected.txt
index cb3c93b..c14426d7 100644
--- a/third_party/blink/web_tests/platform/win/external/wpt/webnn/idlharness.https.any-expected.txt
+++ b/third_party/blink/web_tests/platform/win/external/wpt/webnn/idlharness.https.any-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 408 tests; 279 PASS, 129 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 408 tests; 282 PASS, 126 FAIL, 0 TIMEOUT, 0 NOTRUN.
 FAIL idl_test setup promise_test: Unhandled rejection with value: object "NotSupportedError: The input layout nchw is not supported."
 PASS idl_test validation
 PASS Partial interface MLContext: original interface defined
@@ -245,7 +245,7 @@
 PASS MLGraphBuilder interface: operation reshape(MLOperand, sequence<unsigned long?>)
 PASS MLGraphBuilder interface: operation sigmoid(MLOperand)
 PASS MLGraphBuilder interface: operation sigmoid()
-FAIL MLGraphBuilder interface: operation slice(MLOperand, sequence<unsigned long>, sequence<unsigned long>) assert_own_property: interface prototype object missing non-static operation expected property "slice" missing
+PASS MLGraphBuilder interface: operation slice(MLOperand, sequence<unsigned long>, sequence<unsigned long>)
 FAIL MLGraphBuilder interface: operation softmax(MLOperand) assert_equals: property has wrong .length expected 0 but got 1
 FAIL MLGraphBuilder interface: operation softmax() assert_equals: property has wrong .length expected 0 but got 1
 FAIL MLGraphBuilder interface: operation softplus(MLOperand, optional MLSoftplusOptions) assert_own_property: interface prototype object missing non-static operation expected property "softplus" missing
@@ -385,8 +385,8 @@
 PASS MLGraphBuilder interface: builder must inherit property "sigmoid(MLOperand)" with the proper type
 PASS MLGraphBuilder interface: calling sigmoid(MLOperand) on builder with too few arguments must throw TypeError
 PASS MLGraphBuilder interface: builder must inherit property "sigmoid()" with the proper type
-FAIL MLGraphBuilder interface: builder must inherit property "slice(MLOperand, sequence<unsigned long>, sequence<unsigned long>)" with the proper type assert_inherits: property "slice" not found in prototype chain
-FAIL MLGraphBuilder interface: calling slice(MLOperand, sequence<unsigned long>, sequence<unsigned long>) on builder with too few arguments must throw TypeError assert_inherits: property "slice" not found in prototype chain
+PASS MLGraphBuilder interface: builder must inherit property "slice(MLOperand, sequence<unsigned long>, sequence<unsigned long>)" with the proper type
+PASS MLGraphBuilder interface: calling slice(MLOperand, sequence<unsigned long>, sequence<unsigned long>) on builder with too few arguments must throw TypeError
 PASS MLGraphBuilder interface: builder must inherit property "softmax(MLOperand)" with the proper type
 PASS MLGraphBuilder interface: calling softmax(MLOperand) on builder with too few arguments must throw TypeError
 PASS MLGraphBuilder interface: builder must inherit property "softmax()" with the proper type
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/webnn/idlharness.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/webnn/idlharness.https.any.worker-expected.txt
index 523abe88..3a04951 100644
--- a/third_party/blink/web_tests/platform/win/external/wpt/webnn/idlharness.https.any.worker-expected.txt
+++ b/third_party/blink/web_tests/platform/win/external/wpt/webnn/idlharness.https.any.worker-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 414 tests; 278 PASS, 136 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 414 tests; 281 PASS, 133 FAIL, 0 TIMEOUT, 0 NOTRUN.
 FAIL idl_test setup promise_test: Unhandled rejection with value: object "NotSupportedError: Failed to execute 'buildSync' on 'MLGraphBuilder': The input layout nchw is not supported."
 PASS idl_test validation
 PASS Partial interface MLContext: original interface defined
@@ -250,7 +250,7 @@
 PASS MLGraphBuilder interface: operation reshape(MLOperand, sequence<unsigned long?>)
 PASS MLGraphBuilder interface: operation sigmoid(MLOperand)
 PASS MLGraphBuilder interface: operation sigmoid()
-FAIL MLGraphBuilder interface: operation slice(MLOperand, sequence<unsigned long>, sequence<unsigned long>) assert_own_property: interface prototype object missing non-static operation expected property "slice" missing
+PASS MLGraphBuilder interface: operation slice(MLOperand, sequence<unsigned long>, sequence<unsigned long>)
 FAIL MLGraphBuilder interface: operation softmax(MLOperand) assert_equals: property has wrong .length expected 0 but got 1
 FAIL MLGraphBuilder interface: operation softmax() assert_equals: property has wrong .length expected 0 but got 1
 FAIL MLGraphBuilder interface: operation softplus(MLOperand, optional MLSoftplusOptions) assert_own_property: interface prototype object missing non-static operation expected property "softplus" missing
@@ -391,8 +391,8 @@
 PASS MLGraphBuilder interface: builder must inherit property "sigmoid(MLOperand)" with the proper type
 PASS MLGraphBuilder interface: calling sigmoid(MLOperand) on builder with too few arguments must throw TypeError
 PASS MLGraphBuilder interface: builder must inherit property "sigmoid()" with the proper type
-FAIL MLGraphBuilder interface: builder must inherit property "slice(MLOperand, sequence<unsigned long>, sequence<unsigned long>)" with the proper type assert_inherits: property "slice" not found in prototype chain
-FAIL MLGraphBuilder interface: calling slice(MLOperand, sequence<unsigned long>, sequence<unsigned long>) on builder with too few arguments must throw TypeError assert_inherits: property "slice" not found in prototype chain
+PASS MLGraphBuilder interface: builder must inherit property "slice(MLOperand, sequence<unsigned long>, sequence<unsigned long>)" with the proper type
+PASS MLGraphBuilder interface: calling slice(MLOperand, sequence<unsigned long>, sequence<unsigned long>) on builder with too few arguments must throw TypeError
 PASS MLGraphBuilder interface: builder must inherit property "softmax(MLOperand)" with the proper type
 PASS MLGraphBuilder interface: calling softmax(MLOperand) on builder with too few arguments must throw TypeError
 PASS MLGraphBuilder interface: builder must inherit property "softmax()" with the proper type
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/webnn/slice.https.any-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/webnn/slice.https.any-expected.txt
new file mode 100644
index 0000000..6e62630
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/external/wpt/webnn/slice.https.any-expected.txt
@@ -0,0 +1,8 @@
+This is a testharness.js-based test.
+FAIL slice float32 1D tensor / async promise_test: Unhandled rejection with value: object "NotSupportedError: The operator (slice) is not supported."
+FAIL slice float32 2D tensor / async promise_test: Unhandled rejection with value: object "NotSupportedError: The operator (slice) is not supported."
+FAIL slice float32 3D tensor / async promise_test: Unhandled rejection with value: object "NotSupportedError: The operator (slice) is not supported."
+FAIL slice float32 4D tensor / async promise_test: Unhandled rejection with value: object "NotSupportedError: The operator (slice) is not supported."
+FAIL slice float32 5D tensor / async promise_test: Unhandled rejection with value: object "NotSupportedError: The operator (slice) is not supported."
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/webnn/slice.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/webnn/slice.https.any.worker-expected.txt
new file mode 100644
index 0000000..fdda7cb
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/external/wpt/webnn/slice.https.any.worker-expected.txt
@@ -0,0 +1,13 @@
+This is a testharness.js-based test.
+FAIL slice float32 1D tensor / sync Failed to execute 'buildSync' on 'MLGraphBuilder': The operator (slice) is not supported.
+FAIL slice float32 2D tensor / sync Failed to execute 'buildSync' on 'MLGraphBuilder': The operator (slice) is not supported.
+FAIL slice float32 3D tensor / sync Failed to execute 'buildSync' on 'MLGraphBuilder': The operator (slice) is not supported.
+FAIL slice float32 4D tensor / sync Failed to execute 'buildSync' on 'MLGraphBuilder': The operator (slice) is not supported.
+FAIL slice float32 5D tensor / sync Failed to execute 'buildSync' on 'MLGraphBuilder': The operator (slice) is not supported.
+FAIL slice float32 1D tensor / async promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function"
+FAIL slice float32 2D tensor / async promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function"
+FAIL slice float32 3D tensor / async promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function"
+FAIL slice float32 4D tensor / async promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function"
+FAIL slice float32 5D tensor / async promise_test: Unhandled rejection with value: object "TypeError: builder.build is not a function"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
index 5188d0b..b4ea454 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -1190,6 +1190,7 @@
 [Worker]     method resample2d
 [Worker]     method reshape
 [Worker]     method sigmoid
+[Worker]     method slice
 [Worker]     method softmax
 [Worker]     method sub
 [Worker]     method transpose
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
index 8720a07..a8455577 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -5547,6 +5547,7 @@
     method resample2d
     method reshape
     method sigmoid
+    method slice
     method softmax
     method sub
     method transpose
diff --git a/tools/clang/plugins/ChromeClassTester.cpp b/tools/clang/plugins/ChromeClassTester.cpp
index 0792336..e691bfc 100644
--- a/tools/clang/plugins/ChromeClassTester.cpp
+++ b/tools/clang/plugins/ChromeClassTester.cpp
@@ -7,8 +7,6 @@
 
 #include "ChromeClassTester.h"
 
-#include <algorithm>
-
 #include "Util.h"
 #include "clang/AST/AST.h"
 #include "clang/Basic/FileManager.h"
@@ -91,10 +89,6 @@
     filename.insert(0, 1, '/');
   }
 
-  // When using distributed cross compilation build tools, file paths can have
-  // separators which differ from ones at this platform. Make them consistent.
-  std::replace(filename.begin(), filename.end(), '\\', '/');
-
   // Don't check autogenerated files. ninja puts them in $OUT_DIR/gen.
   if (filename.find("/gen/") != std::string::npos)
     return LocationType::kThirdParty;
diff --git a/tools/clang/plugins/Util.cpp b/tools/clang/plugins/Util.cpp
index 5b6ebb41..08fbc6a 100644
--- a/tools/clang/plugins/Util.cpp
+++ b/tools/clang/plugins/Util.cpp
@@ -4,6 +4,8 @@
 
 #include "Util.h"
 
+#include <algorithm>
+
 #include "clang/AST/Decl.h"
 #include "clang/Basic/SourceManager.h"
 #include "llvm/Support/Casting.h"
@@ -48,5 +50,10 @@
     return "";
   }
 
-  return ploc.getFilename();
+  std::string name = ploc.getFilename();
+
+  // File paths can have separators which differ from ones at this platform.
+  // Make them consistent.
+  std::replace(name.begin(), name.end(), '\\', '/');
+  return name;
 }
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 41365e1..95d67b3e 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -34381,6 +34381,7 @@
   <int value="515" label="SMART_CARD_PROVIDER_PRIVATE_ON_TRANSMIT_REQUESTED"/>
   <int value="516" label="SMART_CARD_PROVIDER_PRIVATE_ON_CONTROL_REQUESTED"/>
   <int value="517" label="OS_EVENTS_ON_POWER_EVENT"/>
+  <int value="518" label="SMART_CARD_PROVIDER_PRIVATE_ON_GET_ATTRIB_REQUESTED"/>
 </enum>
 
 <enum name="ExtensionFileWriteResult">
@@ -44710,8 +44711,8 @@
 <enum name="FileSystemProviderOperationCompletion">
   <int value="0" label="CompletedNormally"/>
   <int value="1" label="CompletedAfterWarning"/>
-  <int value="2" label="AbortedManually"/>
-  <int value="3" label="AbortedOnTimeout"/>
+  <int value="2" label="AbortedFromNotification"/>
+  <int value="3" label="AbortedInternally"/>
 </enum>
 
 <enum name="FileType">
@@ -59465,6 +59466,8 @@
       label="WebViewCpuAffinityRestrictToLittleCores:disabled"/>
   <int value="-1725507605" label="enable-web-midi"/>
   <int value="-1722208902" label="CCTModuleCustomRequestHeader:disabled"/>
+  <int value="-1720654843"
+      label="AutofillMoveLegalTermsAndIconForNewCardEnrollment:enabled"/>
   <int value="-1720576957" label="ThirdPartyStoragePartitioning:disabled"/>
   <int value="-1719833926" label="disable-answers-in-suggest"/>
   <int value="-1719699712" label="AudioPlayerJsModules:enabled"/>
@@ -60080,6 +60083,7 @@
       label="DesktopPWAsMigrationUserDisplayModeCleanUp:enabled"/>
   <int value="-1408869905"
       label="AutofillEnforceMinRequiredFieldsForQuery:disabled"/>
+  <int value="-1408800976" label="LaunchWindowsNativeHostsDirectly:enabled"/>
   <int value="-1408696172" label="CompositeBGColorAnimation:enabled"/>
   <int value="-1408370474" label="AssistantRoutines:enabled"/>
   <int value="-1408288176" label="enable-account-consistency"/>
@@ -61190,6 +61194,7 @@
   <int value="-832561975" label="enable-picture-in-picture"/>
   <int value="-832154680"
       label="AutofillEnforceDelaysInStrikeDatabase:enabled"/>
+  <int value="-832058463" label="LaunchWindowsNativeHostsDirectly:disabled"/>
   <int value="-831855839"
       label="DeprecateOldKeyboardShortcutsAccelerator:enabled"/>
   <int value="-831066457" label="IncognitoBrandConsistencyForDesktop:disabled"/>
@@ -62312,6 +62317,8 @@
   <int value="-229995076" label="AltClickAndSixPackCustomization:disabled"/>
   <int value="-226826278" label="ForceEnableFastCheckoutCapabilities:disabled"/>
   <int value="-226715863" label="SHA1ServerSignature:enabled"/>
+  <int value="-226542943"
+      label="AutofillMoveLegalTermsAndIconForNewCardEnrollment:disabled"/>
   <int value="-225505731" label="CCTModule:enabled"/>
   <int value="-225228149" label="ContentSettingsRedesign:enabled"/>
   <int value="-223595595" label="OSKResizesVisualViewportByDefault:enabled"/>
@@ -90301,6 +90308,12 @@
   <int value="5" label="Unknown error."/>
 </enum>
 
+<enum name="RelatedActiveContentsSyncAccessInfo">
+  <int value="0" label="kNoSyncAccess"/>
+  <int value="1" label="kPotentiallySyncAccessibleDefaultSiteInstance"/>
+  <int value="2" label="kPotentiallySyncAccessibleNormalSiteInstance"/>
+</enum>
+
 <enum name="RelaunchNotificationShowResult">
   <obsolete>
     Removed in M90.
diff --git a/tools/metrics/histograms/metadata/android/histograms.xml b/tools/metrics/histograms/metadata/android/histograms.xml
index f139e3bb8..626d216 100644
--- a/tools/metrics/histograms/metadata/android/histograms.xml
+++ b/tools/metrics/histograms/metadata/android/histograms.xml
@@ -763,7 +763,7 @@
 </histogram>
 
 <histogram name="Android.ContactsPicker.ContactCount" units="Contacts"
-    expires_after="2023-09-10">
+    expires_after="2023-11-19">
   <owner>finnur@chromium.org</owner>
   <owner>twellington@chromium.org</owner>
   <summary>
@@ -773,7 +773,7 @@
 </histogram>
 
 <histogram name="Android.ContactsPicker.DialogAction"
-    enum="ContactsPickerDialogAction" expires_after="2023-09-10">
+    enum="ContactsPickerDialogAction" expires_after="2023-11-19">
   <owner>finnur@chromium.org</owner>
   <owner>twellington@chromium.org</owner>
   <summary>
@@ -1389,7 +1389,7 @@
 </histogram>
 
 <histogram name="Android.FeatureModules.StartupTime" units="ms"
-    expires_after="2023-09-18">
+    expires_after="2023-11-19">
   <owner>agrieve@chromium.org</owner>
   <owner>fredmello@chromium.org</owner>
   <owner>tiborg@chromium.org</owner>
@@ -3014,7 +3014,7 @@
 </histogram>
 
 <histogram name="Android.RequestDesktopSite.DomainSettingChanged"
-    enum="Boolean" expires_after="2023-08-13">
+    enum="Boolean" expires_after="2023-11-19">
   <owner>shuyng@google.com</owner>
   <owner>twellington@chromium.org</owner>
   <summary>
@@ -3585,7 +3585,7 @@
 </histogram>
 
 <histogram name="Android.TabSwitcher.SetupRecyclerView.Time" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>skavuluru@chromium.org</owner>
   <owner>twellington@chromium.org</owner>
   <owner>clank-large-form-factors@google.com</owner>
@@ -3674,7 +3674,7 @@
 </histogram>
 
 <histogram name="Android.Toolbar.BitmapCapture" enum="ToolbarCaptureType"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>skym@chromium.org</owner>
   <owner>seacow@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/apps/histograms.xml b/tools/metrics/histograms/metadata/apps/histograms.xml
index ae0e1a2..264d5b7 100644
--- a/tools/metrics/histograms/metadata/apps/histograms.xml
+++ b/tools/metrics/histograms/metadata/apps/histograms.xml
@@ -986,7 +986,7 @@
 </histogram>
 
 <histogram name="Apps.AppList.Search.Federated.Actions"
-    enum="AppListFederatedActions" expires_after="2023-07-01">
+    enum="AppListFederatedActions" expires_after="2024-02-01">
   <owner>amandadeacon@chromium.org</owner>
   <owner>wrong@chromium.org</owner>
   <summary>
@@ -1009,7 +1009,7 @@
 </histogram>
 
 <histogram name="Apps.AppList.Search.Federated.InitStatus"
-    enum="AppListFederatedInitStatus" expires_after="2023-07-01">
+    enum="AppListFederatedInitStatus" expires_after="2024-02-01">
   <owner>amandadeacon@chromium.org</owner>
   <owner>wrong@chromium.org</owner>
   <summary>
@@ -1019,7 +1019,7 @@
 </histogram>
 
 <histogram name="Apps.AppList.Search.Federated.ReportStatus"
-    enum="AppListFederatedReportStatus" expires_after="2023-07-01">
+    enum="AppListFederatedReportStatus" expires_after="2024-02-01">
   <owner>amandadeacon@chromium.org</owner>
   <owner>wrong@chromium.org</owner>
   <summary>
@@ -1029,7 +1029,7 @@
 </histogram>
 
 <histogram name="Apps.AppList.Search.Federated.SearchSessionConclusion"
-    enum="AppListFederatedSearchSessionConclusion" expires_after="2023-09-01">
+    enum="AppListFederatedSearchSessionConclusion" expires_after="2024-02-01">
   <owner>amandadeacon@chromium.org</owner>
   <owner>tby@chromium.org</owner>
   <summary>
@@ -2540,7 +2540,7 @@
 </histogram>
 
 <histogram name="Apps.MediaApp.Load.OtherOpenWindowCount" units="windows"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>tapted@chromium.org</owner>
   <owner>patricialor@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/arc/histograms.xml b/tools/metrics/histograms/metadata/arc/histograms.xml
index 0d2d4ce0..df35a118 100644
--- a/tools/metrics/histograms/metadata/arc/histograms.xml
+++ b/tools/metrics/histograms/metadata/arc/histograms.xml
@@ -1762,7 +1762,7 @@
 </histogram>
 
 <histogram name="Arc.OptInResult" enum="ArcOptInResult"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>mhasank@google.com</owner>
   <owner>khmel@google.com</owner>
   <owner>arc-core@google.com</owner>
@@ -1939,7 +1939,7 @@
 </histogram>
 
 <histogram name="Arc.Policy.InstallTypesOnDevice" enum="AppInstallType"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>batoon@google.com</owner>
   <owner>arc-commercial@google.com</owner>
   <summary>
@@ -2750,7 +2750,7 @@
 </histogram>
 
 <histogram name="Arc.Wayland.LateTiming.Event" enum="WaylandTimingEvent"
-    expires_after="2023-09-16">
+    expires_after="2023-11-19">
   <owner>alanding@google.com</owner>
   <owner>arc-performance@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/ash/histograms.xml b/tools/metrics/histograms/metadata/ash/histograms.xml
index 7d3b69e3e..30418a54 100644
--- a/tools/metrics/histograms/metadata/ash/histograms.xml
+++ b/tools/metrics/histograms/metadata/ash/histograms.xml
@@ -1258,7 +1258,7 @@
 </histogram>
 
 <histogram name="Ash.Calendar.FetchEvents.FetchDuration" units="ms"
-    expires_after="2023-09-18">
+    expires_after="2023-11-19">
   <owner>rtinkoff@google.com</owner>
   <owner>jiamingc@google.com</owner>
   <owner>cros-status-area-eng@google.com</owner>
@@ -1308,7 +1308,7 @@
 </histogram>
 
 <histogram name="Ash.Calendar.FetchEvents.Result"
-    enum="CalendarEventFetchApiError" expires_after="2023-09-18">
+    enum="CalendarEventFetchApiError" expires_after="2023-11-19">
   <owner>rtinkoff@google.com</owner>
   <owner>jiamingc@google.com</owner>
   <owner>cros-status-area-eng@google.com</owner>
@@ -1362,7 +1362,7 @@
 </histogram>
 
 <histogram name="Ash.Calendar.MonthDwellTime" units="ms"
-    expires_after="2023-09-18">
+    expires_after="2023-11-19">
   <owner>kradtke@chromium.org</owner>
   <owner>cros-status-area-eng@google.com</owner>
   <summary>
@@ -1372,7 +1372,7 @@
 </histogram>
 
 <histogram name="Ash.Calendar.ScrollSource" enum="CalendarViewScrollSource"
-    expires_after="2023-09-18">
+    expires_after="2023-11-19">
   <owner>jiamingc@google.com</owner>
   <owner>cros-status-area-eng@google.com</owner>
   <summary>
@@ -1397,7 +1397,7 @@
 </histogram>
 
 <histogram name="Ash.Calendar.TimeToSeeTodaysEventDots" units="ms"
-    expires_after="2023-09-18">
+    expires_after="2023-11-19">
   <owner>newcomer@google.com</owner>
   <owner>cros-status-area-eng@google.com</owner>
   <summary>
@@ -3563,7 +3563,7 @@
 </histogram>
 
 <histogram name="Ash.Lacros.Launch.Mode.Daily" enum="LacrosLaunchMode"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>skuhne@chromium.org</owner>
   <owner>lacros-team@google.com</owner>
   <summary>
@@ -4056,7 +4056,7 @@
 
 <histogram
     name="Ash.Notification.GroupNotification.SlideOut.AnimationSmoothness"
-    units="%" expires_after="2023-09-19">
+    units="%" expires_after="2023-11-19">
   <owner>amehfooz@chromium.org</owner>
   <owner>cros-status-area-eng@google.com</owner>
   <summary>
@@ -4640,7 +4640,7 @@
 </histogram>
 
 <histogram name="Ash.Overview.WindowDrag.Workflow" enum="OverviewDragAction"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>xdai@chromium.org</owner>
   <owner>chromeos-wmp@google.com</owner>
   <summary>
@@ -4931,7 +4931,7 @@
 </histogram>
 
 <histogram name="Ash.PrivacyIndicators.AppAccessUpdate.Type" enum="AppType"
-    expires_after="2023-09-19">
+    expires_after="2023-11-19">
   <owner>leandre@chromium.org</owner>
   <owner>cros-status-area-eng@google.com</owner>
   <summary>
@@ -4942,7 +4942,7 @@
 </histogram>
 
 <histogram name="Ash.PrivacyIndicators.LaunchSettings" enum="AppType"
-    expires_after="2023-09-19">
+    expires_after="2023-11-19">
   <owner>leandre@chromium.org</owner>
   <owner>cros-status-area-eng@google.com</owner>
   <summary>
@@ -4953,7 +4953,7 @@
 </histogram>
 
 <histogram name="Ash.PrivacyIndicators.NumberOfAppsAccessingCamera"
-    units="count" expires_after="2023-09-19">
+    units="count" expires_after="2023-11-19">
   <owner>leandre@chromium.org</owner>
   <owner>cros-status-area-eng@google.com</owner>
   <summary>
@@ -4973,7 +4973,7 @@
 </histogram>
 
 <histogram name="Ash.PrivacyIndicators.NumberOfRepeatedShows" units="shows"
-    expires_after="2023-09-19">
+    expires_after="2023-11-19">
   <owner>leandre@chromium.org</owner>
   <owner>cros-status-area-eng@google.com</owner>
   <summary>
@@ -4984,7 +4984,7 @@
 </histogram>
 
 <histogram name="Ash.PrivacyIndicators.NumberOfShowsPerSession" units="shows"
-    expires_after="2023-09-19">
+    expires_after="2023-11-19">
   <owner>leandre@chromium.org</owner>
   <owner>cros-status-area-eng@google.com</owner>
   <summary>
@@ -4994,7 +4994,7 @@
 </histogram>
 
 <histogram name="Ash.PrivacyIndicators.ShowType" enum="PrivacyIndicatorsType"
-    expires_after="2023-09-19">
+    expires_after="2023-11-19">
   <owner>leandre@chromium.org</owner>
   <owner>cros-status-area-eng@google.com</owner>
   <summary>
@@ -5337,7 +5337,7 @@
 </histogram>
 
 <histogram name="Ash.Shelf.NumberOfItems" units="Icons"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>anasalazar@chromium.org</owner>
   <owner>mmourgos@google.com</owner>
   <summary>
@@ -5357,7 +5357,7 @@
 </histogram>
 
 <histogram name="Ash.Shelf.NumberOfUnpinnedItems" units="Icons"
-    expires_after="2023-08-27">
+    expires_after="2023-11-19">
   <owner>anasalazar@chromium.org</owner>
   <owner>mmourgos@google.com</owner>
   <summary>
@@ -5578,7 +5578,7 @@
 </histogram>
 
 <histogram name="Ash.Shelf.ShutdownConfirmationBubble.Action"
-    enum="ShutdownConfirmationBubbleAction" expires_after="2023-09-17">
+    enum="ShutdownConfirmationBubbleAction" expires_after="2023-11-19">
   <owner>sherrilin@google.com</owner>
   <owner>cros-lurs@google.com</owner>
   <summary>
@@ -6219,7 +6219,7 @@
 </histogram>
 
 <histogram name="Ash.UnifiedSystemView.Button.Activated"
-    enum="QsButtonCatalogName" expires_after="2023-09-14">
+    enum="QsButtonCatalogName" expires_after="2023-11-19">
   <owner>jiamingc@google.com</owner>
   <owner>cros-status-area-eng@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/autofill/histograms.xml b/tools/metrics/histograms/metadata/autofill/histograms.xml
index a40e7fa..df050ce 100644
--- a/tools/metrics/histograms/metadata/autofill/histograms.xml
+++ b/tools/metrics/histograms/metadata/autofill/histograms.xml
@@ -666,7 +666,7 @@
 </histogram>
 
 <histogram name="Autofill.BetterAuth.CardUnmaskDuration.Fido" units="ms"
-    expires_after="2023-11-12">
+    expires_after="2024-05-01">
   <owner>jsaul@google.com</owner>
   <owner>siyua@chromium.org</owner>
   <owner>autofill-auth-team@google.com</owner>
@@ -678,7 +678,7 @@
 
 <histogram
     name="Autofill.BetterAuth.CardUnmaskDuration.Fido.{CardType}.{Result}"
-    units="ms" expires_after="2023-07-01">
+    units="ms" expires_after="2024-05-01">
   <owner>jsaul@google.com</owner>
   <owner>siyua@chromium.org</owner>
   <owner>autofill-auth-team@google.com</owner>
@@ -713,7 +713,7 @@
 
 <histogram
     name="Autofill.BetterAuth.CardUnmaskPreflightCalledWithFidoOptInStatus"
-    enum="Boolean" expires_after="2023-11-12">
+    enum="Boolean" expires_after="2024-05-01">
   <owner>jsaul@google.com</owner>
   <owner>siyua@chromium.org</owner>
   <owner>autofill-auth-team@google.com</owner>
@@ -734,7 +734,7 @@
 </histogram>
 
 <histogram name="Autofill.BetterAuth.CardUnmaskPreflightDuration" units="ms"
-    expires_after="2023-10-15">
+    expires_after="2024-05-01">
   <owner>jsaul@google.com</owner>
   <owner>siyua@chromium.org</owner>
   <owner>autofill-auth-team@google.com</owner>
@@ -747,7 +747,7 @@
 </histogram>
 
 <histogram name="Autofill.BetterAuth.CardUnmaskPreflightInitiated"
-    enum="Boolean" expires_after="2023-11-12">
+    enum="Boolean" expires_after="2024-05-01">
   <owner>vinnypersky@google.com</owner>
   <owner>autofill-auth-team@google.com</owner>
   <summary>
@@ -759,7 +759,7 @@
 </histogram>
 
 <histogram name="Autofill.BetterAuth.CardUnmaskTypeDecision"
-    enum="AutofillCreditCardUnmaskDecisionMetric" expires_after="2023-11-12">
+    enum="AutofillCreditCardUnmaskDecisionMetric" expires_after="2024-05-01">
   <owner>jsaul@google.com</owner>
   <owner>siyua@chromium.org</owner>
   <owner>autofill-auth-team@google.com</owner>
@@ -773,7 +773,7 @@
 
 <histogram
     name="Autofill.BetterAuth.FlowEvents.{BetterAuthFlowType}.{CardType}"
-    enum="AutofillCreditCardAuthenticationEvents" expires_after="2023-07-01">
+    enum="AutofillCreditCardAuthenticationEvents" expires_after="2024-05-01">
   <owner>jsaul@google.com</owner>
   <owner>siyua@chromium.org</owner>
   <owner>autofill-auth-team@google.com</owner>
@@ -788,7 +788,7 @@
 
 <histogram
     name="Autofill.BetterAuth.FlowEvents{AutofillCreditCardAuthenticationFlows}"
-    enum="AutofillCreditCardAuthenticationEvents" expires_after="2023-07-01">
+    enum="AutofillCreditCardAuthenticationEvents" expires_after="2024-05-01">
   <owner>jsaul@google.com</owner>
   <owner>siyua@chromium.org</owner>
   <owner>autofill-auth-team@google.com</owner>
@@ -809,7 +809,7 @@
 
 <histogram
     name="Autofill.BetterAuth.OptInCalled{AutofillCreditCardWebauthnOptInOrigin}"
-    enum="AutofillCreditCardWebauthnOptInParameters" expires_after="2023-07-01">
+    enum="AutofillCreditCardWebauthnOptInParameters" expires_after="2024-05-01">
   <owner>jsaul@google.com</owner>
   <owner>siyua@chromium.org</owner>
   <owner>autofill-auth-team@google.com</owner>
@@ -825,7 +825,7 @@
 </histogram>
 
 <histogram name="Autofill.BetterAuth.OptInPromoNotOfferedReason"
-    enum="WebauthnOptInPromoNotOfferedReason" expires_after="2023-11-12">
+    enum="WebauthnOptInPromoNotOfferedReason" expires_after="2024-05-01">
   <owner>vinnypersky@google.com</owner>
   <owner>shgar@google.com</owner>
   <summary>
@@ -839,7 +839,7 @@
 
 <histogram
     name="Autofill.BetterAuth.OptInPromoShown{AutofillCreditCardWebauthnOptInOrigin}"
-    enum="BooleanHit" expires_after="2023-07-01">
+    enum="BooleanHit" expires_after="2024-05-01">
   <owner>jsaul@google.com</owner>
   <owner>siyua@chromium.org</owner>
   <owner>autofill-auth-team@google.com</owner>
@@ -862,7 +862,7 @@
 
 <histogram
     name="Autofill.BetterAuth.OptInPromoUserDecision{AutofillCreditCardWebauthnOptInOrigin}"
-    enum="AutofillWebauthnOptInPromoUserDecision" expires_after="2023-07-01">
+    enum="AutofillWebauthnOptInPromoUserDecision" expires_after="2024-05-01">
   <owner>jsaul@google.com</owner>
   <owner>siyua@chromium.org</owner>
   <owner>autofill-auth-team@google.com</owner>
@@ -878,7 +878,7 @@
 </histogram>
 
 <histogram name="Autofill.BetterAuth.OptOutCalled.FromSettingsPage"
-    enum="BooleanHit" expires_after="2023-09-03">
+    enum="BooleanHit" expires_after="2024-05-01">
   <owner>jsaul@google.com</owner>
   <owner>siyua@chromium.org</owner>
   <owner>autofill-auth-team@google.com</owner>
@@ -895,7 +895,7 @@
 
 <histogram
     name="Autofill.BetterAuth.UserPerceivedLatencyOnCardSelection.OptedIn.Duration"
-    units="ms" expires_after="2023-10-08">
+    units="ms" expires_after="2024-05-01">
   <owner>jsaul@google.com</owner>
   <owner>siyua@chromium.org</owner>
   <owner>autofill-auth-team@google.com</owner>
@@ -911,7 +911,7 @@
 <histogram
     name="Autofill.BetterAuth.UserPerceivedLatencyOnCardSelection.OptedIn.TimedOutCvcFallback"
     enum="AutofillCreditCardUserPerceivedLatencyFollowUp"
-    expires_after="2023-07-01">
+    expires_after="2024-05-01">
   <owner>jsaul@google.com</owner>
   <owner>siyua@chromium.org</owner>
   <owner>autofill-auth-team@google.com</owner>
@@ -926,7 +926,7 @@
 
 <histogram
     name="Autofill.BetterAuth.UserPerceivedLatencyOnCardSelection{AutofillFidoAuthenticationEnabledState}"
-    enum="AutofillCreditCardPreflightCallEvent" expires_after="2023-07-01">
+    enum="AutofillCreditCardPreflightCallEvent" expires_after="2024-05-01">
   <owner>jsaul@google.com</owner>
   <owner>siyua@chromium.org</owner>
   <owner>autofill-auth-team@google.com</owner>
@@ -944,7 +944,7 @@
 </histogram>
 
 <histogram name="Autofill.BetterAuth.UserVerifiabilityCheckDuration" units="ms"
-    expires_after="2023-11-12">
+    expires_after="2024-05-01">
   <owner>jsaul@google.com</owner>
   <owner>siyua@chromium.org</owner>
   <owner>autofill-auth-team@google.com</owner>
@@ -957,7 +957,7 @@
 
 <histogram
     name="Autofill.BetterAuth.WebauthnResult{AutofillFidoUserVerificationFlow}"
-    enum="AutofillCreditCardWebauthnResultMetric" expires_after="2023-07-01">
+    enum="AutofillCreditCardWebauthnResultMetric" expires_after="2024-05-01">
   <owner>jsaul@google.com</owner>
   <owner>siyua@chromium.org</owner>
   <owner>autofill-auth-team@google.com</owner>
@@ -1608,9 +1608,9 @@
 </histogram>
 
 <histogram name="Autofill.ExpirationDateFixFlowPrompt.Events"
-    enum="AutofillExpirationDateFixFlowPromptEvent" expires_after="2023-07-01">
-  <owner>siashah@google.com</owner>
+    enum="AutofillExpirationDateFixFlowPromptEvent" expires_after="2024-05-01">
   <owner>jsaul@google.com</owner>
+  <owner>siashah@google.com</owner>
   <owner>payments-autofill-team@google.com</owner>
   <summary>
     Events tracking the usage of the expiration date fix flow prompt. This
@@ -1620,9 +1620,9 @@
 </histogram>
 
 <histogram name="Autofill.ExpirationDateFixFlowPromptShown" enum="Boolean"
-    expires_after="2023-07-01">
-  <owner>siashah@google.com</owner>
+    expires_after="2024-05-01">
   <owner>jsaul@google.com</owner>
+  <owner>siashah@google.com</owner>
   <owner>payments-autofill-team@google.com</owner>
   <summary>
     The number of times the expiration date fix flow prompt is shown.
@@ -2653,7 +2653,7 @@
 </histogram>
 
 <histogram name="Autofill.LocalCardMigrationDecision"
-    enum="AutofillLocalCardMigrationDecisionMetric" expires_after="2023-09-01">
+    enum="AutofillLocalCardMigrationDecisionMetric" expires_after="2023-11-19">
   <owner>sujiezhu@google.com</owner>
   <owner>siyua@chromium.org</owner>
   <owner>jsaul@google.com</owner>
@@ -4661,7 +4661,7 @@
 
 <histogram
     name="Autofill.UnmaskPrompt.Duration{AutofillUnmaskPromptCloseReasonEvents}"
-    units="ms" expires_after="2023-07-01">
+    units="ms" expires_after="2024-05-01">
   <owner>jsaul@google.com</owner>
   <owner>siyua@chromium.org</owner>
   <summary>
@@ -4717,7 +4717,7 @@
 </histogram>
 
 <histogram name="Autofill.UnmaskPrompt.GetRealPanResult"
-    enum="AutofillGetRealPanResult" expires_after="2023-07-01">
+    enum="AutofillGetRealPanResult" expires_after="2024-05-01">
   <owner>jsaul@google.com</owner>
   <owner>siyua@chromium.org</owner>
   <summary>
@@ -4728,7 +4728,7 @@
 </histogram>
 
 <histogram name="Autofill.UnmaskPrompt.GetRealPanResult.{CardType}"
-    enum="AutofillGetRealPanResult" expires_after="2023-07-01">
+    enum="AutofillGetRealPanResult" expires_after="2024-05-01">
   <owner>jsaul@google.com</owner>
   <owner>siyua@chromium.org</owner>
   <owner>payments-autofill-team@google.com</owner>
@@ -4742,7 +4742,7 @@
 </histogram>
 
 <histogram name="Autofill.UnmaskPrompt.TimeBeforeAbandonUnmasking" units="ms"
-    expires_after="2023-07-01">
+    expires_after="2024-05-01">
   <owner>jsaul@google.com</owner>
   <owner>siyua@chromium.org</owner>
   <summary>
@@ -4755,7 +4755,7 @@
 </histogram>
 
 <histogram name="Autofill.UnmaskPrompt.UnmaskingDuration" units="ms"
-    expires_after="2023-07-01">
+    expires_after="2024-05-01">
   <owner>jsaul@google.com</owner>
   <owner>siyua@chromium.org</owner>
   <summary>
@@ -4766,7 +4766,7 @@
 </histogram>
 
 <histogram name="Autofill.UnmaskPrompt.UnmaskingDuration.{CardType}.{Result}"
-    units="ms" expires_after="2023-07-01">
+    units="ms" expires_after="2024-05-01">
   <owner>jsaul@google.com</owner>
   <owner>siyua@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/blink/histograms.xml b/tools/metrics/histograms/metadata/blink/histograms.xml
index 28ca689..0a77dfa 100644
--- a/tools/metrics/histograms/metadata/blink/histograms.xml
+++ b/tools/metrics/histograms/metadata/blink/histograms.xml
@@ -846,19 +846,6 @@
   </summary>
 </histogram>
 
-<histogram name="Blink.DecodedImage.AvifDensity.KiBWeighted"
-    units="0.01 bits per pixel" expires_after="2022-10-01">
-  <owner>jyrki@google.com</owner>
-  <owner>compression-dev@google.com</owner>
-  <summary>
-    The compressed image size in KiB per image density measured in 0.01 bits per
-    pixel. This is logged once per image load after the whole image is loaded
-    and only for AVIFs with at least 100 pixels on the smallest dimension (width
-    or height). The reported count for a sample represents the image size
-    rounded to the nearest KiB.
-  </summary>
-</histogram>
-
 <histogram name="Blink.DecodedImage.JpegDensity.KiBWeighted"
     units="0.01 bits per pixel" expires_after="2023-10-22">
   <owner>jyrki@google.com</owner>
@@ -872,19 +859,6 @@
   </summary>
 </histogram>
 
-<histogram name="Blink.DecodedImage.WebPDensity.KiBWeighted"
-    units="0.01 bits per pixel" expires_after="2022-10-01">
-  <owner>jyrki@google.com</owner>
-  <owner>compression-dev@google.com</owner>
-  <summary>
-    The compressed image size in KiB per image density measured in 0.01 bits per
-    pixel. This is logged once per image load after the whole image is loaded
-    and only for WebPs with at least 100 pixels on the smallest dimension (width
-    or height). The reported count for a sample represents the image size
-    rounded to the nearest KiB.
-  </summary>
-</histogram>
-
 <histogram name="Blink.DecodedImage.WebPFileFormat" enum="WebPFileFormat"
     expires_after="2023-11-12">
   <owner>mcasas@chromium.org</owner>
@@ -966,7 +940,7 @@
 </histogram>
 
 <histogram name="Blink.FedCm.ApprovedClientsSize" units="clients"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>yigu@chromium.org</owner>
   <owner>web-identity-eng@google.com</owner>
   <summary>
@@ -1093,7 +1067,7 @@
 </histogram>
 
 <histogram name="Blink.FedCm.CloseVerifySheet.Android" enum="Boolean"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>yigu@chromium.org</owner>
   <owner>web-identity-eng@google.com</owner>
   <summary>
@@ -1103,7 +1077,7 @@
 </histogram>
 
 <histogram name="Blink.FedCm.CloseVerifySheet.Desktop" enum="Boolean"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>yigu@chromium.org</owner>
   <owner>web-identity-eng@google.com</owner>
   <summary>
@@ -1233,7 +1207,7 @@
 </histogram>
 
 <histogram name="Blink.FedCm.Status.RequestIdToken"
-    enum="FedCmRequestIdTokenStatus" expires_after="2023-09-17">
+    enum="FedCmRequestIdTokenStatus" expires_after="2023-11-19">
   <owner>yigu@chromium.org</owner>
   <owner>web-identity-eng@google.com</owner>
   <summary>
@@ -1313,7 +1287,7 @@
 </histogram>
 
 <histogram name="Blink.FedCm.Timing.ShowAccountsDialog" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>yigu@chromium.org</owner>
   <owner>web-identity-eng@google.com</owner>
   <summary>
@@ -1349,7 +1323,7 @@
 </histogram>
 
 <histogram name="Blink.FedCm.WebContentsVisible" enum="Boolean"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>yigu@chromium.org</owner>
   <owner>web-identity-eng@google.com</owner>
   <summary>
@@ -1487,7 +1461,7 @@
 </histogram>
 
 <histogram name="Blink.Fonts.VariableFontsRatio"
-    enum="WebFontInstantiationResult" expires_after="2023-09-17">
+    enum="WebFontInstantiationResult" expires_after="2023-11-19">
   <owner>drott@chromium.org</owner>
   <owner>layout-dev@chromium.org</owner>
   <summary>
@@ -1719,7 +1693,7 @@
 </histogram>
 
 <histogram name="Blink.HTMLParsing.ChunkCount4" units="chunks"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>masonf@chromium.org</owner>
   <owner>dom-dev@chromium.org</owner>
   <summary>
@@ -1733,7 +1707,7 @@
 </histogram>
 
 <histogram name="Blink.HTMLParsing.InputCharacterCount4" units="characters"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>masonf@chromium.org</owner>
   <owner>dom-dev@chromium.org</owner>
   <summary>
@@ -1821,7 +1795,7 @@
 </histogram>
 
 <histogram name="Blink.HTMLParsing.TokensParsedMax4" units="tokens"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>masonf@chromium.org</owner>
   <owner>dom-dev@chromium.org</owner>
   <summary>
@@ -1834,7 +1808,7 @@
 </histogram>
 
 <histogram name="Blink.HTMLParsing.TokensParsedMin4" units="tokens"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>masonf@chromium.org</owner>
   <owner>dom-dev@chromium.org</owner>
   <summary>
@@ -1888,7 +1862,7 @@
 </histogram>
 
 <histogram name="Blink.HTMLParsing.YieldedTimeMin4" units="microseconds"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>masonf@chromium.org</owner>
   <owner>dom-dev@chromium.org</owner>
   <summary>
@@ -2600,7 +2574,7 @@
 </histogram>
 
 <histogram name="Blink.NotificationManager.GetPermissionStatusTime" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>cduvall@chromium.org</owner>
   <owner>jam@chromium.org</owner>
   <summary>
@@ -2770,7 +2744,7 @@
 </histogram>
 
 <histogram name="Blink.ResourceRequest.RedirectDelay" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>cduvall@chromium.org</owner>
   <owner>jam@chromium.org</owner>
   <summary>
@@ -3634,7 +3608,7 @@
 </histogram>
 
 <histogram name="Blink.VisibleLoadTime.LazyLoadImages" units="ms"
-    expires_after="2023-09-01">
+    expires_after="2023-11-19">
   <owner>pdr@chromium.org</owner>
   <owner>paint-dev@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/bluetooth/histograms.xml b/tools/metrics/histograms/metadata/bluetooth/histograms.xml
index 66f7921..ebfa290 100644
--- a/tools/metrics/histograms/metadata/bluetooth/histograms.xml
+++ b/tools/metrics/histograms/metadata/bluetooth/histograms.xml
@@ -1881,7 +1881,7 @@
 </histogram>
 
 <histogram name="Bluetooth.Web.Characteristic.ReadValue.Outcome"
-    enum="WebBluetoothGATTOperationOutcome" expires_after="2023-09-17">
+    enum="WebBluetoothGATTOperationOutcome" expires_after="2023-11-19">
   <owner>cmumford@chromium.org</owner>
   <owner>deviceapi-team@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/bookmarks/histograms.xml b/tools/metrics/histograms/metadata/bookmarks/histograms.xml
index be65fcb..5c5fc9c5 100644
--- a/tools/metrics/histograms/metadata/bookmarks/histograms.xml
+++ b/tools/metrics/histograms/metadata/bookmarks/histograms.xml
@@ -632,7 +632,7 @@
 </histogram>
 
 <histogram name="Bookmarks.Times.OnProfileLoad.MostRecentlyUsedBookmarkInDays"
-    units="days" expires_after="2023-08-08">
+    units="days" expires_after="2023-11-19">
   <owner>wylieb@chromium.org</owner>
   <owner>chrome-collections@google.com</owner>
   <component>UI&gt;Browser&gt;Bookmarks</component>
diff --git a/tools/metrics/histograms/metadata/browsing_topics/histograms.xml b/tools/metrics/histograms/metadata/browsing_topics/histograms.xml
index 20ebd77..dd1b8ac 100644
--- a/tools/metrics/histograms/metadata/browsing_topics/histograms.xml
+++ b/tools/metrics/histograms/metadata/browsing_topics/histograms.xml
@@ -34,7 +34,7 @@
 </histogram>
 
 <histogram name="BrowsingTopics.BrowsingTopicsState.LoadFinishStatus"
-    enum="BooleanSuccess" expires_after="2023-09-17">
+    enum="BooleanSuccess" expires_after="2023-11-19">
   <owner>yaoxia@chromium.org</owner>
   <owner>jkarlin@chromium.org</owner>
   <summary>
@@ -44,7 +44,7 @@
 </histogram>
 
 <histogram name="BrowsingTopics.EpochTopicsCalculation.CalculatorResultStatus"
-    enum="BrowsingTopicsCalculatorResultStatus" expires_after="2023-09-17">
+    enum="BrowsingTopicsCalculatorResultStatus" expires_after="2023-11-19">
   <owner>yaoxia@chromium.org</owner>
   <owner>jkarlin@chromium.org</owner>
   <summary>
@@ -55,7 +55,7 @@
 
 <histogram
     name="BrowsingTopics.EpochTopicsCalculation.EligibleDistinctHistoryHostsCount"
-    units="hosts" expires_after="2023-09-17">
+    units="hosts" expires_after="2023-11-19">
   <owner>yaoxia@chromium.org</owner>
   <owner>jkarlin@chromium.org</owner>
   <summary>
@@ -80,7 +80,7 @@
 
 <histogram
     name="BrowsingTopics.EpochTopicsCalculation.ObservationContextDomainsCountPerTopTopic"
-    units="context domains" expires_after="2023-09-17">
+    units="context domains" expires_after="2023-11-19">
   <owner>yaoxia@chromium.org</owner>
   <owner>jkarlin@chromium.org</owner>
   <summary>
@@ -183,7 +183,7 @@
 </histogram>
 
 <histogram name="BrowsingTopics.SiteDataStorage.InitStatus"
-    enum="BooleanSuccess" expires_after="2023-09-17">
+    enum="BooleanSuccess" expires_after="2023-11-19">
   <owner>yaoxia@chromium.org</owner>
   <owner>jkarlin@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/chrome/histograms.xml b/tools/metrics/histograms/metadata/chrome/histograms.xml
index 3f93525..997aa087 100644
--- a/tools/metrics/histograms/metadata/chrome/histograms.xml
+++ b/tools/metrics/histograms/metadata/chrome/histograms.xml
@@ -238,7 +238,7 @@
 </histogram>
 
 <histogram name="Chrome.ProcessSingleton.TimeToNotify" units="ms"
-    expires_after="2023-07-30">
+    expires_after="2023-11-19">
   <owner>etienneb@chromium.org</owner>
   <owner>gab@chromium.org</owner>
   <summary>
@@ -250,7 +250,7 @@
 
 <histogram
     name="Chrome.SystemNetworkContextManager.NetworkSandboxLaunchFailed.ErrorCode"
-    enum="LaunchErrorCodes" expires_after="2023-06-30">
+    enum="LaunchErrorCodes" expires_after="2023-12-31">
   <owner>wfh@chromium.org</owner>
   <owner>mmenke@chromium.org</owner>
   <summary>
@@ -263,7 +263,7 @@
 
 <histogram
     name="Chrome.SystemNetworkContextManager.NetworkSandboxLaunchFailed.WinLastError"
-    enum="WinGetLastError" expires_after="2023-06-30">
+    enum="WinGetLastError" expires_after="2023-12-31">
   <owner>wfh@chromium.org</owner>
   <owner>mmenke@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/chromeos/histograms.xml b/tools/metrics/histograms/metadata/chromeos/histograms.xml
index e953781..cda1f6e 100644
--- a/tools/metrics/histograms/metadata/chromeos/histograms.xml
+++ b/tools/metrics/histograms/metadata/chromeos/histograms.xml
@@ -290,7 +290,7 @@
 </histogram>
 
 <histogram name="ChromeOS.Camera.AutoFraming.EnabledCount" units="times"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>kamesan@chromium.org</owner>
   <owner>chromeos-camera-eng@google.com</owner>
   <summary>
@@ -310,7 +310,7 @@
 </histogram>
 
 <histogram name="ChromeOS.Camera.AutoFraming.Error" enum="AutoFramingError"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>kamesan@chromium.org</owner>
   <owner>chromeos-camera-eng@google.com</owner>
   <summary>
@@ -619,7 +619,7 @@
 </histogram>
 
 <histogram name="ChromeOS.Camera.HDRnet.MaxOutputBuffersRendered"
-    units="buffers" expires_after="2023-09-17">
+    units="buffers" expires_after="2023-11-19">
   <owner>jcliang@chromium.org</owner>
   <owner>chromeos-camera-eng@google.com</owner>
   <summary>
@@ -1787,7 +1787,7 @@
 </histogram>
 
 <histogram name="ChromeOS.LanguagePacks.GetPackState.FeatureId"
-    enum="LanguagePackFeatureIds" expires_after="2023-09-17">
+    enum="LanguagePackFeatureIds" expires_after="2023-11-19">
   <owner>claudiomagni@chromium.org</owner>
   <owner>mlcui@google.com</owner>
   <owner>dvallet@chromium.org</owner>
@@ -1858,7 +1858,7 @@
 </histogram>
 
 <histogram name="ChromeOS.LanguagePacks.InstallPack.Success"
-    enum="LanguagePackFeatureSuccess" expires_after="2023-09-03">
+    enum="LanguagePackFeatureSuccess" expires_after="2023-11-19">
   <owner>claudiomagni@chromium.org</owner>
   <owner>mlcui@google.com</owner>
   <owner>dvallet@chromium.org</owner>
@@ -1879,7 +1879,7 @@
 </histogram>
 
 <histogram name="ChromeOS.LanguagePacks.Mojo.GetPackInfo.Feature"
-    enum="LanguagePackMojoFeatureId" expires_after="2023-09-03">
+    enum="LanguagePackMojoFeatureId" expires_after="2023-11-19">
   <owner>mlcui@google.com</owner>
   <owner>cros-borders-eng@google.com</owner>
   <summary>
@@ -1899,7 +1899,7 @@
 </histogram>
 
 <histogram name="ChromeOS.LanguagePacks.Mojo.InstallPack.Feature"
-    enum="LanguagePackMojoFeatureId" expires_after="2023-09-03">
+    enum="LanguagePackMojoFeatureId" expires_after="2023-11-19">
   <owner>mlcui@google.com</owner>
   <owner>cros-borders-eng@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/commerce/histograms.xml b/tools/metrics/histograms/metadata/commerce/histograms.xml
index c995fe9..240a6e7 100644
--- a/tools/metrics/histograms/metadata/commerce/histograms.xml
+++ b/tools/metrics/histograms/metadata/commerce/histograms.xml
@@ -42,7 +42,7 @@
 </variants>
 
 <histogram name="Commerce.Carts.AddToCartButtonDetection" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>yuezhanggg@chromium.org</owner>
   <owner>wychen@chromium.org</owner>
   <owner>chrome-shopping@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/compositing/histograms.xml b/tools/metrics/histograms/metadata/compositing/histograms.xml
index 0ca780e..7435f79 100644
--- a/tools/metrics/histograms/metadata/compositing/histograms.xml
+++ b/tools/metrics/histograms/metadata/compositing/histograms.xml
@@ -439,7 +439,7 @@
 
 <histogram
     name="Compositing.Display.OverlayProcessorUsingStrategy.FramesAttemptingRequiredOverlays"
-    units="boolean" expires_after="2023-09-17">
+    units="boolean" expires_after="2023-11-19">
   <owner>zoraiznaeem@chromium.org</owner>
   <owner>graphics-dev@chromium.org</owner>
   <summary>
@@ -652,7 +652,7 @@
 </histogram>
 
 <histogram name="Compositing.Renderer.CommitHung" units="boolean"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>skobes@chromium.org</owner>
   <owner>input-dev@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/content/histograms.xml b/tools/metrics/histograms/metadata/content/histograms.xml
index f26d0adc..984bf37 100644
--- a/tools/metrics/histograms/metadata/content/histograms.xml
+++ b/tools/metrics/histograms/metadata/content/histograms.xml
@@ -167,7 +167,7 @@
 </histogram>
 
 <histogram name="ContentSettings.NumberOfExceptions" units="units"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>engedy@chromium.org</owner>
   <owner>src/components/permissions/PERMISSIONS_OWNERS</owner>
   <summary>
@@ -178,7 +178,7 @@
 </histogram>
 
 <histogram name="ContentSettings.PermissionRequested" enum="PermissionType"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>engedy@chromium.org</owner>
   <owner>src/components/permissions/PERMISSIONS_OWNERS</owner>
   <summary>
@@ -788,7 +788,7 @@
 </histogram>
 
 <histogram name="ContentSuggestions.Feed.CanBeShown" enum="BooleanAllowed"
-    expires_after="2023-08-01">
+    expires_after="2023-11-19">
   <owner>harringtond@chromium.org</owner>
   <owner>thegreenfrog@chromium.org</owner>
   <owner>feed@chromium.org</owner>
@@ -925,7 +925,7 @@
 </histogram>
 
 <histogram name="ContentSuggestions.Feed.ContentLifetime.InvalidAgeIsPresent"
-    enum="Boolean" expires_after="2023-09-17">
+    enum="Boolean" expires_after="2023-11-19">
   <owner>birnie@google.com</owner>
   <owner>feed@chromium.org</owner>
   <summary>
@@ -937,7 +937,7 @@
 </histogram>
 
 <histogram name="ContentSuggestions.Feed.ContentLifetime.StaleAge" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>birnie@google.com</owner>
   <owner>feed@chromium.org</owner>
   <summary>
@@ -948,7 +948,7 @@
 </histogram>
 
 <histogram name="ContentSuggestions.Feed.ContentLifetime.StaleAgeIsPresent"
-    enum="Boolean" expires_after="2023-09-17">
+    enum="Boolean" expires_after="2023-11-19">
   <owner>birnie@google.com</owner>
   <owner>feed@chromium.org</owner>
   <summary>
@@ -1078,7 +1078,7 @@
 </histogram>
 
 <histogram name="ContentSuggestions.Feed.ManualRefreshInterval" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>jianli@chromium.org</owner>
   <owner>feed@chromium.org</owner>
   <summary>
@@ -1520,7 +1520,7 @@
 </histogram>
 
 <histogram name="ContentSuggestions.Feed.UploadActionsBatchStatus"
-    enum="FeedUploadActionsBatchStatus" expires_after="2023-07-23">
+    enum="FeedUploadActionsBatchStatus" expires_after="2023-11-19">
   <owner>iwells@chromium.org</owner>
   <owner>harringtond@chromium.org</owner>
   <owner>feed@chromium.org</owner>
@@ -1739,7 +1739,7 @@
 </histogram>
 
 <histogram name="ContentSuggestions.Feed.WebFeed.FollowCount.Engaged"
-    units="follows" expires_after="2023-11-12">
+    units="follows" expires_after="2023-11-19">
   <owner>harringtond@chromium.org</owner>
   <owner>feed@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/cookie/histograms.xml b/tools/metrics/histograms/metadata/cookie/histograms.xml
index 9a0b5f5..1650f47 100644
--- a/tools/metrics/histograms/metadata/cookie/histograms.xml
+++ b/tools/metrics/histograms/metadata/cookie/histograms.xml
@@ -72,7 +72,7 @@
 </histogram>
 
 <histogram name="Cookie.CommitProblem" enum="CookieCommitProblem"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>morlovich@chromium.org</owner>
   <summary>
     Recorded when a problem occurs trying to commit changes to the cookie store
@@ -203,7 +203,7 @@
 </histogram>
 
 <histogram name="Cookie.CrossSiteRedirectDowngradeChangesInclusionAge"
-    units="minutes" expires_after="2023-09-17">
+    units="minutes" expires_after="2023-11-19">
   <owner>bingler@chromium.org</owner>
   <owner>miketaylr@chromium.org</owner>
   <summary>
@@ -277,7 +277,7 @@
   </summary>
 </histogram>
 
-<histogram name="Cookie.DomainSet" enum="Boolean" expires_after="2023-09-03">
+<histogram name="Cookie.DomainSet" enum="Boolean" expires_after="2023-11-19">
   <owner>bingler@chromium.org</owner>
   <owner>miketaylr@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/cras/histograms.xml b/tools/metrics/histograms/metadata/cras/histograms.xml
index a984d46..ee60a44 100644
--- a/tools/metrics/histograms/metadata/cras/histograms.xml
+++ b/tools/metrics/histograms/metadata/cras/histograms.xml
@@ -723,7 +723,7 @@
 </histogram>
 
 <histogram name="Cras.StreamCreateError" enum="CrasStreamCreateError"
-    expires_after="2023-09-10">
+    expires_after="2023-11-19">
   <owner>hychao@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>Record the errors happen when CRAS server creats a stream.</summary>
diff --git a/tools/metrics/histograms/metadata/crostini/histograms.xml b/tools/metrics/histograms/metadata/crostini/histograms.xml
index 4c8b7d2..3f55c057 100644
--- a/tools/metrics/histograms/metadata/crostini/histograms.xml
+++ b/tools/metrics/histograms/metadata/crostini/histograms.xml
@@ -44,7 +44,7 @@
 </histogram>
 
 <histogram name="Crostini.AppLaunchResult" enum="CrostiniResult"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>davidmunro@google.com</owner>
   <owner>clumptini@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/custom_tabs/histograms.xml b/tools/metrics/histograms/metadata/custom_tabs/histograms.xml
index 54cff15..333c7ad8 100644
--- a/tools/metrics/histograms/metadata/custom_tabs/histograms.xml
+++ b/tools/metrics/histograms/metadata/custom_tabs/histograms.xml
@@ -287,7 +287,7 @@
 </histogram>
 
 <histogram name="CustomTabs.HadInteractionOnClose.FormStillActive"
-    enum="Boolean" expires_after="2023-09-17">
+    enum="Boolean" expires_after="2023-11-19">
   <owner>katzz@google.com</owner>
   <owner>chrome-connective-tissue@google.com</owner>
   <summary>
@@ -338,7 +338,7 @@
 </histogram>
 
 <histogram name="CustomTabs.IncognitoCCTCallerId" enum="IncognitoCCTCallerId"
-    expires_after="2023-07-16">
+    expires_after="2023-11-19">
   <owner>roagarwal@chromium.org</owner>
   <owner>chrome-incognito@google.com</owner>
   <owner>cct-team@google.com</owner>
@@ -536,7 +536,7 @@
 </histogram>
 
 <histogram name="CustomTabs.SessionDisconnectStatus"
-    enum="CustomTabsSessionDisconnectStatus" expires_after="2023-09-17">
+    enum="CustomTabsSessionDisconnectStatus" expires_after="2023-11-19">
   <owner>kgrosu@google.com</owner>
   <owner>chrome-connective-tissue@google.com</owner>
   <summary>
@@ -763,7 +763,7 @@
 </histogram>
 
 <histogram name="TrustedWebActivity.LocationPermissionRequestIsGranted"
-    enum="Boolean" expires_after="2023-09-03">
+    enum="Boolean" expires_after="2023-11-19">
   <owner>eirage@chromium.org</owner>
   <owner>peconn@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/dev/histograms.xml b/tools/metrics/histograms/metadata/dev/histograms.xml
index bbc1b9b..ce7178a 100644
--- a/tools/metrics/histograms/metadata/dev/histograms.xml
+++ b/tools/metrics/histograms/metadata/dev/histograms.xml
@@ -520,6 +520,16 @@
   </summary>
 </histogram>
 
+<histogram name="DevTools.Workspaces.PopulateWallClockTime" units="ms"
+    expires_after="M120">
+  <owner>bmeurer@chromium.org</owner>
+  <owner>hablich@chromium.org</owner>
+  <summary>
+    Wall clock time elapsed to initially populate a Workspaces folder. Recorded
+    in the FileSystem#populate() method of FileSystemWorkspaceBinding.ts.
+  </summary>
+</histogram>
+
 </histograms>
 
 </histogram-configuration>
diff --git a/tools/metrics/histograms/metadata/enterprise/histograms.xml b/tools/metrics/histograms/metadata/enterprise/histograms.xml
index 858cb3d..d72abe3 100644
--- a/tools/metrics/histograms/metadata/enterprise/histograms.xml
+++ b/tools/metrics/histograms/metadata/enterprise/histograms.xml
@@ -1215,7 +1215,7 @@
 </histogram>
 
 <histogram name="Enterprise.Dlp.DataTransferControllerStarted" enum="Boolean"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>poromov@chromium.org</owner>
   <owner>chromeos-dlp@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/feature_engagement/histograms.xml b/tools/metrics/histograms/metadata/feature_engagement/histograms.xml
index 2eda8e2b..c57db17 100644
--- a/tools/metrics/histograms/metadata/feature_engagement/histograms.xml
+++ b/tools/metrics/histograms/metadata/feature_engagement/histograms.xml
@@ -399,7 +399,7 @@
 </histogram>
 
 <histogram name="InProductHelp.DismissalReason.iOS"
-    enum="InProductHelpDismissalReason" expires_after="2023-09-03">
+    enum="InProductHelpDismissalReason" expires_after="2023-11-19">
   <owner>lpromero@google.com</owner>
   <owner>gambard@chromium.org</owner>
   <summary>
@@ -515,7 +515,7 @@
 </histogram>
 
 <histogram name="InProductHelp.SnoozeAction" enum="InProductHelpSnoozeAction"
-    expires_after="2023-09-03">
+    expires_after="2023-11-19">
   <owner>haileywang@chromium.org</owner>
   <owner>shaktisahu@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/google/histograms.xml b/tools/metrics/histograms/metadata/google/histograms.xml
index 1f5061d..c0d18b61 100644
--- a/tools/metrics/histograms/metadata/google/histograms.xml
+++ b/tools/metrics/histograms/metadata/google/histograms.xml
@@ -52,7 +52,7 @@
 </histogram>
 
 <histogram name="GoogleUpdate.UpdateErrorCode" enum="GoogleUpdateErrorCode"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>sorin@chromium.org</owner>
   <owner>waffles@chromium.org</owner>
   <summary>The error code for a failed on-demand update check.</summary>
diff --git a/tools/metrics/histograms/metadata/gpu/histograms.xml b/tools/metrics/histograms/metadata/gpu/histograms.xml
index c08d4454..c7d61fa5 100644
--- a/tools/metrics/histograms/metadata/gpu/histograms.xml
+++ b/tools/metrics/histograms/metadata/gpu/histograms.xml
@@ -263,7 +263,7 @@
 </histogram>
 
 <histogram name="GPU.ANGLE.D3D11CreateDeviceError" enum="Hresult"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>jonahr@google.com</owner>
   <owner>angle-team@google.com</owner>
   <summary>
@@ -275,7 +275,7 @@
 </histogram>
 
 <histogram name="GPU.ANGLE.D3D11FeatureLevel" enum="D3DFeatureLevel"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>jonahr@google.com</owner>
   <owner>angle-team@google.com</owner>
   <summary>
@@ -289,7 +289,7 @@
 </histogram>
 
 <histogram name="GPU.ANGLE.D3D11InitializeResult" enum="D3D11InitializeResult"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>jonahr@google.com</owner>
   <owner>angle-team@google.com</owner>
   <summary>
@@ -300,7 +300,7 @@
 </histogram>
 
 <histogram name="GPU.ANGLE.D3D9InitializeResult" enum="D3D9InitializeResult"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>jonahr@google.com</owner>
   <owner>angle-team@google.com</owner>
   <summary>
@@ -474,7 +474,7 @@
 </histogram>
 
 <histogram name="GPU.D3DShaderModel" enum="ShaderModel"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>jonahr@google.com</owner>
   <owner>angle-team@google.com</owner>
   <summary>
@@ -1189,7 +1189,7 @@
 </histogram>
 
 <histogram name="GPU.PassthroughDoLinkProgramTime" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>jonahr@google.com</owner>
   <owner>angle-team@google.com</owner>
   <summary>
@@ -1617,7 +1617,7 @@
 </histogram>
 
 <histogram name="GPU.WebGLDisplayType" enum="EGLDisplayType"
-    expires_after="2023-08-27">
+    expires_after="2023-11-19">
   <owner>geofflang@chromium.org</owner>
   <owner>graphics-dev@chromium.org</owner>
   <summary>
@@ -1889,7 +1889,7 @@
 </histogram>
 
 <histogram name="Viz.FrameSinkVideoCapturer.I420.CaptureDuration" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>bialpio@chromium.org</owner>
   <owner>media-capture-dev@chromium.org</owner>
   <summary>
@@ -1903,7 +1903,7 @@
 </histogram>
 
 <histogram name="Viz.FrameSinkVideoCapturer.I420.CaptureSucceeded"
-    enum="BooleanSuccess" expires_after="2023-09-17">
+    enum="BooleanSuccess" expires_after="2023-11-19">
   <owner>bialpio@chromium.org</owner>
   <owner>media-capture-dev@chromium.org</owner>
   <summary>
@@ -1915,7 +1915,7 @@
 </histogram>
 
 <histogram name="Viz.FrameSinkVideoCapturer.I420.TotalDuration" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>bialpio@chromium.org</owner>
   <owner>media-capture-dev@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/history/histograms.xml b/tools/metrics/histograms/metadata/history/histograms.xml
index 98250ad9..7f230a047 100644
--- a/tools/metrics/histograms/metadata/history/histograms.xml
+++ b/tools/metrics/histograms/metadata/history/histograms.xml
@@ -1957,7 +1957,7 @@
 </histogram>
 
 <histogram name="History.DomainCount1Day_V3" units="domains"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>mpearson@chromium.org</owner>
   <owner>mjzhang@chromium.org</owner>
   <owner>chrome-analysis-team@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/input/histograms.xml b/tools/metrics/histograms/metadata/input/histograms.xml
index 418e33b..97369d8 100644
--- a/tools/metrics/histograms/metadata/input/histograms.xml
+++ b/tools/metrics/histograms/metadata/input/histograms.xml
@@ -91,7 +91,7 @@
 
 <histogram
     name="InputMethod.Assistive.AutocorrectV2.Actions.PK.EnabledByDefault"
-    enum="IMEAutocorrectActions" expires_after="2023-09-17">
+    enum="IMEAutocorrectActions" expires_after="2023-11-19">
   <owner>zacpartridge@google.com</owner>
   <owner>essential-inputs-team@google.com</owner>
   <summary>
@@ -990,7 +990,7 @@
 </histogram>
 
 <histogram name="InputMethod.Handwriting.LanguageModelLoadTime" units="ms"
-    expires_after="2023-08-20">
+    expires_after="2023-11-19">
   <owner>curtismcmullan@chromium.org</owner>
   <owner>essential-inputs-team@google.com</owner>
   <summary>
@@ -1001,7 +1001,7 @@
 </histogram>
 
 <histogram name="InputMethod.Handwriting.LanguagePackState"
-    enum="LanguagePackState" expires_after="2023-08-20">
+    enum="LanguagePackState" expires_after="2023-11-19">
   <owner>curtismcmullan@chromium.org</owner>
   <owner>essential-inputs-team@google.com</owner>
   <summary>
@@ -1172,7 +1172,7 @@
 </histogram>
 
 <histogram name="InputMethod.PhysicalKeyboard.Korean.Action"
-    enum="KoreanAction" expires_after="2023-08-27">
+    enum="KoreanAction" expires_after="2023-11-19">
   <owner>shend@chromium.org</owner>
   <owner>essential-inputs-team@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/ios/histograms.xml b/tools/metrics/histograms/metadata/ios/histograms.xml
index 792927d..c2327db 100644
--- a/tools/metrics/histograms/metadata/ios/histograms.xml
+++ b/tools/metrics/histograms/metadata/ios/histograms.xml
@@ -309,7 +309,7 @@
 </histogram>
 
 <histogram name="IOS.CredentialExtension.IsEnabled.Startup" enum="Boolean"
-    expires_after="2023-09-03">
+    expires_after="2023-11-19">
   <owner>veronguyen@google.com</owner>
   <owner>tmartino@chromium.org</owner>
   <summary>
@@ -772,7 +772,7 @@
 </histogram>
 
 <histogram name="IOS.Frame.FirstContentfulPaint.MainFrame" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>danieltwhite@chromium.org</owner>
   <owner>ajuma@chromium.org</owner>
   <summary>
@@ -788,7 +788,7 @@
 </histogram>
 
 <histogram name="IOS.Frame.FirstContentfulPaint.SubFrame" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>danieltwhite@chromium.org</owner>
   <owner>ajuma@chromium.org</owner>
   <summary>
@@ -1177,7 +1177,7 @@
 </histogram>
 
 <histogram name="IOS.MainThreadFreezeDetection.RecordGenerationTime" units="ms"
-    expires_after="2023-09-12">
+    expires_after="2023-11-19">
   <owner>justincohen@chromium.org</owner>
   <owner>olivierrobin@chromium.org</owner>
   <summary>
@@ -1531,7 +1531,7 @@
 </histogram>
 
 <histogram name="IOS.OpenIn.DownloadResult" enum="IOSOpenInDownloadResult"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>ewannpv@chromium.org</owner>
   <owner>mrefaat@chromium.org</owner>
   <owner>bling-team@google.com</owner>
@@ -1567,7 +1567,7 @@
 </histogram>
 
 <histogram name="IOS.PageLoad.DefaultModeMobile" enum="Boolean"
-    expires_after="2023-09-03">
+    expires_after="2023-11-19">
   <owner>gambard@chromium.org</owner>
   <owner>ajuma@chromium.org</owner>
   <summary>
@@ -1659,7 +1659,7 @@
 </histogram>
 
 <histogram name="IOS.PasswordManager.PasswordsWithFavicons.Count" units="count"
-    expires_after="2023-09-03">
+    expires_after="2023-11-19">
   <owner>veronguyen@google.com</owner>
   <owner>tmartino@chromium.org</owner>
   <summary>
@@ -1762,7 +1762,7 @@
 </histogram>
 
 <histogram name="IOS.Process.ActivePrewarm" enum="Boolean"
-    expires_after="2023-09-03">
+    expires_after="2023-11-19">
   <owner>justincohen@google.com</owner>
   <owner>olivierrobin@google.com</owner>
   <summary>
@@ -2399,7 +2399,7 @@
 </histogram>
 
 <histogram name="IOS.TabGrid.TabSelected.TimeSinceLastActivation" units="ms"
-    expires_after="2023-08-31">
+    expires_after="2023-11-19">
   <owner>gambard@chromium.org</owner>
   <owner>lpromero@chromium.org</owner>
   <owner>bling-team@google.com</owner>
@@ -2639,7 +2639,7 @@
 </histogram>
 
 <histogram name="IOS.Variations.CreateTrials.SeedExpiry"
-    enum="VariationsSeedExpiry" expires_after="2023-08-11">
+    enum="VariationsSeedExpiry" expires_after="2023-11-19">
   <owner>ginnyhuang@chromium.org</owner>
   <owner>bling-get-set-up@google.com</owner>
   <summary>
@@ -2662,7 +2662,7 @@
 </histogram>
 
 <histogram name="IOS.Variations.FirstRun.SeedFetchTime" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>ginnyhuang@chromium.org</owner>
   <owner>bling-get-set-up@google.com</owner>
   <summary>
@@ -2687,7 +2687,7 @@
 </histogram>
 
 <histogram name="IOS.Web.URLDidChangeToEmptyURL" enum="BooleanHit"
-    expires_after="2023-09-03">
+    expires_after="2023-11-19">
   <owner>gambard@chromium.org</owner>
   <owner>justincohen@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/media/histograms.xml b/tools/metrics/histograms/metadata/media/histograms.xml
index f4ee071f..fc8d96b 100644
--- a/tools/metrics/histograms/metadata/media/histograms.xml
+++ b/tools/metrics/histograms/metadata/media/histograms.xml
@@ -1332,7 +1332,7 @@
 </histogram>
 
 <histogram name="Media.AudioInputDevice.AudioServiceDelay" units="ms"
-    expires_after="2023-11-12">
+    expires_after="2023-11-19">
   <owner>fhernqvist@google.com</owner>
   <owner>olka@chromium.org</owner>
   <owner>webrtc-audio-uma@google.com</owner>
@@ -1690,7 +1690,7 @@
 </histogram>
 
 <histogram name="Media.AudioSystem.GetDeviceDescription.Result"
-    enum="BooleanSuccess" expires_after="2023-09-17">
+    enum="BooleanSuccess" expires_after="2023-11-19">
   <owner>toprice@chromium.org</owner>
   <owner>olka@chromium.org</owner>
   <summary>
@@ -3462,7 +3462,7 @@
 </histogram>
 
 <histogram name="Media.MediaDevices.GetDisplayMedia.Latency" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>toprice@chromium.org</owner>
   <owner>agpalak@chromium.org</owner>
   <owner>video-cmi-apis@google.com</owner>
@@ -3475,7 +3475,7 @@
 </histogram>
 
 <histogram name="Media.MediaDevices.GetDisplayMedia.Result"
-    enum="UserMediaRequestResult" expires_after="2023-09-17">
+    enum="UserMediaRequestResult" expires_after="2023-11-19">
   <owner>toprice@chromium.org</owner>
   <owner>agpalak@chromium.org</owner>
   <owner>video-cmi-apis@google.com</owner>
@@ -5437,7 +5437,7 @@
 </histogram>
 
 <histogram name="Media.VideoCapture.StartErrorCode" enum="VideoCaptureError"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>toprice@chromium.org</owner>
   <owner>video-cmi-apis@google.com</owner>
   <summary>
@@ -6567,7 +6567,7 @@
 </histogram>
 
 <histogram name="MediaRouter.PresentationRequest.AvailabilityUrlType"
-    enum="PresentationUrlType" expires_after="2023-09-17">
+    enum="PresentationUrlType" expires_after="2023-11-19">
   <owner>takumif@chromium.org</owner>
   <owner>mfoltz@chromium.org</owner>
   <owner>openscreen-eng@google.com</owner>
@@ -6629,7 +6629,7 @@
 </histogram>
 
 <histogram name="MediaRouter.RemotePlayback.SessionLoadTime" units="ms"
-    expires_after="2023-09-03">
+    expires_after="2023-11-19">
   <owner>muyaoxu@chromium.org</owner>
   <owner>openscreen-eng@google.com</owner>
   <summary>
@@ -6642,7 +6642,7 @@
 </histogram>
 
 <histogram name="MediaRouter.RemotePlayback.SessionStartsBeforeTimeout"
-    enum="Boolean" expires_after="2023-08-27">
+    enum="Boolean" expires_after="2023-11-19">
   <owner>muyaoxu@chromium.org</owner>
   <owner>openscreen-eng@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/memory/histograms.xml b/tools/metrics/histograms/metadata/memory/histograms.xml
index 0fa0320..7987670 100644
--- a/tools/metrics/histograms/metadata/memory/histograms.xml
+++ b/tools/metrics/histograms/metadata/memory/histograms.xml
@@ -388,7 +388,7 @@
 </histogram>
 
 <histogram name="Memory.Browser.PrivateSwapFootprint" units="MB"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>erikchen@chromium.org</owner>
   <owner>ssid@chromium.org</owner>
   <summary>
@@ -424,7 +424,7 @@
 </histogram>
 
 <histogram name="Memory.Browser.SharedMemoryFootprint" units="MB"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>erikchen@chromium.org</owner>
   <summary>
     A rough estimate of the shared memory footprint of the browser process.
@@ -1199,7 +1199,7 @@
 </histogram>
 
 <histogram name="Memory.Extension.PrivateMemoryFootprint" units="MB"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>erikchen@chromium.org</owner>
   <owner>ssid@chromium.org</owner>
   <summary>
@@ -1364,7 +1364,7 @@
 </histogram>
 
 <histogram name="Memory.Gpu.SharedMemoryFootprint" units="MB"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>erikchen@chromium.org</owner>
   <owner>ssid@chromium.org</owner>
   <summary>
@@ -1391,7 +1391,7 @@
 </histogram>
 
 <histogram name="Memory.LowMemoryKiller.Count" units="low-memory kills"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>khmel@google.com</owner>
   <owner>vovoy@google.com</owner>
   <summary>
@@ -1401,7 +1401,7 @@
 </histogram>
 
 <histogram name="Memory.LowMemoryKiller.FirstKillLatency" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>khmel@google.com</owner>
   <owner>vovoy@google.com</owner>
   <summary>
@@ -2202,7 +2202,7 @@
 </histogram>
 
 <histogram name="Memory.ProcessCount" units="processes"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>creis@chromium.org</owner>
   <owner>nasko@chromium.org</owner>
   <summary>
@@ -2285,7 +2285,7 @@
 </histogram>
 
 <histogram name="Memory.Renderer.SharedMemoryFootprint" units="MB"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>erikchen@chromium.org</owner>
   <owner>ssid@chromium.org</owner>
   <summary>
@@ -2316,7 +2316,7 @@
 </histogram>
 
 <histogram name="Memory.RenderProcessHost.Count.All" units="processes"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>alexmos@chromium.org</owner>
   <owner>creis@chromium.org</owner>
   <owner>lukasza@chromium.org</owner>
@@ -2336,7 +2336,7 @@
 </histogram>
 
 <histogram name="Memory.RenderProcessHost.Count.InitializedAndNotDead"
-    units="processes" expires_after="2023-09-17">
+    units="processes" expires_after="2023-11-19">
   <owner>alexmos@chromium.org</owner>
   <owner>creis@chromium.org</owner>
   <owner>lukasza@chromium.org</owner>
@@ -2464,7 +2464,7 @@
 </histogram>
 
 <histogram name="Memory.System.MemAvailableMB" units="MB"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>andreaorru@chromium.org</owner>
   <owner>hidehiko@chromium.org</owner>
   <summary>
@@ -2476,7 +2476,7 @@
   </summary>
 </histogram>
 
-<histogram name="Memory.System.MemUsedMB" units="MB" expires_after="2023-09-17">
+<histogram name="Memory.System.MemUsedMB" units="MB" expires_after="2023-11-19">
   <owner>andreaorru@chromium.org</owner>
   <owner>hidehiko@chromium.org</owner>
   <summary>
@@ -2672,7 +2672,7 @@
 </histogram>
 
 <histogram name="Memory.Total.SharedMemoryFootprint" units="MB"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>erikchen@chromium.org</owner>
   <owner>ssid@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/mobile/histograms.xml b/tools/metrics/histograms/metadata/mobile/histograms.xml
index 7bc0c703f..165e594 100644
--- a/tools/metrics/histograms/metadata/mobile/histograms.xml
+++ b/tools/metrics/histograms/metadata/mobile/histograms.xml
@@ -115,7 +115,7 @@
 </histogram>
 
 <histogram name="Mobile.ContextMenu.LensSupportStatus"
-    enum="IOSLensSupportStatus" expires_after="2023-08-26">
+    enum="IOSLensSupportStatus" expires_after="2023-11-19">
   <owner>hujasonx@google.com</owner>
   <owner>lens-in-bling-team@google.com</owner>
   <summary>
@@ -231,7 +231,7 @@
 </histogram>
 
 <histogram name="Mobile.Keyboard.LensSupportStatus" enum="IOSLensSupportStatus"
-    expires_after="2023-08-26">
+    expires_after="2023-11-19">
   <owner>hujasonx@google.com</owner>
   <owner>lens-in-bling-team@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/navigation/histograms.xml b/tools/metrics/histograms/metadata/navigation/histograms.xml
index 2b62c1e..e0b74bc 100644
--- a/tools/metrics/histograms/metadata/navigation/histograms.xml
+++ b/tools/metrics/histograms/metadata/navigation/histograms.xml
@@ -105,8 +105,9 @@
   <owner>bfcache-dev@chromium.org</owner>
   <summary>
     When navigating back to a page in the session history and the
-    BackForwardCache wasn't used because of the related browsing instances, this
-    records the reason why the browsing instance wasn't swapped.
+    BackForwardCache wasn't used because of the other active WebContents objects
+    in the BrowsingInstance, this records the reason why the browsing instance
+    wasn't swapped.
 
     This is recorded for all websites regardless whether back-forward cache is
     enabled or not.
@@ -145,8 +146,41 @@
     the first place based on the features used, or it might have been evicted
     while being in the cache.
 
-    This is recorded for all websites regardless whether back-forward cache is
-    enabled or not.
+    This is recorded for all websites regardless of whether back-forward cache
+    is enabled or not.
+  </summary>
+</histogram>
+
+<histogram
+    name="BackForwardCache.AllSites.HistoryNavigationOutcome.RelatedActiveContents.Count"
+    units="count" expires_after="2023-10-21">
+  <owner>rakina@chromium.org</owner>
+  <owner>bfcache-dev@chromium.org</owner>
+  <summary>
+    When navigating back to a page in the session history and the
+    BackForwardCache wasn't used because of other active WebContents objects in
+    the BrowsingInstance, this records the number of other active pages/related
+    active contents using the same BrowsingInstance.
+
+    This is recorded for all websites regardless of whether back-forward cache
+    is enabled or not.
+  </summary>
+</histogram>
+
+<histogram
+    name="BackForwardCache.AllSites.HistoryNavigationOutcome.RelatedActiveContents.IsPotentiallySyncAccessible"
+    enum="RelatedActiveContentsSyncAccessInfo" expires_after="2023-10-21">
+  <owner>rakina@chromium.org</owner>
+  <owner>bfcache-dev@chromium.org</owner>
+  <summary>
+    When navigating back to a page in the session history and the
+    BackForwardCache wasn't used because of other active WebContents objects in
+    the BrowsingInstance, this Records whether the page was potentially
+    synchronously accessible by other pages/related active contents using the
+    same BrowsingInstance, at the time the page was navigated away from.
+
+    This is recorded for all websites regardless of whether back-forward cache
+    is enabled or not.
   </summary>
 </histogram>
 
@@ -271,8 +305,9 @@
   <owner>bfcache-dev@chromium.org</owner>
   <summary>
     When navigating back to a page in the session history and the
-    BackForwardCache wasn't used because of the related browsing instances, this
-    records the reason why the browsing instance wasn't swapped.
+    BackForwardCache wasn't used because of the other active WebContents objects
+    in the BrowsingInstance, this records the reason why the browsing instance
+    wasn't swapped.
 
     This is recorded when back-forward cache is enabled for this navigation
     (back-forward cache feature is enabled and the domain is in the scope of the
@@ -355,6 +390,41 @@
   </summary>
 </histogram>
 
+<histogram
+    name="BackForwardCache.HistoryNavigationOutcome.RelatedActiveContents.Count"
+    units="count" expires_after="2023-10-21">
+  <owner>rakina@chromium.org</owner>
+  <owner>bfcache-dev@chromium.org</owner>
+  <summary>
+    When navigating back to a page in the session history and the
+    BackForwardCache wasn't used because of other active WebContents objects in
+    the BrowsingInstance, this records the number of other active pages/related
+    active contents using the same BrowsingInstance.
+
+    This is recorded when back-forward cache is enabled for this navigation
+    (back-forward cache feature is enabled and the domain is in the scope of the
+    experiment).
+  </summary>
+</histogram>
+
+<histogram
+    name="BackForwardCache.HistoryNavigationOutcome.RelatedActiveContents.IsPotentiallySyncAccessible"
+    enum="RelatedActiveContentsSyncAccessInfo" expires_after="2023-10-21">
+  <owner>rakina@chromium.org</owner>
+  <owner>bfcache-dev@chromium.org</owner>
+  <summary>
+    When navigating back to a page in the session history and the
+    BackForwardCache wasn't used because of other active WebContents objects in
+    the BrowsingInstance, this Records whether the page was potentially
+    synchronously accessible by other pages/related active contents using the
+    same BrowsingInstance, at the time the page was navigated away from.
+
+    This is recorded when back-forward cache is enabled for this navigation
+    (back-forward cache feature is enabled and the domain is in the scope of the
+    experiment).
+  </summary>
+</histogram>
+
 <histogram name="BackForwardCache.MainFrameHasPageshowListenersOnRestore"
     enum="BooleanPresent" expires_after="M82">
   <owner>altimin@chromium.org</owner>
@@ -368,7 +438,7 @@
 </histogram>
 
 <histogram name="BackForwardCache.PageWithForm.RestoreResult"
-    enum="BackForwardCacheHistoryNavigationOutcome" expires_after="2023-09-17">
+    enum="BackForwardCacheHistoryNavigationOutcome" expires_after="2023-11-19">
   <owner>wenyufu@chromium.org</owner>
   <owner>bfcache-dev@chromium.org</owner>
   <summary>
@@ -385,7 +455,7 @@
 </histogram>
 
 <histogram name="BackForwardCache.PageWithForm.Storable"
-    enum="BackForwardCachePageWithFormStorable" expires_after="2023-09-17">
+    enum="BackForwardCachePageWithFormStorable" expires_after="2023-11-19">
   <owner>wenyufu@chromium.org</owner>
   <owner>bfcache-dev@chromium.org</owner>
   <summary>
@@ -668,7 +738,7 @@
 </histogram>
 
 <histogram name="Navigation.Guest.IsHTTPOrHTTPS"
-    enum="BooleanHttpBasedOrOtherScheme" expires_after="2023-09-17">
+    enum="BooleanHttpBasedOrOtherScheme" expires_after="2023-11-19">
   <owner>alexmos@chromium.org</owner>
   <owner>creis@chromium.org</owner>
   <owner>wjmaclean@chromium.org</owner>
@@ -681,7 +751,7 @@
 </histogram>
 
 <histogram name="Navigation.Guest.IsMainFrame" enum="BooleanMainFrame"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>alexmos@chromium.org</owner>
   <owner>creis@chromium.org</owner>
   <owner>wjmaclean@chromium.org</owner>
@@ -727,7 +797,7 @@
 </histogram>
 
 <histogram name="Navigation.IsGuest" enum="NavigationIsGuest"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>alexmos@chromium.org</owner>
   <owner>creis@chromium.org</owner>
   <owner>wjmaclean@chromium.org</owner>
@@ -824,7 +894,7 @@
 </histogram>
 
 <histogram name="Navigation.MainFrame.MaxFrameCount" units="frames"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>michaelpg@chromium.org</owner>
   <owner>yilkal@chromium.org</owner>
   <owner>cros-families-eng@google.com</owner>
@@ -1004,7 +1074,7 @@
 </histogram>
 
 <histogram name="Navigation.OnBeforeUnloadBrowserToRendererIpcTime" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>sky@chromium.org</owner>
   <owner>jam@chromium.org</owner>
   <summary>
@@ -1014,7 +1084,7 @@
 </histogram>
 
 <histogram name="Navigation.OnBeforeUnloadLegacyPostTaskTime" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>sky@chromium.org</owner>
   <owner>jam@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/net/histograms.xml b/tools/metrics/histograms/metadata/net/histograms.xml
index 5b2b4b94..5256278c 100644
--- a/tools/metrics/histograms/metadata/net/histograms.xml
+++ b/tools/metrics/histograms/metadata/net/histograms.xml
@@ -221,7 +221,7 @@
 </histogram>
 
 <histogram name="HttpCache.AddTransactionToEntry" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>bashi@chromium.org</owner>
   <owner>net-dev@chromium.org</owner>
   <summary>
@@ -385,7 +385,7 @@
 </histogram>
 
 <histogram name="Net.AlternateServiceFailed" enum="NetErrorCodes"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>tbansal@chromium.org</owner>
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/OWNERS</owner>
@@ -1340,7 +1340,7 @@
 </histogram>
 
 <histogram name="Net.DNS.JobQueueTime.Success" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>horo@chromium.org</owner>
   <owner>net-dev@chromium.org</owner>
   <summary>
@@ -1509,7 +1509,7 @@
 </histogram>
 
 <histogram name="Net.DNS.SecureDnsMode.Automatic.ResolveTime" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>horo@chromium.org</owner>
   <owner>doh-core@google.com</owner>
   <summary>
@@ -1521,7 +1521,7 @@
 </histogram>
 
 <histogram name="Net.DNS.SecureDnsMode.Off.ResolveTime" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>horo@chromium.org</owner>
   <owner>doh-core@google.com</owner>
   <summary>
@@ -1533,7 +1533,7 @@
 </histogram>
 
 <histogram name="Net.DNS.SecureDnsMode.Secure.ResolveTime" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>horo@chromium.org</owner>
   <owner>doh-core@google.com</owner>
   <summary>
@@ -2252,7 +2252,7 @@
 </histogram>
 
 <histogram name="Net.ProxyScriptFetcher.SuccessDuration" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>dschinazi@chromium.org</owner>
   <summary>
     The time taken to successfully fetch a PAC script. This does not include
@@ -2315,7 +2315,7 @@
 </histogram>
 
 <histogram name="Net.QuicChromiumClientStream.HandleOnCloseConnectionError"
-    enum="QuicErrorCodes" expires_after="2023-09-17">
+    enum="QuicErrorCodes" expires_after="2023-11-19">
   <owner>renjietang@chromium.org</owner>
   <owner>src/net/OWNERS</owner>
   <summary>
@@ -2324,14 +2324,14 @@
 </histogram>
 
 <histogram name="Net.QuicChromiumClientStream.HandleOnCloseNetError"
-    enum="NetErrorCodes" expires_after="2023-09-17">
+    enum="NetErrorCodes" expires_after="2023-11-19">
   <owner>renjietang@chromium.org</owner>
   <owner>src/net/OWNERS</owner>
   <summary>Log the net error code when QUIC stream handle closes.</summary>
 </histogram>
 
 <histogram name="Net.QuicChromiumClientStream.HandleOnCloseStreamError"
-    enum="QuicRstStreamErrorCodes" expires_after="2023-09-17">
+    enum="QuicRstStreamErrorCodes" expires_after="2023-11-19">
   <owner>renjietang@chromium.org</owner>
   <owner>src/net/OWNERS</owner>
   <summary>Log the stream error code when QUIC stream handle closes.</summary>
@@ -2345,7 +2345,7 @@
 </histogram>
 
 <histogram name="Net.QuicConnection.MultiPortPathCreationCancelled"
-    enum="PathValidationReason" expires_after="2023-09-17">
+    enum="PathValidationReason" expires_after="2023-11-19">
   <owner>renjietang@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -2364,7 +2364,7 @@
 </histogram>
 
 <histogram name="Net.QuicConnection.WritePacketStatus" enum="QuicWriteStatus"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>wub@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -2567,7 +2567,7 @@
 </histogram>
 
 <histogram name="Net.QuicHttpStream.ProcessResponseHeaderSuccess"
-    enum="BooleanSuccess" expires_after="2023-09-17">
+    enum="BooleanSuccess" expires_after="2023-11-19">
   <owner>renjietang@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -2621,7 +2621,7 @@
 </histogram>
 
 <histogram name="Net.QuicMultiPort.NumMultiPortFailureWhenPathDegrading"
-    units="times" expires_after="2023-09-17">
+    units="times" expires_after="2023-11-19">
   <owner>renjietang@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -2631,7 +2631,7 @@
 </histogram>
 
 <histogram name="Net.QuicMultiPort.NumMultiPortFailureWhenPathNotDegrading"
-    units="times" expires_after="2023-09-17">
+    units="times" expires_after="2023-11-19">
   <owner>renjietang@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -2661,7 +2661,7 @@
 </histogram>
 
 <histogram name="Net.QuicNetworkDegradingDurationTillNewNetworkMadeDefault"
-    units="ms" expires_after="2023-09-17">
+    units="ms" expires_after="2023-11-19">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -2671,7 +2671,7 @@
 </histogram>
 
 <histogram name="Net.QuicNetworkDisconnectionDuration" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -2881,7 +2881,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.CloseAllSessionsError" enum="NetErrorCodes"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -2900,7 +2900,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.ClosedByRtoAtClient.ReceivedPacketCount"
-    units="packets" expires_after="2023-09-17">
+    units="packets" expires_after="2023-11-19">
   <owner>wub@chromium.org</owner>
   <owner>fayang@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
@@ -2911,7 +2911,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.ClosedByRtoAtClient.SentPacketCount"
-    units="packets" expires_after="2023-09-17">
+    units="packets" expires_after="2023-11-19">
   <owner>wub@chromium.org</owner>
   <owner>fayang@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
@@ -2922,7 +2922,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.ClosedDuringInitializeSession" enum="Boolean"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -2932,7 +2932,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.CloseSessionOnError" enum="NetErrorCodes"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3134,7 +3134,7 @@
 
 <histogram
     name="Net.QuicSession.ConnectionCloseErrorCodeServerIetfApplicationGQuicErrorMissing"
-    enum="QuicHttp3ErrorCodes" expires_after="2023-09-17">
+    enum="QuicHttp3ErrorCodes" expires_after="2023-11-19">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3237,7 +3237,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.ConnectionDuration" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>renjietang@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3620,7 +3620,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.LastSentPacketContentBeforePublicReset"
-    units="bitfield value" expires_after="2023-07-16">
+    units="bitfield value" expires_after="2023-11-19">
   <owner>fayang@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3640,7 +3640,7 @@
 
 <histogram
     name="Net.QuicSession.MaxConsecutiveRtoWithForwardProgressAndBlackholeDetected"
-    units="count" expires_after="2023-09-17">
+    units="count" expires_after="2023-11-19">
   <owner>fayang@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3678,7 +3678,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.MigrateToSocketSuccess" enum="Boolean"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>renjietang@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3895,7 +3895,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.PacketWriteTime" units="units"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3926,7 +3926,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.PlatformNotification"
-    enum="QuicPlatformNotification" expires_after="2023-09-17">
+    enum="QuicPlatformNotification" expires_after="2023-11-19">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3998,7 +3998,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.PushedBytes" units="count"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -4097,7 +4097,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.ReceivedSettings.EnableExtendedConnect"
-    enum="Boolean" expires_after="2023-09-17">
+    enum="Boolean" expires_after="2023-11-19">
   <owner>momoka@google.com</owner>
   <owner>ricea@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
@@ -4226,7 +4226,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.ServerSideMtu" units="bytes"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -5552,7 +5552,7 @@
   <summary>Chromium error code from call to RandomBind() UDP socket.</summary>
 </histogram>
 
-<histogram name="Net.UDPSocketWinClose" units="ms" expires_after="2023-09-17">
+<histogram name="Net.UDPSocketWinClose" units="ms" expires_after="2023-11-19">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/OWNERS</owner>
   <summary>The time spent in closesocket call in UDPSocketWin::Close.</summary>
diff --git a/tools/metrics/histograms/metadata/network/histograms.xml b/tools/metrics/histograms/metadata/network/histograms.xml
index 725b3643..fa77f9db 100644
--- a/tools/metrics/histograms/metadata/network/histograms.xml
+++ b/tools/metrics/histograms/metadata/network/histograms.xml
@@ -718,7 +718,7 @@
 </histogram>
 
 <histogram name="Network.CaptivePortalResult" enum="CaptivePortalNetworkState"
-    expires_after="2023-09-18">
+    expires_after="2023-11-19">
   <owner>stevenjb@chromium.org</owner>
   <owner>cros-network-health-team@google.com</owner>
   <summary>
@@ -729,7 +729,7 @@
 </histogram>
 
 <histogram name="Network.CaptivePortalStatusCode" enum="HttpResponseCode"
-    expires_after="2023-09-18">
+    expires_after="2023-11-19">
   <owner>stevenjb@chromium.org</owner>
   <owner>cros-network-health-team@google.com</owner>
   <summary>
@@ -1795,7 +1795,7 @@
 </histogram>
 
 <histogram name="Network.NetworkPortalDetectorResult"
-    enum="NetworkPortalStatus" expires_after="2023-09-18">
+    enum="NetworkPortalStatus" expires_after="2023-11-19">
   <owner>stevenjb@chromium.org</owner>
   <owner>cros-network-health-team@google.com</owner>
   <summary>
@@ -1806,7 +1806,7 @@
 </histogram>
 
 <histogram name="Network.NetworkPortalDetectorRunCount" units="attempts"
-    expires_after="2023-09-18">
+    expires_after="2023-11-19">
   <owner>stevenjb@chromium.org</owner>
   <owner>cros-network-health-team@google.com</owner>
   <summary>
@@ -1816,7 +1816,7 @@
 </histogram>
 
 <histogram name="Network.NetworkPortalDetectorType" enum="NetworkTechnology"
-    expires_after="2023-09-18">
+    expires_after="2023-11-19">
   <owner>stevenjb@chromium.org</owner>
   <owner>cros-network-health-team@google.com</owner>
   <summary>
@@ -1828,7 +1828,7 @@
 </histogram>
 
 <histogram name="Network.NetworkPortalNotificationState"
-    enum="CaptivePortalNetworkState" expires_after="2023-09-18">
+    enum="CaptivePortalNetworkState" expires_after="2023-11-19">
   <owner>stevenjb@chromium.org</owner>
   <owner>cros-network-health-team@google.com</owner>
   <summary>
@@ -1839,7 +1839,7 @@
 </histogram>
 
 <histogram name="Network.NetworkPortalSigninMode"
-    enum="NetworkPortalSigninMode" expires_after="2023-09-18">
+    enum="NetworkPortalSigninMode" expires_after="2023-11-19">
   <owner>stevenjb@chromium.org</owner>
   <owner>cros-network-health-team@google.com</owner>
   <summary>
@@ -1849,7 +1849,7 @@
 </histogram>
 
 <histogram name="Network.NetworkPortalSigninSource"
-    enum="NetworkPortalSigninSource" expires_after="2023-09-18">
+    enum="NetworkPortalSigninSource" expires_after="2023-11-19">
   <owner>stevenjb@chromium.org</owner>
   <owner>cros-network-health-team@google.com</owner>
   <summary>
@@ -1888,7 +1888,7 @@
 </histogram>
 
 <histogram name="Network.PortalSuspectedToOnlineTime" units="ms"
-    expires_after="2023-09-18">
+    expires_after="2023-11-19">
   <owner>stevenjb@chromium.org</owner>
   <owner>cros-network-health-team@google.com</owner>
   <summary>
@@ -1899,7 +1899,7 @@
 </histogram>
 
 <histogram name="Network.RedirectFoundToOnlineTime" units="ms"
-    expires_after="2023-09-18">
+    expires_after="2023-11-19">
   <owner>stevenjb@chromium.org</owner>
   <owner>cros-network-health-team@google.com</owner>
   <summary>
@@ -2029,7 +2029,7 @@
 </histogram>
 
 <histogram name="Network.Shill.Cellular.PortalResult"
-    enum="NetworkPortalResult" expires_after="2023-09-17">
+    enum="NetworkPortalResult" expires_after="2023-11-19">
   <owner>ejcaruso@chromium.org</owner>
   <owner>cros-network-metrics@google.com</owner>
   <summary>
@@ -2059,7 +2059,7 @@
 </histogram>
 
 <histogram name="Network.Shill.Cellular.TimeOnline" units="seconds"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>ejcaruso@chromium.org</owner>
   <owner>cros-network-metrics@google.com</owner>
   <summary>
@@ -2070,7 +2070,7 @@
 </histogram>
 
 <histogram name="Network.Shill.Cellular.TimeToConfig" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>ejcaruso@chromium.org</owner>
   <owner>cros-network-metrics@google.com</owner>
   <summary>
@@ -2080,7 +2080,7 @@
 </histogram>
 
 <histogram name="Network.Shill.Cellular.TimeToConnect" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>ejcaruso@chromium.org</owner>
   <owner>cros-network-metrics@google.com</owner>
   <summary>
@@ -2090,7 +2090,7 @@
 </histogram>
 
 <histogram name="Network.Shill.Cellular.TimeToDisable" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>ejcaruso@chromium.org</owner>
   <owner>cros-network-metrics@google.com</owner>
   <summary>
@@ -2100,7 +2100,7 @@
 </histogram>
 
 <histogram name="Network.Shill.Cellular.TimeToEnable" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>ejcaruso@chromium.org</owner>
   <owner>cros-network-metrics@google.com</owner>
   <summary>
@@ -2120,7 +2120,7 @@
 </histogram>
 
 <histogram name="Network.Shill.Cellular.TimeToOnline" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>ejcaruso@chromium.org</owner>
   <owner>cros-network-metrics@google.com</owner>
   <summary>
@@ -2293,7 +2293,7 @@
 </histogram>
 
 <histogram name="Network.Shill.Ethernet.TimeOnline" units="seconds"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>hugobenichi@google.com</owner>
   <owner>cros-network-metrics@google.com</owner>
   <summary>
@@ -2384,7 +2384,7 @@
 </histogram>
 
 <histogram name="Network.Shill.PortalDetector.AttemptsToDisconnect.Cellular"
-    units="attempts" expires_after="2023-09-18">
+    units="attempts" expires_after="2023-11-19">
   <owner>stevenjb@chromium.org</owner>
   <owner>cros-network-metrics@google.com</owner>
   <summary>
@@ -2417,7 +2417,7 @@
 </histogram>
 
 <histogram name="Network.Shill.PortalDetector.AttemptsToOnline.Cellular"
-    units="attempts" expires_after="2023-09-18">
+    units="attempts" expires_after="2023-11-19">
   <owner>stevenjb@chromium.org</owner>
   <owner>cros-network-metrics@google.com</owner>
   <summary>
@@ -2437,7 +2437,7 @@
 </histogram>
 
 <histogram name="Network.Shill.PortalDetector.AttemptsToOnline.Wifi"
-    units="attempts" expires_after="2023-09-18">
+    units="attempts" expires_after="2023-11-19">
   <owner>stevenjb@chromium.org</owner>
   <owner>cros-network-metrics@google.com</owner>
   <summary>
@@ -2478,7 +2478,7 @@
 </histogram>
 
 <histogram name="Network.Shill.PortalDetector.InitialResult.Cellular"
-    enum="PortalDetectorResult" expires_after="2023-09-18">
+    enum="PortalDetectorResult" expires_after="2023-11-19">
   <owner>stevenjb@chromium.org</owner>
   <owner>cros-network-metrics@google.com</owner>
   <summary>
@@ -2498,7 +2498,7 @@
 </histogram>
 
 <histogram name="Network.Shill.PortalDetector.InitialResult.Wifi"
-    enum="PortalDetectorResult" expires_after="2023-09-18">
+    enum="PortalDetectorResult" expires_after="2023-11-19">
   <owner>stevenjb@chromium.org</owner>
   <owner>cros-network-metrics@google.com</owner>
   <summary>
@@ -2508,7 +2508,7 @@
 </histogram>
 
 <histogram name="Network.Shill.PortalDetector.RepeatResult.Cellular"
-    enum="PortalDetectorResult" expires_after="2023-09-18">
+    enum="PortalDetectorResult" expires_after="2023-11-19">
   <owner>stevenjb@chromium.org</owner>
   <owner>cros-network-metrics@google.com</owner>
   <summary>
@@ -2528,7 +2528,7 @@
 </histogram>
 
 <histogram name="Network.Shill.PortalDetector.RepeatResult.Wifi"
-    enum="PortalDetectorResult" expires_after="2023-09-18">
+    enum="PortalDetectorResult" expires_after="2023-11-19">
   <owner>stevenjb@chromium.org</owner>
   <owner>cros-network-metrics@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/new_tab_page/histograms.xml b/tools/metrics/histograms/metadata/new_tab_page/histograms.xml
index 5ccc417..24df9a5 100644
--- a/tools/metrics/histograms/metadata/new_tab_page/histograms.xml
+++ b/tools/metrics/histograms/metadata/new_tab_page/histograms.xml
@@ -35,7 +35,7 @@
 </histogram>
 
 <histogram name="NewTabPage.ActioniOS" enum="NewTabPageActioniOS"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>justincohen@chromium.org</owner>
   <owner>gambard@chromium.org</owner>
   <summary>
@@ -218,7 +218,7 @@
 </histogram>
 
 <histogram name="NewTabPage.Carts.DiscountConsentStatusAtLoad"
-    enum="CartDiscountConsentStatus" expires_after="2023-09-17">
+    enum="CartDiscountConsentStatus" expires_after="2023-11-19">
   <owner>yuezhanggg@chromium.org</owner>
   <owner>wychen@chromium.org</owner>
   <owner>chrome-shopping@google.com</owner>
@@ -952,7 +952,7 @@
 </histogram>
 
 <histogram name="NewTabPage.Lens.UploadDialog.DialogError"
-    enum="NewTabPageLensUploadDialogErrors" expires_after="2023-09-17">
+    enum="NewTabPageLensUploadDialogErrors" expires_after="2023-11-19">
   <owner>nguyenbryan@google.com</owner>
   <owner>yowakita@google.com</owner>
   <owner>bbonnet@google.com</owner>
@@ -1747,7 +1747,7 @@
 </histogram>
 
 <histogram name="NewTabPage.SearchResumptionModule.Show"
-    enum="SearchResumptionModule.ModuleShowStatus" expires_after="2023-09-10">
+    enum="SearchResumptionModule.ModuleShowStatus" expires_after="2023-11-19">
   <owner>hanxi@chromium.org</owner>
   <owner>xinyiji@chromium.org</owner>
   <summary>
@@ -1954,7 +1954,7 @@
 </histogram>
 
 <histogram name="NewTabPage.TimeSinceLastNTP" units="ms"
-    expires_after="2023-09-03">
+    expires_after="2023-11-19">
   <owner>tiborg@chromium.org</owner>
   <owner>yyushkina@chromium.org</owner>
   <owner>chrome-desktop-ntp@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/optimization/histograms.xml b/tools/metrics/histograms/metadata/optimization/histograms.xml
index 2d6ff3c..976e25d 100644
--- a/tools/metrics/histograms/metadata/optimization/histograms.xml
+++ b/tools/metrics/histograms/metadata/optimization/histograms.xml
@@ -693,7 +693,7 @@
 </histogram>
 
 <histogram name="OptimizationGuide.PageContentAnnotations.EntityCollection_50"
-    enum="OptimizationGuidePageEntityCollection" expires_after="2023-09-17">
+    enum="OptimizationGuidePageEntityCollection" expires_after="2023-11-19">
   <owner>tbansal@chromium.org</owner>
   <owner>chrome-intelligence-core@google.com</owner>
   <summary>
@@ -816,7 +816,7 @@
 <histogram
     name="OptimizationGuide.PageContentAnnotationsService.ContentAnnotationsStorageStatus"
     enum="OptimizationGuidePageContentAnnotationsStorageStatus"
-    expires_after="2023-11-12">
+    expires_after="2023-11-19">
   <owner>sophiechang@chromium.org</owner>
   <owner>mcrouse@chromium.org</owner>
   <summary>
@@ -1280,7 +1280,7 @@
 
 <histogram
     name="OptimizationGuide.PredictionModelFetcher.GetModelsResponse.NetErrorCode"
-    enum="NetErrorCodes" expires_after="2023-11-12">
+    enum="NetErrorCodes" expires_after="2023-11-19">
   <owner>mcrouse@chromium.org</owner>
   <owner>sophiechang@chromium.org</owner>
   <summary>
@@ -1310,7 +1310,7 @@
 
 <histogram
     name="OptimizationGuide.PredictionModelFetcher.GetModelsResponse.Status"
-    enum="HttpResponseCode" expires_after="2023-11-12">
+    enum="HttpResponseCode" expires_after="2023-11-19">
   <owner>mcrouse@chromium.org</owner>
   <owner>sophiechang@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml
index 067a7c9b..b6ba130 100644
--- a/tools/metrics/histograms/metadata/others/histograms.xml
+++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -311,7 +311,7 @@
 </histogram>
 
 <histogram name="AccessCodeCast.Ui.AccessCodeNotFoundCount" units="instances"
-    expires_after="2023-07-23">
+    expires_after="2023-11-19">
   <owner>bzielinski@google.com</owner>
   <owner>cros-edu-eng@google.com</owner>
   <summary>
@@ -1573,7 +1573,7 @@
 </histogram>
 
 <histogram name="BlueZ.AdvertisementMonitor.NumOfMonitors" units="count"
-    expires_after="2023-06-11">
+    expires_after="2023-12-11">
   <owner>apusaka@chromium.org</owner>
   <owner>chromeos-bt-platform-sw-core@google.com</owner>
   <summary>
@@ -1584,7 +1584,7 @@
 </histogram>
 
 <histogram name="BlueZ.AdvertisementMonitor.{Filter}.FilterPatternsPerMinute"
-    units="count" expires_after="2023-06-11">
+    units="count" expires_after="2023-12-11">
   <owner>apusaka@chromium.org</owner>
   <owner>chromeos-bt-platform-sw-core@google.com</owner>
   <summary>
@@ -1600,7 +1600,7 @@
 </histogram>
 
 <histogram name="BlueZ.AdvertisementMonitor.{Filter}.{Operation}.Result"
-    enum="BlueZResultOfAdvertisementMonitor" expires_after="2023-06-11">
+    enum="BlueZResultOfAdvertisementMonitor" expires_after="2023-12-11">
   <owner>apusaka@chromium.org</owner>
   <owner>chromeos-bt-platform-sw-core@google.com</owner>
   <summary>
@@ -2091,7 +2091,7 @@
 </histogram>
 
 <histogram name="Cast.Sender.RemotePlayback.InitiationLocation"
-    enum="RemotePlaybackInitiationLocation" expires_after="2023-09-17">
+    enum="RemotePlaybackInitiationLocation" expires_after="2023-11-19">
   <owner>muyaoxu@google.com</owner>
   <owner>openscreen-eng@google.com</owner>
   <summary>
@@ -4731,7 +4731,7 @@
 </histogram>
 
 <histogram name="DemoMode.UserClicksAndPresses" units="clicks"
-    expires_after="2023-08-27">
+    expires_after="2023-11-19">
   <owner>lbowen@google.com</owner>
   <owner>cros-demo-mode-eng@google.com</owner>
   <summary>
@@ -5983,7 +5983,7 @@
 </histogram>
 
 <histogram name="Feedback.ChromeOSApp.PostSubmitAction"
-    enum="FeedbackAppPostSubmitAction" expires_after="2023-09-17">
+    enum="FeedbackAppPostSubmitAction" expires_after="2023-11-19">
   <owner>longbowei@google.com</owner>
   <owner>xiangdongkong@google.com</owner>
   <owner>cros-feedback-app@google.com</owner>
@@ -6270,7 +6270,7 @@
 </histogram>
 
 <histogram name="FirstRun.NewUserExperience.GoogleAppsInteraction"
-    enum="NuxGoogleAppsInteractions" expires_after="2023-09-17">
+    enum="NuxGoogleAppsInteractions" expires_after="2023-11-19">
   <owner>johntlee@chromium.org</owner>
   <owner>dpapad@chromium.org</owner>
   <summary>
@@ -6284,7 +6284,7 @@
 </histogram>
 
 <histogram name="FirstRun.NewUserExperience.GoogleAppsSelection"
-    enum="NuxGoogleAppsSelections" expires_after="2023-09-17">
+    enum="NuxGoogleAppsSelections" expires_after="2023-11-19">
   <owner>johntlee@chromium.org</owner>
   <owner>dpapad@chromium.org</owner>
   <summary>
@@ -6348,7 +6348,7 @@
 </histogram>
 
 <histogram name="FirstRun.NewUserExperience.SignInInterstitialInteraction"
-    enum="NuxSignInInterstitialInteractions" expires_after="2023-09-17">
+    enum="NuxSignInInterstitialInteractions" expires_after="2023-11-19">
   <owner>johntlee@chromium.org</owner>
   <owner>dpapad@chromium.org</owner>
   <summary>
@@ -6391,7 +6391,7 @@
 </histogram>
 
 <histogram name="FirstRun.Stage" enum="FirstRunStageResult"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>tinazwang@chromium.org</owner>
   <owner>bling-get-started@google.com</owner>
   <summary>
@@ -6659,7 +6659,7 @@
 </histogram>
 
 <histogram name="Gamepad.UnknownGamepadConnected" enum="GamepadSource"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>mattreynolds@chromium.org</owner>
   <owner>deviceapi-team@google.com</owner>
   <summary>
@@ -8134,7 +8134,7 @@
 </histogram>
 
 <histogram name="Mojo.Channel.WriteQueuePendingMessages" units="count"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>amistry@chromium.org</owner>
   <owner>bgeffon@chromium.org</owner>
   <owner>rockot@google.com</owner>
@@ -8763,7 +8763,7 @@
 </histogram>
 
 <histogram name="OSCrypt.BackendUsage" enum="LinuxPasswordStoreUsage"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>cfroussios@chromium.org</owner>
   <owner>mamir@chromium.org</owner>
   <summary>
@@ -11641,7 +11641,7 @@
 </histogram>
 
 <histogram name="Shutdown.Renderers.Total" units="renderers"
-    expires_after="2023-09-03">
+    expires_after="2023-11-19">
   <owner>etienneb@chromium.org</owner>
   <owner>gab@chromium.org</owner>
   <summary>
@@ -13445,7 +13445,7 @@
 </histogram>
 
 <histogram name="Tracing.SharedBufferIsValid" enum="BooleanSuccess"
-    expires_after="2023-09-19">
+    expires_after="2023-11-19">
   <owner>eseckler@chromium.org</owner>
   <owner>tracing@chromium.org</owner>
   <summary>
@@ -13746,7 +13746,7 @@
 </histogram>
 
 <histogram name="UserImage.Changed2" enum="ChromeOSUserImageId2"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>jasontt@chromium.org</owner>
   <owner>assistive-eng@google.com</owner>
   <summary>
@@ -14001,7 +14001,7 @@
 </histogram>
 
 <histogram name="VoiceInteraction.FailureEventSource"
-    enum="VoiceInteractionEventSource" expires_after="2023-08-20">
+    enum="VoiceInteractionEventSource" expires_after="2023-11-19">
   <owner>basiaz@google.com</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/page/histograms.xml b/tools/metrics/histograms/metadata/page/histograms.xml
index 3dc8958d..60f05ac3 100644
--- a/tools/metrics/histograms/metadata/page/histograms.xml
+++ b/tools/metrics/histograms/metadata/page/histograms.xml
@@ -718,7 +718,7 @@
 
 <histogram
     name="PageLoad.Clients.FencedFrames.PaintTiming.NavigationToFirstContentfulPaint"
-    units="ms" expires_after="2023-09-17">
+    units="ms" expires_after="2023-11-19">
   <owner>toyoshim@chromium.org</owner>
   <owner>mparch-dev@chromium.org</owner>
   <summary>
@@ -744,7 +744,7 @@
 
 <histogram
     name="PageLoad.Clients.FencedFrames.PaintTiming.NavigationToFirstPaint"
-    units="ms" expires_after="2023-08-30">
+    units="ms" expires_after="2023-11-19">
   <owner>toyoshim@chromium.org</owner>
   <owner>mparch-dev@chromium.org</owner>
   <summary>
@@ -756,7 +756,7 @@
 
 <histogram
     name="PageLoad.Clients.FencedFrames.PaintTiming.NavigationToLargestContentfulPaint2"
-    units="ms" expires_after="2023-09-17">
+    units="ms" expires_after="2023-11-19">
   <owner>toyoshim@chromium.org</owner>
   <owner>mparch-dev@chromium.org</owner>
   <summary>
@@ -1266,7 +1266,7 @@
 
 <histogram
     name="PageLoad.Clients.ThirdParty.Frames.Opaque.NavigationToFirstContentfulPaint"
-    units="ms" expires_after="2023-09-03">
+    units="ms" expires_after="2023-11-19">
   <owner>awillia@chromium.org</owner>
   <owner>djmitche@chromium.org</owner>
   <summary>
@@ -1283,7 +1283,7 @@
 
 <histogram
     name="PageLoad.Clients.ThirdParty.Frames.Opaque.NavigationToLargestContentfulPaint"
-    units="ms" expires_after="2023-09-03">
+    units="ms" expires_after="2023-11-19">
   <owner>awillia@chromium.org</owner>
   <owner>djmitche@chromium.org</owner>
   <summary>
@@ -2406,7 +2406,7 @@
 </histogram>
 
 <histogram name="PageLoad.Internal.PageType" enum="PageLoadTrackerPageType"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>toyoshim@chromium.org</owner>
   <owner>mparch-dev@chromium.org</owner>
   <summary>
@@ -2474,7 +2474,7 @@
 </histogram>
 
 <histogram name="PageLoad.Internal.Prerender2.Event"
-    enum="PageLoadPrerenderEvent" expires_after="2023-09-17">
+    enum="PageLoadPrerenderEvent" expires_after="2023-11-19">
   <owner>kenoss@chromium.org</owner>
   <owner>src/content/browser/preloading/prerender/OWNERS</owner>
   <summary>
@@ -2596,7 +2596,7 @@
 </histogram>
 
 <histogram name="PageLoad.LayoutInstability.CumulativeShiftScore"
-    units="scorex10" expires_after="2023-09-17">
+    units="scorex10" expires_after="2023-11-19">
   <owner>bmcquade@chromium.org</owner>
   <owner>skobes@chromium.org</owner>
   <summary>
@@ -2813,7 +2813,7 @@
 </histogram>
 
 <histogram name="PageLoad.PageTiming.NavigationToFirstForeground" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>bmcquade@chromium.org</owner>
   <owner>csharrison@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/password/histograms.xml b/tools/metrics/histograms/metadata/password/histograms.xml
index ebb4643..b750056 100644
--- a/tools/metrics/histograms/metadata/password/histograms.xml
+++ b/tools/metrics/histograms/metadata/password/histograms.xml
@@ -179,7 +179,7 @@
 </histogram>
 
 <histogram name="KeyboardAccessory.AccessoryToggleClicked"
-    enum="AccessoryToggleType" expires_after="M117">
+    enum="AccessoryToggleType" expires_after="2023-11-19">
   <owner>ioanap@chromium.org</owner>
   <owner>fhorschig@chromium.org</owner>
   <summary>
@@ -1028,7 +1028,7 @@
 </histogram>
 
 <histogram name="PasswordManager.BulkCheck.CanceledTime" units="ms"
-    expires_after="2023-09-10">
+    expires_after="2023-11-19">
   <owner>vasilii@chromium.org</owner>
   <owner>vsemeniuk@google.com</owner>
   <summary>
@@ -1613,7 +1613,7 @@
 </histogram>
 
 <histogram name="PasswordManager.FillingSuccessIOS" enum="BooleanSuccess"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>theocristea@google.com</owner>
   <owner>kazinova@google.com</owner>
   <owner>vsemeniuk@google.com</owner>
@@ -1634,7 +1634,7 @@
 </histogram>
 
 <histogram name="PasswordManager.FirstRendererFillingResult"
-    enum="PasswordManagerFirstRendererFillingResult" expires_after="2023-09-17">
+    enum="PasswordManagerFirstRendererFillingResult" expires_after="2023-11-19">
   <owner>kazinova@google.com</owner>
   <owner>battre@chromium.org</owner>
   <summary>
@@ -1996,7 +1996,7 @@
 </histogram>
 
 <histogram name="PasswordManager.ItemSelected.OffTheRecord" units="units"
-    expires_after="2023-09-19">
+    expires_after="2023-11-19">
   <owner>arabm@chromium.org</owner>
   <owner>chrome-privacy-team@google.com</owner>
   <summary>
@@ -2485,7 +2485,7 @@
 </histogram>
 
 <histogram name="PasswordManager.PasswordExport.Event"
-    enum="PasswordExportEvent" expires_after="2023-08-27">
+    enum="PasswordExportEvent" expires_after="2023-11-19">
   <owner>ioanap@chromium.org</owner>
   <owner>kazinova@google.com</owner>
   <summary>
@@ -2496,7 +2496,7 @@
 </histogram>
 
 <histogram name="PasswordManager.PasswordManagementBubble.UserAction"
-    enum="PasswordManagementBubbleInteractions" expires_after="2023-09-01">
+    enum="PasswordManagementBubbleInteractions" expires_after="2023-11-19">
   <owner>mamir@chromium.org</owner>
   <owner>rgod@google.com</owner>
   <summary>
@@ -3192,7 +3192,7 @@
 </histogram>
 
 <histogram name="PasswordManager.RequirementsSpecFetcher.HttpResponseCode"
-    enum="HttpResponseCode" expires_after="2023-09-04">
+    enum="HttpResponseCode" expires_after="2023-11-19">
   <owner>kazinova@google.com</owner>
   <owner>battre@chromium.org</owner>
   <summary>
@@ -3451,7 +3451,7 @@
 </histogram>
 
 <histogram name="PasswordManager.StoresUsedForFillingInLast28Days"
-    enum="PasswordManagerFillingSource" expires_after="2023-08-20">
+    enum="PasswordManagerFillingSource" expires_after="2023-11-19">
   <owner>mamir@chromium.org</owner>
   <owner>treib@chromium.org</owner>
   <summary>
@@ -3463,7 +3463,7 @@
 </histogram>
 
 <histogram name="PasswordManager.StoresUsedForFillingInLast7Days"
-    enum="PasswordManagerFillingSource" expires_after="2023-08-20">
+    enum="PasswordManagerFillingSource" expires_after="2023-11-19">
   <owner>mamir@chromium.org</owner>
   <owner>treib@chromium.org</owner>
   <summary>
@@ -3545,7 +3545,7 @@
 
 <histogram
     name="PasswordManager.SyncControllerDelegateNotifiesCredentialManager.Success"
-    enum="Boolean" expires_after="2023-09-17">
+    enum="Boolean" expires_after="2023-11-19">
   <owner>kazinova@google.com</owner>
   <owner>ioanap@chromium.org</owner>
   <summary>
@@ -3738,7 +3738,7 @@
 </histogram>
 
 <histogram name="PasswordManager.UnenrolledFromUPMDueToErrors" enum="Boolean"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>kazinova@google.com</owner>
   <owner>ioanap@chromium.org</owner>
   <owner>fhorschig@chromium.org</owner>
@@ -3786,7 +3786,7 @@
 </histogram>
 
 <histogram name="PasswordManager.UnifiedPasswordManager.WasMigrationDone"
-    enum="BooleanSuccess" expires_after="2023-09-17">
+    enum="BooleanSuccess" expires_after="2023-11-19">
   <owner>vsemeniuk@google.com</owner>
   <owner>fhorschig@chromium.org</owner>
   <summary>
@@ -4053,7 +4053,7 @@
 </histogram>
 
 <histogram name="PasswordManager.{Store}LoginDatabaseEncryptionStatus"
-    enum="LoginDatabaseEncryptionStatus" expires_after="2023-06-30">
+    enum="LoginDatabaseEncryptionStatus" expires_after="2023-10-30">
   <owner>derinel@google.com</owner>
   <owner>mamir@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/payment/histograms.xml b/tools/metrics/histograms/metadata/payment/histograms.xml
index 2f4645e3..f8a8052 100644
--- a/tools/metrics/histograms/metadata/payment/histograms.xml
+++ b/tools/metrics/histograms/metadata/payment/histograms.xml
@@ -222,7 +222,7 @@
 <histogram
     name="PaymentRequest.SecurePaymentConfirmation.Funnel.EnrollSystemPromptResult"
     enum="SecurePaymentConfirmationEnrollSystemPromptResult"
-    expires_after="2023-08-20">
+    expires_after="2023-11-19">
   <owner>rouslan@chromium.org</owner>
   <owner>web-payments-team@google.com</owner>
   <summary>
@@ -237,7 +237,7 @@
 <histogram
     name="PaymentRequest.SecurePaymentConfirmation.Funnel.SystemPromptResult"
     enum="SecurePaymentConfirmationSystemPromptResult"
-    expires_after="2023-08-20">
+    expires_after="2023-11-19">
   <owner>rouslan@chromium.org</owner>
   <owner>web-payments-team@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/performance_controls/histograms.xml b/tools/metrics/histograms/metadata/performance_controls/histograms.xml
index 82920e1..5875134d 100644
--- a/tools/metrics/histograms/metadata/performance_controls/histograms.xml
+++ b/tools/metrics/histograms/metadata/performance_controls/histograms.xml
@@ -89,7 +89,7 @@
 </histogram>
 
 <histogram name="PerformanceControls.HighEfficiency.IPHEnableMode"
-    units="BooleanEnableMode" expires_after="2023-09-17">
+    units="BooleanEnableMode" expires_after="2023-11-19">
   <owner>agale@chromium.org</owner>
   <owner>chrome-performance-ui-sea@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/permissions/histograms.xml b/tools/metrics/histograms/metadata/permissions/histograms.xml
index 41eafb0..7578f93d 100644
--- a/tools/metrics/histograms/metadata/permissions/histograms.xml
+++ b/tools/metrics/histograms/metadata/permissions/histograms.xml
@@ -539,7 +539,7 @@
 </histogram>
 
 <histogram name="Permissions.Engagement.Dismissed" units="%"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>engedy@chromium.org</owner>
   <owner>src/components/permissions/PERMISSIONS_OWNERS</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/platform/histograms.xml b/tools/metrics/histograms/metadata/platform/histograms.xml
index e6cca782..1ed2ac4 100644
--- a/tools/metrics/histograms/metadata/platform/histograms.xml
+++ b/tools/metrics/histograms/metadata/platform/histograms.xml
@@ -1356,7 +1356,7 @@
 </histogram>
 
 <histogram name="Platform.Modemfwd.CheckForWedgedModemResult"
-    enum="ModemfwdCheckForWedgedModemResult" expires_after="2023-09-17">
+    enum="ModemfwdCheckForWedgedModemResult" expires_after="2023-11-19">
   <owner>andrewlassalle@google.com</owner>
   <owner>cros-connectivity@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/power/histograms.xml b/tools/metrics/histograms/metadata/power/histograms.xml
index f40b5476..ea6eb2c 100644
--- a/tools/metrics/histograms/metadata/power/histograms.xml
+++ b/tools/metrics/histograms/metadata/power/histograms.xml
@@ -320,7 +320,7 @@
 </histogram>
 
 <histogram name="PerformanceMonitor.ResourceCoalition.Availability"
-    enum="CoalitionIDAvailability" expires_after="2023-09-17">
+    enum="CoalitionIDAvailability" expires_after="2023-11-19">
   <owner>fdoray@chromium.org</owner>
   <owner>catan-team@chromium.org</owner>
   <summary>
@@ -831,7 +831,7 @@
 </histogram>
 
 <histogram name="Power.BatteryChargeHealth" units="%"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>puthik@chromium.org</owner>
   <owner>chromeos-platform-power@google.com</owner>
   <summary>
@@ -1062,7 +1062,7 @@
 </histogram>
 
 <histogram name="Power.BatteryDischargeRateWhileSuspended" units="mW"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>puthik@chromium.org</owner>
   <owner>chromeos-platform-power@google.com</owner>
   <summary>
@@ -1294,7 +1294,7 @@
 </histogram>
 
 <histogram name="Power.CpuTimeSecondsPerProcessType" enum="ProcessType2"
-    expires_after="2023-11-12">
+    expires_after="2023-11-19">
   <owner>eseckler@chromium.org</owner>
   <owner>skyostil@chromium.org</owner>
   <owner>woa-performance@google.com</owner>
@@ -1985,7 +1985,7 @@
 </histogram>
 
 <histogram name="Power.KernelResumeTimeOnAC" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>puthik@chromium.org</owner>
   <owner>chromeos-platform-power@google.com</owner>
   <summary>
@@ -2023,7 +2023,7 @@
 </histogram>
 
 <histogram name="Power.KeyboardBacklightLevel" units="%"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>tbroch@chromium.org</owner>
   <summary>
     The level of the keyboard backlight as a percentage. Sampled every 30
@@ -2340,7 +2340,7 @@
 </histogram>
 
 <histogram name="Power.SuspendAttempt" enum="SuspendAttempt"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>puthik@chromium.org</owner>
   <owner>chromeos-platform-power@google.com</owner>
   <summary>
@@ -2389,7 +2389,7 @@
 </histogram>
 
 <histogram name="Power.SuspendResult" enum="SuspendResult"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>puthik@chromium.org</owner>
   <owner>chromeos-platform-power@google.com</owner>
   <summary>
@@ -2576,7 +2576,7 @@
 </histogram>
 
 <histogram name="PowerML.SmartDimModel.Result"
-    enum="PowerMLSmartDimModelResult" expires_after="2023-09-20">
+    enum="PowerMLSmartDimModelResult" expires_after="2023-11-19">
   <owner>napper@chromium.org</owner>
   <owner>thanhdng@chromium.org</owner>
   <summary>
@@ -2589,7 +2589,7 @@
 </histogram>
 
 <histogram name="PowerML.SmartDimParameter.Result"
-    enum="PowerMLSmartDimParameterResult" expires_after="2023-09-20">
+    enum="PowerMLSmartDimParameterResult" expires_after="2023-11-19">
   <owner>napper@chromium.org</owner>
   <owner>thanhdng@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/print/histograms.xml b/tools/metrics/histograms/metadata/print/histograms.xml
index 10906c9..93346aa 100644
--- a/tools/metrics/histograms/metadata/print/histograms.xml
+++ b/tools/metrics/histograms/metadata/print/histograms.xml
@@ -219,7 +219,7 @@
 </histogram>
 
 <histogram name="PrintPreview.RendererError" enum="PrintPreviewFailureType"
-    expires_after="2023-09-03">
+    expires_after="2023-11-19">
   <owner>thestig@chromium.org</owner>
   <owner>dhoss@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/printing/histograms.xml b/tools/metrics/histograms/metadata/printing/histograms.xml
index 5379407..a30230b 100644
--- a/tools/metrics/histograms/metadata/printing/histograms.xml
+++ b/tools/metrics/histograms/metadata/printing/histograms.xml
@@ -413,7 +413,7 @@
 </histogram>
 
 <histogram name="Printing.Oop.PrintResult" enum="PrintOopResult"
-    expires_after="2023-09-19">
+    expires_after="2023-11-19">
   <owner>awscreen@chromium.org</owner>
   <owner>thestig@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/profile/histograms.xml b/tools/metrics/histograms/metadata/profile/histograms.xml
index 0ac25bd..9d420af 100644
--- a/tools/metrics/histograms/metadata/profile/histograms.xml
+++ b/tools/metrics/histograms/metadata/profile/histograms.xml
@@ -457,7 +457,7 @@
 </histogram>
 
 <histogram name="Profile.NumberOfProfilesAtProfileSwitch" units="profiles"
-    expires_after="2023-08-08">
+    expires_after="2023-11-19">
   <owner>droger@chromium.org</owner>
   <owner>chrome-signin-team@google.com</owner>
   <summary>
@@ -948,7 +948,7 @@
 </histogram>
 
 <histogram name="ProfilePicker.UiVisited" enum="ProfilePickerPages"
-    expires_after="2023-08-27">
+    expires_after="2023-11-19">
   <owner>msalama@chromium.org</owner>
   <owner>chrome-signin-team@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/quick_answers/histograms.xml b/tools/metrics/histograms/metadata/quick_answers/histograms.xml
index 08470f95..cd28ff2 100644
--- a/tools/metrics/histograms/metadata/quick_answers/histograms.xml
+++ b/tools/metrics/histograms/metadata/quick_answers/histograms.xml
@@ -245,7 +245,7 @@
 </histogram>
 
 <histogram name="QuickAnswers.Result" enum="QuickAnswersResultType"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>angelaxiao@chromium.org</owner>
   <owner>yawano@google.com</owner>
   <owner>llin@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/quota/histograms.xml b/tools/metrics/histograms/metadata/quota/histograms.xml
index bebed7f..bf518a1 100644
--- a/tools/metrics/histograms/metadata/quota/histograms.xml
+++ b/tools/metrics/histograms/metadata/quota/histograms.xml
@@ -33,7 +33,7 @@
 </histogram>
 
 <histogram name="Quota.AgeOfOriginInDays" units="days"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>ayui@chromium.org</owner>
   <owner>chrome-owp-storage@google.com</owner>
   <summary>
@@ -214,7 +214,7 @@
 </histogram>
 
 <histogram name="Quota.QuotaDatabaseError" enum="SqliteLoggedResultCode"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>ayui@chromium.org</owner>
   <owner>chrome-owp-storage@google.com</owner>
   <summary>Errors reported by SQLite while using the quota database.</summary>
diff --git a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
index 1309310..7ed6a00 100644
--- a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
+++ b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
@@ -325,7 +325,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.BrowserThrottle.TotalDelay" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>xinghuilu@chromium.org</owner>
   <owner>chrome-counter-abuse-alerts@google.com</owner>
   <summary>
@@ -482,7 +482,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.ClientSafeBrowsingReport.ReportType"
-    enum="ClientSafeBrowsingReportType" expires_after="2023-09-17">
+    enum="ClientSafeBrowsingReportType" expires_after="2023-11-19">
   <owner>xinghuilu@chromium.org</owner>
   <owner>chrome-counter-abuse-alerts@google.com</owner>
   <summary>
@@ -1704,7 +1704,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.RendererThrottle.TotalDelay" units="ms"
-    expires_after="2023-11-12">
+    expires_after="2023-11-19">
   <owner>xinghuilu@chromium.org</owner>
   <owner>chrome-counter-abuse-alerts@google.com</owner>
   <summary>
@@ -1951,7 +1951,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.RT.LocalMatch.Result"
-    enum="SafeBrowsingAllowlistAsyncMatch" expires_after="2023-09-17">
+    enum="SafeBrowsingAllowlistAsyncMatch" expires_after="2023-11-19">
   <owner>thefrog@chromium.org</owner>
   <owner>chrome-counter-abuse-alerts@google.com</owner>
   <summary>
@@ -2135,7 +2135,7 @@
 
 <histogram
     name="SafeBrowsing.TailoredSecurity.ConsentedDesktopDialogDisabledOutcome"
-    enum="SafeBrowsingTailoredSecurityOutcome" expires_after="2023-09-17">
+    enum="SafeBrowsingTailoredSecurityOutcome" expires_after="2023-11-19">
   <owner>jacastro@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -2223,7 +2223,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.TailoredSecurityService.OAuthTokenCompletion"
-    enum="BooleanSuccess" expires_after="2023-09-17">
+    enum="BooleanSuccess" expires_after="2023-11-19">
   <owner>jacastro@chromium.org</owner>
   <owner>chrome-counter-abuse-alerts@google.com</owner>
   <summary>
@@ -2234,7 +2234,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.TailoredSecurityService.OAuthTokenErrorState"
-    enum="GoogleServiceAuthError" expires_after="2023-09-17">
+    enum="GoogleServiceAuthError" expires_after="2023-11-19">
   <owner>jacastro@chromium.org</owner>
   <owner>chrome-counter-abuse-alerts@google.com</owner>
   <summary>
@@ -2245,7 +2245,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.TailoredSecurityService.OAuthTokenResponseCode"
-    units="code" expires_after="2023-09-17">
+    units="code" expires_after="2023-11-19">
   <owner>jacastro@chromium.org</owner>
   <owner>chrome-counter-abuse-alerts@google.com</owner>
   <summary>
@@ -2346,7 +2346,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.V4Database.Size" units="KB"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>vakh@chromium.org</owner>
   <owner>chrome-counter-abuse-alerts@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/security/histograms.xml b/tools/metrics/histograms/metadata/security/histograms.xml
index d6c2363..d5f90d8 100644
--- a/tools/metrics/histograms/metadata/security/histograms.xml
+++ b/tools/metrics/histograms/metadata/security/histograms.xml
@@ -196,7 +196,7 @@
 
 <histogram
     name="Security.HttpsFirstModeWithEngagementHeuristic.AccumulatedHostCount"
-    units="hostnames" expires_after="2023-09-10">
+    units="hostnames" expires_after="2023-11-19">
   <owner>meacer@chromium.org</owner>
   <owner>trusty-transport@chromium.org</owner>
   <summary>
@@ -207,7 +207,7 @@
 </histogram>
 
 <histogram name="Security.HttpsFirstModeWithEngagementHeuristic.Duration"
-    units="seconds" expires_after="2023-09-10">
+    units="seconds" expires_after="2023-11-19">
   <owner>meacer@chromium.org</owner>
   <owner>trusty-transport@chromium.org</owner>
   <summary>
@@ -218,7 +218,7 @@
 </histogram>
 
 <histogram name="Security.HttpsFirstModeWithEngagementHeuristic.HostCount"
-    units="hostnames" expires_after="2023-09-10">
+    units="hostnames" expires_after="2023-11-19">
   <owner>meacer@chromium.org</owner>
   <owner>trusty-transport@chromium.org</owner>
   <summary>
@@ -230,7 +230,7 @@
 
 <histogram
     name="Security.HttpsFirstModeWithEngagementHeuristic.NavigationEvent"
-    enum="HttpsFirstModeNavigationEvent" expires_after="2023-09-10">
+    enum="HttpsFirstModeNavigationEvent" expires_after="2023-11-19">
   <owner>meacer@chromium.org</owner>
   <owner>cthomp@chromium.org</owner>
   <owner>trusty-transport@chromium.org</owner>
@@ -242,7 +242,7 @@
 </histogram>
 
 <histogram name="Security.HttpsFirstModeWithEngagementHeuristic.State"
-    enum="SiteEngagementHeuristicState" expires_after="2023-09-10">
+    enum="SiteEngagementHeuristicState" expires_after="2023-11-19">
   <owner>meacer@chromium.org</owner>
   <owner>trusty-transport@chromium.org</owner>
   <summary>
@@ -284,7 +284,7 @@
 </histogram>
 
 <histogram name="Security.PageInfo.AboutThisSiteInteraction"
-    enum="AboutThisSiteInteraction" expires_after="2023-09-17">
+    enum="AboutThisSiteInteraction" expires_after="2023-11-19">
   <owner>dullweber@chromium.org</owner>
   <owner>olesiamarukhno@chromium.org</owner>
   <summary>
@@ -474,7 +474,7 @@
 </histogram>
 
 <histogram name="Security.SafetyTips.SafetyTipShown" enum="SafetyTipStatus"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>jdeblasio@chromium.org</owner>
   <owner>trusty-transport@chromium.org</owner>
   <summary>
@@ -516,7 +516,7 @@
 </histogram>
 
 <histogram name="Security.SCTAuditing.OptIn.ReportDeduplicated" enum="Boolean"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>cthomp@chromium.org</owner>
   <owner>trusty-transport@chromium.org</owner>
   <summary>
@@ -527,7 +527,7 @@
 </histogram>
 
 <histogram name="Security.SCTAuditing.OptIn.ReportersHWM" units="reporters"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>cthomp@chromium.org</owner>
   <owner>trusty-transport@chromium.org</owner>
   <summary>
@@ -537,7 +537,7 @@
 </histogram>
 
 <histogram name="Security.SCTAuditing.OptIn.ReportSampled" enum="Boolean"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>cthomp@chromium.org</owner>
   <owner>trusty-transport@chromium.org</owner>
   <summary>
@@ -548,7 +548,7 @@
 </histogram>
 
 <histogram name="Security.SCTAuditing.OptIn.ReportSize" units="bytes"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>cthomp@chromium.org</owner>
   <owner>trusty-transport@chromium.org</owner>
   <summary>
@@ -558,7 +558,7 @@
 </histogram>
 
 <histogram name="Security.SCTAuditing.OptIn.ReportSucceeded" enum="Boolean"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>cthomp@chromium.org</owner>
   <owner>trusty-transport@chromium.org</owner>
   <summary>
@@ -569,7 +569,7 @@
 </histogram>
 
 <histogram name="Security.SCTAuditing.OptOut.DroppedDueToLogNotFound"
-    enum="Boolean" expires_after="2023-09-17">
+    enum="Boolean" expires_after="2023-11-19">
   <owner>cthomp@chromium.org</owner>
   <owner>trusty-transport@chromium.org</owner>
   <summary>
@@ -580,7 +580,7 @@
 </histogram>
 
 <histogram name="Security.SCTAuditing.OptOut.LookupQueryResult"
-    enum="SCTLookupQueryResult" expires_after="2023-09-17">
+    enum="SCTLookupQueryResult" expires_after="2023-11-19">
   <owner>cthomp@chromium.org</owner>
   <owner>nsatragno@chromium.org</owner>
   <owner>trusty-transport@chromium.org</owner>
@@ -591,7 +591,7 @@
 </histogram>
 
 <histogram name="Security.SCTAuditing.OptOut.PopularSCTSkipped" enum="Boolean"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>cthomp@chromium.org</owner>
   <owner>nsatragno@chromium.org</owner>
   <owner>trusty-transport@chromium.org</owner>
@@ -603,7 +603,7 @@
 </histogram>
 
 <histogram name="Security.SCTAuditing.OptOut.ReportCount" units="reports"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>cthomp@chromium.org</owner>
   <owner>jdeblasio@chromium.org</owner>
   <summary>
@@ -966,7 +966,7 @@
 </histogram>
 
 <histogram name="SiteIsolation.OutOfProcessIframes" units="oopifs"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>alexmos@chromium.org</owner>
   <owner>creis@chromium.org</owner>
   <owner>lukasza@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/session/histograms.xml b/tools/metrics/histograms/metadata/session/histograms.xml
index 380a5f9..c1876d7 100644
--- a/tools/metrics/histograms/metadata/session/histograms.xml
+++ b/tools/metrics/histograms/metadata/session/histograms.xml
@@ -72,7 +72,7 @@
 </histogram>
 
 <histogram name="Session.OpenedTabCounts" units="operations"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>rohitrao@chromium.org</owner>
   <owner>marq@chromium.org</owner>
   <summary>
@@ -826,7 +826,7 @@
 </histogram>
 
 <histogram name="Session.WebStates.NativeRestoreSessionFromCache"
-    enum="BooleanSuccess" expires_after="2023-09-03">
+    enum="BooleanSuccess" expires_after="2023-11-19">
   <owner>justincohen@chromium.org</owner>
   <owner>ajuma@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/settings/histograms.xml b/tools/metrics/histograms/metadata/settings/histograms.xml
index 83d7d34..b427b31 100644
--- a/tools/metrics/histograms/metadata/settings/histograms.xml
+++ b/tools/metrics/histograms/metadata/settings/histograms.xml
@@ -342,7 +342,7 @@
 
 <histogram name="Settings.PrivacyGuide.StepsEligibleAndReached"
     enum="SettingsPrivacyGuideStepsEligibleAndReached"
-    expires_after="2023-08-21">
+    expires_after="2023-11-19">
   <owner>rainhard@chromium.org</owner>
   <owner>aisulu@chromium.org</owner>
   <owner>chrome-friendly-settings@google.com</owner>
@@ -970,7 +970,7 @@
 </histogram>
 
 <histogram name="Settings.TrackedPreferenceWantedReset"
-    enum="TrackedPreference" expires_after="2023-09-17">
+    enum="TrackedPreference" expires_after="2023-11-19">
   <owner>proberge@chromium.org</owner>
   <owner>junhao.huang@microsoft.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/sharing/histograms.xml b/tools/metrics/histograms/metadata/sharing/histograms.xml
index 298d1b2..771d9b8 100644
--- a/tools/metrics/histograms/metadata/sharing/histograms.xml
+++ b/tools/metrics/histograms/metadata/sharing/histograms.xml
@@ -362,7 +362,7 @@
 </histogram>
 
 <histogram name="Sharing.Screenshot.Action" enum="SharingScreenshotAction"
-    expires_after="2023-09-03">
+    expires_after="2023-11-19">
   <owner>jeffreycohen@chromium.org</owner>
   <owner>src/chrome/browser/share/OWNERS</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/signin/histograms.xml b/tools/metrics/histograms/metadata/signin/histograms.xml
index af52280..96dfb9a 100644
--- a/tools/metrics/histograms/metadata/signin/histograms.xml
+++ b/tools/metrics/histograms/metadata/signin/histograms.xml
@@ -470,7 +470,7 @@
 </histogram>
 
 <histogram name="Signin.Enterprise.WorkProfile.ProfileCreatedWithPolicySet"
-    enum="BooleanCreated" expires_after="2023-09-15">
+    enum="BooleanCreated" expires_after="2023-11-19">
   <owner>pastarmovj@chromium.org</owner>
   <owner>ydago@chromium.org</owner>
   <summary>
@@ -762,7 +762,7 @@
 </histogram>
 
 <histogram name="Signin.IOSLoginMethodAndSyncState"
-    enum="SigninIOSLoginMethodAndSyncState" expires_after="2023-08-08">
+    enum="SigninIOSLoginMethodAndSyncState" expires_after="2023-11-19">
   <owner>jlebel@chromium.org</owner>
   <owner>msarda@chromium.org</owner>
   <owner>chrome-signin-team@google.com</owner>
@@ -780,7 +780,7 @@
 </histogram>
 
 <histogram name="Signin.IOSNumberOfDeviceAccounts" units="accounts"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>jlebel@chromium.org</owner>
   <owner>msarda@chromium.org</owner>
   <owner>chrome-signin-team@google.com</owner>
@@ -1311,7 +1311,7 @@
 </histogram>
 
 <histogram name="Signin.SSOAuth.GetIdentities.ErrorCode"
-    enum="SigninSSOAuthGetIdentitiesErrorCode" expires_after="2023-09-03">
+    enum="SigninSSOAuthGetIdentitiesErrorCode" expires_after="2023-11-19">
   <owner>jlebel@chromium.org</owner>
   <owner>chrome-signin-team@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/stability/histograms.xml b/tools/metrics/histograms/metadata/stability/histograms.xml
index 6508755..3c4b464 100644
--- a/tools/metrics/histograms/metadata/stability/histograms.xml
+++ b/tools/metrics/histograms/metadata/stability/histograms.xml
@@ -558,7 +558,7 @@
 </histogram>
 
 <histogram name="Stability.MobileSessionShutdownType"
-    enum="MobileSessionShutdownType" expires_after="2023-09-17">
+    enum="MobileSessionShutdownType" expires_after="2023-11-19">
   <owner>michaeldo@chromium.org</owner>
   <owner>olivierrobin@chromium.org</owner>
   <summary>
@@ -575,7 +575,7 @@
 </histogram>
 
 <histogram name="Stability.MobileSessionShutdownType2"
-    enum="MobileSessionShutdownType" expires_after="2023-09-17">
+    enum="MobileSessionShutdownType" expires_after="2023-11-19">
   <owner>justincohen@chromium.org</owner>
   <owner>ajuma@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/startup/histograms.xml b/tools/metrics/histograms/metadata/startup/histograms.xml
index 29f9019f..4918375 100644
--- a/tools/metrics/histograms/metadata/startup/histograms.xml
+++ b/tools/metrics/histograms/metadata/startup/histograms.xml
@@ -57,7 +57,7 @@
 
 <histogram
     name="Startup.Android.Cold.FirstNavigationCommitOccurredPreForeground"
-    enum="Boolean" expires_after="2023-09-17">
+    enum="Boolean" expires_after="2023-11-19">
   <owner>blundell@chromium.org</owner>
   <owner>yfriedman@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/storage/histograms.xml b/tools/metrics/histograms/metadata/storage/histograms.xml
index 0cebd259..c9d1b34 100644
--- a/tools/metrics/histograms/metadata/storage/histograms.xml
+++ b/tools/metrics/histograms/metadata/storage/histograms.xml
@@ -41,7 +41,7 @@
 </histogram>
 
 <histogram name="API.StorageAccess.AllowedRequests2" enum="StorageAccessResult"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>mkwst@chromium.org</owner>
   <owner>brandm@microsoft.com</owner>
   <summary>
@@ -1199,7 +1199,7 @@
 </histogram>
 
 <histogram name="Storage.SharedStorage.Worklet.Timing.Set" units="ms"
-    expires_after="2023-07-31">
+    expires_after="2023-11-19">
   <owner>cammie@chromium.org</owner>
   <owner>yaoxia@chromium.org</owner>
   <owner>chrome-ads-histograms@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/sync/histograms.xml b/tools/metrics/histograms/metadata/sync/histograms.xml
index aeb2fd3..10745dd 100644
--- a/tools/metrics/histograms/metadata/sync/histograms.xml
+++ b/tools/metrics/histograms/metadata/sync/histograms.xml
@@ -185,7 +185,7 @@
 </histogram>
 
 <histogram name="Sync.BookmarkModelMerger.ValidInputUpdates" units="bookmarks"
-    expires_after="2023-09-19">
+    expires_after="2023-11-19">
   <owner>rushans@google.com</owner>
   <owner>mastiz@chromium.org</owner>
   <component>Services&gt;Sync</component>
@@ -1569,7 +1569,7 @@
 </histogram>
 
 <histogram name="Sync.TrustedVaultErrorShownOnFirstTimeSync2" enum="Boolean"
-    expires_after="2023-09-15">
+    expires_after="2023-11-19">
   <owner>mmoskvitin@google.com</owner>
   <owner>mastiz@chromium.org</owner>
   <component>Services&gt;Sync</component>
diff --git a/tools/metrics/histograms/metadata/tab/histograms.xml b/tools/metrics/histograms/metadata/tab/histograms.xml
index eaeb1a6..6344ba0 100644
--- a/tools/metrics/histograms/metadata/tab/histograms.xml
+++ b/tools/metrics/histograms/metadata/tab/histograms.xml
@@ -394,7 +394,7 @@
 </histogram>
 
 <histogram name="Tab.RendererTermination.AliveRenderersCount" units="renderers"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>ajuma@chromium.org</owner>
   <owner>bling-fundamentals@google.com</owner>
   <summary>
@@ -457,7 +457,7 @@
 </histogram>
 
 <histogram name="Tab.StateAtRendererTermination" enum="TabForegroundState"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>gambard@chromium.org</owner>
   <owner>olivierrobin@chromium.org</owner>
   <summary>
@@ -1052,7 +1052,7 @@
 </histogram>
 
 <histogram name="TabManager.Discarding.ReloadToCloseTime" units="ms"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>chrisha@chromium.org</owner>
   <owner>catan-team@chromium.org</owner>
   <summary>
@@ -1322,7 +1322,7 @@
 </histogram>
 
 <histogram name="Tabs.NTPCountAtStartup" units="tabs"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>gogerald@chromium.org</owner>
   <owner>nasims@google.com</owner>
   <summary>[iOS] The number of NTP tabs open at cold launch.</summary>
@@ -2319,7 +2319,7 @@
 </histogram>
 
 <histogram name="Tabs.Tasks.OrderValidOnStartup" units="boolean"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>ckitagawa@chromium.org</owner>
   <owner>fredmello@chromium.org</owner>
   <summary>
@@ -2329,7 +2329,7 @@
 </histogram>
 
 <histogram name="Tabs.Tasks.TabAddedWithValidProposedPosition" units="boolean"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>ckitagawa@chromium.org</owner>
   <owner>fredmello@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/translate/histograms.xml b/tools/metrics/histograms/metadata/translate/histograms.xml
index cb2af2c..f129b23e 100644
--- a/tools/metrics/histograms/metadata/translate/histograms.xml
+++ b/tools/metrics/histograms/metadata/translate/histograms.xml
@@ -257,7 +257,7 @@
 </histogram>
 
 <histogram name="Translate.LanguageDetection.TFLiteModelEvaluationDuration"
-    units="ms" expires_after="2023-09-17">
+    units="ms" expires_after="2023-11-19">
   <owner>rajendrant@chromium.org</owner>
   <owner>mcrouse@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/uma/histograms.xml b/tools/metrics/histograms/metadata/uma/histograms.xml
index be90eb4..1d1d162f0a 100644
--- a/tools/metrics/histograms/metadata/uma/histograms.xml
+++ b/tools/metrics/histograms/metadata/uma/histograms.xml
@@ -940,7 +940,7 @@
 </histogram>
 
 <histogram name="UMA.TruncatedEvents.UserAction" units="events"
-    expires_after="2023-11-12">
+    expires_after="2023-11-19">
   <owner>rkaplow@chromium.org</owner>
   <owner>src/base/metrics/OWNERS</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/v8/histograms.xml b/tools/metrics/histograms/metadata/v8/histograms.xml
index caaf830b..3d08e32 100644
--- a/tools/metrics/histograms/metadata/v8/histograms.xml
+++ b/tools/metrics/histograms/metadata/v8/histograms.xml
@@ -1560,7 +1560,7 @@
 </histogram>
 
 <histogram name="V8.UnhandledExceptionCountInMainThread"
-    units="BooleanOccurred" expires_after="2023-09-17">
+    units="BooleanOccurred" expires_after="2023-11-19">
   <owner>chikamune@chromium.org</owner>
   <owner>sisidovski@chromium.org</owner>
   <owner>hiroshige@chromium.org</owner>
@@ -1575,7 +1575,7 @@
 </histogram>
 
 <histogram name="V8.UnhandledExceptionCountInWorker" units="BooleanOccurred"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>chikamune@chromium.org</owner>
   <owner>sisidovski@chromium.org</owner>
   <owner>hiroshige@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/variations/histograms.xml b/tools/metrics/histograms/metadata/variations/histograms.xml
index 45c92f9..3c10757d 100644
--- a/tools/metrics/histograms/metadata/variations/histograms.xml
+++ b/tools/metrics/histograms/metadata/variations/histograms.xml
@@ -23,7 +23,7 @@
 <histograms>
 
 <histogram name="ChildProcess.FieldTrials.CreateFromShmemSuccess"
-    enum="BooleanSuccess" expires_after="2023-09-17">
+    enum="BooleanSuccess" expires_after="2023-11-19">
   <owner>asvitkine@chromium.org</owner>
   <owner>src/base/metrics/OWNERS</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/web_apk/histograms.xml b/tools/metrics/histograms/metadata/web_apk/histograms.xml
index a2c8db1a..64682e5f 100644
--- a/tools/metrics/histograms/metadata/web_apk/histograms.xml
+++ b/tools/metrics/histograms/metadata/web_apk/histograms.xml
@@ -343,7 +343,7 @@
 </histogram>
 
 <histogram name="WebApk.WebappRegistry.NumberOfOrigins" units="count"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>eirage@chromium.org</owner>
   <owner>src/chrome/android/webapk/OWNERS</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/web_rtc/histograms.xml b/tools/metrics/histograms/metadata/web_rtc/histograms.xml
index 53d94f85..0887b9f 100644
--- a/tools/metrics/histograms/metadata/web_rtc/histograms.xml
+++ b/tools/metrics/histograms/metadata/web_rtc/histograms.xml
@@ -1059,7 +1059,7 @@
 </histogram>
 
 <histogram name="WebRTC.DesktopCapture.Win.WgcCaptureSessionGetFrameResult"
-    enum="WebRtcWgcCaptureSessionGetFrameResult" expires_after="2023-09-03">
+    enum="WebRtcWgcCaptureSessionGetFrameResult" expires_after="2023-11-19">
   <owner>alcooper@chromium.org</owner>
   <owner>auorion@microsoft.com</owner>
   <owner>edgecapabilitiesdev@microsoft.com</owner>
diff --git a/tools/metrics/histograms/metadata/webapps/histograms.xml b/tools/metrics/histograms/metadata/webapps/histograms.xml
index a00670a0..cf15917 100644
--- a/tools/metrics/histograms/metadata/webapps/histograms.xml
+++ b/tools/metrics/histograms/metadata/webapps/histograms.xml
@@ -123,7 +123,7 @@
 </histogram>
 
 <histogram name="Launch.BrowserTab.WebAppLaunchHandlerClientMode"
-    enum="WebAppLaunchHandlerClientMode" expires_after="2023-09-17">
+    enum="WebAppLaunchHandlerClientMode" expires_after="2023-11-19">
   <owner>alancutter@chromium.org</owner>
   <owner>desktop-pwas-team@google.com</owner>
   <summary>
@@ -788,7 +788,7 @@
 </histogram>
 
 <histogram name="WebApp.Install.Result" enum="BooleanSuccess"
-    expires_after="2023-09-17">
+    expires_after="2023-11-19">
   <owner>phillis@chromium.org</owner>
   <owner>desktop-pwas-team@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/windows/histograms.xml b/tools/metrics/histograms/metadata/windows/histograms.xml
index ec01f065..2660bdeb 100644
--- a/tools/metrics/histograms/metadata/windows/histograms.xml
+++ b/tools/metrics/histograms/metadata/windows/histograms.xml
@@ -260,6 +260,17 @@
   </summary>
 </histogram>
 
+<histogram name="Windows.RendererCodeIntegrityEnabled" enum="BooleanEnabled"
+    expires_after="M118">
+  <owner>ajgo@chromium.org</owner>
+  <owner>wfh@chromium.org</owner>
+  <summary>
+    Records whether or not Renderer code integrity is enabled. This is enabled
+    by default but can be overridden by policy. This is recorded each time a new
+    renderer process starts.
+  </summary>
+</histogram>
+
 <histogram name="Windows.TouchDrag.Success" enum="BooleanSuccess"
     expires_after="2021-12-01">
   <owner>davidbienvenu@chromium.org</owner>
diff --git a/ui/chromeos/file_manager_strings.grdp b/ui/chromeos/file_manager_strings.grdp
index 660f419f..732ad96 100644
--- a/ui/chromeos/file_manager_strings.grdp
+++ b/ui/chromeos/file_manager_strings.grdp
@@ -1816,4 +1816,7 @@
   <message name="IDS_FILE_BROWSER_DRIVE_SYNC_ERROR_TITLE" translateable="false" desc="Title of system notification displayed when an error occurred while syncing Google Drive files">
     Sync error
   </message>
+  <message name="IDS_FILE_BROWSER_BULK_PINNING_ITEM_UNAVAILABLE_OFFLINE" translateable="false" desc="The text used when the bulk pinning of Google Drive items has failed due to insufficient space.">
+    Item unavailable offline
+  </message>
 </grit-part>
diff --git a/ui/chromeos/styles/cros_sys_colors.json5 b/ui/chromeos/styles/cros_sys_colors.json5
index 14309e6..2d84b3a 100644
--- a/ui/chromeos/styles/cros_sys_colors.json5
+++ b/ui/chromeos/styles/cros_sys_colors.json5
@@ -459,9 +459,18 @@
       light: '$cros.ref.primary90',
       dark: '$cros.ref.secondary30',
     },
-    'illo.color2': '$cros.sys.positive',
-    'illo.color3': '$cros.sys.warning',
-    'illo.color4': '$cros.sys.error',
+    'illo.color2': {
+      light: '$cros.ref.green60',
+      dark: '$cros.ref.green70',
+    },
+    'illo.color3': {
+      light: '$cros.ref.yellow70',
+      dark: '$cros.ref.yellow80',
+    },
+    'illo.color4': {
+      light: '$cros.ref.red60',
+      dark: '$cros.ref.red60',
+    },
     'illo.color5': {
       light: '$cros.ref.tertiary70',
       dark: '$cros.ref.tertiary40',
diff --git a/ui/file_manager/file_manager/BUILD.gn b/ui/file_manager/file_manager/BUILD.gn
index 98ce99f..da0809c 100644
--- a/ui/file_manager/file_manager/BUILD.gn
+++ b/ui/file_manager/file_manager/BUILD.gn
@@ -61,6 +61,7 @@
     "foreground/images/files/ui/bulk_pinning_done.svg",
     "foreground/images/files/ui/bulk_pinning_offline.svg",
     "foreground/images/files/ui/check.svg",
+    "foreground/images/files/ui/cant_pin.svg",
     "foreground/images/files/ui/cloud_done.svg",
     "foreground/images/files/ui/cloud_error.svg",
     "foreground/images/files/ui/cloud_offline.svg",
diff --git a/ui/file_manager/file_manager/containers/search_container_unittest.ts b/ui/file_manager/file_manager/containers/search_container_unittest.ts
index c9d42d8..305279e3 100644
--- a/ui/file_manager/file_manager/containers/search_container_unittest.ts
+++ b/ui/file_manager/file_manager/containers/search_container_unittest.ts
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js';
 import {CrInputElement} from 'chrome://resources/cr_elements/cr_input/cr_input.js';
 
 import {EntryLocation} from '../externs/entry_location.js';
@@ -59,16 +58,7 @@
       volumeManager, searchWrapper, optionsContainer, pathContainer);
 }
 
-/**
- * Resets flags state.
- */
-export function tearDown() {
-  loadTimeData.resetForTesting();
-}
-
-export async function testQueryUpdatedV1() {
-  loadTimeData.overrideValues({FILES_SEARCH_V2: false});
-
+export async function testQueryUpdated() {
   // Test 1: Enter a query.
   const input = searchWrapper.querySelector('cr-input') as CrInputElement;
   input.value = 'hello';
@@ -96,5 +86,3 @@
     return state.search;
   });
 }
-
-// TODO(b:241868453): Add test for V2
diff --git a/ui/file_manager/file_manager/foreground/css/file_manager.css b/ui/file_manager/file_manager/foreground/css/file_manager.css
index 6b61f495..2c50d8f 100644
--- a/ui/file_manager/file_manager/foreground/css/file_manager.css
+++ b/ui/file_manager/file_manager/foreground/css/file_manager.css
@@ -1236,6 +1236,19 @@
   --empty-folder-svg-file-color: var(--cros-illustration-secondary-color);
   --empty-folder-svg-ellipse-color: var(--cros-illustration-color-1);
   --empty-folder-svg-folder-color: var(--cros-illustration-color-1-shade-2);
+
+
+  /* TODO(b/283366482) Remove this manual GM3 -> GM2 mapping once b/280712160
+  fixed. */
+  --cros-sys-illo-color1: var(--cros-illustration-color-1);
+  --cros-sys-illo-color1-2: var(--cros-illustration-color-1-shade-2);
+  --cros-sys-illo-secondary: var(--cros-illustration-secondary-color);
+  --cros-sys-illo-color3: var(--cros-illustration-color-3);
+  --cros-sys-illo-color5: var(--cros-illustration-color-5);
+  --cros-sys-illo-color2: var(--cros-illustration-color-2);
+  --cros-sys-illo-base: var(--cros-illustration-base-color);
+
+
   margin-top: 64px;
   text-align: center;
 }
@@ -1406,17 +1419,21 @@
 #list-container.thumbnail-view li.pinned:not([renaming]):not(.dim-offline) .inline-status,
 #list-container.thumbnail-view li.pinned:not([renaming]):not(.dim-offline)[data-sync-status=not_found] .inline-status xf-icon,
 #list-container.thumbnail-view li:not([renaming])[data-sync-status]:not([data-sync-status=not_found]) .inline-status,
-#list-container.thumbnail-view li:not([renaming])[data-sync-status]:not([data-sync-status=not_found]) .inline-status .progress {
+#list-container.thumbnail-view li:not([renaming])[data-sync-status]:not([data-sync-status=not_found]) .inline-status .progress,
+#list-container.thumbnail-view li.cant-pin:not([renaming]) .inline-status,
+#list-container.thumbnail-view li.cant-pin:not([renaming]) .inline-status xf-icon[type=cant-pin] {
   display: flex;
 }
 
-#list-container.thumbnail-view li.pinned .inline-status xf-icon[type=offline] {
+#list-container.thumbnail-view li.pinned .inline-status xf-icon[type=offline],
+#list-container.thumbnail-view li.cant-pin .inline-status xf-icon[type=cant-pin] {
   --xf-icon-color: var(--cros-icon-color-secondary);
 }
 
 /* Only display outlines for entries with thumbnails. */
 #list-container.thumbnail-view li:has(.thumbnail) .inline-status .progress,
-#list-container.thumbnail-view li.pinned:has(.thumbnail) .inline-status xf-icon[type=offline] {
+#list-container.thumbnail-view li.pinned:has(.thumbnail) .inline-status xf-icon[type=offline],
+#list-container.thumbnail-view li.cant-pin:has(.thumbnail) .inline-status xf-icon[type=cant-pin] {
   --xf-icon-color-outline: var(--cros-bg-color);
 }
 
@@ -2362,12 +2379,15 @@
 #list-container .list li.pinned:not([renaming]):not(.dim-offline) .inline-status,
 #list-container .list li.pinned:not([renaming]):not(.dim-offline)[data-sync-status=not_found] .inline-status xf-icon,
 #list-container .list li:not([renaming])[data-sync-status]:not([data-sync-status=not_found]) .inline-status,
-#list-container .list li:not([renaming])[data-sync-status]:not([data-sync-status=not_found]) .inline-status .progress {
+#list-container .list li:not([renaming])[data-sync-status]:not([data-sync-status=not_found]) .inline-status .progress,
+#list-container .list li.cant-pin:not([renaming]) .inline-status,
+#list-container .list li.cant-pin:not([renaming]) .inline-status xf-icon[type=cant-pin] {
   display: flex;
 }
 
 #list-container .list li.encrypted .encryption-status xf-icon[type=encrypted],
-#list-container .list li.pinned .inline-status xf-icon[type=offline] {
+#list-container .list li.pinned .inline-status xf-icon[type=offline],
+#list-container .list li.cant-pin .inline-status xf-icon[type=cant-pin] {
   --xf-icon-color: var(--cros-icon-color-secondary);
 }
 
diff --git a/ui/file_manager/file_manager/foreground/css/file_manager_gm3.css b/ui/file_manager/file_manager/foreground/css/file_manager_gm3.css
index 94b00e0..62b3927 100644
--- a/ui/file_manager/file_manager/foreground/css/file_manager_gm3.css
+++ b/ui/file_manager/file_manager/foreground/css/file_manager_gm3.css
@@ -1191,11 +1191,14 @@
 #list-container.thumbnail-view li.pinned:not([renaming]):not(.dim-offline) .inline-status,
 #list-container.thumbnail-view li.pinned:not([renaming]):not(.dim-offline)[data-sync-status=not_found] .inline-status xf-icon,
 #list-container.thumbnail-view li:not([renaming])[data-sync-status]:not([data-sync-status=not_found]) .inline-status,
-#list-container.thumbnail-view li:not([renaming])[data-sync-status]:not([data-sync-status=not_found]) .inline-status .progress {
+#list-container.thumbnail-view li:not([renaming])[data-sync-status]:not([data-sync-status=not_found]) .inline-status .progress,
+#list-container.thumbnail-view li.cant-pin:not([renaming]) .inline-status,
+#list-container.thumbnail-view li.cant-pin:not([renaming]) .inline-status xf-icon[type=cant-pin] {
   display: flex;
 }
 
-#list-container.thumbnail-view li.pinned .inline-status xf-icon[type=offline] {
+#list-container.thumbnail-view li.pinned .inline-status xf-icon[type=offline],
+#list-container.thumbnail-view li.cant-pin .inline-status xf-icon[type=cant-pin] {
   --xf-icon-color: currentColor;
 }
 
@@ -2121,12 +2124,15 @@
 #list-container .list li.pinned:not([renaming]):not(.dim-offline) .inline-status,
 #list-container .list li.pinned:not([renaming]):not(.dim-offline)[data-sync-status=not_found] .inline-status xf-icon,
 #list-container .list li:not([renaming])[data-sync-status]:not([data-sync-status=not_found]) .inline-status,
-#list-container .list li:not([renaming])[data-sync-status]:not([data-sync-status=not_found]) .inline-status .progress {
+#list-container .list li:not([renaming])[data-sync-status]:not([data-sync-status=not_found]) .inline-status .progress,
+#list-container .list li.cant-pin:not([renaming]) .inline-status,
+#list-container .list li.cant-pin:not([renaming]) .inline-status xf-icon[type=cant-pin] {
   display: flex;
 }
 
 #list-container .list li.encrypted .encryption-status xf-icon[type=encrypted],
-#list-container .list li.pinned .inline-status xf-icon[type=offline] {
+#list-container .list li.pinned .inline-status xf-icon[type=offline],
+#list-container .list li.cant-pin .inline-status xf-icon[type=cant-pin] {
   --xf-icon-color: currentColor;
 }
 
diff --git a/ui/file_manager/file_manager/foreground/images/files/ui/cant_pin.svg b/ui/file_manager/file_manager/foreground/images/files/ui/cant_pin.svg
new file mode 100644
index 0000000..979a6f7d
--- /dev/null
+++ b/ui/file_manager/file_manager/foreground/images/files/ui/cant_pin.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" style="enable-background:new 0 0 16 16" viewBox="0 0 16 16"><path d="M2 6.2h12v3.6H2z"/><path d="M3 7.2h10v1.6H3z"/></svg>
\ No newline at end of file
diff --git a/ui/file_manager/file_manager/foreground/js/constants.js b/ui/file_manager/file_manager/foreground/js/constants.js
index a66fc66..8612eeae 100644
--- a/ui/file_manager/file_manager/foreground/js/constants.js
+++ b/ui/file_manager/file_manager/foreground/js/constants.js
@@ -134,6 +134,7 @@
   BULK_PINNING_DONE: 'bulk_pinning_done',
   BULK_PINNING_OFFLINE: 'bulk_pinning_offline',
   CAMERA_FOLDER: 'camera-folder',
+  CANT_PIN: 'cant-pin',
   CHECK: 'check',
   CLOUD_DONE: 'cloud_done',
   CLOUD_ERROR: 'cloud_error',
diff --git a/ui/file_manager/file_manager/foreground/js/empty_folder_controller.js b/ui/file_manager/file_manager/foreground/js/empty_folder_controller.js
index e2824e6c0..d2d24e0 100644
--- a/ui/file_manager/file_manager/foreground/js/empty_folder_controller.js
+++ b/ui/file_manager/file_manager/foreground/js/empty_folder_controller.js
@@ -41,7 +41,6 @@
 /**
  * The reauthentication required image for ODFS. There are no files when
  * reauthentication is required (scan fails).
- * TODO(b/279109210): fix light/dark colours.
  * @type {string}
  * @const
  */
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_grid.js b/ui/file_manager/file_manager/foreground/js/ui/file_grid.js
index 3ab15d8..043206f 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/file_grid.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/file_grid.js
@@ -811,9 +811,10 @@
     const bottom = li.ownerDocument.createElement('div');
     bottom.className = 'thumbnail-bottom';
 
-    const {contentMimeType, availableOffline, pinned} =
+    const {contentMimeType, availableOffline, pinned, canPin} =
         this.metadataModel_.getCache(
-            [entry], ['contentMimeType', 'availableOffline', 'pinned'])[0] ||
+            [entry],
+            ['contentMimeType', 'availableOffline', 'pinned', 'canPin'])[0] ||
         {};
 
     const locationInfo = this.volumeManager_.getLocationInfo(entry);
@@ -840,7 +841,14 @@
 
     const inlineStatusIcon = li.ownerDocument.createElement('xf-icon');
     inlineStatusIcon.size = 'extra_small';
-    inlineStatusIcon.type = 'offline';
+    if (util.isDriveFsBulkPinningEnabled() && !util.isNullOrUndefined(canPin) &&
+        !canPin) {
+      inlineStatusIcon.type = 'cant-pin';
+      li.classList.toggle('cant-pin', true);
+    } else {
+      inlineStatusIcon.type = 'offline';
+      li.classList.toggle('cant-pin', false);
+    }
     inlineStatus.appendChild(inlineStatusIcon);
 
     if (util.isInlineSyncStatusEnabled()) {
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_table.js b/ui/file_manager/file_manager/foreground/js/ui/file_table.js
index cb36ae4..ddec7bfe 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/file_table.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/file_table.js
@@ -1034,6 +1034,7 @@
                   'syncStatus',
                   'progress',
                   'shortcut',
+                  'canPin',
                 ])[0],
             util.isTeamDriveRoot(entry));
         listItem.toggleAttribute(
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_table_list.js b/ui/file_manager/file_manager/foreground/js/ui/file_table_list.js
index 5bb230f4..35929b1 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/file_table_list.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/file_table_list.js
@@ -368,6 +368,7 @@
     'progress',
     'contentMimeType',
     'shortcut',
+    'canPin',
   ])[0];
   filelist.updateListItemExternalProps(
       li, entry, externalProps, util.isTeamDriveRoot(entry));
@@ -571,37 +572,61 @@
       }
 
       const inlineStatus = li.querySelector('.inline-status');
-      if (inlineStatus) {
-        // Clear the inline status' aria label and set it to "in progress",
-        // "queued", or "available offline" with the respective order of
-        // precedence if applicable.
-        inlineStatus.setAttribute(
-            'aria-label',
-            externalProps.pinned ? str('OFFLINE_COLUMN_LABEL') : '');
+      if (!inlineStatus) {
+        return;
+      }
 
-        const {syncStatus} = externalProps;
-        let progress = externalProps.progress ?? 0;
-        if (util.isInlineSyncStatusEnabled() && syncStatus) {
-          switch (syncStatus) {
-            case chrome.fileManagerPrivate.SyncStatus.QUEUED:
-            case chrome.fileManagerPrivate.SyncStatus.ERROR:
-              progress = 0;
-              inlineStatus.setAttribute('aria-label', str('QUEUED_LABEL'));
-              break;
-            case chrome.fileManagerPrivate.SyncStatus.IN_PROGRESS:
-              inlineStatus.setAttribute(
-                  'aria-label',
-                  `${str('IN_PROGRESS_LABEL')} - ${
-                      (progress * 100).toFixed(0)}%`);
-              break;
-            default:
-              break;
-          }
+      if (util.isDriveFsBulkPinningEnabled()) {
+        const inlineIcon = inlineStatus.querySelector('xf-icon');
 
-          li.setAttribute('data-sync-status', syncStatus);
-          li.querySelector('.progress')
-              .setAttribute('progress', progress.toFixed(2));
+        if (!util.isNullOrUndefined(externalProps.canPin) &&
+            !externalProps.canPin) {
+          // Items that can't be pinned should show a dashed icon to indicate
+          // they cannot be used offline (e.g. google forms can't be made
+          // available offline).
+          li.classList.toggle('cant-pin', true);
+          inlineIcon.type = 'cant-pin';
+          inlineStatus.setAttribute(
+              'aria-label', str('DRIVE_ITEM_UNAVAILABLE_OFFLINE'));
+          return;
         }
+
+        // In the event a previous item that could not be pinned has instead
+        // become pinnable, ensure the inline status icon is reset and the class
+        // is removed.
+        li.classList.toggle('cant-pin', false);
+        inlineIcon.type = 'offline';
+      }
+
+      // Clear the inline status' aria label and set it to "in progress",
+      // "queued", or "available offline" with the respective order of
+      // precedence if applicable.
+      inlineStatus.setAttribute(
+          'aria-label',
+          externalProps.pinned ? str('OFFLINE_COLUMN_LABEL') : '');
+
+      const {syncStatus} = externalProps;
+      let progress = externalProps.progress ?? 0;
+      if (util.isInlineSyncStatusEnabled() && syncStatus) {
+        switch (syncStatus) {
+          case chrome.fileManagerPrivate.SyncStatus.QUEUED:
+          case chrome.fileManagerPrivate.SyncStatus.ERROR:
+            progress = 0;
+            inlineStatus.setAttribute('aria-label', str('QUEUED_LABEL'));
+            break;
+          case chrome.fileManagerPrivate.SyncStatus.IN_PROGRESS:
+            inlineStatus.setAttribute(
+                'aria-label',
+                `${str('IN_PROGRESS_LABEL')} - ${
+                    (progress * 100).toFixed(0)}%`);
+            break;
+          default:
+            break;
+        }
+
+        li.setAttribute('data-sync-status', syncStatus);
+        li.querySelector('.progress')
+            .setAttribute('progress', progress.toFixed(2));
       }
     };
 
diff --git a/ui/file_manager/file_manager/widgets/xf_icon.ts b/ui/file_manager/file_manager/widgets/xf_icon.ts
index 4135423..c7239a3e 100644
--- a/ui/file_manager/file_manager/widgets/xf_icon.ts
+++ b/ui/file_manager/file_manager/widgets/xf_icon.ts
@@ -192,6 +192,10 @@
       -webkit-mask-image: url(../foreground/images/volumes/camera.svg);
     }
 
+    :host([type="cant-pin"]) span {
+      -webkit-mask-image: url(../foreground/images/files/ui/cant_pin.svg);
+    }
+
     :host([type="computer"]) span {
       -webkit-mask-image: url(../foreground/images/volumes/computer.svg);
     }
diff --git a/ui/file_manager/integration_tests/file_manager/drive_specific.js b/ui/file_manager/integration_tests/file_manager/drive_specific.js
index 979da600..f6b3dcea 100644
--- a/ui/file_manager/integration_tests/file_manager/drive_specific.js
+++ b/ui/file_manager/integration_tests/file_manager/drive_specific.js
@@ -1491,3 +1491,26 @@
   await remoteCall.waitForElement(
       appId, '[command="#toggle-pinned"]:not([hidden][disabled])');
 };
+
+/**
+ * Tests that files that can't be pinned should have the correct CSS class
+ * applied to them. When they go back to being able to be pinned (e.g. from Docs
+ * offline coming back online) then ensure the inline icon is updated.
+ */
+testcase.driveCantPinItemsShouldHaveClassNameAndGetUpdatedWhenCanPin =
+    async () => {
+  const appId =
+      await setupAndWaitUntilReady(RootPath.DRIVE, [], [ENTRIES.cantPinFile]);
+
+  // Ensure the `cant_pin.txt` file has the cant-pin class.
+  await remoteCall.waitForElement(
+      appId, '#file-list [file-name="text.txt"].cant-pin');
+
+  // Update the file metadata to ensure the file can now be pinned.
+  await sendTestMessage(
+      {name: 'setCanPin', path: '/root/text.txt', canPin: true});
+
+  // Wait for the `.cant-pin` class to be removed.
+  await remoteCall.waitForElement(
+      appId, '#file-list [file-name="text.txt"]:not(.cant-pin)');
+};
diff --git a/ui/file_manager/integration_tests/test_util.js b/ui/file_manager/integration_tests/test_util.js
index 4b25785..8020c649 100644
--- a/ui/file_manager/integration_tests/test_util.js
+++ b/ui/file_manager/integration_tests/test_util.js
@@ -379,6 +379,8 @@
  *
  * alternateUrl: File's Drive alternate URL. Defaults to an empty string.
  *
+ * canPin: Whether the item can be pinned or not. Defaults to true.
+ *
  * @typedef {{
  *    type: EntryType,
  *    sourceFileName: (string|undefined),
@@ -396,6 +398,7 @@
  *    pinned: (boolean|undefined),
  *    availableOffline: (boolean|undefined),
  *    alternateUrl: (string|undefined),
+ *    canPin: (boolean|undefined),
  * }}
  */
 export let TestEntryInfoOptions;
@@ -429,6 +432,7 @@
     this.pinned = !!options.pinned;
     this.availableOffline = !!options.availableOffline;
     this.alternateUrl = options.alternateUrl || '';
+    this.canPin = options.canPin !== undefined ? !!options.canPin : true;
     Object.freeze(this);
   }
 
@@ -1637,6 +1641,18 @@
     sizeText: '64 bytes',
     typeText: 'TRASHINFO',
   }),
+
+  cantPinFile: new TestEntryInfo({
+    type: EntryType.FILE,
+    sourceFileName: 'text.txt',
+    targetPath: 'text.txt',
+    mimeType: 'text/plain',
+    lastModifiedTime: 'Mar 20, 2012, 11:40 PM',
+    nameText: 'text.txt',
+    sizeText: '51 bytes',
+    typeText: 'Plain text',
+    canPin: false,
+  }),
 };