diff --git a/DEPS b/DEPS
index 83d30faa..5c04cb8 100644
--- a/DEPS
+++ b/DEPS
@@ -304,15 +304,15 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'a727ba9e976ba2c2882c1ca126079880d32550e5',
+  'skia_revision': '6ec1f74e13e49ae02c524f252181e545587f0868',
   # 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': '759353818cc4133aca7f32d55dca3b1e480b14e3',
+  'v8_revision': '33a3f3040458162854a6b0f6b2b12887ed99b075',
   # 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': '8e2b87ac4e168290653cbe22d0a33ace29de9a20',
+  'angle_revision': '61728827d2e5ecce685578bc54bb2c744b65fc9a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -331,7 +331,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Fuchsia sdk
   # and whatever else without interference from each other.
-  'fuchsia_version': 'version:11.20230103.1.1',
+  'fuchsia_version': 'version:11.20230104.0.1',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling google-toolbox-for-mac
   # and whatever else without interference from each other.
@@ -355,7 +355,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # and whatever else without interference from each other.
-  'freetype_revision': 'ace97a02a4461bbdae29da4019c105eead95e277',
+  'freetype_revision': '0bcb664de8ea44299f57c45d01433328596bc2a7',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # and whatever else without interference from each other.
@@ -383,7 +383,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': '885c387859e58c1847304add14a532e99d4c4c93',
+  'devtools_frontend_revision': 'e067d1574a0afe409be3e4ce4f18f4e56e6beb0e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libprotobuf-mutator
   # and whatever else without interference from each other.
@@ -419,7 +419,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': '4cef4362b0654b52e3c1a6ee5a3133456cf0107d',
+  'dawn_revision': '7c26d3152dab9d733393b4394b146ca86d4664eb',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -443,7 +443,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling nearby
   # and whatever else without interference from each other.
-  'nearby_revision': '7e82794d4da4612b1e0409faaf3a96876f11a8de',
+  'nearby_revision': '6edd1d11b0a6d5f502cc29394eaf8ee0c62f5930',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling securemessage
   # and whatever else without interference from each other.
@@ -770,12 +770,12 @@
 
   'src/clank': {
     'url': 'https://chrome-internal.googlesource.com/clank/internal/apps.git' + '@' +
-    'b4b88a3dd8228112e0c5e1ea87d610c32d8953e8',
+    '4fd455be8be02791ebe805a6291561ea5a86c1b4',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
   'src/docs/website': {
-    'url': Var('chromium_git') + '/website.git' + '@' + 'e117812e480d06f9724475f15c28fbd6cde2d070',
+    'url': Var('chromium_git') + '/website.git' + '@' + '76a2b9434a11ad136aa14c3cf98c354e6a138072',
   },
 
   'src/ios/third_party/earl_grey2/src': {
@@ -1210,7 +1210,7 @@
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
 
   'src/third_party/devtools-frontend-internal': {
-      'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + 'c2971db011f3d1c4399a10c69b768e2ab19ca442',
+      'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + '78dae60e4194d5fa1116a1e835d2e74cbc718a44',
     'condition': 'checkout_src_internal',
   },
 
@@ -1639,7 +1639,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '7d9bdde6f8d732767f0fce4273f492648335c77a',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '5d21cea244356ef7dcc225131564ecfe778348fa',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1821,7 +1821,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'd1b65aa5a88f6efd900604dfcda840154e9f16e2',
 
   'src/third_party/webgpu-cts/src':
-    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '861b209779ea94d2225d5630d00f8b9bdd203eaf',
+    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '0673bb68c214c0a6c56d00b30e6600dcc9f02b93',
 
   'src/third_party/webrtc':
     Var('webrtc_git') + '/src.git' + '@' + '0c2981364f4ba1ee189afd69de02893bd3d3bdc1',
@@ -1894,7 +1894,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@1f2e6baa9c1277e1d87537c083369045d7140712',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@758a833aa6cc6b962f2ef119e0da54d6642cddfb',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index b6a4697..62cecef 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -3795,6 +3795,8 @@
     "test_shell_delegate.h",
     "wallpaper/test_wallpaper_controller_client.cc",
     "wallpaper/test_wallpaper_controller_client.h",
+    "wallpaper/test_wallpaper_drivefs_delegate.cc",
+    "wallpaper/test_wallpaper_drivefs_delegate.h",
     "wallpaper/wallpaper_controller_test_api.cc",
     "wallpaper/wallpaper_controller_test_api.h",
     "wm/cursor_manager_test_api.cc",
diff --git a/ash/public/cpp/wallpaper/wallpaper_controller_client.h b/ash/public/cpp/wallpaper/wallpaper_controller_client.h
index 82506a68..3ccf6272 100644
--- a/ash/public/cpp/wallpaper/wallpaper_controller_client.h
+++ b/ash/public/cpp/wallpaper/wallpaper_controller_client.h
@@ -42,16 +42,6 @@
       const std::string& collection_id,
       DailyWallpaperUrlFetchedCallback callback) = 0;
 
-  // TODO(b/245611754) move to `WallpaperDriveFsDelegate`.
-  virtual void SaveWallpaperToDriveFs(
-      const AccountId& account_id,
-      const base::FilePath& origin,
-      base::OnceCallback<void(bool)> wallpaper_saved_callback) = 0;
-
-  // TODO(b/245611754) move to `WallpaperDriveFsDelegate`.
-  virtual base::FilePath GetWallpaperPathFromDriveFs(
-      const AccountId& account_id) = 0;
-
   virtual void GetFilesId(
       const AccountId& account_id,
       base::OnceCallback<void(const std::string&)> files_id_callback) const = 0;
diff --git a/ash/public/cpp/wallpaper/wallpaper_drivefs_delegate.h b/ash/public/cpp/wallpaper/wallpaper_drivefs_delegate.h
index 2538ee95..4e15ca1 100644
--- a/ash/public/cpp/wallpaper/wallpaper_drivefs_delegate.h
+++ b/ash/public/cpp/wallpaper/wallpaper_drivefs_delegate.h
@@ -7,6 +7,7 @@
 
 #include "ash/public/cpp/ash_public_export.h"
 #include "ash/public/cpp/image_downloader.h"
+#include "base/files/file_path.h"
 #include "base/functional/callback_forward.h"
 #include "base/time/time.h"
 #include "components/account_id/account_id.h"
@@ -18,12 +19,28 @@
  public:
   virtual ~WallpaperDriveFsDelegate() = default;
 
+  // Gets the path that synced custom wallpaper is saved to in DriveFS. Returns
+  // empty path if DriveFS is inaccessible. If DriveFS is available and mounted
+  // and `DriveIntegrationService` is available for `account_id`, should always
+  // return a valid path.
+  virtual base::FilePath GetWallpaperPath(const AccountId& account_id) = 0;
+
+  // Copies `source` to DriveFS. This function does not check that `source` is a
+  // valid jpg file, so the caller must do so. Calls `callback` when the
+  // operation finishes.
+  virtual void SaveWallpaper(
+      const AccountId& account_id,
+      const base::FilePath& source,
+      base::OnceCallback<void(bool success)> callback) = 0;
+
+  using GetWallpaperModificationTimeCallback =
+      base::OnceCallback<void(base::Time modification_time)>;
   // Gets the `modification_time` of the wallpaper file saved in DriveFS. If
   // unable to retrieve it because the file does not exist or DriveFS is not
   // mounted, replies with a default constructed `base::Time()`.
   virtual void GetWallpaperModificationTime(
       const AccountId& account_id,
-      base::OnceCallback<void(base::Time modification_time)> callback) = 0;
+      GetWallpaperModificationTimeCallback callback) = 0;
 
   // Downloads and decodes DriveFS wallpaper file. Replies with default
   // constructed `gfx::ImageSkia` in case of failure, such as the file not
diff --git a/ash/system/federated/federated_service_controller.cc b/ash/system/federated/federated_service_controller.cc
index 1193a24..9b46a19b 100644
--- a/ash/system/federated/federated_service_controller.cc
+++ b/ash/system/federated/federated_service_controller.cc
@@ -70,10 +70,10 @@
       federated_service_->StartScheduling();
     }
 
-    // On session first login, reports one example for
-    // "timezone_code_population", a trivial F.A. task for prove-out purpose.
+    // On session first login, reports one example for "timezone_code_phh", a
+    // trivial F.A. task for prove-out purpose.
     if (!reported_) {
-      federated_service_->ReportExample("timezone_code_population",
+      federated_service_->ReportExample("timezone_code_phh",
                                         CreateBrellaAnalyticsExamplePtr());
       reported_ = true;
     }
diff --git a/ash/wallpaper/test_wallpaper_controller_client.cc b/ash/wallpaper/test_wallpaper_controller_client.cc
index 6a97b79..498dcf0 100644
--- a/ash/wallpaper/test_wallpaper_controller_client.cc
+++ b/ash/wallpaper/test_wallpaper_controller_client.cc
@@ -48,8 +48,6 @@
   set_default_wallpaper_count_ = 0;
   fetch_daily_refresh_wallpaper_param_ = std::string();
   fetch_daily_refresh_info_fails_ = false;
-  get_wallpaper_path_from_drive_fs_account_id_.clear();
-  save_wallpaper_to_drive_fs_account_id_.clear();
   fake_files_ids_.clear();
   wallpaper_sync_enabled_ = true;
 }
@@ -131,20 +129,6 @@
   std::move(callback).Run(absl::nullopt);
 }
 
-void TestWallpaperControllerClient::SaveWallpaperToDriveFs(
-    const AccountId& account_id,
-    const base::FilePath& origin,
-    base::OnceCallback<void(bool)> wallpaper_saved_callback) {
-  save_wallpaper_to_drive_fs_account_id_ = account_id;
-  std::move(wallpaper_saved_callback).Run(true);
-}
-
-base::FilePath TestWallpaperControllerClient::GetWallpaperPathFromDriveFs(
-    const AccountId& account_id) {
-  get_wallpaper_path_from_drive_fs_account_id_ = account_id;
-  return base::FilePath();
-}
-
 void TestWallpaperControllerClient::GetFilesId(
     const AccountId& account_id,
     base::OnceCallback<void(const std::string&)> files_id_callback) const {
diff --git a/ash/wallpaper/test_wallpaper_controller_client.h b/ash/wallpaper/test_wallpaper_controller_client.h
index 5841786b..d53c34b 100644
--- a/ash/wallpaper/test_wallpaper_controller_client.h
+++ b/ash/wallpaper/test_wallpaper_controller_client.h
@@ -44,12 +44,6 @@
   std::string get_fetch_daily_refresh_wallpaper_param() const {
     return fetch_daily_refresh_wallpaper_param_;
   }
-  AccountId get_save_wallpaper_to_drive_fs_account_id() const {
-    return save_wallpaper_to_drive_fs_account_id_;
-  }
-  AccountId get_wallpaper_path_from_drive_fs_account_id() const {
-    return get_wallpaper_path_from_drive_fs_account_id_;
-  }
 
   void set_fetch_daily_refresh_info_fails(bool fails) {
     fetch_daily_refresh_info_fails_ = fails;
@@ -96,12 +90,6 @@
   void FetchGooglePhotosAccessToken(
       const AccountId& account_id,
       FetchGooglePhotosAccessTokenCallback callback) override;
-  void SaveWallpaperToDriveFs(
-      const AccountId& account_id,
-      const base::FilePath& origin,
-      base::OnceCallback<void(bool)> wallpaper_saved_callback) override;
-  base::FilePath GetWallpaperPathFromDriveFs(
-      const AccountId& account_id) override;
   void GetFilesId(const AccountId& account_id,
                   base::OnceCallback<void(const std::string&)>
                       files_id_callback) const override;
@@ -113,8 +101,6 @@
   size_t fetch_images_for_collection_count_ = 0;
   std::string fetch_daily_refresh_wallpaper_param_;
   bool fetch_daily_refresh_info_fails_ = false;
-  AccountId get_wallpaper_path_from_drive_fs_account_id_;
-  AccountId save_wallpaper_to_drive_fs_account_id_;
   std::unordered_map<AccountId, std::string> fake_files_ids_;
   bool wallpaper_sync_enabled_ = true;
   bool fetch_images_for_collection_fails_ = false;
diff --git a/ash/wallpaper/test_wallpaper_drivefs_delegate.cc b/ash/wallpaper/test_wallpaper_drivefs_delegate.cc
new file mode 100644
index 0000000..1606c44
--- /dev/null
+++ b/ash/wallpaper/test_wallpaper_drivefs_delegate.cc
@@ -0,0 +1,53 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/wallpaper/test_wallpaper_drivefs_delegate.h"
+
+#include "base/callback.h"
+#include "base/files/file_path.h"
+#include "base/notreached.h"
+#include "base/time/time.h"
+#include "components/account_id/account_id.h"
+#include "ui/gfx/image/image_skia.h"
+
+namespace ash {
+
+TestWallpaperDriveFsDelegate::TestWallpaperDriveFsDelegate() = default;
+
+TestWallpaperDriveFsDelegate::~TestWallpaperDriveFsDelegate() = default;
+
+void TestWallpaperDriveFsDelegate::Reset() {
+  save_wallpaper_account_id_.clear();
+  get_wallpaper_path_account_id_.clear();
+}
+
+base::FilePath TestWallpaperDriveFsDelegate::GetWallpaperPath(
+    const AccountId& account_id) {
+  get_wallpaper_path_account_id_ = account_id;
+  return base::FilePath();
+}
+
+void TestWallpaperDriveFsDelegate::SaveWallpaper(
+    const AccountId& account_id,
+    const base::FilePath& source,
+    base::OnceCallback<void(bool)> callback) {
+  save_wallpaper_account_id_ = account_id;
+  std::move(callback).Run(true);
+}
+
+void TestWallpaperDriveFsDelegate::GetWallpaperModificationTime(
+    const AccountId& account_id,
+    GetWallpaperModificationTimeCallback callback) {
+  NOTIMPLEMENTED_LOG_ONCE();
+  std::move(callback).Run(base::Time());
+}
+
+void TestWallpaperDriveFsDelegate::DownloadAndDecodeWallpaper(
+    const AccountId& account_id,
+    ImageDownloader::DownloadCallback callback) {
+  NOTIMPLEMENTED_LOG_ONCE();
+  std::move(callback).Run(gfx::ImageSkia());
+}
+
+}  // namespace ash
diff --git a/ash/wallpaper/test_wallpaper_drivefs_delegate.h b/ash/wallpaper/test_wallpaper_drivefs_delegate.h
new file mode 100644
index 0000000..a1b285504
--- /dev/null
+++ b/ash/wallpaper/test_wallpaper_drivefs_delegate.h
@@ -0,0 +1,55 @@
+// 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 ASH_WALLPAPER_TEST_WALLPAPER_DRIVEFS_DELEGATE_H_
+#define ASH_WALLPAPER_TEST_WALLPAPER_DRIVEFS_DELEGATE_H_
+
+#include "ash/public/cpp/wallpaper/wallpaper_drivefs_delegate.h"
+
+#include "ash/public/cpp/image_downloader.h"
+#include "base/files/file_path.h"
+#include "components/account_id/account_id.h"
+
+namespace ash {
+
+class TestWallpaperDriveFsDelegate : public WallpaperDriveFsDelegate {
+ public:
+  TestWallpaperDriveFsDelegate();
+
+  TestWallpaperDriveFsDelegate(const TestWallpaperDriveFsDelegate&) = delete;
+  TestWallpaperDriveFsDelegate& operator=(const TestWallpaperDriveFsDelegate&) =
+      delete;
+
+  ~TestWallpaperDriveFsDelegate() override;
+
+  void Reset();
+
+  AccountId get_save_wallpaper_account_id() const {
+    return save_wallpaper_account_id_;
+  }
+
+  AccountId get_wallpaper_path_account_id() const {
+    return get_wallpaper_path_account_id_;
+  }
+
+  // WallpaperDriveFsDelegate:
+  base::FilePath GetWallpaperPath(const AccountId& account_id) override;
+  void SaveWallpaper(const AccountId& account_id,
+                     const base::FilePath& source,
+                     base::OnceCallback<void(bool success)> callback) override;
+  void GetWallpaperModificationTime(
+      const AccountId& account_id,
+      GetWallpaperModificationTimeCallback callback) override;
+  void DownloadAndDecodeWallpaper(
+      const AccountId& account_id,
+      ImageDownloader::DownloadCallback callback) override;
+
+ private:
+  AccountId save_wallpaper_account_id_;
+  AccountId get_wallpaper_path_account_id_;
+};
+
+}  // namespace ash
+
+#endif  // ASH_WALLPAPER_TEST_WALLPAPER_DRIVEFS_DELEGATE_H_
diff --git a/ash/wallpaper/wallpaper_controller_impl.cc b/ash/wallpaper/wallpaper_controller_impl.cc
index 995f1c8a..8910276 100644
--- a/ash/wallpaper/wallpaper_controller_impl.cc
+++ b/ash/wallpaper/wallpaper_controller_impl.cc
@@ -3242,7 +3242,7 @@
     return;
   if (!wallpaper_controller_client_->IsWallpaperSyncEnabled(account_id))
     return;
-  wallpaper_controller_client_->SaveWallpaperToDriveFs(
+  drivefs_delegate_->SaveWallpaper(
       account_id, origin_path,
       base::BindOnce(&WallpaperControllerImpl::WallpaperSavedToDriveFS,
                      weak_factory_.GetWeakPtr(), account_id));
@@ -3261,37 +3261,24 @@
 void WallpaperControllerImpl::HandleCustomWallpaperInfoSyncedIn(
     const AccountId& account_id,
     const WallpaperInfo& wallpaper_info) {
-  base::FilePath drivefs_path =
-      wallpaper_controller_client_->GetWallpaperPathFromDriveFs(account_id);
-  if (drivefs_path.empty()) {
-    VLOG(1)
-        << "Skip syncing down custom wallpaper because DriveFS is unavailable.";
-    return;
-  }
-
   drivefs_delegate_->GetWallpaperModificationTime(
       account_id,
       base::BindOnce(
           &WallpaperControllerImpl::OnGetDriveFsWallpaperModificationTime,
-          weak_factory_.GetWeakPtr(), account_id, wallpaper_info,
-          drivefs_path));
+          weak_factory_.GetWeakPtr(), account_id, wallpaper_info));
 }
 
 void WallpaperControllerImpl::OnGetDriveFsWallpaperModificationTime(
     const AccountId& account_id,
     const WallpaperInfo& wallpaper_info,
-    const base::FilePath& drivefs_path,
     base::Time modification_time) {
   if (modification_time.is_null() || modification_time < wallpaper_info.date) {
     // If the drivefs image modification time is null, watch DriveFS for the
     // file being created. If the file exists but is older than synced wallpaper
     // info, watch for the file being updated by the other device.
+    // TODO(b/245987972) listen for file changed events from DriveFS.
     VLOG(1) << "Skip syncing custom wallpaper from DriveFS because it is not "
                "found or out of date";
-    drive_fs_wallpaper_watcher_.Watch(
-        drivefs_path, base::FilePathWatcher::Type::kNonRecursive,
-        base::BindRepeating(&WallpaperControllerImpl::DriveFsWallpaperChanged,
-                            weak_factory_.GetWeakPtr()));
     return;
   }
   base::FilePath path_in_prefs = base::FilePath(wallpaper_info.location);
diff --git a/ash/wallpaper/wallpaper_controller_impl.h b/ash/wallpaper/wallpaper_controller_impl.h
index 0543f1b5..6b0e251 100644
--- a/ash/wallpaper/wallpaper_controller_impl.h
+++ b/ash/wallpaper/wallpaper_controller_impl.h
@@ -749,7 +749,6 @@
   void OnGetDriveFsWallpaperModificationTime(
       const AccountId& account_id,
       const WallpaperInfo& wallpaper_info,
-      const base::FilePath& drivefs_path,
       base::Time modification_time);
 
   PrefService* GetUserPrefServiceSyncable(const AccountId& account_id) const;
diff --git a/ash/wallpaper/wallpaper_controller_unittest.cc b/ash/wallpaper/wallpaper_controller_unittest.cc
index b52f8406..c6ad0a0 100644
--- a/ash/wallpaper/wallpaper_controller_unittest.cc
+++ b/ash/wallpaper/wallpaper_controller_unittest.cc
@@ -27,6 +27,7 @@
 #include "ash/style/dark_light_mode_controller_impl.h"
 #include "ash/test/ash_test_base.h"
 #include "ash/wallpaper/test_wallpaper_controller_client.h"
+#include "ash/wallpaper/test_wallpaper_drivefs_delegate.h"
 #include "ash/wallpaper/wallpaper_pref_manager.h"
 #include "ash/wallpaper/wallpaper_utils/wallpaper_resizer.h"
 #include "ash/wallpaper/wallpaper_view.h"
@@ -391,6 +392,10 @@
                       custom_wallpaper_dir_.GetPath(), policy_wallpaper);
     client_.ResetCounts();
     controller_->SetClient(&client_);
+    std::unique_ptr<TestWallpaperDriveFsDelegate> drivefs_delegate =
+        std::make_unique<TestWallpaperDriveFsDelegate>();
+    drivefs_delegate_ = drivefs_delegate.get();
+    controller_->SetDriveFsDelegate(std::move(drivefs_delegate));
     client_.set_fake_files_id_for_account_id(kAccountId1, kWallpaperFilesId1);
     client_.set_fake_files_id_for_account_id(kAccountId2, kWallpaperFilesId2);
   }
@@ -711,6 +716,7 @@
   base::HistogramTester histogram_tester_;
 
   TestWallpaperControllerClient client_;
+  raw_ptr<TestWallpaperDriveFsDelegate> drivefs_delegate_;
   std::unique_ptr<TestImageDownloader> test_image_downloader_;
 
   const AccountId kChildAccountId =
@@ -1435,7 +1441,7 @@
       base::FilePath(kWallpaperFilesId1).Append(kFileName1).value(), layout,
       WallpaperType::kCustomized, base::Time::Now().LocalMidnight());
   EXPECT_TRUE(wallpaper_info.MatchesSelection(expected_wallpaper_info));
-  EXPECT_EQ(kAccountId1, client_.get_save_wallpaper_to_drive_fs_account_id());
+  EXPECT_EQ(kAccountId1, drivefs_delegate_->get_save_wallpaper_account_id());
 }
 
 TEST_F(WallpaperControllerTest, SetThirdPartyWallpaper_NonactiveUser) {
@@ -3414,7 +3420,7 @@
       base::FilePath(kWallpaperFilesId1).Append(kFileName1).value(), layout,
       WallpaperType::kCustomized, base::Time::Now().LocalMidnight());
   EXPECT_TRUE(wallpaper_info.MatchesSelection(expected_wallpaper_info));
-  EXPECT_EQ(kAccountId1, client_.get_save_wallpaper_to_drive_fs_account_id());
+  EXPECT_EQ(kAccountId1, drivefs_delegate_->get_save_wallpaper_account_id());
 
   // Now set another custom wallpaper for |kUser1|. Verify that the on-screen
   // wallpaper doesn't change since |kUser1| is not active, but wallpaper info
@@ -3821,7 +3827,7 @@
   ClearLogin();
 
   SimulateUserLogin(kAccountId1);
-  EXPECT_EQ(kAccountId1, client_.get_save_wallpaper_to_drive_fs_account_id());
+  EXPECT_EQ(kAccountId1, drivefs_delegate_->get_save_wallpaper_account_id());
 }
 
 TEST_F(WallpaperControllerTest, OnGoogleDriveMounted) {
@@ -3830,7 +3836,7 @@
 
   SimulateUserLogin(kAccountId1);
   controller_->SyncLocalAndRemotePrefs(kAccountId1);
-  EXPECT_EQ(kAccountId1, client_.get_save_wallpaper_to_drive_fs_account_id());
+  EXPECT_EQ(kAccountId1, drivefs_delegate_->get_save_wallpaper_account_id());
 }
 
 TEST_F(WallpaperControllerTest, OnGoogleDriveMounted_WallpaperIsntCustom) {
@@ -3838,7 +3844,7 @@
   pref_manager_->SetLocalWallpaperInfo(kAccountId1, local_info);
 
   controller_->SyncLocalAndRemotePrefs(kAccountId1);
-  EXPECT_TRUE(client_.get_save_wallpaper_to_drive_fs_account_id().empty());
+  EXPECT_TRUE(drivefs_delegate_->get_save_wallpaper_account_id().empty());
 }
 
 TEST_F(WallpaperControllerTest, OnGoogleDriveMounted_AlreadySynced) {
@@ -3856,11 +3862,11 @@
                                          /*file_path=*/"", image);
   RunAllTasksUntilIdle();
 
-  client_.ResetCounts();
+  drivefs_delegate_->Reset();
 
   // Should not reupload image if it has already been synced.
   controller_->SyncLocalAndRemotePrefs(kAccountId1);
-  EXPECT_FALSE(client_.get_save_wallpaper_to_drive_fs_account_id().is_valid());
+  EXPECT_FALSE(drivefs_delegate_->get_save_wallpaper_account_id().is_valid());
 }
 
 TEST_F(WallpaperControllerTest, OnGoogleDriveMounted_OldLocalInfo) {
@@ -3876,9 +3882,7 @@
   SimulateUserLogin(kAccountId1);
 
   controller_->SyncLocalAndRemotePrefs(kAccountId1);
-  EXPECT_FALSE(client_.get_save_wallpaper_to_drive_fs_account_id().is_valid());
-  // This is called by WallpaperController::HandleCustomWallpaperSyncedIn.
-  EXPECT_EQ(client_.get_wallpaper_path_from_drive_fs_account_id(), kAccountId1);
+  EXPECT_FALSE(drivefs_delegate_->get_save_wallpaper_account_id().is_valid());
 }
 
 TEST_F(WallpaperControllerTest, OnGoogleDriveMounted_NewLocalInfo) {
@@ -3895,7 +3899,7 @@
   SimulateUserLogin(kAccountId1);
 
   controller_->SyncLocalAndRemotePrefs(kAccountId1);
-  EXPECT_EQ(kAccountId1, client_.get_save_wallpaper_to_drive_fs_account_id());
+  EXPECT_EQ(kAccountId1, drivefs_delegate_->get_save_wallpaper_account_id());
 }
 
 TEST_F(WallpaperControllerTest,
diff --git a/ash/webui/camera_app_ui/camera_app_ui.cc b/ash/webui/camera_app_ui/camera_app_ui.cc
index fe588eac..5818791 100644
--- a/ash/webui/camera_app_ui/camera_app_ui.cc
+++ b/ash/webui/camera_app_ui/camera_app_ui.cc
@@ -75,10 +75,10 @@
               url, std::move(callback)));
 }
 
-content::WebUIDataSource* CreateCameraAppUIHTMLSource(
-    CameraAppUIDelegate* delegate) {
-  content::WebUIDataSource* source =
-      content::WebUIDataSource::Create(kChromeUICameraAppHost);
+void CreateAndAddCameraAppUIHTMLSource(content::BrowserContext* browser_context,
+                                       CameraAppUIDelegate* delegate) {
+  content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd(
+      browser_context, kChromeUICameraAppHost);
 
   source->DisableTrustedTypesCSP();
 
@@ -112,8 +112,6 @@
   source->OverrideContentSecurityPolicy(
       network::mojom::CSPDirectiveName::ObjectSrc,
       std::string("object-src 'self';"));
-
-  return source;
 }
 
 // Translates the renderer-side source ID to video device id.
@@ -246,8 +244,7 @@
   window()->SetProperty(kMinimizeOnBackKey, false);
 
   // Set up the data source.
-  content::WebUIDataSource::Add(browser_context,
-                                CreateCameraAppUIHTMLSource(delegate_.get()));
+  CreateAndAddCameraAppUIHTMLSource(browser_context, delegate_.get());
 
   // Add ability to request chrome-untrusted: URLs
   web_ui->AddRequestableScheme(content::kChromeUIUntrustedScheme);
diff --git a/ash/webui/camera_app_ui/camera_app_untrusted_ui.cc b/ash/webui/camera_app_ui/camera_app_untrusted_ui.cc
index deba4c93a..11a49ba1 100644
--- a/ash/webui/camera_app_ui/camera_app_untrusted_ui.cc
+++ b/ash/webui/camera_app_ui/camera_app_untrusted_ui.cc
@@ -18,9 +18,11 @@
 
 namespace {
 
-content::WebUIDataSource* CreateUntrustedCameraAppUIHTMLSource() {
+void CreateAndAddUntrustedCameraAppUIHTMLSource(
+    content::BrowserContext* browser_context) {
   content::WebUIDataSource* untrusted_source =
-      content::WebUIDataSource::Create(kChromeUIUntrustedCameraAppURL);
+      content::WebUIDataSource::CreateAndAdd(browser_context,
+                                             kChromeUIUntrustedCameraAppURL);
   untrusted_source->AddResourcePaths(
       base::make_span(kAshCameraAppResources, kAshCameraAppResourcesSize));
   untrusted_source->AddFrameAncestor(GURL(kChromeUICameraAppURL));
@@ -38,19 +40,14 @@
   untrusted_source->OverrideContentSecurityPolicy(
       network::mojom::CSPDirectiveName::TrustedTypes,
       std::string("trusted-types ga-js-static video-processor-js-static;"));
-
-  return untrusted_source;
 }
 
 }  // namespace
 
 CameraAppUntrustedUI::CameraAppUntrustedUI(content::WebUI* web_ui)
     : ui::UntrustedWebUIController(web_ui) {
-  content::WebUIDataSource* untrusted_source =
-      CreateUntrustedCameraAppUIHTMLSource();
-
-  auto* browser_context = web_ui->GetWebContents()->GetBrowserContext();
-  content::WebUIDataSource::Add(browser_context, untrusted_source);
+  CreateAndAddUntrustedCameraAppUIHTMLSource(
+      web_ui->GetWebContents()->GetBrowserContext());
 }
 
 CameraAppUntrustedUI::~CameraAppUntrustedUI() = default;
diff --git a/ash/webui/camera_app_ui/resources/js/mojo/device_operator.ts b/ash/webui/camera_app_ui/resources/js/mojo/device_operator.ts
index ddc5920..56dddd50 100644
--- a/ash/webui/camera_app_ui/resources/js/mojo/device_operator.ts
+++ b/ash/webui/camera_app_ui/resources/js/mojo/device_operator.ts
@@ -8,6 +8,7 @@
 import {Point} from '../geometry.js';
 import * as state from '../state.js';
 import {
+  CameraSuspendError,
   ErrorLevel,
   ErrorType,
   Facing,
@@ -597,9 +598,10 @@
 
     function suspendObserver(val: boolean) {
       if (val) {
+        console.warn('camera suspended');
         for (const [effect, event] of reprocessEvents.entries()) {
           if (effect === Effect.PORTRAIT_MODE) {
-            event.signalError(new Error('camera suspended'));
+            event.signalError(new CameraSuspendError());
           }
         }
       }
diff --git a/ash/webui/camera_app_ui/resources/js/type.ts b/ash/webui/camera_app_ui/resources/js/type.ts
index a6de866..a4767c3e 100644
--- a/ash/webui/camera_app_ui/resources/js/type.ts
+++ b/ash/webui/camera_app_ui/resources/js/type.ts
@@ -463,6 +463,16 @@
 }
 
 /**
+ * Throws when the camera is suspended while reprocess effects are ongoing.
+ */
+export class CameraSuspendError extends Error {
+  constructor(message = 'camera suspended') {
+    super(message);
+    this.name = this.constructor.name;
+  }
+}
+
+/**
  * Types of local storage key.
  */
 export enum LocalStorageKey {
diff --git a/ash/webui/camera_app_ui/resources/js/views/camera.ts b/ash/webui/camera_app_ui/resources/js/views/camera.ts
index c19eb95..a0fcad0 100644
--- a/ash/webui/camera_app_ui/resources/js/views/camera.ts
+++ b/ash/webui/camera_app_ui/resources/js/views/camera.ts
@@ -39,6 +39,7 @@
 import * as state from '../state.js';
 import * as toast from '../toast.js';
 import {
+  CameraSuspendError,
   CanceledError,
   ErrorLevel,
   ErrorType,
@@ -486,7 +487,7 @@
           return;
         }
         hasError = true;
-        if (e instanceof CanceledError) {
+        if (e instanceof CanceledError || e instanceof CameraSuspendError) {
           return;
         }
         error.reportError(
diff --git a/ash/webui/face_ml_app_ui/face_ml_app_untrusted_ui.cc b/ash/webui/face_ml_app_ui/face_ml_app_untrusted_ui.cc
index 586c234..ae2c2a0a 100644
--- a/ash/webui/face_ml_app_ui/face_ml_app_untrusted_ui.cc
+++ b/ash/webui/face_ml_app_ui/face_ml_app_untrusted_ui.cc
@@ -18,9 +18,10 @@
 
 namespace {
 
-content::WebUIDataSource* CreateFaceMLAppUntrustedDataSource() {
-  content::WebUIDataSource* source =
-      content::WebUIDataSource::Create(kChromeUIFaceMLAppUntrustedURL);
+void CreateAndAddFaceMLAppUntrustedDataSource(content::WebUI* web_ui) {
+  content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd(
+      web_ui->GetWebContents()->GetBrowserContext(),
+      kChromeUIFaceMLAppUntrustedURL);
   source->SetDefaultResource(IDR_ASH_FACE_ML_APP_UNTRUSTED_APP_HTML);
   source->AddResourcePaths(base::make_span(
       kAshFaceMlAppUntrustedResources, kAshFaceMlAppUntrustedResourcesSize));
@@ -48,19 +49,13 @@
   // Allow images to also handle data urls.
   source->OverrideContentSecurityPolicy(
       network::mojom::CSPDirectiveName::ImgSrc, "img-src blob: data: 'self';");
-
-  return source;
 }
 
 }  // namespace
 
 FaceMLAppUntrustedUI::FaceMLAppUntrustedUI(content::WebUI* web_ui)
     : ui::UntrustedWebUIController(web_ui) {
-  content::WebUIDataSource* untrusted_source =
-      CreateFaceMLAppUntrustedDataSource();
-
-  auto* browser_context = web_ui->GetWebContents()->GetBrowserContext();
-  content::WebUIDataSource::Add(browser_context, untrusted_source);
+  CreateAndAddFaceMLAppUntrustedDataSource(web_ui);
 }
 
 FaceMLAppUntrustedUI::~FaceMLAppUntrustedUI() = default;
diff --git a/ash/webui/file_manager/file_manager_ui.cc b/ash/webui/file_manager/file_manager_ui.cc
index 59809fe..0370b940 100644
--- a/ash/webui/file_manager/file_manager_ui.cc
+++ b/ash/webui/file_manager/file_manager_ui.cc
@@ -42,17 +42,15 @@
   // unique ID to each window.
   ++window_counter_;
 
-  auto* browser_context = web_ui->GetWebContents()->GetBrowserContext();
-  auto* trusted_source = CreateTrustedAppDataSource(window_counter_);
-  content::WebUIDataSource::Add(browser_context, trusted_source);
+  CreateAndAddTrustedAppDataSource(web_ui, window_counter_);
   // Add ability to request chrome-untrusted: URLs
   web_ui->AddRequestableScheme(content::kChromeUIUntrustedScheme);
 }
 
-content::WebUIDataSource* FileManagerUI::CreateTrustedAppDataSource(
-    int window_number) {
-  content::WebUIDataSource* source =
-      content::WebUIDataSource::Create(kChromeUIFileManagerHost);
+void FileManagerUI::CreateAndAddTrustedAppDataSource(content::WebUI* web_ui,
+                                                     int window_number) {
+  content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd(
+      web_ui->GetWebContents()->GetBrowserContext(), kChromeUIFileManagerHost);
 
   // Setup chrome://file-manager main and default page.
   source->AddResourcePath("", IDR_FILE_MANAGER_SWA_MAIN_HTML);
@@ -92,8 +90,6 @@
 
   // TODO(crbug.com/1098685): Trusted Type remaining WebUI.
   source->DisableTrustedTypesCSP();
-
-  return source;
 }
 
 int FileManagerUI::GetNumInstances() {
diff --git a/ash/webui/file_manager/file_manager_ui.h b/ash/webui/file_manager/file_manager_ui.h
index 1c37d0d6..c4acd1d 100644
--- a/ash/webui/file_manager/file_manager_ui.h
+++ b/ash/webui/file_manager/file_manager_ui.h
@@ -53,7 +53,8 @@
   static int GetNumInstances();
 
  private:
-  content::WebUIDataSource* CreateTrustedAppDataSource(int window_number);
+  void CreateAndAddTrustedAppDataSource(content::WebUI* web_ui,
+                                        int window_number);
 
   // mojom::PageHandlerFactory:
   void CreatePageHandler(
diff --git a/ash/webui/help_app_ui/help_app_kids_magazine_untrusted_ui.cc b/ash/webui/help_app_ui/help_app_kids_magazine_untrusted_ui.cc
index 7127b82..bb1a6bb 100644
--- a/ash/webui/help_app_ui/help_app_kids_magazine_untrusted_ui.cc
+++ b/ash/webui/help_app_ui/help_app_kids_magazine_untrusted_ui.cc
@@ -29,8 +29,10 @@
   return input;
 }
 
-content::WebUIDataSource* CreateHelpAppKidsMagazineUntrustedDataSource() {
-  content::WebUIDataSource* source = content::WebUIDataSource::Create(
+void CreateAndAddHelpAppKidsMagazineUntrustedDataSource(
+    content::WebUI* web_ui) {
+  content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd(
+      web_ui->GetWebContents()->GetBrowserContext(),
       kChromeUIHelpAppKidsMagazineUntrustedURL);
   // Set index.html as the default resource.
   source->SetDefaultResource(IDR_HELP_APP_KIDS_MAGAZINE_INDEX_HTML);
@@ -54,7 +56,6 @@
   source->OverrideContentSecurityPolicy(
       network::mojom::CSPDirectiveName::ScriptSrc,
       "script-src 'self' https://www.gstatic.com;");
-  return source;
 }
 
 }  // namespace
@@ -75,11 +76,7 @@
 HelpAppKidsMagazineUntrustedUI::HelpAppKidsMagazineUntrustedUI(
     content::WebUI* web_ui)
     : ui::UntrustedWebUIController(web_ui) {
-  content::WebUIDataSource* untrusted_source =
-      CreateHelpAppKidsMagazineUntrustedDataSource();
-
-  auto* browser_context = web_ui->GetWebContents()->GetBrowserContext();
-  content::WebUIDataSource::Add(browser_context, untrusted_source);
+  CreateAndAddHelpAppKidsMagazineUntrustedDataSource(web_ui);
 }
 
 HelpAppKidsMagazineUntrustedUI::~HelpAppKidsMagazineUntrustedUI() = default;
diff --git a/ash/webui/help_app_ui/help_app_ui.cc b/ash/webui/help_app_ui/help_app_ui.cc
index 8fecabded..79436ecb 100644
--- a/ash/webui/help_app_ui/help_app_ui.cc
+++ b/ash/webui/help_app_ui/help_app_ui.cc
@@ -31,8 +31,10 @@
 namespace ash {
 
 namespace {
-content::WebUIDataSource* CreateHostDataSource() {
-  auto* source = content::WebUIDataSource::Create(kChromeUIHelpAppHost);
+content::WebUIDataSource* CreateAndAddHostDataSource(
+    content::BrowserContext* browser_context) {
+  content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd(
+      browser_context, kChromeUIHelpAppHost);
 
   // TODO(b/218419680): Remove index_dark_light_html when the dark/light flag is
   // no longer needed.
@@ -55,8 +57,8 @@
     : MojoWebUIController(web_ui), delegate_(std::move(delegate)) {
   content::BrowserContext* browser_context =
       web_ui->GetWebContents()->GetBrowserContext();
-  content::WebUIDataSource* host_source = CreateHostDataSource();
-  content::WebUIDataSource::Add(browser_context, host_source);
+  content::WebUIDataSource* host_source =
+      CreateAndAddHostDataSource(browser_context);
   // We need a CSP override to use the chrome-untrusted:// scheme in the host.
   std::string csp =
       std::string("frame-src ") + kChromeUIHelpAppUntrustedURL + ";";
diff --git a/ash/webui/help_app_ui/help_app_untrusted_ui.cc b/ash/webui/help_app_ui/help_app_untrusted_ui.cc
index de04b423..d3bd076 100644
--- a/ash/webui/help_app_ui/help_app_untrusted_ui.cc
+++ b/ash/webui/help_app_ui/help_app_untrusted_ui.cc
@@ -20,11 +20,12 @@
 
 namespace {
 
-content::WebUIDataSource* CreateHelpAppUntrustedDataSource(
+void CreateAndAddHelpAppUntrustedDataSource(
+    content::BrowserContext* browser_context,
     base::RepeatingCallback<void(content::WebUIDataSource*)>
         populate_load_time_data_callback) {
-  content::WebUIDataSource* source =
-      content::WebUIDataSource::Create(kChromeUIHelpAppUntrustedURL);
+  content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd(
+      browser_context, kChromeUIHelpAppUntrustedURL);
   // app.html is the default resource because it has routing logic to handle all
   // the other paths.
   source->SetDefaultResource(IDR_HELP_APP_APP_HTML);
@@ -51,7 +52,6 @@
   source->OverrideContentSecurityPolicy(
       network::mojom::CSPDirectiveName::ChildSrc,
       "child-src 'self' chrome-untrusted://help-app-kids-magazine;");
-  return source;
 }
 
 }  // namespace
@@ -61,11 +61,9 @@
     base::RepeatingCallback<void(content::WebUIDataSource* source)>
         populate_load_time_data_callback)
     : ui::UntrustedWebUIController(web_ui) {
-  content::WebUIDataSource* untrusted_source =
-      CreateHelpAppUntrustedDataSource(populate_load_time_data_callback);
-
-  auto* browser_context = web_ui->GetWebContents()->GetBrowserContext();
-  content::WebUIDataSource::Add(browser_context, untrusted_source);
+  CreateAndAddHelpAppUntrustedDataSource(
+      web_ui->GetWebContents()->GetBrowserContext(),
+      populate_load_time_data_callback);
 }
 
 HelpAppUntrustedUI::~HelpAppUntrustedUI() = default;
diff --git a/ash/webui/media_app_ui/media_app_guest_ui.cc b/ash/webui/media_app_ui/media_app_guest_ui.cc
index eb58fb6f..f5ef536 100644
--- a/ash/webui/media_app_ui/media_app_guest_ui.cc
+++ b/ash/webui/media_app_ui/media_app_guest_ui.cc
@@ -105,11 +105,11 @@
   }
 }
 
-content::WebUIDataSource* CreateMediaAppUntrustedDataSource(
+content::WebUIDataSource* CreateAndAddMediaAppUntrustedDataSource(
     content::WebUI* web_ui,
     MediaAppGuestUIDelegate* delegate) {
-  content::WebUIDataSource* source =
-      content::WebUIDataSource::Create(kChromeUIMediaAppGuestURL);
+  content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd(
+      web_ui->GetWebContents()->GetBrowserContext(), kChromeUIMediaAppGuestURL);
   // Add resources from ash_media_app_resources.pak.
   source->AddResourcePath("app.html", IDR_MEDIA_APP_APP_HTML);
   source->AddResourcePath("receiver.js", IDR_MEDIA_APP_RECEIVER_JS);
@@ -190,16 +190,13 @@
        base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
 
   content::WebUIDataSource* untrusted_source =
-      CreateMediaAppUntrustedDataSource(web_ui, delegate);
+      CreateAndAddMediaAppUntrustedDataSource(web_ui, delegate);
 
   MaybeConfigureTestableDataSource(
       untrusted_source, "media_app/untrusted",
       base::BindRepeating(&IsFontRequest),
       base::BindRepeating(&MediaAppGuestUI::StartFontDataRequest,
                           weak_factory_.GetWeakPtr()));
-
-  auto* browser_context = web_ui->GetWebContents()->GetBrowserContext();
-  content::WebUIDataSource::Add(browser_context, untrusted_source);
 }
 
 MediaAppGuestUI::~MediaAppGuestUI() {
diff --git a/ash/webui/media_app_ui/media_app_ui.cc b/ash/webui/media_app_ui/media_app_ui.cc
index 540ea7b..f9bfc27 100644
--- a/ash/webui/media_app_ui/media_app_ui.cc
+++ b/ash/webui/media_app_ui/media_app_ui.cc
@@ -36,9 +36,10 @@
     {"fileFilterVideo", IDS_MEDIA_APP_FILE_FILTER_VIDEO},
 };
 
-content::WebUIDataSource* CreateHostDataSource() {
-  content::WebUIDataSource* source =
-      content::WebUIDataSource::Create(kChromeUIMediaAppHost);
+content::WebUIDataSource* CreateAndAddHostDataSource(
+    content::BrowserContext* browser_context) {
+  content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd(
+      browser_context, kChromeUIMediaAppHost);
 
   // Add resources from ash_media_app_resources.pak.
   // TODO(b/218419680): Remove index_dark_light_html when the dark/light flag is
@@ -109,8 +110,8 @@
     : MojoWebUIController(web_ui), delegate_(std::move(delegate)) {
   content::BrowserContext* browser_context =
       web_ui->GetWebContents()->GetBrowserContext();
-  content::WebUIDataSource* host_source = CreateHostDataSource();
-  content::WebUIDataSource::Add(browser_context, host_source);
+  content::WebUIDataSource* host_source =
+      CreateAndAddHostDataSource(browser_context);
 
   // The guest is in an <iframe>. Add it to CSP.
   std::string csp = std::string("frame-src ") + kChromeUIMediaAppGuestURL + ";";
diff --git a/ash/webui/projector_app/public/cpp/projector_app_constants.cc b/ash/webui/projector_app/public/cpp/projector_app_constants.cc
index c616f0c..8fa9675 100644
--- a/ash/webui/projector_app/public/cpp/projector_app_constants.cc
+++ b/ash/webui/projector_app/public/cpp/projector_app_constants.cc
@@ -9,7 +9,7 @@
 const char kChromeUIProjectorAppHost[] = "projector";
 const char kChromeUIProjectorAnnotatorHost[] = "projector-annotator";
 
-// content::WebUIDataSource::Create() requires trailing slash.
+// content::WebUIDataSource::CreateAndAdd() requires trailing slash.
 const char kChromeUIUntrustedProjectorUrl[] = "chrome-untrusted://projector/";
 const char kChromeUIUntrustedProjectorPwaUrl[] =
     "https://screencast.apps.chrome";
diff --git a/ash/webui/projector_app/trusted_projector_annotator_ui.cc b/ash/webui/projector_app/trusted_projector_annotator_ui.cc
index 5224962..9650a73 100644
--- a/ash/webui/projector_app/trusted_projector_annotator_ui.cc
+++ b/ash/webui/projector_app/trusted_projector_annotator_ui.cc
@@ -23,9 +23,10 @@
 
 namespace {
 
-content::WebUIDataSource* CreateProjectorAnnotatorHTMLSource() {
-  content::WebUIDataSource* source =
-      content::WebUIDataSource::Create(kChromeUIProjectorAnnotatorHost);
+void CreateAndAddProjectorAnnotatorHTMLSource(content::WebUI* web_ui) {
+  content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd(
+      web_ui->GetWebContents()->GetBrowserContext(),
+      kChromeUIProjectorAnnotatorHost);
 
   // TODO(b/216523790): Split trusted annotator resources into a separate
   // bundle.
@@ -50,8 +51,6 @@
       network::mojom::CSPDirectiveName::TrustedTypes,
       "trusted-types polymer-html-literal "
       "polymer-template-event-attribute-policy;");
-
-  return source;
 }
 
 }  // namespace
@@ -68,9 +67,7 @@
   auto handler = std::make_unique<ash::AnnotatorMessageHandler>();
   web_ui->AddMessageHandler(std::move(handler));
 
-  auto* browser_context = web_ui->GetWebContents()->GetBrowserContext();
-  content::WebUIDataSource::Add(browser_context,
-                                CreateProjectorAnnotatorHTMLSource());
+  CreateAndAddProjectorAnnotatorHTMLSource(web_ui);
 
   // The Annotator and Projector SWA embed contents in a sandboxed
   // chrome-untrusted:// iframe.
diff --git a/ash/webui/projector_app/trusted_projector_ui.cc b/ash/webui/projector_app/trusted_projector_ui.cc
index 7a189f3..e63c790 100644
--- a/ash/webui/projector_app/trusted_projector_ui.cc
+++ b/ash/webui/projector_app/trusted_projector_ui.cc
@@ -25,9 +25,9 @@
 
 namespace {
 
-content::WebUIDataSource* CreateProjectorHTMLSource() {
-  content::WebUIDataSource* source =
-      content::WebUIDataSource::Create(kChromeUIProjectorAppHost);
+void CreateAndAddProjectorHTMLSource(content::WebUI* web_ui) {
+  content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd(
+      web_ui->GetWebContents()->GetBrowserContext(), kChromeUIProjectorAppHost);
 
   source->AddResourcePaths(base::make_span(
       kAshProjectorAppTrustedResources, kAshProjectorAppTrustedResourcesSize));
@@ -46,8 +46,6 @@
       network::mojom::CSPDirectiveName::TrustedTypes,
       "trusted-types polymer-html-literal "
       "polymer-template-event-attribute-policy;");
-
-  return source;
 }
 
 }  // namespace
@@ -56,8 +54,7 @@
                                        const GURL& url,
                                        PrefService* pref_service)
     : MojoBubbleWebUIController(web_ui, /*enable_chrome_send=*/true) {
-  auto* browser_context = web_ui->GetWebContents()->GetBrowserContext();
-  content::WebUIDataSource::Add(browser_context, CreateProjectorHTMLSource());
+  CreateAndAddProjectorHTMLSource(web_ui);
 
   // The Annotator and Projector SWA embed contents in a sandboxed
   // chrome-untrusted:// iframe.
diff --git a/ash/webui/projector_app/untrusted_projector_annotator_ui.cc b/ash/webui/projector_app/untrusted_projector_annotator_ui.cc
index 6bdd7e46..10bab51 100644
--- a/ash/webui/projector_app/untrusted_projector_annotator_ui.cc
+++ b/ash/webui/projector_app/untrusted_projector_annotator_ui.cc
@@ -26,10 +26,12 @@
 
 namespace {
 
-content::WebUIDataSource* CreateProjectorAnnotatorHTMLSource(
+void CreateAndAddProjectorAnnotatorHTMLSource(
+    content::WebUI* web_ui,
     UntrustedProjectorAnnotatorUIDelegate* delegate) {
-  content::WebUIDataSource* source =
-      content::WebUIDataSource::Create(kChromeUIUntrustedAnnotatorUrl);
+  content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd(
+      web_ui->GetWebContents()->GetBrowserContext(),
+      kChromeUIUntrustedAnnotatorUrl);
 
   // TODO(b/216523790): Split untrusted annotator resources into a separate
   // bundle.
@@ -90,8 +92,6 @@
 
   delegate->PopulateLoadTimeData(source);
   source->UseStringsJs();
-
-  return source;
 }
 
 }  // namespace
@@ -100,9 +100,7 @@
     content::WebUI* web_ui,
     UntrustedProjectorAnnotatorUIDelegate* delegate)
     : UntrustedWebUIController(web_ui) {
-  auto* browser_context = web_ui->GetWebContents()->GetBrowserContext();
-  content::WebUIDataSource::Add(browser_context,
-                                CreateProjectorAnnotatorHTMLSource(delegate));
+  CreateAndAddProjectorAnnotatorHTMLSource(web_ui, delegate);
 }
 
 UntrustedProjectorAnnotatorUI::~UntrustedProjectorAnnotatorUI() = default;
diff --git a/ash/webui/projector_app/untrusted_projector_ui.cc b/ash/webui/projector_app/untrusted_projector_ui.cc
index f2e9069..02002e4 100644
--- a/ash/webui/projector_app/untrusted_projector_ui.cc
+++ b/ash/webui/projector_app/untrusted_projector_ui.cc
@@ -23,10 +23,11 @@
 
 namespace {
 
-content::WebUIDataSource* CreateProjectorHTMLSource(
-    UntrustedProjectorUIDelegate* delegate) {
-  content::WebUIDataSource* source =
-      content::WebUIDataSource::Create(kChromeUIUntrustedProjectorUrl);
+void CreateAndAddProjectorHTMLSource(content::WebUI* web_ui,
+                                     UntrustedProjectorUIDelegate* delegate) {
+  content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd(
+      web_ui->GetWebContents()->GetBrowserContext(),
+      kChromeUIUntrustedProjectorUrl);
 
   source->AddResourcePaths(
       base::make_span(kAshProjectorAppUntrustedResources,
@@ -80,8 +81,6 @@
 
   delegate->PopulateLoadTimeData(source);
   source->UseStringsJs();
-
-  return source;
 }
 
 }  // namespace
@@ -90,9 +89,7 @@
     content::WebUI* web_ui,
     UntrustedProjectorUIDelegate* delegate)
     : UntrustedWebUIController(web_ui) {
-  auto* browser_context = web_ui->GetWebContents()->GetBrowserContext();
-  content::WebUIDataSource::Add(browser_context,
-                                CreateProjectorHTMLSource(delegate));
+  CreateAndAddProjectorHTMLSource(web_ui, delegate);
 }
 
 UntrustedProjectorUI::~UntrustedProjectorUI() = default;
diff --git a/ash/webui/shortcut_customization_ui/resources/js/accelerator_lookup_manager.ts b/ash/webui/shortcut_customization_ui/resources/js/accelerator_lookup_manager.ts
index d31e0d5..22b9496c 100644
--- a/ash/webui/shortcut_customization_ui/resources/js/accelerator_lookup_manager.ts
+++ b/ash/webui/shortcut_customization_ui/resources/js/accelerator_lookup_manager.ts
@@ -17,9 +17,6 @@
  */
 type AcceleratorLookupKey = string;
 type AcceleratorLookupMap = Map<AcceleratorId, StandardAcceleratorInfo[]>;
-type AcceleratorLayoutLookupMap =
-    Map<AcceleratorCategory, Map<AcceleratorSubcategory, LayoutInfo[]>>;
-type AcceleratorNameLookupMap = Map<AcceleratorId, AcceleratorName>;
 type ReverseAcceleratorLookupMap = Map<AcceleratorLookupKey, AcceleratorId>;
 
 /**
@@ -28,6 +25,7 @@
  * handled in this class.
  */
 export class AcceleratorLookupManager {
+  private layoutInfoProvider = new LayoutInfoProvider();
   /**
    * A map with the key set to a concatenated string of the accelerator's
    * '{source}-{action_id}', this concatenation uniquely identifies one
@@ -36,21 +34,7 @@
    * AcceleratorInfos for one accelerator.
    */
   private acceleratorLookup: AcceleratorLookupMap = new Map();
-  /**
-   * A multi-layered map container. The top-most layer is a map with the key
-   * as the accelerator's category (e.g. Tabs & Windows, Page & Web Browser).
-   * The value of the top-most map is another map in which the key is the
-   * accelerator's subcategory (e.g. System Controls, System Apps) and the value
-   * is an Array of LayoutInfo. This map serves as a way to find all
-   * LayoutInfo's of a given subsection of accelerators, where each LayoutInfo
-   * corresponds to one AcceleratorRow.
-   */
-  private acceleratorLayoutLookup: AcceleratorLayoutLookupMap = new Map();
-  /**
-   * A map with the string key formatted as `${source_id}-${action_id}` and
-   * the value as the string corresponding to the accelerator's name.
-   */
-  private acceleratorNameLookup: AcceleratorNameLookupMap = new Map();
+
   /**
    * A map with the key as a stringified version of AcceleratorKey and the
    * value as the unique string identifier `${source_id}-${action_id}`. Note
@@ -82,24 +66,17 @@
   getAcceleratorLayout(
       category: AcceleratorCategory,
       subCategory: AcceleratorSubcategory): LayoutInfo[] {
-    const categoryMap = this.acceleratorLayoutLookup.get(category);
-    assert(categoryMap);
-    const subCategoryMap = categoryMap.get(subCategory);
-    assert(subCategoryMap);
-    return subCategoryMap;
+    return this.layoutInfoProvider.getAcceleratorLayout(category, subCategory);
   }
 
   getSubcategories(category: AcceleratorCategory):
       Map<AcceleratorSubcategory, LayoutInfo[]>|undefined {
-    return this.acceleratorLayoutLookup.get(category);
+    return this.layoutInfoProvider.getSubcategories(category);
   }
 
   getAcceleratorName(source: number|string, action: number|string):
       AcceleratorName {
-    const uuid: AcceleratorId = getAcceleratorId(source, action);
-    const acceleratorName = this.acceleratorNameLookup.get(uuid);
-    assert(acceleratorName);
-    return acceleratorName;
+    return this.layoutInfoProvider.getAcceleratorName(source, action);
   }
 
   /**
@@ -172,41 +149,7 @@
   }
 
   setAcceleratorLayoutLookup(layoutInfoList: MojoLayoutInfo[]): void {
-    for (const entry of layoutInfoList) {
-      // This check is necessary because the layout info list may contain
-      // references to accelerators that are not always present
-      // (e.g. developer or debug mode accelerators).
-      const acceleratorExists = this.acceleratorLookup.has(
-          getAcceleratorId(entry.source, entry.action));
-      if (!acceleratorExists) {
-        continue;
-      }
-
-      if (!this.acceleratorLayoutLookup.has(entry.category)) {
-        this.acceleratorLayoutLookup.set(entry.category, new Map());
-      }
-
-      const subcatMap = this.acceleratorLayoutLookup.get(entry.category);
-      if (!subcatMap!.has(entry.subCategory)) {
-        subcatMap!.set(entry.subCategory, []);
-      }
-
-      const sanitizedLayoutInfo: LayoutInfo = {
-        source: entry.source,
-        style: entry.style,
-        description: mojoString16ToString(entry.description),
-        category: entry.category,
-        subCategory: entry.subCategory,
-        action: entry.action,
-      };
-
-      this.getAcceleratorLayout(entry.category, entry.subCategory)
-          .push(sanitizedLayoutInfo);
-
-      // Add the entry to the AcceleratorNameLookup.
-      const uuid = getAcceleratorId(entry.source, entry.action);
-      this.acceleratorNameLookup.set(uuid, sanitizedLayoutInfo.description);
-    }
+    this.layoutInfoProvider.initializeLayoutInfo(layoutInfoList);
   }
 
   replaceAccelerator(
@@ -416,8 +359,7 @@
 
   reset(): void {
     this.acceleratorLookup.clear();
-    this.acceleratorNameLookup.clear();
-    this.acceleratorLayoutLookup.clear();
+    this.layoutInfoProvider.resetLookupMaps();
     this.reverseAcceleratorLookup.clear();
   }
 
@@ -433,3 +375,108 @@
 }
 
 let managerInstance: AcceleratorLookupManager|null = null;
+
+
+function createSanitizedLayoutInfo(entry: MojoLayoutInfo): LayoutInfo {
+  return {...entry, description: mojoString16ToString(entry.description)};
+}
+
+type AcceleratorLayoutLookupMap =
+    Map<AcceleratorCategory, Map<AcceleratorSubcategory, LayoutInfo[]>>;
+type AcceleratorNameLookupMap = Map<AcceleratorId, AcceleratorName>;
+
+interface LayoutProviderInterface {
+  getAcceleratorLayout(
+      category: AcceleratorCategory,
+      subCategory: AcceleratorSubcategory): LayoutInfo[];
+  getSubcategories(category: AcceleratorCategory):
+      Map<AcceleratorSubcategory, LayoutInfo[]>|undefined;
+  getAcceleratorName(source: number|string, action: number|string):
+      AcceleratorName;
+  initializeLayoutInfo(layoutInfoList: MojoLayoutInfo[]): void;
+  resetLookupMaps(): void;
+}
+
+// Responsible for initializing/maintaining layout information for
+// accelerators.
+class LayoutInfoProvider implements LayoutProviderInterface {
+  /**
+   * A multi-layered map container. The top-most layer is a map with the key
+   * as the accelerator's category (e.g. Tabs & Windows, Page & Web Browser).
+   * The value of the top-most map is another map in which the key is the
+   * accelerator's subcategory (e.g. System Controls, System Apps) and the value
+   * is an Array of LayoutInfo. This map serves as a way to find all
+   * LayoutInfo's of a given subsection of accelerators, where each LayoutInfo
+   * corresponds to one AcceleratorRow.
+   */
+  private acceleratorLayoutLookup: AcceleratorLayoutLookupMap = new Map();
+  /**
+   * A map with the string key formatted as `${source_id}-${action_id}` and
+   * the value as the string corresponding to the accelerator's name.
+   */
+  private acceleratorNameLookup: AcceleratorNameLookupMap = new Map();
+
+  getAcceleratorLayout(
+      category: AcceleratorCategory,
+      subCategory: AcceleratorSubcategory): LayoutInfo[] {
+    const categoryMap = this.acceleratorLayoutLookup.get(category);
+    assert(categoryMap);
+    const subCategoryMap = categoryMap.get(subCategory);
+    assert(subCategoryMap);
+    return subCategoryMap;
+  }
+
+  getSubcategories(category: AcceleratorCategory):
+      Map<AcceleratorSubcategory, LayoutInfo[]>|undefined {
+    return this.acceleratorLayoutLookup.get(category);
+  }
+
+  getAcceleratorName(source: number|string, action: number|string):
+      AcceleratorName {
+    const uuid: AcceleratorId = getAcceleratorId(source, action);
+    const acceleratorName = this.acceleratorNameLookup.get(uuid);
+    assert(acceleratorName);
+    return acceleratorName;
+  }
+
+  initializeLayoutInfo(layoutInfoList: MojoLayoutInfo[]): void {
+    this.initializeCategoryMaps(layoutInfoList);
+    for (const entry of layoutInfoList) {
+      // The Accelerator layout table doesn't currently contain any
+      // developer/debug accelerators. Once they are added, we need to
+      // check if they should be shown or not. This assert is to ensure that
+      // this case is handled once developer/debug accelerators are added.
+      assert(
+          entry.category !== AcceleratorCategory.kDebug &&
+          entry.category !== AcceleratorCategory.kDeveloper);
+      const layoutInfo = createSanitizedLayoutInfo(entry);
+      this.getAcceleratorLayout(entry.category, entry.subCategory)
+          .push(layoutInfo);
+      this.addEntrytoAcceleratorNameLookup(
+          getAcceleratorId(entry.source, entry.action), layoutInfo.description);
+    }
+  }
+
+  initializeCategoryMaps(layoutInfoList: MojoLayoutInfo[]): void {
+    for (const entry of layoutInfoList) {
+      if (!this.acceleratorLayoutLookup.has(entry.category)) {
+        this.acceleratorLayoutLookup.set(entry.category, new Map());
+      }
+
+      const subcatMap = this.acceleratorLayoutLookup.get(entry.category);
+      if (!subcatMap!.has(entry.subCategory)) {
+        subcatMap!.set(entry.subCategory, []);
+      }
+    }
+  }
+
+  private addEntrytoAcceleratorNameLookup(uuid: string, description: string):
+      void {
+    this.acceleratorNameLookup.set(uuid, description);
+  }
+
+  resetLookupMaps(): void {
+    this.acceleratorLayoutLookup.clear();
+    this.acceleratorNameLookup.clear();
+  }
+}
diff --git a/ash/webui/shortcut_customization_ui/resources/js/fake_data.ts b/ash/webui/shortcut_customization_ui/resources/js/fake_data.ts
index e2da87b..b9bcd984 100644
--- a/ash/webui/shortcut_customization_ui/resources/js/fake_data.ts
+++ b/ash/webui/shortcut_customization_ui/resources/js/fake_data.ts
@@ -90,9 +90,10 @@
       },
     }],
   },
-  [AcceleratorSource.kBrowser]: {
+  // TODO(michaelcheco): Separate Browser and Ambient accelerators.
+  [AcceleratorSource.kAmbient]: {
     // New Tab
-    [1001]: [{
+    [0]: [{
       type: AcceleratorType.kDefault,
       state: AcceleratorState.kEnabled,
       locked: true,
@@ -151,8 +152,8 @@
     subCategory: AcceleratorSubcategory.kSystemControls,
     description: stringToMojoString16('New Tab'),
     style: LayoutStyle.kDefault,
-    source: AcceleratorSource.kBrowser,
-    action: 1001,
+    source: AcceleratorSource.kAmbient,
+    action: 0,
   },
 ];
 
@@ -186,7 +187,7 @@
         subCategory: AcceleratorSubcategory.kSystemControls,
         description: stringToMojoString16(description),
         style: LayoutStyle.kDefault,
-        source: AcceleratorSource.kBrowser,
+        source: AcceleratorSource.kAmbient,
         action,
       };
     };
@@ -195,9 +196,9 @@
 
 for (const [index, iconName] of icons.entries()) {
   const actionId = 10000 + index;
-  fakeAcceleratorConfig[AcceleratorSource.kBrowser] = {
-    ...fakeAcceleratorConfig[AcceleratorSource.kBrowser],
+  fakeAcceleratorConfig[AcceleratorSource.kAmbient] = {
+    ...fakeAcceleratorConfig[AcceleratorSource.kAmbient],
     [actionId]: [createFakeMojoAccelInfo(iconName)],
   };
   fakeLayoutInfo.push(createFakeMojoLayoutInfo(`Icon: ${iconName}`, actionId));
-}
\ No newline at end of file
+}
diff --git a/ash/webui/web_applications/test/js_library_test.cc b/ash/webui/web_applications/test/js_library_test.cc
index f880a266..f2af2c98 100644
--- a/ash/webui/web_applications/test/js_library_test.cc
+++ b/ash/webui/web_applications/test/js_library_test.cc
@@ -60,8 +60,11 @@
       base::BindRepeating(&HandleRequest));
 }
 
-content::WebUIDataSource* CreateTrustedSysemAppTestDataSource() {
-  auto* trusted_source = content::WebUIDataSource::Create(kSystemAppTestHost);
+void CreateAndAddTrustedSystemAppTestDataSource(
+    content::BrowserContext* browser_context) {
+  content::WebUIDataSource* trusted_source =
+      content::WebUIDataSource::CreateAndAdd(browser_context,
+                                             kSystemAppTestHost);
 
   // We need a CSP override to be able to embed a chrome-untrusted:// iframe.
   std::string csp =
@@ -70,16 +73,16 @@
       network::mojom::CSPDirectiveName::FrameSrc, csp);
 
   SetRequestFilterForDataSource(*trusted_source);
-  return trusted_source;
 }
 
-content::WebUIDataSource* CreateUntrustedSystemAppTestDataSource() {
-  auto* untrusted_source =
-      content::WebUIDataSource::Create(kUntrustedSystemAppTestURL);
+void CreateAndAddUntrustedSystemAppTestDataSource(
+    content::BrowserContext* browser_context) {
+  content::WebUIDataSource* untrusted_source =
+      content::WebUIDataSource::CreateAndAdd(browser_context,
+                                             kUntrustedSystemAppTestURL);
   untrusted_source->AddFrameAncestor(GURL(kSystemAppTestURL));
 
   SetRequestFilterForDataSource(*untrusted_source);
-  return untrusted_source;
 }
 
 class JsLibraryTestWebUIController : public ui::MojoWebUIController {
@@ -87,11 +90,8 @@
   explicit JsLibraryTestWebUIController(content::WebUI* web_ui)
       : ui::MojoWebUIController(web_ui) {
     auto* browser_context = web_ui->GetWebContents()->GetBrowserContext();
-
-    content::WebUIDataSource::Add(browser_context,
-                                  CreateTrustedSysemAppTestDataSource());
-    content::WebUIDataSource::Add(browser_context,
-                                  CreateUntrustedSystemAppTestDataSource());
+    CreateAndAddTrustedSystemAppTestDataSource(browser_context);
+    CreateAndAddUntrustedSystemAppTestDataSource(browser_context);
 
     // Add ability to request chrome-untrusted: URLs
     web_ui->AddRequestableScheme(content::kChromeUIUntrustedScheme);
diff --git a/base/values.cc b/base/values.cc
index 0d7e0e5..3f5381d8 100644
--- a/base/values.cc
+++ b/base/values.cc
@@ -1581,57 +1581,6 @@
 
 DictionaryValue::DictionaryValue() : Value(Type::DICTIONARY) {}
 
-Value* DictionaryValue::Set(StringPiece path, std::unique_ptr<Value> in_value) {
-  DCHECK(IsStringUTF8AllowingNoncharacters(path));
-  DCHECK(in_value);
-
-  // IMPORTANT NOTE: Do not replace with GetDict.SetByDottedPath() yet, because
-  // the latter fails when over-writing a non-dict intermediate node, while this
-  // method just replaces it with one. This difference makes some tests actually
-  // fail (http://crbug.com/949461).
-  StringPiece current_path(path);
-  Value* current_dictionary = this;
-  for (size_t delimiter_position = current_path.find('.');
-       delimiter_position != StringPiece::npos;
-       delimiter_position = current_path.find('.')) {
-    // Assume that we're indexing into a dictionary.
-    StringPiece key = current_path.substr(0, delimiter_position);
-    Value* child_dictionary =
-        current_dictionary->FindKeyOfType(key, Type::DICTIONARY);
-    if (!child_dictionary) {
-      child_dictionary =
-          current_dictionary->SetKey(key, Value(Type::DICTIONARY));
-    }
-
-    current_dictionary = child_dictionary;
-    current_path = current_path.substr(delimiter_position + 1);
-  }
-
-  // NOTE: We can't use |insert_or_assign| here, as only |try_emplace| does
-  // an explicit conversion from StringPiece to std::string if necessary.
-  auto result = static_cast<DictionaryValue*>(current_dictionary)
-                    ->dict()
-                    .try_emplace(current_path, std::move(in_value));
-  if (!result.second) {
-    // in_value is guaranteed to be still intact at this point.
-    result.first->second = std::move(in_value);
-  }
-  return result.first->second.get();
-}
-
-Value* DictionaryValue::SetBoolean(StringPiece path, bool in_value) {
-  return Set(path, std::make_unique<Value>(in_value));
-}
-
-Value* DictionaryValue::SetString(StringPiece path, StringPiece in_value) {
-  return Set(path, std::make_unique<Value>(in_value));
-}
-
-Value* DictionaryValue::SetString(StringPiece path,
-                                  const std::u16string& in_value) {
-  return Set(path, std::make_unique<Value>(in_value));
-}
-
 bool DictionaryValue::GetDictionary(StringPiece path,
                                     const DictionaryValue** out_value) const {
   const Value* value = GetDict().FindByDottedPath(path);
diff --git a/base/values.h b/base/values.h
index 1d0effd..f7db04e 100644
--- a/base/values.h
+++ b/base/values.h
@@ -1252,36 +1252,6 @@
 
   DictionaryValue();
 
-  // Sets the Value associated with the given path starting from this object.
-  // A path has the form "<key>" or "<key>.<key>.[...]", where "." indexes
-  // into the next DictionaryValue down.  Obviously, "." can't be used
-  // within a key, but there are no other restrictions on keys.
-  // If the key at any step of the way doesn't exist, or exists but isn't
-  // a DictionaryValue, a new DictionaryValue will be created and attached
-  // to the path in that location. `in_value` must be non-null.
-  // Returns a pointer to the inserted value.
-  //
-  // DEPRECATED: prefer `Value::Dict::Set()` (if the path only has one
-  // component, i.e. has no dots), or `Value::Dict::SetByDottedPath()`
-  // otherwise.
-  Value* Set(StringPiece path, std::unique_ptr<Value> in_value);
-
-  // Convenience forms of Set().  These methods will replace any existing
-  // value at that path, even if it has a different type.
-  //
-  // DEPRECATED: prefer `Value::Dict::Set()` (if the path only has one
-  // component, i.e. has no dots), or `Value::Dict::SetByDottedPath()`
-  // otherwise.
-  Value* SetBoolean(StringPiece path, bool in_value);
-  // DEPRECATED: prefer `Value::Dict::Set()` (if the path only has one
-  // component, i.e. has no dots), or `Value::Dict::SetByDottedPath()`
-  // otherwise.
-  Value* SetString(StringPiece path, StringPiece in_value);
-  // DEPRECATED: prefer `Value::Dict::Set()` (if the path only has one
-  // component, i.e. has no dots), or `Value::Dict::SetByDottedPath()`
-  // otherwise.
-  Value* SetString(StringPiece path, const std::u16string& in_value);
-
   // These are convenience forms of `Get()`.  The value will be retrieved
   // and the return value will be true if the path is valid and the value at
   // the end of the path can be returned in the form specified.
diff --git a/base/values_unittest.cc b/base/values_unittest.cc
index 67fd6f7..468a97a 100644
--- a/base/values_unittest.cc
+++ b/base/values_unittest.cc
@@ -2126,7 +2126,6 @@
   // Just remove this test when the old API is removed.
 
   std::unique_ptr<DictionaryValue> child(new DictionaryValue);
-  DictionaryValue* original_child = child.get();
   child->SetStringKey("test", "value");
   EXPECT_EQ(1U, child->DictSize());
 
@@ -2135,16 +2134,16 @@
   EXPECT_EQ("value", *value);
 
   std::unique_ptr<DictionaryValue> base(new DictionaryValue);
-  base->Set("dict", std::move(child));
+  base->GetDict().Set("dict", std::move(child->GetDict()));
   EXPECT_EQ(1U, base->DictSize());
 
-  DictionaryValue* ptr;
-  EXPECT_TRUE(base->GetDictionary("dict", &ptr));
-  EXPECT_EQ(original_child, ptr);
+  DictionaryValue* original_child;
+  EXPECT_TRUE(base->GetDictionary("dict", &original_child));
 
   std::unique_ptr<DictionaryValue> merged(new DictionaryValue);
   merged->MergeDictionary(base.get());
   EXPECT_EQ(1U, merged->DictSize());
+  DictionaryValue* ptr;
   EXPECT_TRUE(merged->GetDictionary("dict", &ptr));
   EXPECT_NE(original_child, ptr);
   value = ptr->GetDict().FindString("test");
@@ -2360,7 +2359,7 @@
   }
   {
     DictionaryValue dict;
-    dict.SetString("hello", "world");
+    dict.SetStringKey("hello", "world");
     DictAdapterForMigration v = dict;
     EXPECT_EQ(&dict.GetDict(), &v.dict_for_test());
   }
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1
index 01d385a..fce0f79 100644
--- a/build/fuchsia/linux_internal.sdk.sha1
+++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@
-11.20230103.1.1
+11.20230103.3.1
diff --git a/cc/paint/paint_op.cc b/cc/paint/paint_op.cc
index bacfb9e..f1348698 100644
--- a/cc/paint/paint_op.cc
+++ b/cc/paint/paint_op.cc
@@ -256,14 +256,24 @@
 static const SerializeFunction g_serialize_functions[kNumOpTypes] = {TYPES(M)};
 #undef M
 
-using DeserializeFunction =
-    PaintOp* (*)(const volatile void* input,
-                 size_t input_size,
-                 void* output,
-                 size_t output_size,
-                 const PaintOp::DeserializeOptions& options);
-
-#define M(T) &T::Deserialize,
+using DeserializeFunction = PaintOp* (*)(PaintOpReader& reader,
+                                         void* output,
+                                         size_t output_size);
+template <typename T>
+PaintOp* Deserialize(PaintOpReader& reader, void* output, size_t output_size) {
+  DCHECK_GE(output_size, sizeof(T));
+  T* op = static_cast<T*>(T::Deserialize(reader, output));
+  if (!op) {
+    return nullptr;
+  }
+  if (!reader.valid() || !op->IsValid()) {
+    op->~T();
+    return nullptr;
+  }
+  op->skip = PaintOpBuffer::ComputeOpSkip(sizeof(T));
+  return op;
+}
+#define M(T) &Deserialize<T>,
 static const DeserializeFunction g_deserialize_functions[kNumOpTypes] = {
     TYPES(M)};
 #undef M
@@ -711,316 +721,149 @@
   writer.Write(dy);
 }
 
-template <typename T>
-void UpdateTypeAndSkip(T* op) {
-  op->type = static_cast<uint8_t>(T::kType);
-  op->skip = PaintOpBuffer::ComputeOpSkip(sizeof(T));
+PaintOp* AnnotateOp::Deserialize(PaintOpReader& reader, void* output) {
+  AnnotateOp* op = new (output) AnnotateOp;
+  reader.Read(&op->annotation_type);
+  reader.Read(&op->rect);
+  reader.Read(&op->data);
+  return op;
 }
 
-template <typename T>
-class PaintOpDeserializer {
- public:
-  static_assert(std::is_base_of<PaintOp, T>::value, "T not a PaintOp.");
-
-  explicit PaintOpDeserializer(const volatile void* input,
-                               size_t input_size,
-                               const PaintOp::DeserializeOptions& options,
-                               T* op)
-      : reader_(input, input_size, options), op_(op) {
-    DCHECK(op_);
-  }
-  PaintOpDeserializer(const PaintOpDeserializer&) = delete;
-  PaintOpDeserializer& operator=(const PaintOpDeserializer&) = delete;
-
-  ~PaintOpDeserializer() {
-    DCHECK(!op_)
-        << "FinalizeOp must be called before PaintOpDeserializer is destroyed. "
-           "type="
-        << T::kType;
-  }
-
-  PaintOp* FinalizeOp(bool force_invalid = false) {
-    DCHECK(op_) << "PaintOp has already been finalized. type=" << T::kType;
-
-    if (force_invalid || !reader_.valid() || !op_->IsValid()) {
-      op_->~T();
-      op_ = nullptr;
-      return nullptr;
-    }
-
-    UpdateTypeAndSkip(op_.get());
-    T* op_snapshot = op_;
-    op_ = nullptr;
-    return op_snapshot;
-  }
-
-  PaintOp* InvalidateAndFinalizeOp() {
-    return FinalizeOp(/*force_invalid=*/true);
-  }
-
-  T* operator->() { return op_; }
-
-  template <typename... Args>
-  void Read(Args&&... args) {
-    reader_.Read(std::forward<Args>(args)...);
-  }
-
-  void ReadData(size_t bytes, void* data) { reader_.ReadData(bytes, data); }
-
-  void ReadSize(size_t* size) { reader_.ReadSize(size); }
-
-  void AssertAlignment(size_t alignment) { reader_.AssertAlignment(alignment); }
-
- private:
-  PaintOpReader reader_;
-  raw_ptr<T> op_;
-};
-
-PaintOp* AnnotateOp::Deserialize(const volatile void* input,
-                                 size_t input_size,
-                                 void* output,
-                                 size_t output_size,
-                                 const DeserializeOptions& options) {
-  DCHECK_GE(output_size, sizeof(AnnotateOp));
-  PaintOpDeserializer<AnnotateOp> deserializer(input, input_size, options,
-                                               new (output) AnnotateOp);
-
-  deserializer.Read(&deserializer->annotation_type);
-  deserializer.Read(&deserializer->rect);
-  deserializer.Read(&deserializer->data);
-  return deserializer.FinalizeOp();
+PaintOp* ClipPathOp::Deserialize(PaintOpReader& reader, void* output) {
+  ClipPathOp* op = new (output) ClipPathOp;
+  reader.Read(&op->path);
+  reader.Read(&op->op);
+  reader.Read(&op->antialias);
+  return op;
 }
 
-PaintOp* ClipPathOp::Deserialize(const volatile void* input,
-                                 size_t input_size,
-                                 void* output,
-                                 size_t output_size,
-                                 const DeserializeOptions& options) {
-  DCHECK_GE(output_size, sizeof(ClipPathOp));
-  PaintOpDeserializer<ClipPathOp> deserializer(input, input_size, options,
-                                               new (output) ClipPathOp);
-
-  deserializer.Read(&deserializer->path);
-  deserializer.Read(&deserializer->op);
-  deserializer.Read(&deserializer->antialias);
-  return deserializer.FinalizeOp();
+PaintOp* ClipRectOp::Deserialize(PaintOpReader& reader, void* output) {
+  ClipRectOp* op = new (output) ClipRectOp;
+  reader.Read(&op->rect);
+  reader.Read(&op->op);
+  reader.Read(&op->antialias);
+  return op;
 }
 
-PaintOp* ClipRectOp::Deserialize(const volatile void* input,
-                                 size_t input_size,
-                                 void* output,
-                                 size_t output_size,
-                                 const DeserializeOptions& options) {
-  DCHECK_GE(output_size, sizeof(ClipRectOp));
-  PaintOpDeserializer<ClipRectOp> deserializer(input, input_size, options,
-                                               new (output) ClipRectOp);
-  deserializer.Read(&deserializer->rect);
-  deserializer.Read(&deserializer->op);
-  deserializer.Read(&deserializer->antialias);
-  return deserializer.FinalizeOp();
+PaintOp* ClipRRectOp::Deserialize(PaintOpReader& reader, void* output) {
+  ClipRRectOp* op = new (output) ClipRRectOp;
+  reader.Read(&op->rrect);
+  reader.Read(&op->op);
+  reader.Read(&op->antialias);
+  return op;
 }
 
-PaintOp* ClipRRectOp::Deserialize(const volatile void* input,
-                                  size_t input_size,
-                                  void* output,
-                                  size_t output_size,
-                                  const DeserializeOptions& options) {
-  DCHECK_GE(output_size, sizeof(ClipRRectOp));
-  PaintOpDeserializer<ClipRRectOp> deserializer(input, input_size, options,
-                                                new (output) ClipRRectOp);
-  deserializer.Read(&deserializer->rrect);
-  deserializer.Read(&deserializer->op);
-  deserializer.Read(&deserializer->antialias);
-  return deserializer.FinalizeOp();
+PaintOp* ConcatOp::Deserialize(PaintOpReader& reader, void* output) {
+  ConcatOp* op = new (output) ConcatOp;
+  reader.Read(&op->matrix);
+  return op;
 }
 
-PaintOp* ConcatOp::Deserialize(const volatile void* input,
-                               size_t input_size,
-                               void* output,
-                               size_t output_size,
-                               const DeserializeOptions& options) {
-  DCHECK_GE(output_size, sizeof(ConcatOp));
-  PaintOpDeserializer<ConcatOp> deserializer(input, input_size, options,
-                                             new (output) ConcatOp);
-  deserializer.Read(&deserializer->matrix);
-  return deserializer.FinalizeOp();
+PaintOp* CustomDataOp::Deserialize(PaintOpReader& reader, void* output) {
+  CustomDataOp* op = new (output) CustomDataOp;
+  reader.Read(&op->id);
+  return op;
 }
 
-PaintOp* CustomDataOp::Deserialize(const volatile void* input,
-                                   size_t input_size,
-                                   void* output,
-                                   size_t output_size,
-                                   const DeserializeOptions& options) {
-  DCHECK_GE(output_size, sizeof(CustomDataOp));
-  PaintOpDeserializer<CustomDataOp> deserializer(input, input_size, options,
-                                                 new (output) CustomDataOp);
-  deserializer.Read(&deserializer->id);
-  return deserializer.FinalizeOp();
+PaintOp* DrawColorOp::Deserialize(PaintOpReader& reader, void* output) {
+  DrawColorOp* op = new (output) DrawColorOp;
+  reader.Read(&op->color);
+  reader.Read(&op->mode);
+  return op;
 }
 
-PaintOp* DrawColorOp::Deserialize(const volatile void* input,
-                                  size_t input_size,
-                                  void* output,
-                                  size_t output_size,
-                                  const DeserializeOptions& options) {
-  DCHECK_GE(output_size, sizeof(DrawColorOp));
-  PaintOpDeserializer<DrawColorOp> deserializer(input, input_size, options,
-                                                new (output) DrawColorOp);
-  deserializer.Read(&deserializer->color);
-  deserializer.Read(&deserializer->mode);
-  return deserializer.FinalizeOp();
+PaintOp* DrawDRRectOp::Deserialize(PaintOpReader& reader, void* output) {
+  DrawDRRectOp* op = new (output) DrawDRRectOp;
+  reader.Read(&op->flags);
+  reader.Read(&op->outer);
+  reader.Read(&op->inner);
+  return op;
 }
 
-PaintOp* DrawDRRectOp::Deserialize(const volatile void* input,
-                                   size_t input_size,
-                                   void* output,
-                                   size_t output_size,
-                                   const DeserializeOptions& options) {
-  DCHECK_GE(output_size, sizeof(DrawDRRectOp));
-  PaintOpDeserializer<DrawDRRectOp> deserializer(input, input_size, options,
-                                                 new (output) DrawDRRectOp);
-  deserializer.Read(&deserializer->flags);
-  deserializer.Read(&deserializer->outer);
-  deserializer.Read(&deserializer->inner);
-  return deserializer.FinalizeOp();
+PaintOp* DrawImageOp::Deserialize(PaintOpReader& reader, void* output) {
+  DrawImageOp* op = new (output) DrawImageOp;
+  reader.Read(&op->flags);
+
+  reader.Read(&op->image);
+  reader.AssertAlignment(alignof(SkScalar));
+  reader.Read(&op->scale_adjustment.fWidth);
+  reader.Read(&op->scale_adjustment.fHeight);
+
+  reader.Read(&op->left);
+  reader.Read(&op->top);
+  reader.Read(&op->sampling);
+
+  return op;
 }
 
-PaintOp* DrawImageOp::Deserialize(const volatile void* input,
-                                  size_t input_size,
-                                  void* output,
-                                  size_t output_size,
-                                  const DeserializeOptions& options) {
-  DCHECK_GE(output_size, sizeof(DrawImageOp));
-  PaintOpDeserializer<DrawImageOp> deserializer(input, input_size, options,
-                                                new (output) DrawImageOp);
-  deserializer.Read(&deserializer->flags);
+PaintOp* DrawImageRectOp::Deserialize(PaintOpReader& reader, void* output) {
+  DrawImageRectOp* op = new (output) DrawImageRectOp;
+  reader.Read(&op->flags);
 
-  deserializer.Read(&deserializer->image);
-  deserializer.AssertAlignment(alignof(SkScalar));
-  deserializer.Read(&deserializer->scale_adjustment.fWidth);
-  deserializer.Read(&deserializer->scale_adjustment.fHeight);
+  reader.Read(&op->image);
+  reader.AssertAlignment(alignof(SkScalar));
+  reader.Read(&op->scale_adjustment.fWidth);
+  reader.Read(&op->scale_adjustment.fHeight);
 
-  deserializer.Read(&deserializer->left);
-  deserializer.Read(&deserializer->top);
-  deserializer.Read(&deserializer->sampling);
-  return deserializer.FinalizeOp();
+  reader.Read(&op->src);
+  reader.Read(&op->dst);
+  reader.Read(&op->sampling);
+  reader.Read(&op->constraint);
+
+  return op;
 }
 
-PaintOp* DrawImageRectOp::Deserialize(const volatile void* input,
-                                      size_t input_size,
-                                      void* output,
-                                      size_t output_size,
-                                      const DeserializeOptions& options) {
-  DCHECK_GE(output_size, sizeof(DrawImageRectOp));
-  PaintOpDeserializer<DrawImageRectOp> deserializer(
-      input, input_size, options, new (output) DrawImageRectOp);
-  deserializer.Read(&deserializer->flags);
-
-  deserializer.Read(&deserializer->image);
-  deserializer.AssertAlignment(alignof(SkScalar));
-  deserializer.Read(&deserializer->scale_adjustment.fWidth);
-  deserializer.Read(&deserializer->scale_adjustment.fHeight);
-
-  deserializer.Read(&deserializer->src);
-  deserializer.Read(&deserializer->dst);
-  deserializer.Read(&deserializer->sampling);
-  deserializer.Read(&deserializer->constraint);
-  return deserializer.FinalizeOp();
+PaintOp* DrawIRectOp::Deserialize(PaintOpReader& reader, void* output) {
+  DrawIRectOp* op = new (output) DrawIRectOp;
+  reader.Read(&op->flags);
+  reader.Read(&op->rect);
+  return op;
 }
 
-PaintOp* DrawIRectOp::Deserialize(const volatile void* input,
-                                  size_t input_size,
-                                  void* output,
-                                  size_t output_size,
-                                  const DeserializeOptions& options) {
-  DCHECK_GE(output_size, sizeof(DrawIRectOp));
-  PaintOpDeserializer<DrawIRectOp> deserializer(input, input_size, options,
-                                                new (output) DrawIRectOp);
-  deserializer.Read(&deserializer->flags);
-  deserializer.Read(&deserializer->rect);
-  return deserializer.FinalizeOp();
+PaintOp* DrawLineOp::Deserialize(PaintOpReader& reader, void* output) {
+  DrawLineOp* op = new (output) DrawLineOp;
+  reader.Read(&op->flags);
+  reader.AssertAlignment(alignof(SkScalar));
+  reader.Read(&op->x0);
+  reader.Read(&op->y0);
+  reader.Read(&op->x1);
+  reader.Read(&op->y1);
+  return op;
 }
 
-PaintOp* DrawLineOp::Deserialize(const volatile void* input,
-                                 size_t input_size,
-                                 void* output,
-                                 size_t output_size,
-                                 const DeserializeOptions& options) {
-  DCHECK_GE(output_size, sizeof(DrawLineOp));
-  PaintOpDeserializer<DrawLineOp> deserializer(input, input_size, options,
-                                               new (output) DrawLineOp);
-  deserializer.Read(&deserializer->flags);
-  deserializer.AssertAlignment(alignof(SkScalar));
-  deserializer.Read(&deserializer->x0);
-  deserializer.Read(&deserializer->y0);
-  deserializer.Read(&deserializer->x1);
-  deserializer.Read(&deserializer->y1);
-  return deserializer.FinalizeOp();
+PaintOp* DrawOvalOp::Deserialize(PaintOpReader& reader, void* output) {
+  DrawOvalOp* op = new (output) DrawOvalOp;
+  reader.Read(&op->flags);
+  reader.Read(&op->oval);
+  return op;
 }
 
-PaintOp* DrawOvalOp::Deserialize(const volatile void* input,
-                                 size_t input_size,
-                                 void* output,
-                                 size_t output_size,
-                                 const DeserializeOptions& options) {
-  DCHECK_GE(output_size, sizeof(DrawOvalOp));
-  PaintOpDeserializer<DrawOvalOp> deserializer(input, input_size, options,
-                                               new (output) DrawOvalOp);
-  deserializer.Read(&deserializer->flags);
-  deserializer.Read(&deserializer->oval);
-  return deserializer.FinalizeOp();
+PaintOp* DrawPathOp::Deserialize(PaintOpReader& reader, void* output) {
+  DrawPathOp* op = new (output) DrawPathOp;
+  reader.Read(&op->flags);
+  reader.Read(&op->path);
+  reader.Read(&op->sk_path_fill_type);
+  op->path.setFillType(static_cast<SkPathFillType>(op->sk_path_fill_type));
+  return op;
 }
 
-PaintOp* DrawPathOp::Deserialize(const volatile void* input,
-                                 size_t input_size,
-                                 void* output,
-                                 size_t output_size,
-                                 const DeserializeOptions& options) {
-  DCHECK_GE(output_size, sizeof(DrawPathOp));
-  PaintOpDeserializer<DrawPathOp> deserializer(input, input_size, options,
-                                               new (output) DrawPathOp);
-  deserializer.Read(&deserializer->flags);
-  deserializer.Read(&deserializer->path);
-  deserializer.Read(&deserializer->sk_path_fill_type);
-  deserializer->path.setFillType(
-      static_cast<SkPathFillType>(deserializer->sk_path_fill_type));
-  return deserializer.FinalizeOp();
-}
-
-PaintOp* DrawRecordOp::Deserialize(const volatile void* input,
-                                   size_t input_size,
-                                   void* output,
-                                   size_t output_size,
-                                   const DeserializeOptions& options) {
-  // TODO(enne): these must be flattened and not sent directly.
-  // TODO(enne): could also consider caching these service side.
+PaintOp* DrawRecordOp::Deserialize(PaintOpReader& reader, void* output) {
+  // These are flattened during serialization.
   return nullptr;
 }
 
-PaintOp* DrawRectOp::Deserialize(const volatile void* input,
-                                 size_t input_size,
-                                 void* output,
-                                 size_t output_size,
-                                 const DeserializeOptions& options) {
-  DCHECK_GE(output_size, sizeof(DrawRectOp));
-  PaintOpDeserializer<DrawRectOp> deserializer(input, input_size, options,
-                                               new (output) DrawRectOp);
-  deserializer.Read(&deserializer->flags);
-  deserializer.Read(&deserializer->rect);
-  return deserializer.FinalizeOp();
+PaintOp* DrawRectOp::Deserialize(PaintOpReader& reader, void* output) {
+  DrawRectOp* op = new (output) DrawRectOp;
+  reader.Read(&op->flags);
+  reader.Read(&op->rect);
+  return op;
 }
 
-PaintOp* DrawRRectOp::Deserialize(const volatile void* input,
-                                  size_t input_size,
-                                  void* output,
-                                  size_t output_size,
-                                  const DeserializeOptions& options) {
-  DCHECK_GE(output_size, sizeof(DrawRRectOp));
-  PaintOpDeserializer<DrawRRectOp> deserializer(input, input_size, options,
-                                                new (output) DrawRRectOp);
-  deserializer.Read(&deserializer->flags);
-  deserializer.Read(&deserializer->rrect);
-  return deserializer.FinalizeOp();
+PaintOp* DrawRRectOp::Deserialize(PaintOpReader& reader, void* output) {
+  DrawRRectOp* op = new (output) DrawRRectOp;
+  reader.Read(&op->flags);
+  reader.Read(&op->rrect);
+  return op;
 }
 
 namespace {
@@ -1032,240 +875,159 @@
 bool DeserializeSkottieMap(
     base::flat_map<SkottieResourceIdHash, T>& map,
     absl::optional<size_t> max_map_size,
-    PaintOpDeserializer<DrawSkottieOp>& deserializer,
-    const base::RepeatingCallback<absl::optional<T>(
-        PaintOpDeserializer<DrawSkottieOp>&)>& value_deserializer) {
+    PaintOpReader& reader,
+    base::FunctionRef<T(PaintOpReader& reader)> value_deserializer) {
   size_t map_size = 0;
-  deserializer.ReadSize(&map_size);
+  reader.ReadSize(&map_size);
   if (max_map_size && map_size > *max_map_size)
     return false;
 
   for (size_t i = 0; i < map_size; ++i) {
     size_t resource_id_hash_raw = 0;
-    deserializer.ReadSize(&resource_id_hash_raw);
+    reader.ReadSize(&resource_id_hash_raw);
     SkottieResourceIdHash resource_id_hash =
         SkottieResourceIdHash::FromUnsafeValue(resource_id_hash_raw);
     if (!resource_id_hash)
       return false;
 
-    absl::optional<T> value = value_deserializer.Run(deserializer);
-    if (!value)
-      return false;
-
+    T value = value_deserializer(reader);
     // Duplicate keys should not happen by design, but defend against it
     // gracefully in case the underlying buffer is corrupted.
-    bool is_new_entry = map.emplace(resource_id_hash, std::move(*value)).second;
+    bool is_new_entry = map.emplace(resource_id_hash, std::move(value)).second;
     if (!is_new_entry)
       return false;
   }
   return true;
 }
 
-absl::optional<SkottieFrameData> DeserializeSkottieFrameData(
-    PaintOpDeserializer<DrawSkottieOp>& deserializer) {
+SkottieFrameData DeserializeSkottieFrameData(PaintOpReader& reader) {
   SkottieFrameData frame_data;
-  deserializer.Read(&frame_data.image);
-  deserializer.Read(&frame_data.quality);
+  reader.Read(&frame_data.image);
+  reader.Read(&frame_data.quality);
   return frame_data;
 }
 
-absl::optional<SkColor> DeserializeSkottieColor(
-    PaintOpDeserializer<DrawSkottieOp>& deserializer) {
+SkColor DeserializeSkottieColor(PaintOpReader& reader) {
   SkColor color = SK_ColorTRANSPARENT;
-  deserializer.Read(&color);
+  reader.Read(&color);
   return color;
 }
 
-absl::optional<SkottieTextPropertyValue> DeserializeSkottieTextPropertyValue(
-    PaintOpDeserializer<DrawSkottieOp>& deserializer) {
+SkottieTextPropertyValue DeserializeSkottieTextPropertyValue(
+    PaintOpReader& reader) {
   size_t text_size = 0u;
-  deserializer.ReadSize(&text_size);
+  reader.ReadSize(&text_size);
   std::string text(text_size, char());
-  deserializer.ReadData(text_size, const_cast<char*>(text.c_str()));
+  reader.ReadData(text_size, const_cast<char*>(text.c_str()));
   SkRect box;
-  deserializer.Read(&box);
+  reader.Read(&box);
   return SkottieTextPropertyValue(std::move(text), gfx::SkRectToRectF(box));
 }
 
 }  // namespace
 
-PaintOp* DrawSkottieOp::Deserialize(const volatile void* input,
-                                    size_t input_size,
-                                    void* output,
-                                    size_t output_size,
-                                    const DeserializeOptions& options) {
-  DCHECK_GE(output_size, sizeof(DrawSkottieOp));
-  PaintOpDeserializer<DrawSkottieOp> deserializer(input, input_size, options,
-                                                  new (output) DrawSkottieOp);
-  deserializer.Read(&deserializer->dst);
+PaintOp* DrawSkottieOp::Deserialize(PaintOpReader& reader, void* output) {
+  DrawSkottieOp* op = new (output) DrawSkottieOp;
+  reader.Read(&op->dst);
+  reader.Read(&op->t);
 
-  SkScalar t;
-  deserializer.Read(&t);
-  deserializer->t = SkScalarToFloat(t);
-
-  deserializer.Read(&deserializer->skottie);
+  reader.Read(&op->skottie);
   // The |skottie| object gets used below, so no point in continuing if it's
   // invalid. That can lead to crashing or unexpected behavior.
-  if (!deserializer->skottie || !deserializer->skottie->is_valid())
-    return deserializer.InvalidateAndFinalizeOp();
+  if (!op->skottie || !op->skottie->is_valid()) {
+    DCHECK(!op->IsValid());
+    return op;
+  }
 
   size_t num_assets_in_animation =
-      deserializer->skottie->GetImageAssetMetadata().asset_storage().size();
-  size_t num_text_nodes_in_animation =
-      deserializer->skottie->GetTextNodeNames().size();
+      op->skottie->GetImageAssetMetadata().asset_storage().size();
+  size_t num_text_nodes_in_animation = op->skottie->GetTextNodeNames().size();
   bool deserialized_all_maps =
-      DeserializeSkottieMap(
-          deserializer->images, /*max_map_size=*/num_assets_in_animation,
-          deserializer, base::BindRepeating(&DeserializeSkottieFrameData)) &&
-      DeserializeSkottieMap(deserializer->color_map,
-                            /*max_map_size=*/absl::nullopt, deserializer,
-                            base::BindRepeating(&DeserializeSkottieColor)) &&
-      DeserializeSkottieMap(
-          deserializer->text_map, /*max_map_size=*/num_text_nodes_in_animation,
-          deserializer,
-          base::BindRepeating(&DeserializeSkottieTextPropertyValue));
-  return deserialized_all_maps ? deserializer.FinalizeOp()
-                               : deserializer.InvalidateAndFinalizeOp();
-}
-
-PaintOp* DrawTextBlobOp::Deserialize(const volatile void* input,
-                                     size_t input_size,
-                                     void* output,
-                                     size_t output_size,
-                                     const DeserializeOptions& options) {
-  DCHECK_GE(output_size, sizeof(DrawTextBlobOp));
-  PaintOpDeserializer<DrawTextBlobOp> deserializer(input, input_size, options,
-                                                   new (output) DrawTextBlobOp);
-  deserializer.Read(&deserializer->flags);
-  unsigned int count = 0;
-  deserializer.Read(&count);
-  deserializer.Read(&deserializer->slug);
-  deserializer->extra_slugs.resize(count - 1);
-  for (auto& slug : deserializer->extra_slugs) {
-    deserializer.Read(&slug);
+      DeserializeSkottieMap<SkottieFrameData>(
+          op->images, /*max_map_size=*/num_assets_in_animation, reader,
+          DeserializeSkottieFrameData) &&
+      DeserializeSkottieMap<SkColor>(op->color_map,
+                                     /*max_map_size=*/absl::nullopt, reader,
+                                     DeserializeSkottieColor) &&
+      DeserializeSkottieMap<SkottieTextPropertyValue>(
+          op->text_map, /*max_map_size=*/num_text_nodes_in_animation, reader,
+          DeserializeSkottieTextPropertyValue);
+  if (!deserialized_all_maps) {
+    op->skottie = nullptr;
+    DCHECK(!op->IsValid());
   }
-  return deserializer.FinalizeOp();
+  return op;
 }
 
-PaintOp* NoopOp::Deserialize(const volatile void* input,
-                             size_t input_size,
-                             void* output,
-                             size_t output_size,
-                             const DeserializeOptions& options) {
-  DCHECK_GE(output_size, sizeof(NoopOp));
-  PaintOpDeserializer<NoopOp> deserializer(input, input_size, options,
-                                           new (output) NoopOp);
-  return deserializer.FinalizeOp();
+PaintOp* DrawTextBlobOp::Deserialize(PaintOpReader& reader, void* output) {
+  DrawTextBlobOp* op = new (output) DrawTextBlobOp;
+  reader.Read(&op->flags);
+  unsigned int count = 0;
+  reader.Read(&count);
+  reader.Read(&op->slug);
+  op->extra_slugs.resize(count - 1);
+  for (auto& extra_slug : op->extra_slugs) {
+    reader.Read(&extra_slug);
+  }
+  return op;
 }
 
-PaintOp* RestoreOp::Deserialize(const volatile void* input,
-                                size_t input_size,
-                                void* output,
-                                size_t output_size,
-                                const DeserializeOptions& options) {
-  DCHECK_GE(output_size, sizeof(RestoreOp));
-  PaintOpDeserializer<RestoreOp> deserializer(input, input_size, options,
-                                              new (output) RestoreOp);
-  return deserializer.FinalizeOp();
+PaintOp* NoopOp::Deserialize(PaintOpReader& reader, void* output) {
+  return new (output) NoopOp;
 }
 
-PaintOp* RotateOp::Deserialize(const volatile void* input,
-                               size_t input_size,
-                               void* output,
-                               size_t output_size,
-                               const DeserializeOptions& options) {
-  DCHECK_GE(output_size, sizeof(RotateOp));
-  PaintOpDeserializer<RotateOp> deserializer(input, input_size, options,
-                                             new (output) RotateOp);
-  deserializer.Read(&deserializer->degrees);
-  return deserializer.FinalizeOp();
+PaintOp* RestoreOp::Deserialize(PaintOpReader& reader, void* output) {
+  return new (output) RestoreOp;
 }
 
-PaintOp* SaveOp::Deserialize(const volatile void* input,
-                             size_t input_size,
-                             void* output,
-                             size_t output_size,
-                             const DeserializeOptions& options) {
-  DCHECK_GE(output_size, sizeof(SaveOp));
-  PaintOpDeserializer<SaveOp> deserializer(input, input_size, options,
-                                           new (output) SaveOp);
-  return deserializer.FinalizeOp();
+PaintOp* RotateOp::Deserialize(PaintOpReader& reader, void* output) {
+  RotateOp* op = new (output) RotateOp;
+  reader.Read(&op->degrees);
+  return op;
 }
 
-PaintOp* SaveLayerOp::Deserialize(const volatile void* input,
-                                  size_t input_size,
-                                  void* output,
-                                  size_t output_size,
-                                  const DeserializeOptions& options) {
-  DCHECK_GE(output_size, sizeof(SaveLayerOp));
-  PaintOpDeserializer<SaveLayerOp> deserializer(input, input_size, options,
-                                                new (output) SaveLayerOp);
-  deserializer.Read(&deserializer->flags);
-  deserializer.Read(&deserializer->bounds);
-  return deserializer.FinalizeOp();
+PaintOp* SaveOp::Deserialize(PaintOpReader& reader, void* output) {
+  return new (output) SaveOp;
 }
 
-PaintOp* SaveLayerAlphaOp::Deserialize(const volatile void* input,
-                                       size_t input_size,
-                                       void* output,
-                                       size_t output_size,
-                                       const DeserializeOptions& options) {
-  DCHECK_GE(output_size, sizeof(SaveLayerAlphaOp));
-  PaintOpDeserializer<SaveLayerAlphaOp> deserializer(
-      input, input_size, options, new (output) SaveLayerAlphaOp);
-  deserializer.Read(&deserializer->bounds);
-  deserializer.Read(&deserializer->alpha);
-  return deserializer.FinalizeOp();
+PaintOp* SaveLayerOp::Deserialize(PaintOpReader& reader, void* output) {
+  SaveLayerOp* op = new (output) SaveLayerOp;
+  reader.Read(&op->flags);
+  reader.Read(&op->bounds);
+  return op;
 }
 
-PaintOp* ScaleOp::Deserialize(const volatile void* input,
-                              size_t input_size,
-                              void* output,
-                              size_t output_size,
-                              const DeserializeOptions& options) {
-  DCHECK_GE(output_size, sizeof(ScaleOp));
-  PaintOpDeserializer<ScaleOp> deserializer(input, input_size, options,
-                                            new (output) ScaleOp);
-  deserializer.Read(&deserializer->sx);
-  deserializer.Read(&deserializer->sy);
-  return deserializer.FinalizeOp();
+PaintOp* SaveLayerAlphaOp::Deserialize(PaintOpReader& reader, void* output) {
+  SaveLayerAlphaOp* op = new (output) SaveLayerAlphaOp;
+  reader.Read(&op->bounds);
+  reader.Read(&op->alpha);
+  return op;
 }
 
-PaintOp* SetMatrixOp::Deserialize(const volatile void* input,
-                                  size_t input_size,
-                                  void* output,
-                                  size_t output_size,
-                                  const DeserializeOptions& options) {
-  DCHECK_GE(output_size, sizeof(SetMatrixOp));
-  PaintOpDeserializer<SetMatrixOp> deserializer(input, input_size, options,
-                                                new (output) SetMatrixOp);
-  deserializer.Read(&deserializer->matrix);
-  return deserializer.FinalizeOp();
+PaintOp* ScaleOp::Deserialize(PaintOpReader& reader, void* output) {
+  ScaleOp* op = new (output) ScaleOp;
+  reader.Read(&op->sx);
+  reader.Read(&op->sy);
+  return op;
 }
 
-PaintOp* SetNodeIdOp::Deserialize(const volatile void* input,
-                                  size_t input_size,
-                                  void* output,
-                                  size_t output_size,
-                                  const DeserializeOptions& options) {
-  DCHECK_GE(output_size, sizeof(SetNodeIdOp));
-  PaintOpDeserializer<SetNodeIdOp> deserializer(input, input_size, options,
-                                                new (output) SetNodeIdOp);
-  deserializer.Read(&deserializer->node_id);
-  return deserializer.FinalizeOp();
+PaintOp* SetMatrixOp::Deserialize(PaintOpReader& reader, void* output) {
+  SetMatrixOp* op = new (output) SetMatrixOp;
+  reader.Read(&op->matrix);
+  return op;
 }
 
-PaintOp* TranslateOp::Deserialize(const volatile void* input,
-                                  size_t input_size,
-                                  void* output,
-                                  size_t output_size,
-                                  const DeserializeOptions& options) {
-  DCHECK_GE(output_size, sizeof(TranslateOp));
-  PaintOpDeserializer<TranslateOp> deserializer(input, input_size, options,
-                                                new (output) TranslateOp);
-  deserializer.Read(&deserializer->dx);
-  deserializer.Read(&deserializer->dy);
-  return deserializer.FinalizeOp();
+PaintOp* SetNodeIdOp::Deserialize(PaintOpReader& reader, void* output) {
+  SetNodeIdOp* op = new (output) SetNodeIdOp;
+  reader.Read(&op->node_id);
+  return op;
+}
+
+PaintOp* TranslateOp::Deserialize(PaintOpReader& reader, void* output) {
+  TranslateOp* op = new (output) TranslateOp;
+  reader.Read(&op->dx);
+  reader.Read(&op->dy);
+  return op;
 }
 
 void AnnotateOp::Raster(const AnnotateOp* op,
@@ -2239,12 +2001,14 @@
 
   uint8_t type;
   uint32_t skip;
-  if (!PaintOpReader::ReadAndValidateOpHeader(input, input_size, &type, &skip))
+  if (!PaintOpReader::ReadAndValidateOpHeader(input, input_size, &type,
+                                              &skip)) {
     return nullptr;
+  }
 
+  PaintOpReader reader(input, skip, options);
   *read_bytes = skip;
-  return g_deserialize_functions[type](input, skip, output, output_size,
-                                       options);
+  return g_deserialize_functions[type](reader, output, output_size);
 }
 
 PaintOp* PaintOp::DeserializeIntoPaintOpBuffer(
@@ -2260,9 +2024,10 @@
     return nullptr;
   }
 
+  PaintOpReader reader(input, skip, options);
   size_t op_skip = PaintOpBuffer::ComputeOpSkip(g_type_to_size[type]);
   if (auto* op = g_deserialize_functions[type](
-          input, skip, buffer->AllocatePaintOp(op_skip), op_skip, options)) {
+          reader, buffer->AllocatePaintOp(op_skip), op_skip)) {
     g_analyze_op_functions[type](buffer, op);
     *read_bytes = skip;
     return op;
diff --git a/cc/paint/paint_op.h b/cc/paint/paint_op.h
index 5c8a3d0..1f3da8c 100644
--- a/cc/paint/paint_op.h
+++ b/cc/paint/paint_op.h
@@ -48,6 +48,7 @@
 namespace cc {
 
 class PaintOpWriter;
+class PaintOpReader;
 
 class CC_PAINT_EXPORT ThreadsafePath : public SkPath {
  public:
@@ -63,9 +64,7 @@
 #define HAS_SERIALIZATION_FUNCTIONS()                                         \
   void Serialize(PaintOpWriter& writer, const PaintFlags* flags_to_serialize, \
                  const SkM44& current_ctm, const SkM44& original_ctm) const;  \
-  static PaintOp* Deserialize(const volatile void* input, size_t input_size,  \
-                              void* output, size_t output_size,               \
-                              const DeserializeOptions& options)
+  static PaintOp* Deserialize(PaintOpReader& reader, void* output)
 
 enum class PaintOpType : uint8_t {
   Annotate,
@@ -775,7 +774,8 @@
                      SkCanvas* canvas,
                      const PlaybackParams& params);
   bool IsValid() const {
-    return !!skottie && !dst.isEmpty() && t >= 0 && t <= 1.f;
+    return skottie && skottie->is_valid() && !dst.isEmpty() && t >= 0 &&
+           t <= 1.f;
   }
   static bool AreEqual(const PaintOp* left, const PaintOp* right);
   bool HasDiscardableImages() const;
diff --git a/cc/paint/paint_op_buffer_unittest.cc b/cc/paint/paint_op_buffer_unittest.cc
index eedcd65..d514e46 100644
--- a/cc/paint/paint_op_buffer_unittest.cc
+++ b/cc/paint/paint_op_buffer_unittest.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 #include <string>
 
+#include "build/build_config.h"
 #include "base/bind.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/scoped_refptr.h"
@@ -2390,7 +2391,13 @@
 // Test that deserializing invalid paint ops fails silently. Skia release
 // asserts on invalid values in several places so these are not safe to pass
 // them to the SkCanvas API.
-TEST(PaintOpBufferTest, ValidateRects) {
+// TODO(crbug.com/1404840): Crashes on MSAN.
+#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER)
+#define MAYBE_ValidateRects DISABLED_ValidateRects
+#else
+#define MAYBE_ValidateRects ValidateRects
+#endif
+TEST(PaintOpBufferTest, MAYBE_ValidateRects) {
   size_t buffer_size = kBufferBytesPerOp;
   auto serialized = AllocateBuffer(buffer_size);
   auto deserialized = AllocateBuffer(buffer_size);
diff --git a/chrome/VERSION b/chrome/VERSION
index adea670..94765e5b 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=111
 MINOR=0
-BUILD=5518
+BUILD=5519
 PATCH=0
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index 685ce36..e0968663 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -4936,6 +4936,21 @@
   <message name="IDS_BRUSCHETTA_NAME" desc="Bruschetta" translateable="false">
     Bruschetta
   </message>
+  <message name="IDS_BRUSCHETTA_INSTALLER_INSTALL_BUTTON" desc="Label for the button in the Bruschetta (codename) installer dialog to begin installing.">
+    Install
+  </message>
+  <message name="IDS_BRUSCHETTA_INSTALLER_CONFIRMATION_TITLE" desc="Title for the installer for Bruschetta (codename_).">
+    Welcome
+  </message>
+    <message name="IDS_BRUSCHETTA_INSTALLER_ONGOING_TITLE" desc="Title for the installer while Bruschetta (codename) is installing.">
+    Installing
+  </message>
+  <message name="IDS_BRUSCHETTA_INSTALLER_ERROR_TITLE" desc="Title for the installer when Bruschetta (codename) fails to install.">
+    Sorry, an error occurred
+  </message>
+  <message name="IDS_BRUSCHETTA_INSTALLER_ERROR_MESSAGE" desc="More detailed message for the installer when Bruschetta (codename, do not translate) fails to install.">
+    Sorry, something went wrong. Please file feedback with #bruschetta in the description. Error code is <ph name="ERROR">$1<ex>UNKNOWN_ERROR</ex></ph>
+  </message>
 
   <!-- Time limit notification -->
   <message name="IDS_SCREEN_TIME_NOTIFICATION_TITLE" desc="The title of the notification when screen usage limit reaches before locking the device.">
diff --git a/chrome/app/chromeos_strings_grdp/IDS_BRUSCHETTA_INSTALLER_CONFIRMATION_TITLE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_BRUSCHETTA_INSTALLER_CONFIRMATION_TITLE.png.sha1
new file mode 100644
index 0000000..ad186007
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_BRUSCHETTA_INSTALLER_CONFIRMATION_TITLE.png.sha1
@@ -0,0 +1 @@
+ffe9230b779bf379fce2b382372e84fd803877fb
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_BRUSCHETTA_INSTALLER_ERROR_MESSAGE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_BRUSCHETTA_INSTALLER_ERROR_MESSAGE.png.sha1
new file mode 100644
index 0000000..8c4296a
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_BRUSCHETTA_INSTALLER_ERROR_MESSAGE.png.sha1
@@ -0,0 +1 @@
+c96dba2e750df3f38448beb5bc084848c5ad08c7
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_BRUSCHETTA_INSTALLER_ERROR_TITLE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_BRUSCHETTA_INSTALLER_ERROR_TITLE.png.sha1
new file mode 100644
index 0000000..8c4296a
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_BRUSCHETTA_INSTALLER_ERROR_TITLE.png.sha1
@@ -0,0 +1 @@
+c96dba2e750df3f38448beb5bc084848c5ad08c7
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_BRUSCHETTA_INSTALLER_INSTALL_BUTTON.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_BRUSCHETTA_INSTALLER_INSTALL_BUTTON.png.sha1
new file mode 100644
index 0000000..ad186007
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_BRUSCHETTA_INSTALLER_INSTALL_BUTTON.png.sha1
@@ -0,0 +1 @@
+ffe9230b779bf379fce2b382372e84fd803877fb
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_BRUSCHETTA_INSTALLER_ONGOING_TITLE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_BRUSCHETTA_INSTALLER_ONGOING_TITLE.png.sha1
new file mode 100644
index 0000000..251d017
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_BRUSCHETTA_INSTALLER_ONGOING_TITLE.png.sha1
@@ -0,0 +1 @@
+ec62bf143f7a560bcca741383d6c23ba43a85b96
\ No newline at end of file
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 62cd662..a502a72a 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -7283,9 +7283,6 @@
       </message>
 
       <!-- Side panel strings -->
-      <message name="IDS_SIDE_PANEL_TITLE" desc="Title of the Side Panel">
-        Side Panel
-      </message>
       <message name="IDS_ACCNAME_SIDE_PANEL_RESIZE" is_accessibility_with_no_ui="true" desc="Screen reader announcement when the side panel resize handle is focused.">
         Side Panel Resize Handle
       </message>
diff --git a/chrome/app/generated_resources_grd/IDS_SIDE_PANEL_TITLE.png.sha1 b/chrome/app/generated_resources_grd/IDS_SIDE_PANEL_TITLE.png.sha1
deleted file mode 100644
index 666dd96..0000000
--- a/chrome/app/generated_resources_grd/IDS_SIDE_PANEL_TITLE.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-a161e3cb622434361ed809148d50bae55832726c
\ No newline at end of file
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index 9763e84..c72d49e 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -76,6 +76,12 @@
   <message name="IDS_SETTINGS_ACCESSIBLE_IMAGE_LABELS_SUBTITLE" desc="Subtitle for screen reader image labels feature.">
     If an image doesn’t have a useful description, Chrome will try to provide one for you. To create descriptions, images are sent to Google.
   </message>
+  <message name="IDS_SETTINGS_PDF_OCR_TITLE" desc="Description for screen reader pdf ocr feature.">
+    Convert images to text
+  </message>
+  <message name="IDS_SETTINGS_PDF_OCR_SUBTITLE" desc="Subtitle for screen reader pdf ocr feature.">
+    Scan PDF images to convert text for screen reader when necessary
+  </message>
   <message name="IDS_SETTINGS_CAPTIONS_ENABLE_LIVE_CAPTION_TITLE" desc="Name of the setting to enable Live Caption feature.">
     Live Caption
   </message>
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_PDF_OCR_SUBTITLE.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_PDF_OCR_SUBTITLE.png.sha1
new file mode 100644
index 0000000..14066ee0
--- /dev/null
+++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_PDF_OCR_SUBTITLE.png.sha1
@@ -0,0 +1 @@
+2b2939b0571ca300abf0551fba1509306e7fd123
\ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_PDF_OCR_TITLE.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_PDF_OCR_TITLE.png.sha1
new file mode 100644
index 0000000..310fb90
--- /dev/null
+++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_PDF_OCR_TITLE.png.sha1
@@ -0,0 +1 @@
+bbeb804c75d2eae2b9791a4f735e0162a1789232
\ No newline at end of file
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index b8f876a..250c9f3 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -6549,10 +6549,6 @@
      FEATURE_VALUE_TYPE(
          autofill::features::kAutofillUseImprovedLabelDisambiguation)},
 
-    {"file-handling-api", flag_descriptions::kFileHandlingAPIName,
-     flag_descriptions::kFileHandlingAPIDescription, kOsDesktop,
-     FEATURE_VALUE_TYPE(blink::features::kFileHandlingAPI)},
-
     {"file-handling-icons", flag_descriptions::kFileHandlingIconsName,
      flag_descriptions::kFileHandlingIconsDescription, kOsDesktop,
      FEATURE_VALUE_TYPE(blink::features::kFileHandlingIcons)},
@@ -9334,6 +9330,13 @@
      flag_descriptions::kUseMojoVideoDecoderForPepperDescription, kOsDesktop,
      FEATURE_VALUE_TYPE(media::kUseMojoVideoDecoderForPepper)},
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+    {"app-deduplication-service-fondue",
+     flag_descriptions::kAppDeduplicationServiceFondueName,
+     flag_descriptions::kAppDeduplicationServiceFondueDescription, kOsCrOS,
+     FEATURE_VALUE_TYPE(features::kAppDeduplicationServiceFondue)},
+#endif
+
     // NOTE: Adding a new flag requires adding a corresponding entry to enum
     // "LoginCustomFlags" in tools/metrics/histograms/enums.xml. See "Flag
     // Histograms" in tools/metrics/histograms/README.md (run the
diff --git a/chrome/browser/apps/app_preload_service/app_preload_server_connector.cc b/chrome/browser/apps/app_preload_service/app_preload_server_connector.cc
index 2f5c618..e03c38f 100644
--- a/chrome/browser/apps/app_preload_service/app_preload_server_connector.cc
+++ b/chrome/browser/apps/app_preload_service/app_preload_server_connector.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/apps/app_preload_service/preload_app_definition.h"
 #include "chrome/browser/apps/app_preload_service/proto/app_provisioning.pb.h"
 #include "chrome/browser/apps/user_type_filter.h"
+#include "components/version_info/channel.h"
 #include "google_apis/google_api_keys.h"
 #include "services/network/public/cpp/resource_request.h"
 #include "services/network/public/cpp/simple_url_loader.h"
@@ -62,6 +63,22 @@
   return apps::proto::AppProvisioningListAppsRequest::USERTYPE_UNKNOWN;
 }
 
+apps::proto::AppProvisioningListAppsRequest::Channel ConvertChannelTypeToProto(
+    const version_info::Channel channel) {
+  switch (channel) {
+    case version_info::Channel::CANARY:
+      return apps::proto::AppProvisioningListAppsRequest::CHANNEL_CANARY;
+    case version_info::Channel::DEV:
+      return apps::proto::AppProvisioningListAppsRequest::CHANNEL_DEV;
+    case version_info::Channel::BETA:
+      return apps::proto::AppProvisioningListAppsRequest::CHANNEL_BETA;
+    case version_info::Channel::STABLE:
+      return apps::proto::AppProvisioningListAppsRequest::CHANNEL_STABLE;
+    case version_info::Channel::UNKNOWN:
+      return apps::proto::AppProvisioningListAppsRequest::CHANNEL_UNDEFINED;
+  }
+}
+
 std::string BuildGetAppsForFirstLoginRequestBody(const apps::DeviceInfo& info) {
   apps::proto::AppProvisioningListAppsRequest request_proto;
   request_proto.set_board(info.board);
@@ -75,6 +92,8 @@
       info.version_info.ash_chrome);
   request_proto.mutable_chrome_os_version()->set_platform(
       info.version_info.platform);
+  request_proto.mutable_chrome_os_version()->set_channel(
+      ConvertChannelTypeToProto(info.version_info.channel));
 
   return request_proto.SerializeAsString();
 }
diff --git a/chrome/browser/apps/app_preload_service/app_preload_server_connector_unittest.cc b/chrome/browser/apps/app_preload_service/app_preload_server_connector_unittest.cc
index 872d339..fc6da8665f 100644
--- a/chrome/browser/apps/app_preload_service/app_preload_server_connector_unittest.cc
+++ b/chrome/browser/apps/app_preload_service/app_preload_server_connector_unittest.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/apps/app_preload_service/device_info_manager.h"
 #include "chrome/browser/apps/app_preload_service/preload_app_definition.h"
 #include "chrome/browser/apps/app_preload_service/proto/app_provisioning.pb.h"
+#include "components/version_info/channel.h"
 #include "content/public/test/browser_task_environment.h"
 #include "net/http/http_request_headers.h"
 #include "services/network/public/cpp/resource_request.h"
@@ -50,6 +51,7 @@
   device_info.user_type = "unmanaged";
   device_info.version_info.ash_chrome = "10.10.10";
   device_info.version_info.platform = "12345.0.0";
+  device_info.version_info.channel = version_info::Channel::STABLE;
   device_info.locale = "en-US";
 
   std::string method;
@@ -84,6 +86,8 @@
             apps::proto::AppProvisioningListAppsRequest::USERTYPE_UNMANAGED);
   EXPECT_EQ(request.chrome_os_version().ash_chrome(), "10.10.10");
   EXPECT_EQ(request.chrome_os_version().platform(), "12345.0.0");
+  EXPECT_EQ(request.chrome_os_version().channel(),
+            apps::proto::AppProvisioningListAppsRequest::CHANNEL_STABLE);
 }
 
 TEST_F(AppPreloadServerConnectorTest, GetAppsForFirstLoginSuccessfulResponse) {
diff --git a/chrome/browser/apps/app_preload_service/device_info_manager.cc b/chrome/browser/apps/app_preload_service/device_info_manager.cc
index a036452..63a0ab0 100644
--- a/chrome/browser/apps/app_preload_service/device_info_manager.cc
+++ b/chrome/browser/apps/app_preload_service/device_info_manager.cc
@@ -9,6 +9,7 @@
 #include "base/task/thread_pool.h"
 #include "chrome/browser/apps/user_type_filter.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/common/channel_info.h"
 #include "chromeos/version/version_loader.h"
 #include "components/language/core/browser/pref_names.h"
 #include "components/prefs/pref_service.h"
@@ -32,6 +33,7 @@
 //  - board
 //  - version_info.ash_chrome
 //  - user_type
+//  - channel
 // The method then asynchronously populates:
 //  - version_info.platform (OnPlatformVersionNumber)
 //  - model (OnModelInfo)
@@ -47,6 +49,7 @@
   device_info.board = base::SysInfo::HardwareModelName();
   device_info.version_info.ash_chrome = version_info::GetVersionNumber();
   device_info.user_type = apps::DetermineUserType(profile_);
+  device_info.version_info.channel = chrome::GetChannel();
 
   // Locale
   PrefService* prefs = profile_->GetPrefs();
diff --git a/chrome/browser/apps/app_preload_service/device_info_manager.h b/chrome/browser/apps/app_preload_service/device_info_manager.h
index 5f40916..7a73ab5 100644
--- a/chrome/browser/apps/app_preload_service/device_info_manager.h
+++ b/chrome/browser/apps/app_preload_service/device_info_manager.h
@@ -12,6 +12,7 @@
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/system/sys_info.h"
+#include "components/version_info/channel.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 class Profile;
@@ -24,6 +25,8 @@
   // The ChromeOS platform version of the device. e.g. "15088.0.0"
   // The value is set to "unknown" if the version was not known.
   std::string platform;
+  // The channel of the build.
+  version_info::Channel channel = version_info::Channel::UNKNOWN;
 };
 
 struct DeviceInfo {
diff --git a/chrome/browser/apps/app_preload_service/device_info_manager_unittest.cc b/chrome/browser/apps/app_preload_service/device_info_manager_unittest.cc
index 8406282..1dc4baf 100644
--- a/chrome/browser/apps/app_preload_service/device_info_manager_unittest.cc
+++ b/chrome/browser/apps/app_preload_service/device_info_manager_unittest.cc
@@ -8,6 +8,7 @@
 
 #include "base/callback.h"
 #include "base/run_loop.h"
+#include "chrome/common/channel_info.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/language/core/browser/pref_names.h"
 #include "components/prefs/pref_service.h"
@@ -33,6 +34,7 @@
     ASSERT_FALSE(device_info.user_type.empty());
     ASSERT_FALSE(device_info.version_info.ash_chrome.empty());
     ASSERT_FALSE(device_info.version_info.platform.empty());
+    ASSERT_EQ(device_info.version_info.channel, chrome::GetChannel());
     ASSERT_EQ(device_info.locale, kTestLocale);
     std::move(on_complete).Run();
   }
diff --git a/chrome/browser/apps/app_preload_service/preload_app_definition.cc b/chrome/browser/apps/app_preload_service/preload_app_definition.cc
index 797fc89..f903d75 100644
--- a/chrome/browser/apps/app_preload_service/preload_app_definition.cc
+++ b/chrome/browser/apps/app_preload_service/preload_app_definition.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/apps/app_preload_service/preload_app_definition.h"
 
+#include "base/strings/string_util.h"
 #include "url/gurl.h"
 
 namespace apps {
@@ -38,6 +39,20 @@
   return GURL(app_proto_.web_extras().original_manifest_url());
 }
 
+GURL PreloadAppDefinition::GetWebAppManifestId() const {
+  DCHECK_EQ(GetPlatform(), AppType::kWeb);
+
+  // TODO(b/264199799): Replace this logic with package ID library methods.
+  if (!base::StartsWith(app_proto_.package_id(), "web:")) {
+    return GURL();
+  }
+
+  // The package_id of web apps are prepended with `web:`.
+  std::string manifest_id = app_proto_.package_id().substr(strlen("web:"));
+
+  return GURL(manifest_id);
+}
+
 std::ostream& operator<<(std::ostream& os, const PreloadAppDefinition& app) {
   os << std::boolalpha;
   os << "- Name: " << app.GetName() << std::endl;
@@ -49,6 +64,7 @@
     os << "  - Manifest URL: " << app.GetWebAppManifestUrl() << std::endl;
     os << "  - Original Manifest URL: " << app.GetWebAppOriginalManifestUrl()
        << std::endl;
+    os << "  - Manifest ID: " << app.GetWebAppManifestId() << std::endl;
   }
 
   os << std::noboolalpha;
diff --git a/chrome/browser/apps/app_preload_service/preload_app_definition.h b/chrome/browser/apps/app_preload_service/preload_app_definition.h
index cdb3dd9c..17521b8 100644
--- a/chrome/browser/apps/app_preload_service/preload_app_definition.h
+++ b/chrome/browser/apps/app_preload_service/preload_app_definition.h
@@ -41,6 +41,11 @@
   // GURL. Must only be called if `GetPlatform()` returns `AppType::kWeb`.
   GURL GetWebAppOriginalManifestUrl() const;
 
+  // Returns the manifest ID of the Web App. This is derived from the package
+  // identifier of the app. Does not attempt to validate the GURL. Must only be
+  // called if `GetPlatform()` returns `AppType::kWeb`.
+  GURL GetWebAppManifestId() const;
+
  private:
   proto::AppProvisioningListAppsResponse_App app_proto_;
 };
diff --git a/chrome/browser/apps/app_preload_service/preload_app_definition_unittest.cc b/chrome/browser/apps/app_preload_service/preload_app_definition_unittest.cc
index e268f19..859ead0 100644
--- a/chrome/browser/apps/app_preload_service/preload_app_definition_unittest.cc
+++ b/chrome/browser/apps/app_preload_service/preload_app_definition_unittest.cc
@@ -21,6 +21,7 @@
 proto::AppProvisioningListAppsResponse_App CreateTestWebApp() {
   proto::AppProvisioningListAppsResponse_App app;
   app.set_name("Test app");
+  app.set_package_id("web:https://example.com/path/to/manifest_id");
   app.mutable_web_extras()->set_manifest_url("https://example.com");
   return app;
 }
@@ -166,4 +167,32 @@
   ASSERT_TRUE(app_def.GetWebAppOriginalManifestUrl().is_empty());
 }
 
+TEST_F(PreloadAppDefinitionTest, GetWebAppManifestId) {
+  proto::AppProvisioningListAppsResponse_App app = CreateTestWebApp();
+  app.set_package_id("web:https://example.com/path/of/manifest_id");
+
+  PreloadAppDefinition app_def(app);
+
+  ASSERT_EQ(app_def.GetWebAppManifestId().spec(),
+            "https://example.com/path/of/manifest_id");
+}
+
+TEST_F(PreloadAppDefinitionTest, GetWebAppManifestIdMalformedPackageId) {
+  proto::AppProvisioningListAppsResponse_App app = CreateTestWebApp();
+  app.set_package_id("web");
+
+  PreloadAppDefinition app_def(app);
+
+  ASSERT_FALSE(app_def.GetWebAppManifestId().is_valid());
+}
+
+TEST_F(PreloadAppDefinitionTest, GetWebAppManifestIdEmptyPackageId) {
+  proto::AppProvisioningListAppsResponse_App app = CreateTestWebApp();
+  app.set_package_id("");
+
+  PreloadAppDefinition app_def(app);
+
+  ASSERT_FALSE(app_def.GetWebAppManifestId().is_valid());
+}
+
 }  // namespace apps
diff --git a/chrome/browser/apps/app_preload_service/proto/app_provisioning.proto b/chrome/browser/apps/app_preload_service/proto/app_provisioning.proto
index 346155f..ec3e28a 100644
--- a/chrome/browser/apps/app_preload_service/proto/app_provisioning.proto
+++ b/chrome/browser/apps/app_preload_service/proto/app_provisioning.proto
@@ -42,17 +42,22 @@
     // the proto file updated.
     CHANNEL_UNKNOWN = 0;
 
+    // Channel used for test images, local dev, etc. where a channel is not
+    // explicitly defined.
+    // Note: Confusingly on the client-side ChromeOS calls this "unknown"
+    CHANNEL_UNDEFINED = 1;
+
     // Canary channel.
-    CHANNEL_CANARY = 1;
+    CHANNEL_CANARY = 2;
 
     // Developer channel.
-    CHANNEL_DEV = 2;
+    CHANNEL_DEV = 3;
 
     // Beta channel.
-    CHANNEL_BETA = 3;
+    CHANNEL_BETA = 4;
 
     // Stable channel.
-    CHANNEL_STABLE = 4;
+    CHANNEL_STABLE = 5;
   }
 
   // The board identifier for the device sending the request.
diff --git a/chrome/browser/apps/app_service/app_icon/app_icon_decoder.cc b/chrome/browser/apps/app_service/app_icon/app_icon_decoder.cc
index d633704..27a32f2 100644
--- a/chrome/browser/apps/app_service/app_icon/app_icon_decoder.cc
+++ b/chrome/browser/apps/app_service/app_icon/app_icon_decoder.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/apps/app_service/app_icon/app_icon_decoder.h"
 
 #include "base/task/thread_pool.h"
+#include "chrome/browser/apps/app_service/app_icon/app_icon_factory.h"
 #include "chrome/browser/image_decoder/image_decoder.h"
 #include "chrome/browser/profiles/profile.h"
 #include "services/data_decoder/public/cpp/data_decoder.h"
@@ -27,10 +28,14 @@
 
 AppIconDecoder::DecodeRequest::DecodeRequest(
     ui::ResourceScaleFactor scale_factor,
-    AppIconDecoder& host)
+    AppIconDecoder& host,
+    gfx::ImageSkia& image_skia,
+    std::set<ui::ResourceScaleFactor>& incomplete_scale_factors)
     : ImageRequest(&GetDataDecoder()),
       scale_factor_(scale_factor),
-      host_(host) {}
+      host_(host),
+      image_skia_(image_skia),
+      incomplete_scale_factors_(incomplete_scale_factors) {}
 
 AppIconDecoder::DecodeRequest::~DecodeRequest() {
   ImageDecoder::Cancel(this);
@@ -38,7 +43,8 @@
 
 void AppIconDecoder::DecodeRequest::OnImageDecoded(const SkBitmap& bitmap) {
   DCHECK(!bitmap.isNull() && !bitmap.empty());
-  host_.UpdateImageSkia(scale_factor_, bitmap);
+  host_.UpdateImageSkia(scale_factor_, bitmap, image_skia_,
+                        incomplete_scale_factors_);
 }
 
 void AppIconDecoder::DecodeRequest::OnDecodeImageFailed() {
@@ -53,11 +59,7 @@
     : base_path_(base_path),
       app_id_(app_id),
       size_in_dip_(size_in_dip),
-      callback_(std::move(callback)) {
-  for (const auto& scale_factor : ui::GetSupportedResourceScaleFactors()) {
-    incomplete_scale_factors_.insert(scale_factor);
-  }
-}
+      callback_(std::move(callback)) {}
 
 AppIconDecoder::~AppIconDecoder() = default;
 
@@ -70,13 +72,71 @@
                      weak_ptr_factory_.GetWeakPtr()));
 }
 
+bool AppIconDecoder::SetScaleFactors(
+    const std::map<ui::ResourceScaleFactor, IconValuePtr>& icon_datas) {
+  for (const auto& [scale_factor, iv] : icon_datas) {
+    if (!iv || iv->icon_type != IconType::kCompressed) {
+      return false;
+    }
+
+    if (HasAdaptiveIconData(iv)) {
+      is_adaptive_icon_ = true;
+      foreground_incomplete_scale_factors_.insert(scale_factor);
+      background_incomplete_scale_factors_.insert(scale_factor);
+    } else if (iv->compressed.empty()) {
+      return false;
+    } else {
+      incomplete_scale_factors_.insert(scale_factor);
+    }
+  }
+
+  if (is_adaptive_icon_ && !incomplete_scale_factors_.empty()) {
+    // Some scales have non-adaptive icons. Then we can't generate the adaptive
+    // icon for all scales. Set `is_adaptive_icon_` as false, and decode the
+    // foreground images only for scales with adaptive icon data.
+    is_adaptive_icon_ = false;
+    for (const auto& [scale_factor, iv] : icon_datas) {
+      incomplete_scale_factors_.insert(scale_factor);
+    }
+  }
+  return true;
+}
+
 void AppIconDecoder::OnIconRead(
     std::map<ui::ResourceScaleFactor, IconValuePtr> icon_datas) {
+  // Check `icon_datas` to set scale factors.
+  if (!SetScaleFactors(icon_datas)) {
+    DiscardDecodeRequest();
+    return;
+  }
+
+  // Create DecodeRequest to decode images safely in a sandboxed service per
+  // security requests.
   for (auto& [scale_factor, iv] : icon_datas) {
-    if (!iv || iv->icon_type != IconType::kCompressed ||
-        iv->compressed.empty()) {
-      DiscardDecodeRequest();
-      return;
+    if (HasAdaptiveIconData(iv)) {
+      if (!is_adaptive_icon_) {
+        // If we can't generate the adaptive icon for all scales, decode the
+        // foreground images only to fill in `image_skia_`.
+        decode_requests_.emplace_back(std::make_unique<DecodeRequest>(
+            scale_factor, *this, image_skia_, incomplete_scale_factors_));
+        ImageDecoder::Start(decode_requests_.back().get(),
+                            std::move(iv->foreground_icon_png_data));
+        continue;
+      }
+
+      // Decode for the foreground image.
+      decode_requests_.emplace_back(std::make_unique<DecodeRequest>(
+          scale_factor, *this, foreground_image_skia_,
+          foreground_incomplete_scale_factors_));
+      ImageDecoder::Start(decode_requests_.back().get(),
+                          std::move(iv->foreground_icon_png_data));
+      // Decode for the background image.
+      decode_requests_.emplace_back(std::make_unique<DecodeRequest>(
+          scale_factor, *this, background_image_skia_,
+          background_incomplete_scale_factors_));
+      ImageDecoder::Start(decode_requests_.back().get(),
+                          std::move(iv->background_icon_png_data));
+      continue;
     }
 
     is_maskable_icon_ = iv->is_maskable_icon;
@@ -87,42 +147,51 @@
           gfx::PNGCodec::Decode(
               reinterpret_cast<const unsigned char*>(&iv->compressed.front()),
               iv->compressed.size(), &bitmap)) {
-        UpdateImageSkia(scale_factor, bitmap);
+        UpdateImageSkia(scale_factor, bitmap, image_skia_,
+                        incomplete_scale_factors_);
       } else {
         DiscardDecodeRequest();
       }
       continue;
     }
 
-    // Create DecodeRequest to decode images safely in a sandboxed service per
-    // ARC app icons' security requests.
-    decode_requests_.emplace_back(
-        std::make_unique<DecodeRequest>(scale_factor, *this));
+    decode_requests_.emplace_back(std::make_unique<DecodeRequest>(
+        scale_factor, *this, image_skia_, incomplete_scale_factors_));
     ImageDecoder::Start(decode_requests_.back().get(),
                         std::move(iv->compressed));
   }
 }
 
-void AppIconDecoder::UpdateImageSkia(ui::ResourceScaleFactor scale_factor,
-                                     const SkBitmap& bitmap) {
+void AppIconDecoder::UpdateImageSkia(
+    ui::ResourceScaleFactor scale_factor,
+    const SkBitmap& bitmap,
+    gfx::ImageSkia& image_skia,
+    std::set<ui::ResourceScaleFactor>& incomplete_scale_factors) {
   gfx::ImageSkiaRep image_rep(bitmap,
                               ui::GetScaleForResourceScaleFactor(scale_factor));
   DCHECK(ui::IsSupportedScale(image_rep.scale()));
 
-  image_skia_.RemoveRepresentation(image_rep.scale());
-  image_skia_.AddRepresentation(image_rep);
-  image_skia_.RemoveUnsupportedRepresentationsForScale(image_rep.scale());
+  image_skia.RemoveRepresentation(image_rep.scale());
+  image_skia.AddRepresentation(image_rep);
+  image_skia.RemoveUnsupportedRepresentationsForScale(image_rep.scale());
 
-  incomplete_scale_factors_.erase(scale_factor);
+  incomplete_scale_factors.erase(scale_factor);
+
+  // For the adaptive icon, generate the adaptive icon with the foreground and
+  // background icon images.
+  if (is_adaptive_icon_) {
+    if (foreground_incomplete_scale_factors_.empty() &&
+        background_incomplete_scale_factors_.empty()) {
+      auto image = apps::CompositeImagesAndApplyMask(foreground_image_skia_,
+                                                     background_image_skia_);
+      image.MakeThreadSafe();
+      CompleteWithImageSkia(image);
+    }
+    return;
+  }
+
   if (incomplete_scale_factors_.empty()) {
-    // 'callback_' is responsible to remove this AppIconDecoder object, then
-    // all decode requests saved in `decode_requests_` can be destroyed, so we
-    // don't need to free  DecodeRequest's objects in `decode_requests_`.
-    auto iv = std::make_unique<apps::IconValue>();
-    iv->icon_type = IconType::kUncompressed;
-    iv->uncompressed = image_skia_;
-    iv->is_maskable_icon = is_maskable_icon_;
-    std::move(callback_).Run(this, std::move(iv));
+    CompleteWithImageSkia(image_skia_);
   }
 }
 
@@ -133,6 +202,17 @@
   std::move(callback_).Run(this, nullptr);
 }
 
+void AppIconDecoder::CompleteWithImageSkia(const gfx::ImageSkia& image_skia) {
+  // 'callback_' is responsible to remove this AppIconDecoder object, then
+  // all decode requests saved in `decode_requests_` can be destroyed, so we
+  // don't need to free  DecodeRequest's objects in `decode_requests_`.
+  auto iv = std::make_unique<apps::IconValue>();
+  iv->icon_type = IconType::kUncompressed;
+  iv->uncompressed = image_skia;
+  iv->is_maskable_icon = is_maskable_icon_;
+  std::move(callback_).Run(this, std::move(iv));
+}
+
 ScopedDecodeRequestForTesting::ScopedDecodeRequestForTesting() {
   g_decode_request_for_testing = true;
 }
diff --git a/chrome/browser/apps/app_service/app_icon/app_icon_decoder.h b/chrome/browser/apps/app_service/app_icon/app_icon_decoder.h
index bfc819e..eb7ef8b 100644
--- a/chrome/browser/apps/app_service/app_icon/app_icon_decoder.h
+++ b/chrome/browser/apps/app_service/app_icon/app_icon_decoder.h
@@ -43,7 +43,10 @@
   // requests.
   class DecodeRequest : public ImageDecoder::ImageRequest {
    public:
-    DecodeRequest(ui::ResourceScaleFactor scale_factor, AppIconDecoder& host);
+    DecodeRequest(ui::ResourceScaleFactor scale_factor,
+                  AppIconDecoder& host,
+                  gfx::ImageSkia& image_skia,
+                  std::set<ui::ResourceScaleFactor>& incomplete_scale_factors);
 
     DecodeRequest(const DecodeRequest&) = delete;
     DecodeRequest& operator=(const DecodeRequest&) = delete;
@@ -57,24 +60,40 @@
    private:
     ui::ResourceScaleFactor scale_factor_;
     AppIconDecoder& host_;
+    gfx::ImageSkia& image_skia_;
+    std::set<ui::ResourceScaleFactor>& incomplete_scale_factors_;
   };
 
-  void OnIconRead(std::map<ui::ResourceScaleFactor, IconValuePtr> icon_data);
+  bool SetScaleFactors(
+      const std::map<ui::ResourceScaleFactor, IconValuePtr>& icon_datas);
 
-  void UpdateImageSkia(ui::ResourceScaleFactor scale_factor,
-                       const SkBitmap& bitmap);
+  void OnIconRead(std::map<ui::ResourceScaleFactor, IconValuePtr> icon_datas);
+
+  void UpdateImageSkia(
+      ui::ResourceScaleFactor scale_factor,
+      const SkBitmap& bitmap,
+      gfx::ImageSkia& image_skia,
+      std::set<ui::ResourceScaleFactor>& incomplete_scale_factors);
 
   void DiscardDecodeRequest();
 
+  void CompleteWithImageSkia(const gfx::ImageSkia& image_skia);
+
   const base::FilePath base_path_;
   const std::string app_id_;
   int32_t size_in_dip_;
   base::OnceCallback<void(AppIconDecoder* decoder, IconValuePtr iv)> callback_;
 
   gfx::ImageSkia image_skia_;
-  std::set<ui::ResourceScaleFactor> incomplete_scale_factors_;
+  gfx::ImageSkia foreground_image_skia_;
+  gfx::ImageSkia background_image_skia_;
 
-  bool is_maskable_icon_;
+  std::set<ui::ResourceScaleFactor> incomplete_scale_factors_;
+  std::set<ui::ResourceScaleFactor> foreground_incomplete_scale_factors_;
+  std::set<ui::ResourceScaleFactor> background_incomplete_scale_factors_;
+
+  bool is_maskable_icon_ = false;
+  bool is_adaptive_icon_ = false;
 
   // Contains pending image decode requests.
   std::vector<std::unique_ptr<DecodeRequest>> decode_requests_;
diff --git a/chrome/browser/apps/app_service/app_icon/app_icon_reader.cc b/chrome/browser/apps/app_service/app_icon/app_icon_reader.cc
index 0437245..a9a0fb5 100644
--- a/chrome/browser/apps/app_service/app_icon/app_icon_reader.cc
+++ b/chrome/browser/apps/app_service/app_icon/app_icon_reader.cc
@@ -61,7 +61,13 @@
       return;
     }
     case IconType::kCompressed:
-      if (icon_effects == apps::IconEffects::kNone) {
+      // If there are icon effects, or the icon is an adaptive icon with the
+      // foreground and background icon files, we need to call AppIconDecoder to
+      // convert the icon files to the uncompressed images, then apply icon
+      // effects, or generate the adaptive icon with the foreground and
+      // background icon files for all scale factors.
+      if (icon_effects == apps::IconEffects::kNone &&
+          !IsAdaptiveIcon(base_path, app_id, size_in_dip)) {
         base::ThreadPool::PostTaskAndReplyWithResult(
             FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
             base::BindOnce(&ReadOnBackgroundThread, base_path, app_id,
@@ -106,44 +112,43 @@
 
   iv->icon_type = icon_type;
 
-  // Apply the icon effects on the uncompressed data. If the caller requests
-  // an uncompressed icon, return the uncompressed result; otherwise, encode
-  // the icon to a compressed icon, return the compressed result.
-  if (icon_effects) {
-    // Per https://www.w3.org/TR/appmanifest/#icon-masks, we apply a white
-    // background in case the maskable icon contains transparent pixels in its
-    // safe zone, and clear the standard icon effect, apply the mask to the icon
-    // without shrinking it.
-    if (iv->is_maskable_icon) {
-      icon_effects &= ~apps::IconEffects::kCrOsStandardIcon;
-      icon_effects |= apps::IconEffects::kCrOsStandardBackground;
-      icon_effects |= apps::IconEffects::kCrOsStandardMask;
-    }
-
-    if (icon_type == apps::IconType::kUncompressed) {
-      // For uncompressed icon, apply the resize and pad effect.
-      icon_effects |= apps::IconEffects::kMdIconStyle;
-
-      // For uncompressed icon, clear the standard icon effects, kBackground
-      // and kMask.
-      icon_effects &= ~apps::IconEffects::kCrOsStandardIcon;
-      icon_effects &= ~apps::IconEffects::kCrOsStandardBackground;
-      icon_effects &= ~apps::IconEffects::kCrOsStandardMask;
-    }
-
-    apps::ApplyIconEffects(
-        icon_effects, size_in_dip, std::move(iv),
-        base::BindOnce(&AppIconReader::OnCompleteWithIconValue,
-                       weak_ptr_factory_.GetWeakPtr(), size_in_dip, icon_type,
-                       std::move(callback)));
+  if (!icon_effects) {
+    // If the caller requests an uncompressed icon, return the uncompressed
+    // result; otherwise, encode the icon to a compressed icon, return the
+    // compressed result.
+    OnCompleteWithIconValue(size_in_dip, icon_type, std::move(callback),
+                            std::move(iv));
     return;
   }
 
-  // If icon effects are none, ReadIcons can return the compressed icon
-  // directly.
-  DCHECK_NE(IconType::kCompressed, icon_type);
+  // Apply the icon effects on the uncompressed data.
 
-  std::move(callback).Run(std::move(iv));
+  // Per https://www.w3.org/TR/appmanifest/#icon-masks, we apply a white
+  // background in case the maskable icon contains transparent pixels in its
+  // safe zone, and clear the standard icon effect, apply the mask to the icon
+  // without shrinking it.
+  if (iv->is_maskable_icon) {
+    icon_effects &= ~apps::IconEffects::kCrOsStandardIcon;
+    icon_effects |= apps::IconEffects::kCrOsStandardBackground;
+    icon_effects |= apps::IconEffects::kCrOsStandardMask;
+  }
+
+  if (icon_type == apps::IconType::kUncompressed) {
+    // For uncompressed icon, apply the resize and pad effect.
+    icon_effects |= apps::IconEffects::kMdIconStyle;
+
+    // For uncompressed icon, clear the standard icon effects, kBackground
+    // and kMask.
+    icon_effects &= ~apps::IconEffects::kCrOsStandardIcon;
+    icon_effects &= ~apps::IconEffects::kCrOsStandardBackground;
+    icon_effects &= ~apps::IconEffects::kCrOsStandardMask;
+  }
+
+  apps::ApplyIconEffects(
+      icon_effects, size_in_dip, std::move(iv),
+      base::BindOnce(&AppIconReader::OnCompleteWithIconValue,
+                     weak_ptr_factory_.GetWeakPtr(), size_in_dip, icon_type,
+                     std::move(callback)));
 }
 
 void AppIconReader::OnCompleteWithIconValue(int32_t size_in_dip,
diff --git a/chrome/browser/apps/app_service/app_icon/app_icon_util.cc b/chrome/browser/apps/app_service/app_icon/app_icon_util.cc
index dc707c8..f343e9b 100644
--- a/chrome/browser/apps/app_service/app_icon/app_icon_util.cc
+++ b/chrome/browser/apps/app_service/app_icon/app_icon_util.cc
@@ -64,6 +64,37 @@
       .AppendASCII(icon_file_name);
 }
 
+bool IsAdaptiveIcon(const base::FilePath& base_path,
+                    const std::string& app_id,
+                    int32_t size_in_dip) {
+  for (auto scale_factor : ui::GetSupportedResourceScaleFactors()) {
+    int icon_size_in_px = apps_util::ConvertDipToPxForScale(
+        size_in_dip, ui::GetScaleForResourceScaleFactor(scale_factor));
+
+    const auto foreground_icon_path =
+        apps::GetForegroundIconPath(base_path, app_id, icon_size_in_px);
+    const auto background_icon_path =
+        apps::GetBackgroundIconPath(base_path, app_id, icon_size_in_px);
+
+    if (!IsAdaptiveIcon(foreground_icon_path, background_icon_path)) {
+      return false;
+    }
+  }
+  return true;
+}
+
+bool IsAdaptiveIcon(const base::FilePath& foreground_icon_path,
+                    const base::FilePath& background_icon_path) {
+  return !foreground_icon_path.empty() && !background_icon_path.empty() &&
+         base::PathExists(foreground_icon_path) &&
+         base::PathExists(background_icon_path);
+}
+
+bool HasAdaptiveIconData(const IconValuePtr& iv) {
+  return iv && !iv->foreground_icon_png_data.empty() &&
+         !iv->background_icon_png_data.empty();
+}
+
 IconValuePtr ReadOnBackgroundThread(const base::FilePath& base_path,
                                     const std::string& app_id,
                                     int32_t icon_size_in_px) {
@@ -80,7 +111,12 @@
     icon_path = apps::GetIconPath(base_path, app_id, icon_size_in_px,
                                   /*is_maskable_icon=*/false);
     if (icon_path.empty() || !base::PathExists(icon_path)) {
-      return nullptr;
+      // The icon might have foreground/background icon files for some scale
+      // factors, then we can use the foreground icon file for this scale.
+      icon_path = GetForegroundIconPath(base_path, app_id, icon_size_in_px);
+      if (icon_path.empty() || !base::PathExists(icon_path)) {
+        return nullptr;
+      }
     }
   }
 
@@ -93,6 +129,32 @@
   return iv;
 }
 
+IconValuePtr ReadAdaptiveIconOnBackgroundThread(const base::FilePath& base_path,
+                                                const std::string& app_id,
+                                                int32_t icon_size_in_px) {
+  auto iv = std::make_unique<IconValue>();
+  iv->icon_type = IconType::kCompressed;
+
+  const auto foreground_icon_path =
+      apps::GetForegroundIconPath(base_path, app_id, icon_size_in_px);
+  const auto background_icon_path =
+      apps::GetBackgroundIconPath(base_path, app_id, icon_size_in_px);
+  if (IsAdaptiveIcon(foreground_icon_path, background_icon_path)) {
+    std::string foreground_icon_data;
+    std::string background_icon_data;
+    if (base::ReadFileToString(foreground_icon_path, &foreground_icon_data) &&
+        base::ReadFileToString(background_icon_path, &background_icon_data)) {
+      iv->foreground_icon_png_data = {foreground_icon_data.begin(),
+                                      foreground_icon_data.end()};
+      iv->background_icon_png_data = {background_icon_data.begin(),
+                                      background_icon_data.end()};
+      return iv;
+    }
+  }
+
+  return nullptr;
+}
+
 std::map<ui::ResourceScaleFactor, IconValuePtr> ReadIconFilesOnBackgroundThread(
     const base::FilePath& base_path,
     const std::string& app_id,
@@ -101,8 +163,16 @@
   for (auto scale_factor : ui::GetSupportedResourceScaleFactors()) {
     int icon_size_in_px = apps_util::ConvertDipToPxForScale(
         size_in_dip, ui::GetScaleForResourceScaleFactor(scale_factor));
+
+    // If some scales have non-adaptive icons, we can't generate the adaptive
+    // icon for all scales. We still get the foregound/background icon data for
+    // the mix scenario, and decode the foreground icon data only, as done in
+    // AppIconDecoder.
+    auto iv =
+        ReadAdaptiveIconOnBackgroundThread(base_path, app_id, icon_size_in_px);
     result[scale_factor] =
-        ReadOnBackgroundThread(base_path, app_id, icon_size_in_px);
+        iv ? std::move(iv)
+           : ReadOnBackgroundThread(base_path, app_id, icon_size_in_px);
   }
   return result;
 }
diff --git a/chrome/browser/apps/app_service/app_icon/app_icon_util.h b/chrome/browser/apps/app_service/app_icon/app_icon_util.h
index 8f59454..c66d5fd 100644
--- a/chrome/browser/apps/app_service/app_icon/app_icon_util.h
+++ b/chrome/browser/apps/app_service/app_icon/app_icon_util.h
@@ -83,18 +83,44 @@
                                      const std::string& app_id,
                                      int32_t icon_size_in_px);
 
-// Reads one single icon file for the given `app_id` and `icon_size_in_px`, and
-// returns the compressed icon. If there is a maskable icon file, reads the
-// maskable icon file. Otherwise, reads other icon file. If there is no
-// appropriate icon file, or failed reading the icon file, return nullptr.
+// Returns true if the icon files for the given `app_id` and `size_in_dip`
+// include the foreground and background icon files for all scale factors.
+// Otherwise, returns false.
+bool IsAdaptiveIcon(const base::FilePath& base_path,
+                    const std::string& app_id,
+                    int32_t size_in_dip);
+
+// Returns true if both `foreground_icon_path` and `background_icon_path` are
+// valid. Otherwise, returns false.
+bool IsAdaptiveIcon(const base::FilePath& foreground_icon_path,
+                    const base::FilePath& background_icon_path);
+
+// Returns true if both `iv` has both `foreground_icon_png_data` and
+// `background_icon_png_data`. Otherwise, returns false.
+bool HasAdaptiveIconData(const IconValuePtr& iv);
+
+// Reads icon file for the given `app_id` and `icon_size_in_px`, and
+// returns the compressed icon.
+//
+// * If there is a maskable icon file, reads the maskable icon file.
+// * Otherwise, reads other icon file.
+// * If there is no appropriate icon file, or failed reading the icon file,
+// returns nullptr.
 IconValuePtr ReadOnBackgroundThread(const base::FilePath& base_path,
                                     const std::string& app_id,
                                     int32_t icon_size_in_px);
 
+// Reads the foreground and background icon files for the given `app_id` and
+// `icon_size_in_px`, and returns the compressed icon. If there is no
+// appropriate icon file, or failed reading the icon file, returns nullptr.
+IconValuePtr ReadAdaptiveIconOnBackgroundThread(const base::FilePath& base_path,
+                                                const std::string& app_id,
+                                                int32_t icon_size_in_px);
+
 // Calls ReadOnBackgroundThread to read icon files for all scale factors for
 // the given `app_id` and `size_in_dip`, and returns the compressed icons for
-// all scale factors. The same as ReadOnBackgroundThread, reads the maskable
-// icon files as the higher priority, and if there is no appropriate icon file,
+// all scale factors. Reads the foreground/background icon data as higher
+// priority, then maskable icon files, and if there is no appropriate icon file,
 // or failed reading the icon file, return nullptr for the scale factor.
 std::map<ui::ResourceScaleFactor, IconValuePtr> ReadIconFilesOnBackgroundThread(
     const base::FilePath& base_path,
diff --git a/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac_unittest.cc b/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac_unittest.cc
index 424e53e..3dd97a3a 100644
--- a/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac_unittest.cc
+++ b/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac_unittest.cc
@@ -5,10 +5,8 @@
 #include "chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.h"
 
 #include "base/bind.h"
-#include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/test/bind.h"
-#include "base/test/scoped_feature_list.h"
 #include "chrome/browser/apps/app_service/app_launch_params.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/web_applications/mojom/user_display_mode.mojom.h"
@@ -21,7 +19,6 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/blink/public/common/features.h"
 #include "url/gurl.h"
 
 namespace web_app {
@@ -185,8 +182,6 @@
 
  private:
   web_app::AppId app_id_;
-  base::test::ScopedFeatureList scoped_feature_list_{
-      blink::features::kFileHandlingAPI};
 };
 
 TEST_F(WebAppShimManagerDelegateTest, LaunchApp) {
diff --git a/chrome/browser/ash/BUILD.gn b/chrome/browser/ash/BUILD.gn
index d5abfd9..8f1e4de 100644
--- a/chrome/browser/ash/BUILD.gn
+++ b/chrome/browser/ash/BUILD.gn
@@ -709,8 +709,9 @@
     "bruschetta/bruschetta_download_client.h",
     "bruschetta/bruschetta_features.cc",
     "bruschetta/bruschetta_features.h",
-    "bruschetta/bruschetta_installer.cc",
     "bruschetta/bruschetta_installer.h",
+    "bruschetta/bruschetta_installer_impl.cc",
+    "bruschetta/bruschetta_installer_impl.h",
     "bruschetta/bruschetta_launcher.cc",
     "bruschetta/bruschetta_launcher.h",
     "bruschetta/bruschetta_mount_provider.cc",
@@ -1080,8 +1081,8 @@
     "file_manager/fileapi_util.h",
     "file_manager/filesystem_api_util.cc",
     "file_manager/filesystem_api_util.h",
-    "file_manager/fusebox_mounter.cc",
-    "file_manager/fusebox_mounter.h",
+    "file_manager/fusebox_daemon.cc",
+    "file_manager/fusebox_daemon.h",
     "file_manager/guest_os_file_tasks.cc",
     "file_manager/guest_os_file_tasks.h",
     "file_manager/io_task.cc",
@@ -4416,6 +4417,7 @@
     # builds as well.
     "../ui/views/frame/immersive_mode_controller_chromeos_unittest.cc",
     "../ui/views/select_file_dialog_extension_unittest.cc",
+    "../ui/webui/ash/cloud_upload/cloud_upload_notification_manager_unittest.cc",
     "../ui/webui/ash/login/l10n_util_test_util.cc",
     "../ui/webui/ash/login/l10n_util_test_util.h",
     "../ui/webui/ash/login/l10n_util_unittest.cc",
@@ -4623,7 +4625,7 @@
     "borealis/infra/state_manager_unittest.cc",
     "borealis/infra/transition_unittest.cc",
     "browser_accelerator_configuration_unittest.cc",
-    "bruschetta/bruschetta_installer_unittest.cc",
+    "bruschetta/bruschetta_installer_impl_unittest.cc",
     "bruschetta/bruschetta_launcher_unittest.cc",
     "bruschetta/bruschetta_mount_provider_unittest.cc",
     "bruschetta/bruschetta_service_unittest.cc",
diff --git a/chrome/browser/ash/accessibility/accessibility_event_rewriter_delegate_impl.cc b/chrome/browser/ash/accessibility/accessibility_event_rewriter_delegate_impl.cc
index 27cc6042..e3eacccb 100644
--- a/chrome/browser/ash/accessibility/accessibility_event_rewriter_delegate_impl.cc
+++ b/chrome/browser/ash/accessibility/accessibility_event_rewriter_delegate_impl.cc
@@ -129,9 +129,9 @@
   extensions::EventRouter* event_router =
       extensions::EventRouter::Get(AccessibilityManager::Get()->profile());
 
-  base::Value point_dict(base::Value::Type::DICTIONARY);
-  point_dict.SetDoubleKey("x", point.x());
-  point_dict.SetDoubleKey("y", point.y());
+  base::Value::Dict point_dict;
+  point_dict.Set("x", point.x());
+  point_dict.Set("y", point.y());
 
   base::Value::List event_args;
   event_args.Append(std::move(point_dict));
diff --git a/chrome/browser/ash/account_manager/account_apps_availability.cc b/chrome/browser/ash/account_manager/account_apps_availability.cc
index ac59faf0..e6cbd1d 100644
--- a/chrome/browser/ash/account_manager/account_apps_availability.cc
+++ b/chrome/browser/ash/account_manager/account_apps_availability.cc
@@ -160,9 +160,9 @@
   // Account shouldn't already exist.
   DCHECK(!IsAccountAvailableInArc(prefs, gaia_id).has_value());
 
-  base::Value account_entry(base::Value::Type::DICTIONARY);
-  account_entry.SetKey(account_manager::prefs::kIsAvailableInArcKey,
-                       base::Value(is_available_in_arc));
+  base::Value::Dict account_entry;
+  account_entry.Set(account_manager::prefs::kIsAvailableInArcKey,
+                    base::Value(is_available_in_arc));
 
   ScopedDictPrefUpdate update(prefs,
                               account_manager::prefs::kAccountAppsAvailability);
@@ -388,7 +388,7 @@
     return;
 
   prefs_->Set(account_manager::prefs::kAccountAppsAvailability,
-              base::Value(base::Value::Type::DICTIONARY));
+              base::Value(base::Value::Type::DICT));
 
   ScopedDictPrefUpdate update(prefs_,
                               account_manager::prefs::kAccountAppsAvailability);
diff --git a/chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher_impl_unittest.cc b/chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher_impl_unittest.cc
index 5b97c03..3a8c3f2 100644
--- a/chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher_impl_unittest.cc
+++ b/chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher_impl_unittest.cc
@@ -109,11 +109,11 @@
 
   EXPECT_EQ(FakeRecommendAppsFetcherDelegate::Result::SUCCESS,
             delegate_.WaitForResult());
-  base::Value expected_apps(base::Value::Type::LIST);
-  base::Value app(base::Value::Type::DICTIONARY);
-  app.SetKey("name", base::Value("Test app 1"));
-  app.SetKey("icon", base::Value("http://test.app"));
-  app.SetKey("package_name", base::Value("test.app1"));
+  base::Value::List expected_apps;
+  base::Value::Dict app;
+  app.Set("name", base::Value("Test app 1"));
+  app.Set("icon", base::Value("http://test.app"));
+  app.Set("package_name", base::Value("test.app1"));
   expected_apps.Append(std::move(app));
 
   EXPECT_EQ(expected_apps, delegate_.loaded_apps());
@@ -172,15 +172,15 @@
 
   EXPECT_EQ(FakeRecommendAppsFetcherDelegate::Result::SUCCESS,
             delegate_.WaitForResult());
-  base::Value expected_apps(base::Value::Type::LIST);
-  base::Value app1(base::Value::Type::DICTIONARY);
-  app1.SetKey("name", base::Value("Test app 1"));
-  app1.SetKey("icon", base::Value("http://test.app"));
-  app1.SetKey("package_name", base::Value("test.app1"));
+  base::Value::List expected_apps;
+  base::Value::Dict app1;
+  app1.Set("name", base::Value("Test app 1"));
+  app1.Set("icon", base::Value("http://test.app"));
+  app1.Set("package_name", base::Value("test.app1"));
   expected_apps.Append(std::move(app1));
 
-  base::Value app2(base::Value::Type::DICTIONARY);
-  app2.SetKey("package_name", base::Value("test.app2"));
+  base::Value::Dict app2;
+  app2.Set("package_name", base::Value("test.app2"));
   expected_apps.Append(std::move(app2));
 
   EXPECT_EQ(expected_apps, delegate_.loaded_apps());
@@ -209,15 +209,15 @@
 
   EXPECT_EQ(FakeRecommendAppsFetcherDelegate::Result::SUCCESS,
             delegate_.WaitForResult());
-  base::Value expected_apps(base::Value::Type::LIST);
-  base::Value app1(base::Value::Type::DICTIONARY);
-  app1.SetKey("name", base::Value("Test app 1"));
-  app1.SetKey("icon", base::Value("http://test.app"));
-  app1.SetKey("package_name", base::Value("test.app1"));
+  base::Value::List expected_apps;
+  base::Value::Dict app1;
+  app1.Set("name", base::Value("Test app 1"));
+  app1.Set("icon", base::Value("http://test.app"));
+  app1.Set("package_name", base::Value("test.app1"));
   expected_apps.Append(std::move(app1));
 
-  base::Value app2(base::Value::Type::DICTIONARY);
-  app2.SetKey("package_name", base::Value("test.app2"));
+  base::Value::Dict app2;
+  app2.Set("package_name", base::Value("test.app2"));
   expected_apps.Append(std::move(app2));
 
   EXPECT_EQ(expected_apps, delegate_.loaded_apps());
diff --git a/chrome/browser/ash/attestation/tpm_challenge_key_result.cc b/chrome/browser/ash/attestation/tpm_challenge_key_result.cc
index da9f436..89d8f08 100644
--- a/chrome/browser/ash/attestation/tpm_challenge_key_result.cc
+++ b/chrome/browser/ash/attestation/tpm_challenge_key_result.cc
@@ -179,15 +179,14 @@
 
 std::ostream& operator<<(std::ostream& os,
                          const TpmChallengeKeyResult& result) {
-  base::Value value(base::Value::Type::DICTIONARY);
+  base::Value::Dict value;
 
-  value.SetIntKey("result_code", static_cast<int>(result.result_code));
+  value.Set("result_code", static_cast<int>(result.result_code));
   if (!result.IsSuccess()) {
-    value.SetStringKey("error_message", result.GetErrorMessage());
+    value.Set("error_message", result.GetErrorMessage());
   }
-  value.SetStringKey("public_key", Base64EncodeStr(result.public_key));
-  value.SetStringKey("challenge_response",
-                     Base64EncodeStr(result.challenge_response));
+  value.Set("public_key", Base64EncodeStr(result.public_key));
+  value.Set("challenge_response", Base64EncodeStr(result.challenge_response));
 
   os << value;
   return os;
diff --git a/chrome/browser/ash/bruschetta/bruschetta_installer.h b/chrome/browser/ash/bruschetta/bruschetta_installer.h
index 6c26107..fef0aa4 100644
--- a/chrome/browser/ash/bruschetta/bruschetta_installer.h
+++ b/chrome/browser/ash/bruschetta/bruschetta_installer.h
@@ -5,39 +5,14 @@
 #ifndef CHROME_BROWSER_ASH_BRUSCHETTA_BRUSCHETTA_INSTALLER_H_
 #define CHROME_BROWSER_ASH_BRUSCHETTA_BRUSCHETTA_INSTALLER_H_
 
-#include "base/check_is_test.h"
 #include "base/guid.h"
-#include "base/memory/raw_ptr.h"
-#include "base/values.h"
 #include "chromeos/ash/components/dbus/concierge/concierge_service.pb.h"
-#include "chromeos/ash/components/dbus/dlcservice/dlcservice_client.h"
-#include "chromeos/ash/components/disks/disk_mount_manager.h"
 #include "components/download/public/background_service/download_metadata.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "url/gurl.h"
-
-class Profile;
 
 namespace bruschetta {
 
 class BruschettaInstaller {
  public:
-  BruschettaInstaller(Profile* profile, base::OnceClosure close_callback);
-
-  BruschettaInstaller(const BruschettaInstaller&) = delete;
-  BruschettaInstaller& operator=(const BruschettaInstaller&) = delete;
-  ~BruschettaInstaller();
-
-  void Cancel();
-  void Install(std::string vm_name, std::string config_id);
-
-  const base::GUID& GetDownloadGuid() const;
-
-  void DownloadStarted(const std::string& guid,
-                       download::DownloadParams::StartResult result);
-  void DownloadFailed();
-  void DownloadSucceeded(const download::CompletionInfo& completion_info);
-
   enum class State {
     kInstallStarted,
     kDlcInstall,
@@ -51,72 +26,30 @@
     kLaunchTerminal,
   };
 
-  class TestingObserver {
+  class Observer {
    public:
     virtual void StateChanged(State state) = 0;
     virtual void Error() = 0;
   };
 
-  void set_observer_for_testing(TestingObserver* observer) {
-    CHECK_IS_TEST();
-    observer_ = observer;
-  }
+  virtual ~BruschettaInstaller() = default;
+
+  virtual void Cancel() = 0;
+  virtual void Install(std::string vm_name, std::string config_id) = 0;
+
+  virtual const base::GUID& GetDownloadGuid() const = 0;
+
+  virtual void DownloadStarted(
+      const std::string& guid,
+      download::DownloadParams::StartResult result) = 0;
+  virtual void DownloadFailed() = 0;
+  virtual void DownloadSucceeded(
+      const download::CompletionInfo& completion_info) = 0;
+
+  virtual void AddObserver(Observer* observer) = 0;
+  virtual void RemoveObserver(Observer* observer) = 0;
 
  private:
-  using DownloadCallback =
-      base::OnceCallback<void(const download::CompletionInfo&)>;
-
-  bool MaybeClose();
-
-  void StartDownload(GURL url, DownloadCallback callback);
-
-  void InstallToolsDlc();
-  void OnToolsDlcInstalled(
-      const ash::DlcserviceClient::InstallResult& install_result);
-  void DownloadFirmware();
-  void OnFirmwareDownloaded(const download::CompletionInfo& completion_info);
-  void MountFirmware(const base::FilePath& path);
-  void OnFirmwareMounted(ash::MountError error_code,
-                         const ash::MountPoint& mount_info);
-  void DownloadBootDisk();
-  void OnBootDiskDownloaded(const download::CompletionInfo& completion_info);
-  void MountBootDisk(const base::FilePath& path);
-  void OnBootDiskMounted(ash::MountError error_code,
-                         const ash::MountPoint& mount_info);
-  void OpenFds();
-  void OnOpenFds(absl::optional<std::pair<base::ScopedFD, base::ScopedFD>> fds);
-  void CreateVmDisk();
-  void OnCreateVmDisk(
-      absl::optional<vm_tools::concierge::CreateDiskImageResponse> result);
-  void StartVm();
-  void OnStartVm(absl::optional<vm_tools::concierge::StartVmResponse> result);
-  void LaunchTerminal();
-
-  void NotifyObserver(State state);
-  void NotifyObserverError();
-
-  bool install_running_ = false;
-
-  std::string vm_name_;
-  std::string config_id_;
-  base::Value::Dict config_;
-
-  base::GUID download_guid_;
-  DownloadCallback download_callback_;
-
-  std::string firmware_mount_path_;
-  std::string boot_disk_mount_path_;
-  base::ScopedFD firmware_fd_;
-  base::ScopedFD boot_disk_fd_;
-  std::string disk_path_;
-
-  const base::raw_ptr<Profile> profile_;
-
-  base::OnceClosure close_closure_;
-
-  base::raw_ptr<TestingObserver> observer_ = nullptr;
-
-  base::WeakPtrFactory<BruschettaInstaller> weak_ptr_factory_{this};
 };
 
 }  // namespace bruschetta
diff --git a/chrome/browser/ash/bruschetta/bruschetta_installer.cc b/chrome/browser/ash/bruschetta/bruschetta_installer_impl.cc
similarity index 80%
rename from chrome/browser/ash/bruschetta/bruschetta_installer.cc
rename to chrome/browser/ash/bruschetta/bruschetta_installer_impl.cc
index 0457651c..cdb05f4 100644
--- a/chrome/browser/ash/bruschetta/bruschetta_installer.cc
+++ b/chrome/browser/ash/bruschetta/bruschetta_installer_impl.cc
@@ -2,8 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ash/bruschetta/bruschetta_installer.h"
+#include "chrome/browser/ash/bruschetta/bruschetta_installer_impl.h"
 
+#include "base/check.h"
 #include "base/files/file_enumerator.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
@@ -64,37 +65,42 @@
 
 }  // namespace
 
-BruschettaInstaller::BruschettaInstaller(Profile* profile,
-                                         base::OnceClosure close_closure)
+BruschettaInstallerImpl::BruschettaInstallerImpl(
+    Profile* profile,
+    base::OnceClosure close_closure)
     : profile_(profile), close_closure_(std::move(close_closure)) {
   BruschettaDownloadClient::SetInstallerInstance(this);
 }
 
-BruschettaInstaller::~BruschettaInstaller() {
+BruschettaInstallerImpl::~BruschettaInstallerImpl() {
   BruschettaDownloadClient::SetInstallerInstance(nullptr);
 }
 
-bool BruschettaInstaller::MaybeClose() {
+bool BruschettaInstallerImpl::MaybeClose() {
   if (!install_running_) {
-    std::move(close_closure_).Run();
+    if (close_closure_) {
+      std::move(close_closure_).Run();
+    }
     return true;
   }
   return false;
 }
 
-void BruschettaInstaller::Cancel() {
+void BruschettaInstallerImpl::Cancel() {
   if (download_guid_.is_valid()) {
     BackgroundDownloadServiceFactory::GetForKey(profile_->GetProfileKey())
         ->CancelDownload(download_guid_.AsLowercaseString());
   }
 
-  if (MaybeClose())
+  if (MaybeClose()) {
     return;
+  }
 
   install_running_ = false;
 }
 
-void BruschettaInstaller::Install(std::string vm_name, std::string config_id) {
+void BruschettaInstallerImpl::Install(std::string vm_name,
+                                      std::string config_id) {
   if (install_running_) {
     LOG(ERROR) << "Install requested while an install is already running";
     return;
@@ -118,22 +124,23 @@
   }
 }
 
-void BruschettaInstaller::InstallToolsDlc() {
+void BruschettaInstallerImpl::InstallToolsDlc() {
   NotifyObserver(State::kDlcInstall);
 
   dlcservice::InstallRequest request;
   request.set_id(crostini::kCrostiniDlcName);
   ash::DlcserviceClient::Get()->Install(
       request,
-      base::BindOnce(&BruschettaInstaller::OnToolsDlcInstalled,
+      base::BindOnce(&BruschettaInstallerImpl::OnToolsDlcInstalled,
                      weak_ptr_factory_.GetWeakPtr()),
       base::DoNothing());
 }
 
-void BruschettaInstaller::OnToolsDlcInstalled(
+void BruschettaInstallerImpl::OnToolsDlcInstalled(
     const ash::DlcserviceClient::InstallResult& install_result) {
-  if (MaybeClose())
+  if (MaybeClose()) {
     return;
+  }
 
   if (install_result.error != dlcservice::kErrorNone) {
     install_running_ = false;
@@ -145,7 +152,8 @@
   DownloadFirmware();
 }
 
-void BruschettaInstaller::StartDownload(GURL url, DownloadCallback callback) {
+void BruschettaInstallerImpl::StartDownload(GURL url,
+                                            DownloadCallback callback) {
   auto* download_service =
       BackgroundDownloadServiceFactory::GetForKey(profile_->GetProfileKey());
 
@@ -154,7 +162,7 @@
   params.client = download::DownloadClient::BRUSCHETTA;
 
   params.guid = download_guid_.AsLowercaseString();
-  params.callback = base::BindOnce(&BruschettaInstaller::DownloadStarted,
+  params.callback = base::BindOnce(&BruschettaInstallerImpl::DownloadStarted,
                                    weak_ptr_factory_.GetWeakPtr());
 
   download_callback_ = std::move(callback);
@@ -173,7 +181,7 @@
   download_service->StartDownload(std::move(params));
 }
 
-void BruschettaInstaller::DownloadStarted(
+void BruschettaInstallerImpl::DownloadStarted(
     const std::string& guid,
     download::DownloadParams::StartResult result) {
   if (guid != download_guid_.AsLowercaseString()) {
@@ -187,7 +195,7 @@
   }
 }
 
-void BruschettaInstaller::DownloadFailed() {
+void BruschettaInstallerImpl::DownloadFailed() {
   download_guid_ = base::GUID();
   download_callback_.Reset();
 
@@ -199,13 +207,13 @@
   NotifyObserverError();
 }
 
-void BruschettaInstaller::DownloadSucceeded(
+void BruschettaInstallerImpl::DownloadSucceeded(
     const download::CompletionInfo& completion_info) {
   download_guid_ = base::GUID();
   std::move(download_callback_).Run(completion_info);
 }
 
-void BruschettaInstaller::DownloadFirmware() {
+void BruschettaInstallerImpl::DownloadFirmware() {
   // We need to generate the download GUID before notifying because the tests
   // need it to set the response.
   download_guid_ = base::GUID::GenerateRandomV4();
@@ -214,14 +222,15 @@
   const std::string* url =
       config_.FindDict(prefs::kPolicyUefiKey)->FindString(prefs::kPolicyURLKey);
   StartDownload(GURL(*url),
-                base::BindOnce(&BruschettaInstaller::OnFirmwareDownloaded,
+                base::BindOnce(&BruschettaInstallerImpl::OnFirmwareDownloaded,
                                weak_ptr_factory_.GetWeakPtr()));
 }
 
-void BruschettaInstaller::OnFirmwareDownloaded(
+void BruschettaInstallerImpl::OnFirmwareDownloaded(
     const download::CompletionInfo& completion_info) {
-  if (MaybeClose())
+  if (MaybeClose()) {
     return;
+  }
 
   const std::string* expected_hash = config_.FindDict(prefs::kPolicyUefiKey)
                                          ->FindString(prefs::kPolicyHashKey);
@@ -238,20 +247,22 @@
   MountFirmware(completion_info.path);
 }
 
-void BruschettaInstaller::MountFirmware(const base::FilePath& path) {
+void BruschettaInstallerImpl::MountFirmware(const base::FilePath& path) {
   NotifyObserver(State::kFirmwareMount);
 
   ash::disks::DiskMountManager::GetInstance()->MountPath(
       path.AsUTF8Unsafe(), "", "", {}, ash::MountType::kArchive,
       ash::MountAccessMode::kReadOnly,
-      base::BindOnce(&BruschettaInstaller::OnFirmwareMounted,
+      base::BindOnce(&BruschettaInstallerImpl::OnFirmwareMounted,
                      weak_ptr_factory_.GetWeakPtr()));
 }
 
-void BruschettaInstaller::OnFirmwareMounted(ash::MountError error_code,
-                                            const ash::MountPoint& mount_info) {
-  if (MaybeClose())
+void BruschettaInstallerImpl::OnFirmwareMounted(
+    ash::MountError error_code,
+    const ash::MountPoint& mount_info) {
+  if (MaybeClose()) {
     return;
+  }
 
   if (error_code != ash::MountError::kSuccess) {
     install_running_ = false;
@@ -265,7 +276,7 @@
   DownloadBootDisk();
 }
 
-void BruschettaInstaller::DownloadBootDisk() {
+void BruschettaInstallerImpl::DownloadBootDisk() {
   // We need to generate the download GUID before notifying because the tests
   // need it to set the response.
   download_guid_ = base::GUID::GenerateRandomV4();
@@ -274,14 +285,15 @@
   const std::string* url = config_.FindDict(prefs::kPolicyImageKey)
                                ->FindString(prefs::kPolicyURLKey);
   StartDownload(GURL(*url),
-                base::BindOnce(&BruschettaInstaller::OnBootDiskDownloaded,
+                base::BindOnce(&BruschettaInstallerImpl::OnBootDiskDownloaded,
                                weak_ptr_factory_.GetWeakPtr()));
 }
 
-void BruschettaInstaller::OnBootDiskDownloaded(
+void BruschettaInstallerImpl::OnBootDiskDownloaded(
     const download::CompletionInfo& completion_info) {
-  if (MaybeClose())
+  if (MaybeClose()) {
     return;
+  }
 
   const std::string* expected_hash = config_.FindDict(prefs::kPolicyImageKey)
                                          ->FindString(prefs::kPolicyHashKey);
@@ -298,20 +310,22 @@
   MountBootDisk(completion_info.path);
 }
 
-void BruschettaInstaller::MountBootDisk(const base::FilePath& path) {
+void BruschettaInstallerImpl::MountBootDisk(const base::FilePath& path) {
   NotifyObserver(State::kBootDiskMount);
 
   ash::disks::DiskMountManager::GetInstance()->MountPath(
       path.AsUTF8Unsafe(), "", "", {}, ash::MountType::kArchive,
       ash::MountAccessMode::kReadOnly,
-      base::BindOnce(&BruschettaInstaller::OnBootDiskMounted,
+      base::BindOnce(&BruschettaInstallerImpl::OnBootDiskMounted,
                      weak_ptr_factory_.GetWeakPtr()));
 }
 
-void BruschettaInstaller::OnBootDiskMounted(ash::MountError error_code,
-                                            const ash::MountPoint& mount_info) {
-  if (MaybeClose())
+void BruschettaInstallerImpl::OnBootDiskMounted(
+    ash::MountError error_code,
+    const ash::MountPoint& mount_info) {
+  if (MaybeClose()) {
     return;
+  }
 
   if (error_code != ash::MountError::kSuccess) {
     install_running_ = false;
@@ -325,7 +339,7 @@
   OpenFds();
 }
 
-void BruschettaInstaller::OpenFds() {
+void BruschettaInstallerImpl::OpenFds() {
   NotifyObserver(State::kOpenFiles);
 
   base::ThreadPool::PostTaskAndReplyWithResult(
@@ -333,7 +347,7 @@
       base::BindOnce(&OpenFdsBlocking, base::FilePath(firmware_mount_path_),
                      base::FilePath(boot_disk_mount_path_),
                      profile_->GetPath()),
-      base::BindOnce(&BruschettaInstaller::OnOpenFds,
+      base::BindOnce(&BruschettaInstallerImpl::OnOpenFds,
                      weak_ptr_factory_.GetWeakPtr()));
 }
 
@@ -391,10 +405,11 @@
 }
 }  // namespace
 
-void BruschettaInstaller::OnOpenFds(
+void BruschettaInstallerImpl::OnOpenFds(
     absl::optional<std::pair<base::ScopedFD, base::ScopedFD>> fds) {
-  if (MaybeClose())
+  if (MaybeClose()) {
     return;
+  }
 
   if (!fds) {
     install_running_ = false;
@@ -409,7 +424,7 @@
   CreateVmDisk();
 }
 
-void BruschettaInstaller::CreateVmDisk() {
+void BruschettaInstallerImpl::CreateVmDisk() {
   NotifyObserver(State::kCreateVmDisk);
 
   auto* client = ash::ConciergeClient::Get();
@@ -424,15 +439,16 @@
   request.set_vm_name(kBruschettaVmName);
   request.set_image_type(vm_tools::concierge::DiskImageType::DISK_IMAGE_AUTO);
 
-  client->CreateDiskImage(request,
-                          base::BindOnce(&BruschettaInstaller::OnCreateVmDisk,
-                                         weak_ptr_factory_.GetWeakPtr()));
+  client->CreateDiskImage(
+      request, base::BindOnce(&BruschettaInstallerImpl::OnCreateVmDisk,
+                              weak_ptr_factory_.GetWeakPtr()));
 }
 
-void BruschettaInstaller::OnCreateVmDisk(
+void BruschettaInstallerImpl::OnCreateVmDisk(
     absl::optional<vm_tools::concierge::CreateDiskImageResponse> result) {
-  if (MaybeClose())
+  if (MaybeClose()) {
     return;
+  }
 
   if (!result ||
       result->status() !=
@@ -452,7 +468,7 @@
   StartVm();
 }
 
-void BruschettaInstaller::StartVm() {
+void BruschettaInstallerImpl::StartVm() {
   NotifyObserver(State::kStartVm);
 
   if (!GetInstallableConfig(profile_, config_id_)) {
@@ -486,6 +502,8 @@
   request.add_kernel_params("earlycon=uart8250,io,0x3f8");
   request.add_kernel_params("g-i/track=latest");
   request.add_kernel_params("glinux/bruschetta-alpha");
+  request.add_kernel_params("g-i/bruschetta-use-gbi=false");
+  request.add_kernel_params("g-i/undefok=bruschetta-use-gbi");
   request.set_timeout(240);
 
   // fds and request.fds must have the same order.
@@ -496,14 +514,15 @@
   fds.push_back(std::move(boot_disk_fd_));
 
   client->StartVmWithFds(std::move(fds), request,
-                         base::BindOnce(&BruschettaInstaller::OnStartVm,
+                         base::BindOnce(&BruschettaInstallerImpl::OnStartVm,
                                         weak_ptr_factory_.GetWeakPtr()));
 }
 
-void BruschettaInstaller::OnStartVm(
+void BruschettaInstallerImpl::OnStartVm(
     absl::optional<vm_tools::concierge::StartVmResponse> result) {
-  if (MaybeClose())
+  if (MaybeClose()) {
     return;
+  }
 
   if (!result || !result->success()) {
     install_running_ = false;
@@ -519,7 +538,7 @@
   LaunchTerminal();
 }
 
-void BruschettaInstaller::LaunchTerminal() {
+void BruschettaInstallerImpl::LaunchTerminal() {
   NotifyObserver(State::kLaunchTerminal);
 
   // TODO(b/231899688): Implement Bruschetta sending an RPC when installation
@@ -537,18 +556,32 @@
   std::move(close_closure_).Run();
 }
 
-void BruschettaInstaller::NotifyObserver(State state) {
-  if (observer_)
+void BruschettaInstallerImpl::NotifyObserver(State state) {
+  if (observer_) {
     observer_->StateChanged(state);
+  }
 }
 
-void BruschettaInstaller::NotifyObserverError() {
-  if (observer_)
+void BruschettaInstallerImpl::NotifyObserverError() {
+  if (observer_) {
     observer_->Error();
+  }
 }
 
-const base::GUID& BruschettaInstaller::GetDownloadGuid() const {
+const base::GUID& BruschettaInstallerImpl::GetDownloadGuid() const {
   return download_guid_;
 }
 
+void BruschettaInstallerImpl::AddObserver(Observer* observer) {
+  // We only support a single observer for now, since we'll only ever have one
+  // (the UI calling us).
+  DCHECK(observer_ == nullptr);
+  observer_ = observer;
+}
+
+void BruschettaInstallerImpl::RemoveObserver(Observer* observer) {
+  DCHECK(observer_ == observer);
+  observer_ = nullptr;
+}
+
 }  // namespace bruschetta
diff --git a/chrome/browser/ash/bruschetta/bruschetta_installer_impl.h b/chrome/browser/ash/bruschetta/bruschetta_installer_impl.h
new file mode 100644
index 0000000..7fb91e4e
--- /dev/null
+++ b/chrome/browser/ash/bruschetta/bruschetta_installer_impl.h
@@ -0,0 +1,104 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ASH_BRUSCHETTA_BRUSCHETTA_INSTALLER_IMPL_H_
+#define CHROME_BROWSER_ASH_BRUSCHETTA_BRUSCHETTA_INSTALLER_IMPL_H_
+
+#include "base/guid.h"
+#include "base/memory/raw_ptr.h"
+#include "base/values.h"
+#include "chrome/browser/ash/bruschetta/bruschetta_installer.h"
+#include "chromeos/ash/components/dbus/concierge/concierge_service.pb.h"
+#include "chromeos/ash/components/dbus/dlcservice/dlcservice_client.h"
+#include "chromeos/ash/components/disks/disk_mount_manager.h"
+#include "components/download/public/background_service/download_metadata.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "url/gurl.h"
+
+class Profile;
+
+namespace bruschetta {
+
+class BruschettaInstallerImpl : public BruschettaInstaller {
+ public:
+  BruschettaInstallerImpl(Profile* profile, base::OnceClosure close_callback);
+
+  BruschettaInstallerImpl(const BruschettaInstallerImpl&) = delete;
+  BruschettaInstallerImpl& operator=(const BruschettaInstallerImpl&) = delete;
+  ~BruschettaInstallerImpl() override;
+
+  void Cancel() override;
+  void Install(std::string vm_name, std::string config_id) override;
+
+  const base::GUID& GetDownloadGuid() const override;
+
+  void DownloadStarted(const std::string& guid,
+                       download::DownloadParams::StartResult result) override;
+  void DownloadFailed() override;
+  void DownloadSucceeded(
+      const download::CompletionInfo& completion_info) override;
+
+  void AddObserver(Observer* observer) override;
+  void RemoveObserver(Observer* observer) override;
+
+ private:
+  using DownloadCallback =
+      base::OnceCallback<void(const download::CompletionInfo&)>;
+
+  bool MaybeClose();
+
+  void StartDownload(GURL url, DownloadCallback callback);
+
+  void InstallToolsDlc();
+  void OnToolsDlcInstalled(
+      const ash::DlcserviceClient::InstallResult& install_result);
+  void DownloadFirmware();
+  void OnFirmwareDownloaded(const download::CompletionInfo& completion_info);
+  void MountFirmware(const base::FilePath& path);
+  void OnFirmwareMounted(ash::MountError error_code,
+                         const ash::MountPoint& mount_info);
+  void DownloadBootDisk();
+  void OnBootDiskDownloaded(const download::CompletionInfo& completion_info);
+  void MountBootDisk(const base::FilePath& path);
+  void OnBootDiskMounted(ash::MountError error_code,
+                         const ash::MountPoint& mount_info);
+  void OpenFds();
+  void OnOpenFds(absl::optional<std::pair<base::ScopedFD, base::ScopedFD>> fds);
+  void CreateVmDisk();
+  void OnCreateVmDisk(
+      absl::optional<vm_tools::concierge::CreateDiskImageResponse> result);
+  void StartVm();
+  void OnStartVm(absl::optional<vm_tools::concierge::StartVmResponse> result);
+  void LaunchTerminal();
+
+  void NotifyObserver(State state);
+  void NotifyObserverError();
+
+  bool install_running_ = false;
+
+  std::string vm_name_;
+  std::string config_id_;
+  base::Value::Dict config_;
+
+  base::GUID download_guid_;
+  DownloadCallback download_callback_;
+
+  std::string firmware_mount_path_;
+  std::string boot_disk_mount_path_;
+  base::ScopedFD firmware_fd_;
+  base::ScopedFD boot_disk_fd_;
+  std::string disk_path_;
+
+  const base::raw_ptr<Profile> profile_;
+
+  base::OnceClosure close_closure_;
+
+  base::raw_ptr<Observer> observer_ = nullptr;
+
+  base::WeakPtrFactory<BruschettaInstallerImpl> weak_ptr_factory_{this};
+};
+
+}  // namespace bruschetta
+
+#endif  // CHROME_BROWSER_ASH_BRUSCHETTA_BRUSCHETTA_INSTALLER_IMPL_H_
diff --git a/chrome/browser/ash/bruschetta/bruschetta_installer_unittest.cc b/chrome/browser/ash/bruschetta/bruschetta_installer_impl_unittest.cc
similarity index 95%
rename from chrome/browser/ash/bruschetta/bruschetta_installer_unittest.cc
rename to chrome/browser/ash/bruschetta/bruschetta_installer_impl_unittest.cc
index fee24ed..6201eb6 100644
--- a/chrome/browser/ash/bruschetta/bruschetta_installer_unittest.cc
+++ b/chrome/browser/ash/bruschetta/bruschetta_installer_impl_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 "chrome/browser/ash/bruschetta/bruschetta_installer.h"
+#include "chrome/browser/ash/bruschetta/bruschetta_installer_impl.h"
 
 #include "base/callback.h"
 #include "base/files/file_util.h"
@@ -52,7 +52,7 @@
     "fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210";
 const base::FilePath kDownloadPath{"/path/to/downloaded/object"};
 
-class MockObserver : public BruschettaInstaller::TestingObserver {
+class MockObserver : public BruschettaInstaller::Observer {
  public:
   MOCK_METHOD(void,
               StateChanged,
@@ -118,11 +118,11 @@
 
     BruschettaServiceFactory::EnableForTesting(&profile_);
 
-    installer_ = std::make_unique<BruschettaInstaller>(
+    installer_ = std::make_unique<BruschettaInstallerImpl>(
         &profile_, base::BindOnce(&BruschettaInstallerTest::CloseCallback,
                                   base::Unretained(this)));
 
-    installer_->set_observer_for_testing(&observer_);
+    installer_->AddObserver(&observer_);
   }
 
   void TearDown() override { ash::disks::DiskMountManager::Shutdown(); }
@@ -526,13 +526,16 @@
 
   download::test::TestDownloadService* download_service_;
   BruschettaDownloadClient download_client_{&profile_};
+  bool destroy_installer_on_completion_ = true;
 
  private:
   // Called when the installer exists, suitable for base::BindOnce.
   void CloseCallback() {
-    // Delete the installer object after it requests closure so we can tell if
-    // it does anything afterwards that assumes it hasn't been deleted yet.
-    installer_.reset();
+    if (destroy_installer_on_completion_) {
+      // Delete the installer object after it requests closure so we can tell if
+      // it does anything afterwards that assumes it hasn't been deleted yet.
+      installer_.reset();
+    }
     run_loop_.Quit();
     run_loop_2_.Quit();
   }
@@ -564,6 +567,17 @@
   EXPECT_FALSE(installer_);
 }
 
+TEST_F(BruschettaInstallerTest, MultipleCancelsNoOp) {
+  destroy_installer_on_completion_ = false;
+  // Should be safe to call cancel multiple times.
+  installer_->Cancel();
+  installer_->Cancel();
+  run_loop_.Run();
+  installer_->Cancel();
+  installer_->Cancel();
+  run_loop_2_.Run();
+}
+
 TEST_P(BruschettaInstallerTest, StopDuringInstall) {
   bool is_error = ExpectStopOnStepN(GetParam());
 
diff --git a/chrome/browser/ash/cert_provisioning/cert_provisioning_scheduler.cc b/chrome/browser/ash/cert_provisioning/cert_provisioning_scheduler.cc
index 95d716c..225b321 100644
--- a/chrome/browser/ash/cert_provisioning/cert_provisioning_scheduler.cc
+++ b/chrome/browser/ash/cert_provisioning/cert_provisioning_scheduler.cc
@@ -297,7 +297,7 @@
       pref_service_->GetDict(GetPrefNameForSerialization(cert_scope_));
 
   for (const auto kv : saved_workers) {
-    const base::Value& saved_worker = kv.second;
+    const base::Value::Dict& saved_worker = kv.second.GetDict();
 
     std::unique_ptr<CertProvisioningWorker> worker =
         CertProvisioningWorkerFactory::Get()->Deserialize(
diff --git a/chrome/browser/ash/cert_provisioning/cert_provisioning_scheduler_unittest.cc b/chrome/browser/ash/cert_provisioning/cert_provisioning_scheduler_unittest.cc
index 0c1054e..7f84b9df 100644
--- a/chrome/browser/ash/cert_provisioning/cert_provisioning_scheduler_unittest.cc
+++ b/chrome/browser/ash/cert_provisioning/cert_provisioning_scheduler_unittest.cc
@@ -536,10 +536,11 @@
           "public_key": "fake_public_key_1",
           "state": 1
         })");
-  base::Value all_saved_workers(base::Value::Type::DICTIONARY);
-  all_saved_workers.SetKey("cert_profile_1", saved_worker.Clone());
+  base::Value::Dict all_saved_workers;
+  all_saved_workers.Set("cert_profile_1", saved_worker.Clone());
 
-  pref_service_.Set(GetPrefNameForSerialization(kCertScope), all_saved_workers);
+  pref_service_.SetDict(GetPrefNameForSerialization(kCertScope),
+                        std::move(all_saved_workers));
 
   MockCertProvisioningWorker* worker =
       mock_factory_.ExpectDeserializeReturnMock(kCertScope, saved_worker);
@@ -796,11 +797,11 @@
           "public_key": "fake_public_key_1",
           "state": 1
         })");
-    base::Value all_saved_workers(base::Value::Type::DICTIONARY);
-    all_saved_workers.SetKey("cert_profile_1", saved_worker.Clone());
+    base::Value::Dict all_saved_workers;
+    all_saved_workers.Set("cert_profile_1", saved_worker.Clone());
 
-    pref_service_.Set(GetPrefNameForSerialization(kCertScope),
-                      all_saved_workers);
+    pref_service_.SetDict(GetPrefNameForSerialization(kCertScope),
+                          std::move(all_saved_workers));
 
     MockCertProvisioningWorker* worker =
         mock_factory_.ExpectDeserializeReturnMock(kCertScope, saved_worker);
diff --git a/chrome/browser/ash/cert_provisioning/cert_provisioning_serializer.cc b/chrome/browser/ash/cert_provisioning/cert_provisioning_serializer.cc
index 02a55a3..e9b8d30 100644
--- a/chrome/browser/ash/cert_provisioning/cert_provisioning_serializer.cc
+++ b/chrome/browser/ash/cert_provisioning/cert_provisioning_serializer.cc
@@ -39,73 +39,71 @@
 }
 
 template <typename T>
-bool DeserializeEnumValue(const base::Value& parent_value,
+bool DeserializeEnumValue(const base::Value::Dict& parent_value,
                           const char* value_name,
                           T* dst) {
-  const base::Value* serialized_enum =
-      parent_value.FindKeyOfType(value_name, base::Value::Type::INTEGER);
+  const absl::optional<int> serialized_enum = parent_value.FindInt(value_name);
   if (!serialized_enum) {
     return false;
   }
-  return ConvertToEnum<T>(serialized_enum->GetInt(), dst);
+  return ConvertToEnum<T>(*serialized_enum, dst);
 }
 
-bool DeserializeStringValue(const base::Value& parent_value,
+bool DeserializeStringValue(const base::Value::Dict& parent_value,
                             const char* value_name,
                             std::string* dst) {
-  const base::Value* serialized_string =
-      parent_value.FindKeyOfType(value_name, base::Value::Type::STRING);
+  const std::string* serialized_string = parent_value.FindString(value_name);
   if (!serialized_string) {
     return false;
   }
-  *dst = serialized_string->GetString();
+  *dst = *serialized_string;
   return true;
 }
 
-bool DeserializeBoolValue(const base::Value& parent_value,
+bool DeserializeBoolValue(const base::Value::Dict& parent_value,
                           const char* value_name,
                           bool* dst) {
-  const base::Value* serialized_bool =
-      parent_value.FindKeyOfType(value_name, base::Value::Type::BOOLEAN);
+  const absl::optional<bool> serialized_bool =
+      parent_value.FindBool(value_name);
   if (!serialized_bool) {
     return false;
   }
-  *dst = serialized_bool->GetBool();
+  *dst = *serialized_bool;
   return true;
 }
 
-bool DeserializeRenewalPeriod(const base::Value& parent_value,
+bool DeserializeRenewalPeriod(const base::Value::Dict& parent_value,
                               const char* value_name,
                               base::TimeDelta* dst) {
-  absl::optional<int> serialized_time = parent_value.FindIntKey(value_name);
+  absl::optional<int> serialized_time = parent_value.FindInt(value_name);
   *dst = base::Seconds(serialized_time.value_or(0));
   return true;
 }
 
-base::Value SerializeCertProfile(const CertProfile& profile) {
+base::Value::Dict SerializeCertProfile(const CertProfile& profile) {
   static_assert(CertProfile::kVersion == 5, "This function should be updated");
 
-  base::Value result(base::Value::Type::DICTIONARY);
-  result.SetStringKey(kKeyNameCertProfileId, profile.profile_id);
-  result.SetStringKey(kKeyNameCertProfileName, profile.name);
-  result.SetStringKey(kKeyNameCertProfileVersion, profile.policy_version);
-  result.SetBoolKey(kKeyNameCertProfileVaEnabled, profile.is_va_enabled);
+  base::Value::Dict result;
+  result.Set(kKeyNameCertProfileId, profile.profile_id);
+  result.Set(kKeyNameCertProfileName, profile.name);
+  result.Set(kKeyNameCertProfileVersion, profile.policy_version);
+  result.Set(kKeyNameCertProfileVaEnabled, profile.is_va_enabled);
 
   if (!profile.renewal_period.is_zero()) {
-    result.SetIntKey(kKeyNameCertProfileRenewalPeriod,
-                     profile.renewal_period.InSeconds());
+    result.Set(kKeyNameCertProfileRenewalPeriod,
+               static_cast<int>(profile.renewal_period.InSeconds()));
   }
 
   return result;
 }
 
-bool DeserializeCertProfile(const base::Value& parent_value,
+bool DeserializeCertProfile(const base::Value::Dict& parent_value,
                             const char* value_name,
                             CertProfile* dst) {
   static_assert(CertProfile::kVersion == 5, "This function should be updated");
 
-  const base::Value* serialized_profile =
-      parent_value.FindKeyOfType(value_name, base::Value::Type::DICTIONARY);
+  const base::Value::Dict* serialized_profile =
+      parent_value.FindDict(value_name);
 
   if (!serialized_profile) {
     return false;
@@ -134,18 +132,18 @@
   return base::Value(base::Base64Encode(public_key));
 }
 
-bool DeserializePublicKey(const base::Value& parent_value,
+bool DeserializePublicKey(const base::Value::Dict& parent_value,
                           const char* value_name,
                           std::vector<uint8_t>* dst) {
-  const base::Value* serialized_public_key =
-      parent_value.FindKeyOfType(value_name, base::Value::Type::STRING);
+  const std::string* serialized_public_key =
+      parent_value.FindString(value_name);
 
   if (!serialized_public_key) {
     return false;
   }
 
   absl::optional<std::vector<uint8_t>> public_key =
-      base::Base64Decode(serialized_public_key->GetString());
+      base::Base64Decode(*serialized_public_key);
   if (!public_key) {
     return false;
   }
@@ -184,24 +182,23 @@
 //   "public_key": <string>,
 //   "invalidation_topic": <string>,
 // }
-base::Value CertProvisioningSerializer::SerializeWorker(
+base::Value::Dict CertProvisioningSerializer::SerializeWorker(
     const CertProvisioningWorkerImpl& worker) {
   static_assert(CertProvisioningWorkerImpl::kVersion == 1,
                 "This function should be updated");
 
-  base::Value result(base::Value::Type::DICTIONARY);
+  base::Value::Dict result;
 
-  result.SetKey(kKeyNameCertProfile,
-                SerializeCertProfile(worker.cert_profile_));
-  result.SetIntKey(kKeyNameCertScope, static_cast<int>(worker.cert_scope_));
-  result.SetIntKey(kKeyNameState, static_cast<int>(worker.state_));
-  result.SetKey(kKeyNamePublicKey, SerializePublicKey(worker.public_key_));
-  result.SetStringKey(kKeyNameInvalidationTopic, worker.invalidation_topic_);
+  result.Set(kKeyNameCertProfile, SerializeCertProfile(worker.cert_profile_));
+  result.Set(kKeyNameCertScope, static_cast<int>(worker.cert_scope_));
+  result.Set(kKeyNameState, static_cast<int>(worker.state_));
+  result.Set(kKeyNamePublicKey, SerializePublicKey(worker.public_key_));
+  result.Set(kKeyNameInvalidationTopic, worker.invalidation_topic_);
   return result;
 }
 
 bool CertProvisioningSerializer::DeserializeWorker(
-    const base::Value& saved_worker,
+    const base::Value::Dict& saved_worker,
     CertProvisioningWorkerImpl* worker) {
   static_assert(CertProvisioningWorkerImpl::kVersion == 1,
                 "This function should be updated");
diff --git a/chrome/browser/ash/cert_provisioning/cert_provisioning_serializer.h b/chrome/browser/ash/cert_provisioning/cert_provisioning_serializer.h
index 0f3465d..88eb0da4 100644
--- a/chrome/browser/ash/cert_provisioning/cert_provisioning_serializer.h
+++ b/chrome/browser/ash/cert_provisioning/cert_provisioning_serializer.h
@@ -24,11 +24,12 @@
   // Deserializes saved worker state |saved_worker| into a just created
   // |worker|. Consider using CertProvisioningWorkerFactory::Deserialize
   // instead of calling it directly.
-  static bool DeserializeWorker(const base::Value& saved_worker,
+  static bool DeserializeWorker(const base::Value::Dict& saved_worker,
                                 CertProvisioningWorkerImpl* worker);
 
  private:
-  static base::Value SerializeWorker(const CertProvisioningWorkerImpl& worker);
+  static base::Value::Dict SerializeWorker(
+      const CertProvisioningWorkerImpl& worker);
 };
 
 }  // namespace cert_provisioning
diff --git a/chrome/browser/ash/cert_provisioning/cert_provisioning_worker.cc b/chrome/browser/ash/cert_provisioning/cert_provisioning_worker.cc
index 7a8421f2..dde2fef 100644
--- a/chrome/browser/ash/cert_provisioning/cert_provisioning_worker.cc
+++ b/chrome/browser/ash/cert_provisioning/cert_provisioning_worker.cc
@@ -233,7 +233,7 @@
     CertScope cert_scope,
     Profile* profile,
     PrefService* pref_service,
-    const base::Value& saved_worker,
+    const base::Value::Dict& saved_worker,
     policy::CloudPolicyClient* cloud_policy_client,
     std::unique_ptr<CertProvisioningInvalidator> invalidator,
     base::RepeatingClosure state_change_callback,
diff --git a/chrome/browser/ash/cert_provisioning/cert_provisioning_worker.h b/chrome/browser/ash/cert_provisioning/cert_provisioning_worker.h
index c684854..bd49dc3 100644
--- a/chrome/browser/ash/cert_provisioning/cert_provisioning_worker.h
+++ b/chrome/browser/ash/cert_provisioning/cert_provisioning_worker.h
@@ -71,7 +71,7 @@
       CertScope cert_scope,
       Profile* profile,
       PrefService* pref_service,
-      const base::Value& saved_worker,
+      const base::Value::Dict& saved_worker,
       policy::CloudPolicyClient* cloud_policy_client,
       std::unique_ptr<CertProvisioningInvalidator> invalidator,
       base::RepeatingClosure state_change_callback,
diff --git a/chrome/browser/ash/cert_provisioning/cert_provisioning_worker_unittest.cc b/chrome/browser/ash/cert_provisioning/cert_provisioning_worker_unittest.cc
index ee11c70..c0d96fcd 100644
--- a/chrome/browser/ash/cert_provisioning/cert_provisioning_worker_unittest.cc
+++ b/chrome/browser/ash/cert_provisioning/cert_provisioning_worker_unittest.cc
@@ -1727,9 +1727,9 @@
 
     worker = CertProvisioningWorkerFactory::Get()->Deserialize(
         kCertScope, GetProfile(), &testing_pref_service_,
-        *pref_val.FindKeyOfType(kCertProfileId, base::Value::Type::DICTIONARY),
-        &cloud_policy_client_, MakeInvalidator(&mock_invalidator),
-        GetStateChangeCallback(), GetResultCallback());
+        *pref_val.GetDict().FindDict(kCertProfileId), &cloud_policy_client_,
+        MakeInvalidator(&mock_invalidator), GetStateChangeCallback(),
+        GetResultCallback());
   }
 
   // Retry start csr request, receive response, try sign challenge.
@@ -1813,9 +1813,9 @@
 
     worker = CertProvisioningWorkerFactory::Get()->Deserialize(
         kCertScope, GetProfile(), &testing_pref_service_,
-        *pref_val.FindKeyOfType(kCertProfileId, base::Value::Type::DICTIONARY),
-        &cloud_policy_client_, std::move(mock_invalidator_obj),
-        GetStateChangeCallback(), GetResultCallback());
+        *pref_val.GetDict().FindDict(kCertProfileId), &cloud_policy_client_,
+        std::move(mock_invalidator_obj), GetStateChangeCallback(),
+        GetResultCallback());
   }
 
   // Retry download cert request, receive response, try import certificate.
diff --git a/chrome/browser/ash/cert_provisioning/mock_cert_provisioning_worker.h b/chrome/browser/ash/cert_provisioning/mock_cert_provisioning_worker.h
index c504490..c7c3480 100644
--- a/chrome/browser/ash/cert_provisioning/mock_cert_provisioning_worker.h
+++ b/chrome/browser/ash/cert_provisioning/mock_cert_provisioning_worker.h
@@ -43,7 +43,7 @@
               (CertScope cert_scope,
                Profile* profile,
                PrefService* pref_service,
-               const base::Value& saved_worker,
+               const base::Value::Dict& saved_worker,
                policy::CloudPolicyClient* cloud_policy_client,
                std::unique_ptr<CertProvisioningInvalidator> invalidator,
                base::RepeatingClosure state_change_callback,
diff --git a/chrome/browser/ash/crostini/crostini_manager.cc b/chrome/browser/ash/crostini/crostini_manager.cc
index 885d752d..03e6c1e 100644
--- a/chrome/browser/ash/crostini/crostini_manager.cc
+++ b/chrome/browser/ash/crostini/crostini_manager.cc
@@ -4116,43 +4116,43 @@
     return false;
   }
 
-  base::Value new_create_options(base::Value::Type::DICT);
+  base::Value::Dict new_create_options;
 
-  base::Value share_paths(base::Value::Type::LIST);
+  base::Value::List share_paths;
   for (const base::FilePath& path : options.share_paths) {
     share_paths.Append(path.value());
   }
-  new_create_options.SetKey(prefs::kCrostiniCreateOptionsSharePathsKey,
-                            std::move(share_paths));
+  new_create_options.Set(prefs::kCrostiniCreateOptionsSharePathsKey,
+                         std::move(share_paths));
 
   if (options.container_username.has_value()) {
-    new_create_options.SetKey(prefs::kCrostiniCreateOptionsContainerUsernameKey,
-                              base::Value(options.container_username.value()));
+    new_create_options.Set(prefs::kCrostiniCreateOptionsContainerUsernameKey,
+                           base::Value(options.container_username.value()));
   }
   if (options.disk_size_bytes.has_value()) {
-    new_create_options.SetKey(
+    new_create_options.Set(
         prefs::kCrostiniCreateOptionsDiskSizeBytesKey,
         base::Value(base::NumberToString(options.disk_size_bytes.value())));
   }
   if (options.image_server_url.has_value()) {
-    new_create_options.SetKey(prefs::kCrostiniCreateOptionsImageServerUrlKey,
-                              base::Value(options.image_server_url.value()));
+    new_create_options.Set(prefs::kCrostiniCreateOptionsImageServerUrlKey,
+                           base::Value(options.image_server_url.value()));
   }
   if (options.image_alias.has_value()) {
-    new_create_options.SetKey(prefs::kCrostiniCreateOptionsImageAliasKey,
-                              base::Value(options.image_alias.value()));
+    new_create_options.Set(prefs::kCrostiniCreateOptionsImageAliasKey,
+                           base::Value(options.image_alias.value()));
   }
   if (options.ansible_playbook.has_value()) {
-    new_create_options.SetKey(
+    new_create_options.Set(
         prefs::kCrostiniCreateOptionsAnsiblePlaybookKey,
         base::Value(options.ansible_playbook.value().value()));
   }
-  new_create_options.SetKey(prefs::kCrostiniCreateOptionsUsedKey,
-                            base::Value(false));
+  new_create_options.Set(prefs::kCrostiniCreateOptionsUsedKey,
+                         base::Value(false));
 
   guest_os::UpdateContainerPref(profile_, container_id,
                                 guest_os::prefs::kContainerCreateOptions,
-                                std::move(new_create_options));
+                                base::Value(std::move(new_create_options)));
   return true;
 }
 
diff --git a/chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_utils.cc b/chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_utils.cc
index 26a4dcb..dd8057d0 100644
--- a/chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_utils.cc
+++ b/chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_utils.cc
@@ -38,12 +38,12 @@
 }  // namespace
 
 std::string FormatJsonRequest(const mojom::TtsRequestPtr tts_request) {
-  base::Value request(base::Value::Type::DICTIONARY);
+  base::Value::Dict request;
 
   // utterance is sent as {'text': {'text_parts': [<utterance>]} }
-  base::Value text_parts(base::Value::Type::LIST);
+  base::Value::List text_parts;
   text_parts.Append(std::move(tts_request->utterance));
-  request.SetPath(kTextPartsPath, std::move(text_parts));
+  request.SetByDottedPath(kTextPartsPath, std::move(text_parts));
 
   // Speech rate, Voice and language are sent as
   // {
@@ -66,26 +66,27 @@
 
   // Add speech rate.
   const float rate = ClampRateToLimits(tts_request->rate);
-  request.SetPath(kSpeechFactorPath, base::Value(rate));
+  request.SetByDottedPath(kSpeechFactorPath, base::Value(rate));
 
   // The voice and language have to be set together to be valid.
   if (tts_request->voice.has_value() && tts_request->lang.has_value()) {
     // Force the server to produce audio based on the current lang.
-    request.SetPath(kForceLanguagePath, base::Value(tts_request->lang.value()));
+    request.SetByDottedPath(kForceLanguagePath,
+                            base::Value(tts_request->lang.value()));
 
     // Produce 'voice_criteria_and_selections'.
-    base::Value selection(base::Value::Type::DICTIONARY);
-    selection.SetKey(kDefaultVoiceKey,
-                     base::Value(std::move(tts_request->voice.value())));
-    base::Value criteria(base::Value::Type::DICTIONARY);
-    criteria.SetKey(kLanguageKey, base::Value(tts_request->lang.value()));
-    base::Value voice_selection(base::Value::Type::DICTIONARY);
-    voice_selection.SetKey(kSelectionKey, std::move(selection));
-    voice_selection.SetKey(kCriteriaKey, std::move(criteria));
-    base::Value voice_criteria_and_selections(base::Value::Type::LIST);
+    base::Value::Dict selection;
+    selection.Set(kDefaultVoiceKey,
+                  base::Value(std::move(tts_request->voice.value())));
+    base::Value::Dict criteria;
+    criteria.Set(kLanguageKey, base::Value(tts_request->lang.value()));
+    base::Value::Dict voice_selection;
+    voice_selection.Set(kSelectionKey, std::move(selection));
+    voice_selection.Set(kCriteriaKey, std::move(criteria));
+    base::Value::List voice_criteria_and_selections;
     voice_criteria_and_selections.Append(std::move(voice_selection));
-    request.SetPath(kVoiceCriteriaAndSelectionsPath,
-                    std::move(voice_criteria_and_selections));
+    request.SetByDottedPath(kVoiceCriteriaAndSelectionsPath,
+                            std::move(voice_criteria_and_selections));
   }
 
   std::string json_request;
diff --git a/chrome/browser/ash/file_manager/app_service_file_tasks_unittest.cc b/chrome/browser/ash/file_manager/app_service_file_tasks_unittest.cc
index ba603e7..796fcbd 100644
--- a/chrome/browser/ash/file_manager/app_service_file_tasks_unittest.cc
+++ b/chrome/browser/ash/file_manager/app_service_file_tasks_unittest.cc
@@ -352,21 +352,10 @@
  public:
   AppServiceFileTasksTestDisabled() {
     feature_list_.InitWithFeatures(
-        {}, {blink::features::kFileHandlingAPI,
-             ash::features::kArcAndGuestOsFileTasksUseAppService});
+        {}, {ash::features::kArcAndGuestOsFileTasksUseAppService});
   }
 };
 
-// Web Apps should not be able to handle files when kFileHandlingAPI is
-// disabled.
-TEST_F(AppServiceFileTasksTestDisabled, FindAppServiceFileTasksText) {
-  AddTextApp();
-  // Find apps for a "text/plain" file.
-  std::vector<FullTaskDescriptor> tasks =
-      FindAppServiceTasks({{"foo.txt", kMimeTypeText}});
-  ASSERT_EQ(0U, tasks.size());
-}
-
 // ARC apps should not be found when kArcAndGuestOsFileTasksUseAppService is
 // disabled.
 TEST_F(AppServiceFileTasksTestDisabled, FindAppServiceArcApp) {
diff --git a/chrome/browser/ash/file_manager/fusebox_daemon.cc b/chrome/browser/ash/file_manager/fusebox_daemon.cc
new file mode 100644
index 0000000..934c5e6
--- /dev/null
+++ b/chrome/browser/ash/file_manager/fusebox_daemon.cc
@@ -0,0 +1,96 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/file_manager/fusebox_daemon.h"
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/check.h"
+#include "base/logging.h"
+#include "chrome/browser/ash/fusebox/fusebox_server.h"
+
+namespace file_manager {
+
+// static
+scoped_refptr<FuseBoxDaemon> FuseBoxDaemon::GetInstance() {
+  static auto* fusebox_daemon = new FuseBoxDaemon;
+  return fusebox_daemon;
+}
+
+FuseBoxDaemon::FuseBoxDaemon() {
+  cros_disks_mount_manager_ = CrosDisksMountManager::GetInstance();
+
+  if (!cros_disks_mount_manager_) {
+    return;  // cros_disks_mount_manager_ can be null in unit_tests.
+  }
+
+  constexpr auto type = ash::MountType::kNetworkStorage;
+  constexpr auto mode = ash::MountAccessMode::kReadWrite;
+
+  cros_disks_mount_manager_->MountPath(
+      CrosDisksFuseBoxHelperURI(),
+      /*source_format*/ {},
+      /*mount_label*/ {},
+      /*options*/ {/* add fusebox --flags here */}, type, mode,
+      base::BindOnce(&FuseBoxDaemon::MountResponse,
+                     weak_ptr_factory_.GetWeakPtr()));
+}
+
+void FuseBoxDaemon::MountResponse(ash::MountError error,
+                                  const FuseBoxMountInfo& info) {
+  if (error == ash::MountError::kSuccess) {
+    mounted_ = true;
+  } else {
+    LOG(ERROR) << CrosDisksFuseBoxHelperURI() << " mount error " << error;
+    mounted_ = (error == ash::MountError::kPathAlreadyMounted);
+  }
+
+  if (mounted_ && !pending_attach_storage_calls_.empty()) {
+    const auto queued = pending_attach_storage_calls_.size();
+    VLOG(1) << "Calling " << queued << " queued AttachStorage calls";
+    for (const auto& it : pending_attach_storage_calls_) {
+      const auto& [url, read_only] = it.second;
+      AttachStorage(it.first, url, read_only);
+    }
+  }
+
+  pending_attach_storage_calls_.clear();
+}
+
+void FuseBoxDaemon::AttachStorage(const std::string& subdir,
+                                  const std::string& url,
+                                  bool read_only) {
+  if (!mounted_) {
+    VLOG(1) << "FuseBox is not mounted: queued AttachStorage call";
+    pending_attach_storage_calls_.emplace(subdir, std::pair{url, read_only});
+    return;
+  }
+
+  if (auto* fusebox_server = fusebox::Server::GetInstance()) {
+    fusebox_server->RegisterFSURLPrefix(subdir, url, read_only);
+  } else {
+    VLOG(1) << "No FuseBox server available for AttachStorage";
+  }
+}
+
+void FuseBoxDaemon::DetachStorage(const std::string& subdir) {
+  pending_attach_storage_calls_.erase(subdir);
+
+  if (auto* fusebox_server = fusebox::Server::GetInstance()) {
+    fusebox_server->UnregisterFSURLPrefix(subdir);
+  } else {
+    VLOG(1) << "No FuseBox server available for DetachStorage";
+  }
+}
+
+FuseBoxDaemon::~FuseBoxDaemon() {
+  if (!cros_disks_mount_manager_) {
+    return;  // cros_disks_mount_manager_ can be null in unit_tests.
+  }
+
+  cros_disks_mount_manager_->UnmountPath(CrosDisksFuseBoxHelperURI(),
+                                         base::DoNothing());
+}
+
+}  // namespace file_manager
diff --git a/chrome/browser/ash/file_manager/fusebox_daemon.h b/chrome/browser/ash/file_manager/fusebox_daemon.h
new file mode 100644
index 0000000..dea507b
--- /dev/null
+++ b/chrome/browser/ash/file_manager/fusebox_daemon.h
@@ -0,0 +1,68 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ASH_FILE_MANAGER_FUSEBOX_DAEMON_H_
+#define CHROME_BROWSER_ASH_FILE_MANAGER_FUSEBOX_DAEMON_H_
+
+#include <map>
+#include <string>
+
+#include "base/component_export.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "chromeos/ash/components/disks/disk_mount_manager.h"
+
+namespace file_manager {
+
+class COMPONENT_EXPORT(ASH_DBUS_CROS_DISKS) FuseBoxDaemon
+    : public base::RefCounted<FuseBoxDaemon> {
+ public:
+  // Returns the fusebox daemon. Creates the fusebox daemon if needed.
+  static scoped_refptr<FuseBoxDaemon> GetInstance();
+
+  // Attach fusebox storage: adds fusebox daemon <mount-point>/subdir used to
+  // serve the content of the Chrome storage::FileSystemURL |url| via FUSE to
+  // the Linux file system. The <mount-point>/subdir content is read-write by
+  // default: use |read_only| true to make the content read-only.
+  void AttachStorage(const std::string& subdir,
+                     const std::string& url,
+                     bool read_only);
+
+  // Detach fusebox storage: removes fusebox daemon <mount-point>/subdir.
+  void DetachStorage(const std::string& subdir);
+
+ private:
+  friend class base::RefCounted<FuseBoxDaemon>;
+
+  FuseBoxDaemon();
+  ~FuseBoxDaemon();
+
+  // Cros-disks mount manager.
+  using CrosDisksMountManager = ::ash::disks::DiskMountManager;
+  CrosDisksMountManager* cros_disks_mount_manager_ = nullptr;
+
+  // FuseBox daemon URI: cros-disks URI protocol is fusebox://<mount-point>.
+  static char* CrosDisksFuseBoxHelperURI() {
+    static char kCrosDisksFuseBoxHelperURI[] = "fusebox://fusebox";
+    return kCrosDisksFuseBoxHelperURI;
+  }
+
+  // Construction creates and mounts the cros-disks fusebox daemon.
+  using FuseBoxMountInfo = ::ash::disks::DiskMountManager::MountPoint;
+  void MountResponse(ash::MountError error, const FuseBoxMountInfo& info);
+
+  // True if the fusebox daemon was successfully mounted.
+  bool mounted_ = false;
+
+  // List of `AttachStorage` calls prior to the fusebox daemon mount.
+  using UrlReadOnlyPair = std::pair<std::string, bool>;
+  std::map<std::string, UrlReadOnlyPair> pending_attach_storage_calls_;
+
+  // base::WeakPtr{this} factory.
+  base::WeakPtrFactory<FuseBoxDaemon> weak_ptr_factory_{this};
+};
+
+}  // namespace file_manager
+
+#endif  // CHROME_BROWSER_ASH_FILE_MANAGER_FUSEBOX_DAEMON_H_
diff --git a/chrome/browser/ash/file_manager/fusebox_mounter.cc b/chrome/browser/ash/file_manager/fusebox_mounter.cc
deleted file mode 100644
index 01d9b419..0000000
--- a/chrome/browser/ash/file_manager/fusebox_mounter.cc
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright 2022 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ash/file_manager/fusebox_mounter.h"
-
-#include <cerrno>
-#include <utility>
-
-#include "ash/constants/ash_features.h"
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/check.h"
-#include "base/logging.h"
-#include "base/memory/weak_ptr.h"
-#include "base/strings/string_util.h"
-#include "base/task/thread_pool.h"
-#include "chrome/browser/ash/fusebox/fusebox_server.h"
-#include "chromeos/ash/components/dbus/cros_disks/cros_disks_client.h"
-#include "chromeos/ash/components/disks/disk_mount_manager.h"
-
-namespace file_manager {
-
-namespace {
-// The first "fusebox" is the URI scheme that is matched by cros-disks'
-// "fusebox_helper.cc". The second "fusebox" is the "foo" in "/media/fuse/foo".
-const char kFuseBoxMounterURI[] = "fusebox://fusebox";
-}  // namespace
-
-FuseBoxMounter::FuseBoxMounter() = default;
-
-FuseBoxMounter::~FuseBoxMounter() = default;
-
-void FuseBoxMounter::AttachStorage(const std::string& subdir,
-                                   const std::string& url,
-                                   bool read_only) {
-  if (!mounted_) {
-    VLOG(1) << "Fusebox isn't mounted, queueing AttachStorage call";
-    pending_attach_storage_calls_.emplace(subdir,
-                                          std::make_pair(url, read_only));
-    return;
-  }
-  fusebox::Server* fusebox_server = fusebox::Server::GetInstance();
-  if (fusebox_server) {
-    fusebox_server->RegisterFSURLPrefix(subdir, url, read_only);
-  } else {
-    VLOG(1) << "No fusebox server available on AttachStorage";
-  }
-}
-
-void FuseBoxMounter::DetachStorage(const std::string& subdir) {
-  if (!mounted_) {
-    VLOG(1) << "Fusebox isn't mounted, removing queued AttachStorage call";
-    pending_attach_storage_calls_.erase(subdir);
-    return;
-  }
-  fusebox::Server* fusebox_server = fusebox::Server::GetInstance();
-  if (fusebox_server) {
-    fusebox_server->UnregisterFSURLPrefix(subdir);
-  } else {
-    VLOG(1) << "No fusebox server available on DetachStorage";
-  }
-}
-
-void FuseBoxMounter::Mount(FuseBoxDiskMountManager* disk_mount_manager) {
-  DCHECK(disk_mount_manager);
-
-  constexpr auto type = ash::MountType::kNetworkStorage;
-  constexpr auto mode = ash::MountAccessMode::kReadWrite;
-
-  disk_mount_manager->MountPath(kFuseBoxMounterURI, /*source_format*/ {},
-                                /*mount_label*/ {},
-                                /*options*/ {}, type, mode,
-                                base::BindOnce(&FuseBoxMounter::MountResponse,
-                                               weak_ptr_factory_.GetWeakPtr()));
-}
-
-void FuseBoxMounter::Unmount(FuseBoxDiskMountManager* disk_mount_manager) {
-  DCHECK(disk_mount_manager);
-
-  if (!mounted_) {
-    VLOG(1) << "FuseBoxMounter::Unmount ignored: not mounted";
-    return;
-  }
-
-  disk_mount_manager->UnmountPath(
-      kFuseBoxMounterURI, base::BindOnce(&FuseBoxMounter::UnmountResponse,
-                                         weak_ptr_factory_.GetWeakPtr()));
-}
-
-void FuseBoxMounter::MountResponse(ash::MountError error,
-                                   const FuseBoxMountInfo& info) {
-  if (error != ash::MountError::kSuccess) {
-    LOG(ERROR) << kFuseBoxMounterURI << " mount error " << error;
-  } else {
-    mounted_ = true;
-    if (!pending_attach_storage_calls_.empty()) {
-      VLOG(1) << "Calling " << pending_attach_storage_calls_.size()
-              << " queued AttachStorage calls";
-      for (const auto& it : pending_attach_storage_calls_) {
-        const auto& [url, read_only] = it.second;
-        AttachStorage(it.first, url, read_only);
-      }
-    }
-  }
-  pending_attach_storage_calls_.clear();
-}
-
-void FuseBoxMounter::UnmountResponse(ash::MountError error) {
-  if (error != ash::MountError::kSuccess) {
-    LOG(ERROR) << kFuseBoxMounterURI << " unmount error " << error;
-  } else {
-    mounted_ = false;
-  }
-  pending_attach_storage_calls_.clear();
-}
-
-}  // namespace file_manager
diff --git a/chrome/browser/ash/file_manager/fusebox_mounter.h b/chrome/browser/ash/file_manager/fusebox_mounter.h
deleted file mode 100644
index 3799224..0000000
--- a/chrome/browser/ash/file_manager/fusebox_mounter.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2022 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_ASH_FILE_MANAGER_FUSEBOX_MOUNTER_H_
-#define CHROME_BROWSER_ASH_FILE_MANAGER_FUSEBOX_MOUNTER_H_
-
-#include <map>
-#include <string>
-
-#include "base/callback_forward.h"
-#include "base/memory/weak_ptr.h"
-#include "chromeos/ash/components/dbus/cros_disks/cros_disks_client.h"
-#include "chromeos/ash/components/disks/disk_mount_manager.h"
-
-namespace file_manager {
-
-using FuseBoxDiskMountManager = ::ash::disks::DiskMountManager;
-
-using FuseBoxMountInfo = ::ash::disks::DiskMountManager::MountPoint;
-
-using UrlReadOnlyPair = std::pair<std::string, bool>;
-
-class FuseBoxMounter {
- public:
-  FuseBoxMounter();
-  FuseBoxMounter(const FuseBoxMounter&) = delete;
-  FuseBoxMounter& operator=(const FuseBoxMounter&) = delete;
-  ~FuseBoxMounter();
-
-  // Attach fusebox storage: adds fusebox daemon <mount-point>/subdir used to
-  // serve the content of the Chrome storage::FileSystemURL |url| via FUSE to
-  // the Linux file system. The <mount-point>/subdir content is read-write by
-  // default: use |read_only| true to make the content read-only.
-  void AttachStorage(const std::string& subdir,
-                     const std::string& url,
-                     bool read_only);
-
-  // Detach fusebox storage: removes fusebox <mountpoint>/subdir.
-  void DetachStorage(const std::string& subdir);
-
-  // Mount fusebox daemon.
-  void Mount(FuseBoxDiskMountManager* disk_mount_manager);
-
-  // Unmount fusebox daemon.
-  void Unmount(FuseBoxDiskMountManager* disk_mount_manager);
-
- private:
-  // Mount response.
-  void MountResponse(ash::MountError error, const FuseBoxMountInfo& info);
-
-  // Unmount response.
-  void UnmountResponse(ash::MountError error);
-
- private:
-  // True if this fusebox instance is mounted.
-  bool mounted_ = false;
-
-  // A list of `AttachStorage` invocations that were called prior to the fusebox
-  // mounting, these get called when fusebox successfully mounts.
-  std::map<std::string, UrlReadOnlyPair> pending_attach_storage_calls_;
-
-  // base::WeakPtr{this} factory.
-  base::WeakPtrFactory<FuseBoxMounter> weak_ptr_factory_{this};
-};
-
-}  // namespace file_manager
-
-#endif  // CHROME_BROWSER_ASH_FILE_MANAGER_FUSEBOX_MOUNTER_H_
diff --git a/chrome/browser/ash/file_manager/volume_manager.cc b/chrome/browser/ash/file_manager/volume_manager.cc
index f2cf71a..7564fb91 100644
--- a/chrome/browser/ash/file_manager/volume_manager.cc
+++ b/chrome/browser/ash/file_manager/volume_manager.cc
@@ -725,8 +725,6 @@
     return;
   }
 
-  fusebox_mounter_.Mount(disk_mount_manager_);
-
   const base::FilePath localVolume =
       file_manager::util::GetMyFilesFolderForProfile(profile_);
   const bool success = RegisterDownloadsMountPoint(profile_, localVolume);
@@ -814,7 +812,6 @@
 
   weak_ptr_factory_.InvalidateWeakPtrs();
 
-  fusebox_mounter_.Unmount(disk_mount_manager_);
   snapshot_manager_.reset();
   pref_change_registrar_.RemoveAll();
   disk_mount_manager_->RemoveObserver(this);
@@ -1322,6 +1319,11 @@
   if (error != base::File::FILE_OK)
     return;
 
+  // Get the FuseBoxDaemon instance.
+  if (!fusebox_daemon_) {
+    fusebox_daemon_ = file_manager::FuseBoxDaemon::GetInstance();
+  }
+
   // Get the FileSystemURL of the FSP storage device.
   const std::string fsid =
       file_system_info.mount_path().BaseName().AsUTF8Unsafe();
@@ -1333,7 +1335,7 @@
 
   // Attach the FSP storage device to the fusebox daemon.
   const std::string subdir = FuseBoxSubdirFSP(file_system_info);
-  fusebox_mounter_.AttachStorage(subdir, url, !file_system_info.writable());
+  fusebox_daemon_->AttachStorage(subdir, url, !file_system_info.writable());
 
   // Create a Volume for the fusebox FSP storage device.
   const base::FilePath mount_path =
@@ -1349,6 +1351,7 @@
     bool result = mount_points->RegisterFileSystem(
         fusebox_fsid, storage::kFileSystemTypeFuseBox,
         storage::FileSystemMountOption(), fusebox_volume->mount_path());
+    LOG_IF(ERROR, !result) << "invalid FuseBox FSP mount path";
     DCHECK(result);
   }
 
@@ -1401,7 +1404,9 @@
   mount_points->RevokeFileSystem(fusebox_fsid);
 
   // Detach the fusebox FSP storage device from the fusebox daemon.
-  fusebox_mounter_.DetachStorage(subdir);
+  if (fusebox_daemon_) {
+    fusebox_daemon_->DetachStorage(subdir);
+  }
 }
 
 void VolumeManager::OnExternalStorageDisabledChangedUnmountCallback(
@@ -1554,6 +1559,7 @@
     bool result = mount_points->RegisterFileSystem(
         fsid, storage::kFileSystemTypeDeviceMediaAsFileStorage,
         storage::FileSystemMountOption(), path);
+    LOG_IF(ERROR, !result) << "invalid MTP mount path";
     DCHECK(result);
   }
 
@@ -1568,6 +1574,11 @@
   std::unique_ptr<Volume> volume = Volume::CreateForMTP(path, label, read_only);
   DoMountEvent(std::move(volume));
 
+  // Get the FuseBoxDaemon instance.
+  if (!fusebox_daemon_) {
+    fusebox_daemon_ = file_manager::FuseBoxDaemon::GetInstance();
+  }
+
   // Get the FileSystemURL of the MTP storage device.
   auto mtp_file_system_url = mount_points->CreateExternalFileSystemURL(
       blink::StorageKey(util::GetFilesAppOrigin()), fsid, {});
@@ -1576,7 +1587,7 @@
 
   // Attach the MTP storage device to the fusebox daemon.
   std::string subdir = FuseBoxSubdirMTP(info.device_id());
-  fusebox_mounter_.AttachStorage(subdir, url, read_only);
+  fusebox_daemon_->AttachStorage(subdir, url, read_only);
 
   // Create a Volume for the fusebox MTP storage device.
   const base::FilePath mount_path =
@@ -1591,6 +1602,7 @@
     bool result = mount_points->RegisterFileSystem(
         fusebox_fsid, storage::kFileSystemTypeFuseBox,
         storage::FileSystemMountOption(), fusebox_volume->mount_path());
+    LOG_IF(ERROR, !result) << "invalid FuseBox MTP mount path";
     DCHECK(result);
   }
 
@@ -1643,7 +1655,9 @@
   mount_points->RevokeFileSystem(fusebox_fsid);
 
   // Detach the fusebox MTP storage device from the fusebox daemon.
-  fusebox_mounter_.DetachStorage(subdir);
+  if (fusebox_daemon_) {
+    fusebox_daemon_->DetachStorage(subdir);
+  }
 }
 
 void VolumeManager::OnDocumentsProviderRootAdded(
@@ -1661,6 +1675,11 @@
       authority, root_id, document_id, title, summary, icon_url, read_only,
       /*optional_fusebox_subdir=*/std::string()));
 
+  // Get the FuseBoxDaemon instance.
+  if (!fusebox_daemon_) {
+    fusebox_daemon_ = file_manager::FuseBoxDaemon::GetInstance();
+  }
+
   // Get the FileSystemURL of the ADP storage device.
   auto* mount_points = storage::ExternalMountPoints::GetSystemInstance();
   auto adp_file_system_url = mount_points->CreateExternalFileSystemURL(
@@ -1672,7 +1691,7 @@
 
   // Attach the ADP storage device to the fusebox daemon.
   std::string subdir = FuseBoxSubdirADP(authority, root_id);
-  fusebox_mounter_.AttachStorage(subdir, url, read_only);
+  fusebox_daemon_->AttachStorage(subdir, url, read_only);
 
   // Create a Volume for the fusebox ADP storage device.
   std::unique_ptr<Volume> fusebox_volume =
@@ -1686,6 +1705,7 @@
     bool result = mount_points->RegisterFileSystem(
         fusebox_fsid, storage::kFileSystemTypeFuseBox,
         storage::FileSystemMountOption(), fusebox_volume->mount_path());
+    LOG_IF(ERROR, !result) << "invalid FuseBox ADP mount path";
     DCHECK(result);
   }
 
@@ -1719,7 +1739,9 @@
   mount_points->RevokeFileSystem(fusebox_fsid);
 
   // Detach the fusebox ADP storage device from the fusebox daemon.
-  fusebox_mounter_.DetachStorage(subdir);
+  if (fusebox_daemon_) {
+    fusebox_daemon_->DetachStorage(subdir);
+  }
 }
 
 void VolumeManager::AddSmbFsVolume(const base::FilePath& mount_point,
diff --git a/chrome/browser/ash/file_manager/volume_manager.h b/chrome/browser/ash/file_manager/volume_manager.h
index ace47d0f..03e186be 100644
--- a/chrome/browser/ash/file_manager/volume_manager.h
+++ b/chrome/browser/ash/file_manager/volume_manager.h
@@ -19,7 +19,7 @@
 #include "chrome/browser/ash/arc/session/arc_session_manager_observer.h"
 #include "chrome/browser/ash/drive/drive_integration_service.h"
 #include "chrome/browser/ash/file_manager/documents_provider_root_manager.h"
-#include "chrome/browser/ash/file_manager/fusebox_mounter.h"
+#include "chrome/browser/ash/file_manager/fusebox_daemon.h"
 #include "chrome/browser/ash/file_manager/io_task_controller.h"
 #include "chrome/browser/ash/file_system_provider/icon_set.h"
 #include "chrome/browser/ash/file_system_provider/observer.h"
@@ -625,7 +625,7 @@
   base::ObserverList<VolumeManagerObserver>::Unchecked observers_;
   GetMtpStorageInfoCallback get_mtp_storage_info_callback_;
   Volumes mounted_volumes_;
-  FuseBoxMounter fusebox_mounter_;
+  scoped_refptr<file_manager::FuseBoxDaemon> fusebox_daemon_;
   std::unique_ptr<SnapshotManager> snapshot_manager_;
   std::unique_ptr<DocumentsProviderRootManager>
       documents_provider_root_manager_;
diff --git a/chrome/browser/ash/fusebox/fusebox_read_writer.cc b/chrome/browser/ash/fusebox/fusebox_read_writer.cc
index 7995baf..6ea3df9 100644
--- a/chrome/browser/ash/fusebox/fusebox_read_writer.cc
+++ b/chrome/browser/ash/fusebox/fusebox_read_writer.cc
@@ -4,10 +4,19 @@
 
 #include "chrome/browser/ash/fusebox/fusebox_read_writer.h"
 
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "base/files/file_util.h"
+#include "base/posix/eintr_wrapper.h"
+#include "base/strings/stringprintf.h"
+#include "base/task/thread_pool.h"
+#include "base/threading/scoped_blocking_call.h"
 #include "chrome/browser/ash/fusebox/fusebox_errno.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "net/base/net_errors.h"
+#include "storage/browser/file_system/file_system_operation_runner.h"
 
 namespace fusebox {
 
@@ -57,9 +66,31 @@
   std::move(callback).Run(response_proto);
 }
 
+ReadWriter::WriteTempFileResult WriteTempFile(
+    base::ScopedFD&& scoped_fd,
+    scoped_refptr<net::StringIOBuffer> buffer,
+    int64_t offset,
+    int length) {
+  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
+                                                base::BlockingType::MAY_BLOCK);
+
+  int fd = scoped_fd.get();
+  char* ptr = buffer->data();
+  if ((HANDLE_EINTR(lseek(fd, static_cast<off_t>(offset), SEEK_SET)) == -1) ||
+      (HANDLE_EINTR(write(fd, ptr, static_cast<size_t>(length))) == -1)) {
+    return std::make_pair(std::move(scoped_fd), errno);
+  }
+  return std::make_pair(std::move(scoped_fd), 0);
+}
+
 }  // namespace
 
-ReadWriter::ReadWriter(const storage::FileSystemURL& fs_url) : fs_url_(fs_url) {
+ReadWriter::ReadWriter(const storage::FileSystemURL& fs_url,
+                       const std::string& profile_path,
+                       bool use_temp_file)
+    : fs_url_(fs_url),
+      profile_path_(profile_path),
+      use_temp_file_(use_temp_file) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 }
 
@@ -71,6 +102,56 @@
 // looks unused, but we need to keep the storage::FileSystemContext reference
 // alive until the callbacks are run.
 
+void ReadWriter::Close(scoped_refptr<storage::FileSystemContext> fs_context,
+                       Close2Callback callback) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+
+  bool trivial = closed_ || !use_temp_file_;
+  closed_ = true;
+  if (trivial) {
+    Close2ResponseProto response_proto;
+    content::GetUIThreadTaskRunner({})->PostTask(
+        FROM_HERE, base::BindOnce(std::move(callback), response_proto));
+    return;
+  }
+
+  close2_fs_context_ = std::move(fs_context);
+  close2_callback_ = std::move(callback);
+  if (!is_loaning_temp_file_scoped_fd_) {
+    Save();
+  }
+}
+
+void ReadWriter::Save() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+  DCHECK(close2_fs_context_);
+  DCHECK(close2_callback_);
+  DCHECK(!is_loaning_temp_file_scoped_fd_);
+  DCHECK(use_temp_file_);
+
+  std::string src_path =
+      created_temp_file_
+          ? base::StringPrintf("/proc/self/fd/%d", temp_file_.get())
+          : "/dev/null";
+
+  constexpr auto outer_callback =
+      [](base::ScopedFD scoped_fd,
+         scoped_refptr<storage::FileSystemContext> fs_context,
+         Close2Callback callback, base::File::Error file_error) {
+        Close2ResponseProto response_proto;
+        if (file_error != base::File::Error::FILE_OK) {
+          response_proto.set_posix_error_code(FileErrorToErrno(file_error));
+        }
+        content::GetUIThreadTaskRunner({})->PostTask(
+            FROM_HERE, base::BindOnce(std::move(callback), response_proto));
+      };
+
+  close2_fs_context_->operation_runner()->CopyInForeignFile(
+      base::FilePath(src_path), fs_url_,
+      base::BindOnce(outer_callback, std::move(temp_file_), close2_fs_context_,
+                     std::move(close2_callback_)));
+}
+
 void ReadWriter::Read(scoped_refptr<storage::FileSystemContext> fs_context,
                       int64_t offset,
                       int64_t length,
@@ -78,6 +159,13 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   DCHECK(!is_in_flight_);
 
+  if (closed_) {
+    content::GetUIThreadTaskRunner({})->PostTask(
+        FROM_HERE, base::BindOnce(&RunRead2CallbackFailure, std::move(callback),
+                                  base::File::Error::FILE_ERROR_FAILED));
+    return;
+  }
+
   // See if we can re-use the previous storage::FileStreamReader.
   std::unique_ptr<storage::FileStreamReader> fs_reader;
   if (fs_reader_ && (read_offset_ == offset)) {
@@ -161,6 +249,48 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   DCHECK(!is_in_flight_);
 
+  if (closed_) {
+    content::GetUIThreadTaskRunner({})->PostTask(
+        FROM_HERE,
+        base::BindOnce(&RunWrite2CallbackFailure, std::move(callback),
+                       base::File::Error::FILE_ERROR_FAILED));
+    return;
+  }
+
+  if (use_temp_file_) {
+    if (!temp_file_.is_valid()) {
+      // Create the temporary file via open and O_TMPFILE, instead of
+      // base::CreateTemporaryFile, to simplify clean-up. With the latter,
+      // there is a garbage collection problem of when to delete no-longer-used
+      // files (as base::File::DeleteOnClose is Windows only). That problem can
+      // be tricky if Chrome crashes before we're done with the temporary file.
+      // With O_TMPFILE, the kernel deletes the file automatically when the
+      // file descriptor is closed, whether via base::ScopedFD destructor or,
+      // for crashes, at process exit.
+      temp_file_.reset(open(profile_path_.c_str(),
+                            O_CLOEXEC | O_EXCL | O_TMPFILE | O_RDWR, 0600));
+      if (!temp_file_.is_valid()) {
+        PLOG(WARNING) << "could not create O_TMPFILE file";
+        content::GetUIThreadTaskRunner({})->PostTask(
+            FROM_HERE,
+            base::BindOnce(&RunWrite2CallbackFailure, std::move(callback),
+                           base::File::Error::FILE_ERROR_NO_SPACE));
+        return;
+      }
+      created_temp_file_ = true;
+    }
+
+    is_in_flight_ = true;
+    is_loaning_temp_file_scoped_fd_ = true;
+    base::ThreadPool::PostTaskAndReplyWithResult(
+        FROM_HERE, {base::MayBlock()},
+        base::BindOnce(&WriteTempFile, std::move(temp_file_), std::move(buffer),
+                       offset, length),
+        base::BindOnce(&OnWriteTempFile, weak_ptr_factory_.GetWeakPtr(),
+                       std::move(callback)));
+    return;
+  }
+
   // See if we can re-use the previous storage::FileStreamWriter.
   std::unique_ptr<storage::FileStreamWriter> fs_writer;
   if (fs_writer_ && (write_offset_ == offset)) {
@@ -185,8 +315,8 @@
 
   is_in_flight_ = true;
   auto pair = base::SplitOnceCallback(base::BindOnce(
-      &ReadWriter::OnWrite, weak_ptr_factory_.GetWeakPtr(), std::move(callback),
-      fs_context, std::move(fs_writer), buffer, offset));
+      &ReadWriter::OnWriteDirect, weak_ptr_factory_.GetWeakPtr(),
+      std::move(callback), fs_context, std::move(fs_writer), buffer, offset));
 
   int result =
       saved_fs_writer->Write(buffer.get(), length, std::move(pair.first));
@@ -195,7 +325,39 @@
   }
 }
 
-void ReadWriter::OnWrite(
+void ReadWriter::OnWriteTempFile(base::WeakPtr<ReadWriter> weak_ptr,
+                                 Write2Callback callback,
+                                 WriteTempFileResult result) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+
+  ReadWriter* self = weak_ptr.get();
+  if (!self) {
+    Write2ResponseProto response_proto;
+    response_proto.set_posix_error_code(EBUSY);
+    content::GetUIThreadTaskRunner({})->PostTask(
+        FROM_HERE, base::BindOnce(std::move(callback), response_proto));
+    return;
+  }
+
+  DCHECK(self->is_in_flight_);
+  self->is_in_flight_ = false;
+  self->is_loaning_temp_file_scoped_fd_ = false;
+
+  self->temp_file_ = std::move(result.first);
+
+  Write2ResponseProto response_proto;
+  if (result.second) {
+    response_proto.set_posix_error_code(result.second);
+  }
+  content::GetUIThreadTaskRunner({})->PostTask(
+      FROM_HERE, base::BindOnce(std::move(callback), response_proto));
+
+  if (self->close2_callback_) {
+    self->Save();
+  }
+}
+
+void ReadWriter::OnWriteDirect(
     base::WeakPtr<ReadWriter> weak_ptr,
     Write2Callback callback,
     scoped_refptr<storage::FileSystemContext> fs_context,  // See § above.
diff --git a/chrome/browser/ash/fusebox/fusebox_read_writer.h b/chrome/browser/ash/fusebox/fusebox_read_writer.h
index 17de68f1..c199e76 100644
--- a/chrome/browser/ash/fusebox/fusebox_read_writer.h
+++ b/chrome/browser/ash/fusebox/fusebox_read_writer.h
@@ -5,7 +5,10 @@
 #ifndef CHROME_BROWSER_ASH_FUSEBOX_FUSEBOX_READ_WRITER_H_
 #define CHROME_BROWSER_ASH_FUSEBOX_FUSEBOX_READ_WRITER_H_
 
+#include <utility>
+
 #include "base/callback_forward.h"
+#include "base/files/scoped_file.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/ash/fusebox/fusebox.pb.h"
 #include "net/base/io_buffer.h"
@@ -35,14 +38,27 @@
 // ends just before the corresponding callback is run.
 class ReadWriter {
  public:
+  using Close2Callback =
+      base::OnceCallback<void(const Close2ResponseProto& response)>;
   using Read2Callback =
       base::OnceCallback<void(const Read2ResponseProto& response)>;
   using Write2Callback =
       base::OnceCallback<void(const Write2ResponseProto& response)>;
 
-  explicit ReadWriter(const storage::FileSystemURL& fs_url);
+  // |use_temp_file| is for the case when the |fs_url| storage system does not
+  // support incremental writes, only atomic "here's the entire contents"
+  // writes, such as MTP (Media Transfer Protocol, e.g. phones attached to a
+  // Chromebook, which is a file-oriented rather than block-oriented protocol).
+  // In this case, the Write calls are diverted to a temporary file and the
+  // Close call saves that temporary file to |fs_url|.
+  ReadWriter(const storage::FileSystemURL& fs_url,
+             const std::string& profile_path,
+             bool use_temp_file);
   ~ReadWriter();
 
+  void Close(scoped_refptr<storage::FileSystemContext> fs_context,
+             Close2Callback callback);
+
   void Read(scoped_refptr<storage::FileSystemContext> fs_context,
             int64_t offset,
             int64_t length,
@@ -54,7 +70,13 @@
              int length,
              Write2Callback callback);
 
+  // The int is a POSIX error code.
+  using WriteTempFileResult = std::pair<base::ScopedFD, int>;
+
  private:
+  // Saves the |temp_file_| to the |fs_url_|.
+  void Save();
+
   // The OnXxx methods are static (but take a WeakPtr) so that the callback
   // will run even if the WeakPtr is invalidated.
 
@@ -66,15 +88,21 @@
                      int64_t offset,
                      int length);
 
-  static void OnWrite(base::WeakPtr<ReadWriter> weak_ptr,
-                      Write2Callback callback,
-                      scoped_refptr<storage::FileSystemContext> fs_context,
-                      std::unique_ptr<storage::FileStreamWriter> fs_writer,
-                      scoped_refptr<net::IOBuffer> buffer,
-                      int64_t offset,
-                      int length);
+  static void OnWriteTempFile(base::WeakPtr<ReadWriter> weak_ptr,
+                              Write2Callback callback,
+                              WriteTempFileResult result);
+
+  static void OnWriteDirect(
+      base::WeakPtr<ReadWriter> weak_ptr,
+      Write2Callback callback,
+      scoped_refptr<storage::FileSystemContext> fs_context,
+      std::unique_ptr<storage::FileStreamWriter> fs_writer,
+      scoped_refptr<net::IOBuffer> buffer,
+      int64_t offset,
+      int length);
 
   const storage::FileSystemURL fs_url_;
+  const std::string profile_path_;
 
   std::unique_ptr<storage::FileStreamReader> fs_reader_;
   // Unused whenever fs_reader_ is nullptr.
@@ -84,9 +112,21 @@
   // Unused whenever fs_writer_ is nullptr.
   int64_t write_offset_ = -1;
 
-  // TODO(b/255703917): snapshot management.
+  scoped_refptr<storage::FileSystemContext> close2_fs_context_;
+  Close2Callback close2_callback_;
+
+  base::ScopedFD temp_file_;
+
+  // True when the FD in |temp_file_| has been loaned out to a separate thread
+  // (separate from the content::BrowserThread::IO thread that this lives on,
+  // which should not be used for blocking I/O).
+  bool is_loaning_temp_file_scoped_fd_ = false;
 
   bool is_in_flight_ = false;
+  bool closed_ = false;
+  bool created_temp_file_ = false;
+
+  const bool use_temp_file_;
 
   base::WeakPtrFactory<ReadWriter> weak_ptr_factory_{this};
 };
diff --git a/chrome/browser/ash/fusebox/fusebox_server.cc b/chrome/browser/ash/fusebox/fusebox_server.cc
index 14fbc5a..f70e64b 100644
--- a/chrome/browser/ash/fusebox/fusebox_server.cc
+++ b/chrome/browser/ash/fusebox/fusebox_server.cc
@@ -39,6 +39,14 @@
 
 Server* g_server_instance = nullptr;
 
+bool UseTempFile(const std::string fs_url_as_string) {
+  // MTP (the protocol) does not support incremental writes. When creating an
+  // MTP file (via FuseBox), we need to supply its contents as a whole. Up
+  // until that transfer, spool incremental writes to a temporary file.
+  return base::StartsWith(fs_url_as_string,
+                          file_manager::util::kFuseBoxSubdirPrefixMTP);
+}
+
 std::pair<std::string, bool> ResolvePrefixMap(
     const fusebox::Server::PrefixMap& prefix_map,
     const std::string& s) {
@@ -420,12 +428,17 @@
 Server::FuseFileMapEntry::FuseFileMapEntry(
     scoped_refptr<storage::FileSystemContext> fs_context_arg,
     storage::FileSystemURL fs_url_arg,
+    const std::string& profile_path_arg,
     bool readable_arg,
-    bool writable_arg)
+    bool writable_arg,
+    bool use_temp_file_arg)
     : fs_context_(fs_context_arg),
       readable_(readable_arg),
       writable_(writable_arg),
-      seqbnd_read_writer_(content::GetIOThreadTaskRunner({}), fs_url_arg) {}
+      seqbnd_read_writer_(content::GetIOThreadTaskRunner({}),
+                          fs_url_arg,
+                          profile_path_arg,
+                          use_temp_file_arg) {}
 
 Server::FuseFileMapEntry::FuseFileMapEntry(FuseFileMapEntry&&) = default;
 
@@ -624,12 +637,11 @@
   }
   FuseFileMapEntry& entry = iter->second;
   base::circular_deque<PendingOp> pending_ops = std::move(entry.pending_ops_);
+  entry.seqbnd_read_writer_.AsyncCall(&ReadWriter::Close)
+      .WithArgs(entry.fs_context_, std::move(callback));
 
   fuse_file_map_.erase(iter);
 
-  Close2ResponseProto response_proto;
-  std::move(callback).Run(response_proto);
-
   for (auto& pending_op : pending_ops) {
     if (absl::holds_alternative<PendingRead2>(pending_op)) {
       Read2ResponseProto read2_response_proto;
@@ -670,9 +682,27 @@
 
   constexpr bool readable = true;
   constexpr bool writable = true;
+  bool use_temp_file = writable && UseTempFile(fs_url_as_string);
 
-  uint64_t fuse_handle = InsertFuseFileMapEntry(
-      FuseFileMapEntry(common.fs_context, common.fs_url, readable, writable));
+  uint64_t fuse_handle = InsertFuseFileMapEntry(FuseFileMapEntry(
+      common.fs_context, common.fs_url,
+      use_temp_file
+          ? ProfileManager::GetActiveUserProfile()->GetPath().AsUTF8Unsafe()
+          : std::string(),
+      readable, writable, use_temp_file));
+
+  if (use_temp_file) {
+    base::Time now = base::Time::Now();
+    base::File::Info info;
+    info.last_modified = now;
+    info.last_accessed = now;
+    info.creation_time = now;
+    CreateResponseProto response_proto;
+    response_proto.set_fuse_handle(fuse_handle);
+    FillInDirEntryProto(response_proto.mutable_stat(), info, common.read_only);
+    std::move(callback).Run(response_proto);
+    return;
+  }
 
   auto on_failure = base::BindOnce(&Server::EraseFuseFileMapEntry,
                                    weak_ptr_factory_.GetWeakPtr(), fuse_handle);
@@ -755,10 +785,19 @@
   bool writable =
       !common.read_only && ((access_mode == AccessMode::WRITE_ONLY) ||
                             (access_mode == AccessMode::READ_WRITE));
+  bool use_temp_file = writable && UseTempFile(fs_url_as_string);
+  if (use_temp_file) {
+    // TODO(b/255703917): allow use_temp_file when modifying existing files,
+    // not just creating new ones.
+    Open2ResponseProto response_proto;
+    response_proto.set_posix_error_code(ENOTSUP);
+    std::move(callback).Run(response_proto);
+    return;
+  }
 
   uint64_t fuse_handle = InsertFuseFileMapEntry(
       FuseFileMapEntry(std::move(common.fs_context), std::move(common.fs_url),
-                       readable, writable));
+                       std::string(), readable, writable, use_temp_file));
 
   Open2ResponseProto response_proto;
   response_proto.set_fuse_handle(fuse_handle);
diff --git a/chrome/browser/ash/fusebox/fusebox_server.h b/chrome/browser/ash/fusebox/fusebox_server.h
index d082e09..3f87afb 100644
--- a/chrome/browser/ash/fusebox/fusebox_server.h
+++ b/chrome/browser/ash/fusebox/fusebox_server.h
@@ -203,8 +203,10 @@
   struct FuseFileMapEntry {
     FuseFileMapEntry(scoped_refptr<storage::FileSystemContext> fs_context_arg,
                      storage::FileSystemURL fs_url_arg,
+                     const std::string& profile_path_arg,
                      bool readable_arg,
-                     bool writable_arg);
+                     bool writable_arg,
+                     bool use_temp_file_arg);
     FuseFileMapEntry(FuseFileMapEntry&&);
     ~FuseFileMapEntry();
 
diff --git a/chrome/browser/ash/wallpaper/wallpaper_drivefs_delegate_impl.cc b/chrome/browser/ash/wallpaper/wallpaper_drivefs_delegate_impl.cc
index 515180e8..03c18ab 100644
--- a/chrome/browser/ash/wallpaper/wallpaper_drivefs_delegate_impl.cc
+++ b/chrome/browser/ash/wallpaper/wallpaper_drivefs_delegate_impl.cc
@@ -6,12 +6,16 @@
 
 #include "ash/public/cpp/image_downloader.h"
 #include "base/files/file_path.h"
+#include "base/files/file_util.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback_forward.h"
+#include "base/task/sequenced_task_runner.h"
+#include "base/task/task_traits.h"
+#include "base/task/thread_pool.h"
+#include "base/unguessable_token.h"
 #include "chrome/browser/ash/drive/drive_integration_service.h"
 #include "chrome/browser/ash/drive/file_system_util.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
-#include "chrome/browser/ui/ash/wallpaper_controller_client_impl.h"
 #include "chromeos/ash/components/drivefs/mojom/drivefs.mojom.h"
 #include "components/account_id/account_id.h"
 #include "components/drive/file_errors.h"
@@ -56,6 +60,10 @@
       }
     )");
 
+constexpr char kDriveFsWallpaperDirName[] = "Chromebook Wallpaper";
+constexpr char kDriveFsWallpaperFileName[] = "wallpaper.jpg";
+constexpr char kDriveFsTempWallpaperFileName[] = "wallpaper-tmp.jpg";
+
 // Gets a pointer to `DriveIntegrationService` to interact with DriveFS.  If
 // DriveFS is not enabled or mounted for this `account_id`, responds with
 // `nullptr`. Caller must check null safety carefully, as DriveFS can crash,
@@ -95,12 +103,84 @@
   return metadata->modification_time;
 }
 
+// Copies file `source` from outside DriveFS, to `destination` inside DriveFS.
+// `destination` must be the path to the DriveFS wallpaper file. Copies the
+// file to a temporary file first, and then swaps it to the final file path, in
+// order to avoid partial writes corrupting the wallpaper image saved to
+// DriveFS. Must be run on a blocking task runner.
+bool CopyFileToDriveFsBlocking(const base::FilePath& source,
+                               const base::FilePath& destination) {
+  DCHECK_EQ(destination.BaseName().value(), kDriveFsWallpaperFileName);
+  const base::FilePath directory = destination.DirName();
+  DCHECK_EQ(directory.BaseName().value(), kDriveFsWallpaperDirName);
+  if (!base::DirectoryExists(directory) && !base::CreateDirectory(directory)) {
+    DVLOG(1) << "Failed to create DriveFS '" << kDriveFsWallpaperDirName
+             << "' directory";
+    return false;
+  }
+
+  base::FilePath temp_file_path =
+      directory.Append(base::UnguessableToken::Create().ToString().append(
+          kDriveFsTempWallpaperFileName));
+
+  if (!base::CopyFile(source, temp_file_path)) {
+    DVLOG(1) << "Failed to copy wallpaper file to DriveFs";
+    base::DeleteFile(temp_file_path);
+    return false;
+  }
+
+  base::File::Error error;
+  if (!base::ReplaceFile(temp_file_path, destination, &error)) {
+    DVLOG(1) << "Failed to move temp wallpaper file with error '" << error
+             << "'";
+    base::DeleteFile(temp_file_path);
+    return false;
+  }
+  return true;
+}
+
 }  // namespace
 
-WallpaperDriveFsDelegateImpl::WallpaperDriveFsDelegateImpl() = default;
+WallpaperDriveFsDelegateImpl::WallpaperDriveFsDelegateImpl()
+    : blocking_task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
+          {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+           base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})) {}
 
 WallpaperDriveFsDelegateImpl::~WallpaperDriveFsDelegateImpl() = default;
 
+base::FilePath WallpaperDriveFsDelegateImpl::GetWallpaperPath(
+    const AccountId& account_id) {
+  auto* drive_integration_service = GetDriveIntegrationService(account_id);
+  if (!drive_integration_service) {
+    VLOG(1)
+        << "Cannot get DriveFS Wallpaper path because DriveFS is unavailable";
+    return base::FilePath();
+  }
+  auto mount_path = drive_integration_service->GetMountPointPath();
+  DCHECK(!mount_path.empty());
+  return mount_path.Append(drive::util::kDriveMyDriveRootDirName)
+      .Append(kDriveFsWallpaperDirName)
+      .Append(kDriveFsWallpaperFileName);
+}
+
+void WallpaperDriveFsDelegateImpl::SaveWallpaper(
+    const AccountId& account_id,
+    const base::FilePath& source,
+    base::OnceCallback<void(bool)> callback) {
+  auto* drive_integration_service = GetDriveIntegrationService(account_id);
+  if (!drive_integration_service) {
+    DVLOG(1)
+        << "Not saving wallpaper to DriveFS because DriveFS is unavailable";
+    std::move(callback).Run(/*success=*/false);
+    return;
+  }
+  blocking_task_runner_->PostTaskAndReplyWithResult(
+      FROM_HERE,
+      base::BindOnce(&CopyFileToDriveFsBlocking, source,
+                     GetWallpaperPath(account_id)),
+      std::move(callback));
+}
+
 void WallpaperDriveFsDelegateImpl::GetWallpaperModificationTime(
     const AccountId& account_id,
     base::OnceCallback<void(base::Time modification_time)> callback) {
@@ -109,15 +189,11 @@
     std::move(callback).Run(base::Time());
     return;
   }
-  // `wallpaper_path` is guaranteed to be non-empty if
-  // `drive_integration_service` is initialized.
-  const base::FilePath wallpaper_path =
-      WallpaperControllerClientImpl::Get()->GetWallpaperPathFromDriveFs(
-          account_id);
-  DCHECK(!wallpaper_path.empty());
+
   drive_integration_service->GetMetadata(
-      wallpaper_path, base::BindOnce(&GetModificationTimeFromDriveMetadata)
-                          .Then(std::move(callback)));
+      GetWallpaperPath(account_id),
+      base::BindOnce(&GetModificationTimeFromDriveMetadata)
+          .Then(std::move(callback)));
 }
 
 void WallpaperDriveFsDelegateImpl::DownloadAndDecodeWallpaper(
@@ -131,15 +207,8 @@
     return;
   }
 
-  // `wallpaper_path` is guaranteed to be non-empty if
-  // `drive_integration_service` is initialized.
-  const base::FilePath wallpaper_path =
-      WallpaperControllerClientImpl::Get()->GetWallpaperPathFromDriveFs(
-          account_id);
-  DCHECK(!wallpaper_path.empty());
-
   drive_integration_service->GetMetadata(
-      wallpaper_path,
+      GetWallpaperPath(account_id),
       base::BindOnce(&WallpaperDriveFsDelegateImpl::OnGetDownloadUrlMetadata,
                      weak_ptr_factory_.GetWeakPtr(), account_id,
                      std::move(callback)));
diff --git a/chrome/browser/ash/wallpaper/wallpaper_drivefs_delegate_impl.h b/chrome/browser/ash/wallpaper/wallpaper_drivefs_delegate_impl.h
index 6b14e4c..364e880 100644
--- a/chrome/browser/ash/wallpaper/wallpaper_drivefs_delegate_impl.h
+++ b/chrome/browser/ash/wallpaper/wallpaper_drivefs_delegate_impl.h
@@ -10,8 +10,11 @@
 #include <string>
 
 #include "ash/public/cpp/image_downloader.h"
+#include "base/files/file_path.h"
 #include "base/functional/callback_forward.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
+#include "base/task/sequenced_task_runner.h"
 #include "base/time/time.h"
 #include "chromeos/ash/components/drivefs/mojom/drivefs.mojom-forward.h"
 #include "components/account_id/account_id.h"
@@ -32,6 +35,10 @@
   ~WallpaperDriveFsDelegateImpl() override;
 
   // WallpaperDriveFsDelegate:
+  base::FilePath GetWallpaperPath(const AccountId& account_id) override;
+  void SaveWallpaper(const AccountId& account_id,
+                     const base::FilePath& source,
+                     base::OnceCallback<void(bool success)> callback) override;
   void GetWallpaperModificationTime(
       const AccountId& account_id,
       base::OnceCallback<void(base::Time modification_time)> callback) override;
@@ -57,6 +64,7 @@
       google_apis::ApiErrorCode error_code,
       const std::string& authentication_token);
 
+  scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
   base::WeakPtrFactory<WallpaperDriveFsDelegateImpl> weak_ptr_factory_{this};
 };
 
diff --git a/chrome/browser/ash/wallpaper/wallpaper_drivefs_delegate_impl_browsertest.cc b/chrome/browser/ash/wallpaper/wallpaper_drivefs_delegate_impl_browsertest.cc
index d45fcd3..b13c891 100644
--- a/chrome/browser/ash/wallpaper/wallpaper_drivefs_delegate_impl_browsertest.cc
+++ b/chrome/browser/ash/wallpaper/wallpaper_drivefs_delegate_impl_browsertest.cc
@@ -8,18 +8,21 @@
 
 #include "ash/shell.h"
 #include "ash/wallpaper/wallpaper_controller_impl.h"
+#include "base/files/file.h"
+#include "base/files/file_path.h"
 #include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
 #include "base/memory/ref_counted_memory.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/run_loop.h"
 #include "base/test/bind.h"
+#include "base/threading/thread_restrictions.h"
 #include "base/time/time.h"
 #include "chrome/browser/ash/drive/drive_integration_service.h"
 #include "chrome/browser/ash/drive/drive_integration_service_browser_test_base.h"
 #include "chrome/browser/ash/drive/file_system_util.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/ash/wallpaper_controller_client_impl.h"
 #include "chrome/browser/ui/browser.h"
 #include "components/account_id/account_id.h"
 #include "components/user_manager/user.h"
@@ -49,25 +52,24 @@
   return output;
 }
 
-// Saves a test wallpaper file and returns the expected metadata `modified_at`
-// time.
-base::Time SaveTestWallpaperFile(const AccountId& account_id) {
-  const base::FilePath wallpaper_path =
-      WallpaperControllerClientImpl::Get()->GetWallpaperPathFromDriveFs(
-          account_id);
-  DCHECK(!wallpaper_path.empty());
-  base::ScopedAllowBlockingForTesting allow_blocking;
-  if (!base::DirectoryExists(wallpaper_path.DirName())) {
-    EXPECT_TRUE(base::CreateDirectory(wallpaper_path.DirName()));
-  }
-  const auto data = EncodeImage(CreateTestImage());
-  const size_t size = base::WriteFile(
-      wallpaper_path, data->front_as<const char>(), data->size());
-  DCHECK_EQ(size, data->size());
+WallpaperDriveFsDelegate* GetWallpaperDriveFsDelegate() {
+  Shell* shell = Shell::Get();
+  auto* wallpaper_controller = shell->wallpaper_controller();
+  return wallpaper_controller->drivefs_delegate_for_testing();
+}
 
-  base::File::Info info;
-  base::GetFileInfo(wallpaper_path, &info);
-  return info.last_modified;
+// Saves a test wallpaper file. If `target` is empty, will default to the
+// DriveFS wallpaper path.
+void SaveTestWallpaperFile(const AccountId& account_id, base::FilePath target) {
+  ASSERT_FALSE(target.empty()) << "target FilePath is required to be non-empty";
+  base::ScopedAllowBlockingForTesting allow_blocking;
+  if (!base::DirectoryExists(target.DirName())) {
+    ASSERT_TRUE(base::CreateDirectory(target.DirName()));
+  }
+  auto data = EncodeImage(CreateTestImage());
+  size_t size =
+      base::WriteFile(target, data->front_as<const char>(), data->size());
+  ASSERT_EQ(size, data->size());
 }
 
 }  // namespace
@@ -84,12 +86,6 @@
 
   ~WallpaperDriveFsDelegateImplBrowserTest() override = default;
 
-  WallpaperDriveFsDelegate* GetWallpaperDriveFsDelegate() const {
-    Shell* shell = Shell::Get();
-    auto* wallpaper_controller = shell->wallpaper_controller();
-    return wallpaper_controller->drivefs_delegate_for_testing();
-  }
-
   const AccountId& GetAccountId() const {
     user_manager::User* user =
         ProfileHelper::Get()->GetUserByProfile(browser()->profile());
@@ -97,8 +93,21 @@
     return user->GetAccountId();
   }
 
-  base::Time GetWallpaperModificationTimeSync(
-      const AccountId& account_id) const {
+  bool SaveWallpaperSync(const AccountId& account_id,
+                         const base::FilePath& source) {
+    base::RunLoop loop;
+    bool out = false;
+    GetWallpaperDriveFsDelegate()->SaveWallpaper(
+        account_id, source,
+        base::BindLambdaForTesting([&out, &loop](bool success) {
+          out = success;
+          loop.Quit();
+        }));
+    loop.Run();
+    return out;
+  }
+
+  base::Time GetWallpaperModificationTimeSync(const AccountId& account_id) {
     base::RunLoop loop;
     base::Time out;
     GetWallpaperDriveFsDelegate()->GetWallpaperModificationTime(
@@ -114,11 +123,13 @@
 IN_PROC_BROWSER_TEST_F(WallpaperDriveFsDelegateImplBrowserTest,
                        EmptyBaseTimeIfNoDriveFs) {
   InitTestFileMountRoot(browser()->profile());
-  SaveTestWallpaperFile(GetAccountId());
+  SaveTestWallpaperFile(
+      GetAccountId(),
+      GetWallpaperDriveFsDelegate()->GetWallpaperPath(GetAccountId()));
 
   drive::DriveIntegrationService* drive_integration_service =
       drive::util::GetIntegrationServiceByProfile(browser()->profile());
-  DCHECK(drive_integration_service);
+  ASSERT_TRUE(drive_integration_service);
   drive_integration_service->SetEnabled(false);
 
   const base::Time modification_time =
@@ -130,10 +141,65 @@
 IN_PROC_BROWSER_TEST_F(WallpaperDriveFsDelegateImplBrowserTest,
                        RespondsWithModifiedAtTime) {
   InitTestFileMountRoot(browser()->profile());
-  const base::Time expected = SaveTestWallpaperFile(GetAccountId());
-  const base::Time actual = GetWallpaperModificationTimeSync(GetAccountId());
-  EXPECT_EQ(actual, expected)
-      << "DriveFS modified_at should match file modified time";
+
+  base::ScopedAllowBlockingForTesting allow_blocking;
+  const base::FilePath drivefs_wallpaper_path =
+      GetWallpaperDriveFsDelegate()->GetWallpaperPath(GetAccountId());
+  ASSERT_FALSE(base::PathExists(drivefs_wallpaper_path));
+
+  SaveTestWallpaperFile(GetAccountId(), drivefs_wallpaper_path);
+
+  base::File::Info file_info;
+  ASSERT_TRUE(base::GetFileInfo(drivefs_wallpaper_path, &file_info));
+
+  const base::Time drivefs_modification_time =
+      GetWallpaperModificationTimeSync(GetAccountId());
+
+  EXPECT_EQ(drivefs_modification_time, file_info.last_modified)
+      << "modification_time matches file info time";
+}
+
+IN_PROC_BROWSER_TEST_F(WallpaperDriveFsDelegateImplBrowserTest, SaveWallpaper) {
+  InitTestFileMountRoot(browser()->profile());
+
+  base::FilePath drivefs_wallpaper_path =
+      GetWallpaperDriveFsDelegate()->GetWallpaperPath(GetAccountId());
+  ASSERT_FALSE(drivefs_wallpaper_path.empty());
+
+  base::ScopedAllowBlockingForTesting scoped_allow_blocking;
+  // Write a jpg file to a tmp directory. This file will be copied into DriveFS.
+  base::ScopedTempDir scoped_temp_dir;
+  ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
+  base::FilePath source_jpg = scoped_temp_dir.GetPath().Append("source.jpg");
+  SaveTestWallpaperFile(GetAccountId(), source_jpg);
+
+  // `SaveWallpaper` should succeed while DriveFS is enabled.
+  EXPECT_TRUE(SaveWallpaperSync(GetAccountId(), source_jpg));
+  // source.jpg was copied to DriveFS wallpaper path.
+  EXPECT_TRUE(base::PathExists(drivefs_wallpaper_path));
+}
+
+IN_PROC_BROWSER_TEST_F(WallpaperDriveFsDelegateImplBrowserTest,
+                       SaveWallpaperDriveFsDisabled) {
+  InitTestFileMountRoot(browser()->profile());
+  base::ScopedAllowBlockingForTesting scoped_allow_blocking;
+
+  // Write a jpg file to a tmp directory. This file will be copied into DriveFS.
+  base::ScopedTempDir scoped_temp_dir;
+  ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
+  base::FilePath source_jpg = scoped_temp_dir.GetPath().Append("source.jpg");
+  SaveTestWallpaperFile(GetAccountId(), source_jpg);
+
+  base::FilePath drivefs_wallpaper_path =
+      GetWallpaperDriveFsDelegate()->GetWallpaperPath(GetAccountId());
+  ASSERT_FALSE(drivefs_wallpaper_path.empty());
+
+  // Call `SaveWallpaper` while DriveFS is disabled. No file should be written.
+  auto* drive_integration_service =
+      drive::util::GetIntegrationServiceByProfile(browser()->profile());
+  drive_integration_service->SetEnabled(false);
+  EXPECT_FALSE(SaveWallpaperSync(GetAccountId(), source_jpg));
+  EXPECT_FALSE(base::PathExists(drivefs_wallpaper_path));
 }
 
 }  // namespace ash
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc
index d616df56..a7d86acf 100644
--- a/chrome/browser/extensions/api/settings_private/prefs_util.cc
+++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -477,6 +477,8 @@
       settings_api::PrefType::PREF_TYPE_BOOLEAN;
   (*s_allowlist)[::prefs::kLiveCaptionLanguageCode] =
       settings_api::PrefType::PREF_TYPE_STRING;
+  (*s_allowlist)[::prefs::kAccessibilityPdfOcrAlwaysActive] =
+      settings_api::PrefType::PREF_TYPE_BOOLEAN;
 #endif
 
   (*s_allowlist)[::prefs::kCaretBrowsingEnabled] =
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 4385c717..4edb5ed 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -157,9 +157,14 @@
     "expiry_milestone": 113
   },
   {
+    "name": "app-deduplication-service-fondue",
+    "owners": [ "nikkifang", "melzhang", "chromeos-apps-foundation-team" ],
+    "expiry_milestone": 118
+  },
+  {
     "name": "app-management-app-details",
-    "owners": [ "ajlinker" ],
-    "expiry_milestone": 112
+    "owners": [ "jshikaram",  "chromeos-apps-foundation-team" ],
+    "expiry_milestone": 118
   },
   {
     "name": "app-menu-mobile-site-option",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index a70e386..34bf3b5 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -52,6 +52,12 @@
         "Enables supervised users to add additional Edu accounts and "
         "simplifies settings UI";
 
+const char kAppDeduplicationServiceFondueName[] =
+    "Identify duplicate app groups.";
+const char kAppDeduplicationServiceFondueDescription[] =
+    "Enables pulling app duplicate data from a Google server to allow clients "
+    "to determine app duplicates.";
+
 const char kLauncherAppSortName[] = "Productivity experiment: Reorder Apps";
 const char kLauncherAppSortDescription[] =
     "To evaluate an enhanced Launcher experience that enables users to reorder "
@@ -1471,11 +1477,6 @@
 const char kFedCmWithoutThirdPartyCookiesDescription[] =
     "Allows the FedCM API to be enabled when third party cookies are disabled.";
 
-const char kFileHandlingAPIName[] = "File Handling API";
-const char kFileHandlingAPIDescription[] =
-    "Enables the file handling API, allowing websites to register as file "
-    "handlers.";
-
 const char kFileHandlingIconsName[] = "File Handling Icons";
 const char kFileHandlingIconsDescription[] =
     "Allows websites using the file handling API to also register file type "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 67f32cf..741051b 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -79,6 +79,9 @@
 extern const char kAttributionReportingDebugModeName[];
 extern const char kAttributionReportingDebugModeDescription[];
 
+extern const char kAppDeduplicationServiceFondueName[];
+extern const char kAppDeduplicationServiceFondueDescription[];
+
 extern const char kBlockInsecureDownloadsName[];
 extern const char kBlockInsecureDownloadsDescription[];
 
@@ -823,9 +826,6 @@
 extern const char kFedCmWithoutThirdPartyCookiesName[];
 extern const char kFedCmWithoutThirdPartyCookiesDescription[];
 
-extern const char kFileHandlingAPIName[];
-extern const char kFileHandlingAPIDescription[];
-
 extern const char kFileHandlingIconsName[];
 extern const char kFileHandlingIconsDescription[];
 
diff --git a/chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer.cc
index 10beeaf97..a15b1211 100644
--- a/chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer.cc
@@ -17,74 +17,6 @@
 #include "url/gurl.h"
 
 namespace {
-// These constants are used to generate the UMA histograms for local network
-// request metrics. If the enums for |DomainType|, |ResourceType|, or |PortType|
-// change, the bitwise arithmetic below must also change.
-static const int kNumNonlocalhostHistograms =
-    ((internal::DOMAIN_TYPE_LOCALHOST << 6) |
-     (internal::RESOURCE_TYPE_LOCALHOST << 1) | 1) + 1;
-static const int kNumLocalhostHistograms =
-    ((internal::DOMAIN_TYPE_LOCALHOST << 5) | (internal::PORT_TYPE_DEV << 1) |
-     1) + 1;
-
-// Generates a histogram for a non-localhost resource using the values stored in
-// |counts| given a combination of domain type, resource type, and status for
-// the resource.
-void CreateHistogram(std::map<const std::string, int> counts,
-                     internal::DomainType domain_type,
-                     internal::ResourceType resource_type,
-                     bool status) {
-  const std::string& histogram_name = internal::GetNonlocalhostHistogramNames()
-                                          .at(domain_type)
-                                          .at(resource_type)
-                                          .at(status);
-  // Because the macro requires a single value for the maximum histogram index,
-  // but we use three variables to distinguish histograms, we bitwise
-  // concatenate them here to uniquely distinguish each combination. If the
-  // enums for |DomainType| or |ResourceType| change, the bitwise arithmetic
-  // below must also change.
-  const int histogram_index =
-      (domain_type << 6) | (resource_type << 1) | (status ? 1 : 0);
-  STATIC_HISTOGRAM_POINTER_GROUP(
-      histogram_name, histogram_index, kNumNonlocalhostHistograms,
-      Add(counts[histogram_name]),
-      base::Histogram::FactoryGet(
-          histogram_name,
-          1,     // min value
-          1000,  // max value
-          50,    // number of buckets
-          base::HistogramBase::kUmaTargetedHistogramFlag));
-}
-
-// Generates a histogram for a localhost resource using the values stored in
-// |counts| given a combination of domain type, port type, and status for
-// the resource.
-void CreateHistogram(std::map<const std::string, int> counts,
-                     internal::DomainType domain_type,
-                     internal::PortType port_type,
-                     bool status) {
-  const std::string& histogram_name = internal::GetLocalhostHistogramNames()
-                                          .at(domain_type)
-                                          .at(port_type)
-                                          .at(status);
-  // Because the macro requires a single value for the maximum histogram index,
-  // but we use three variables to distinguish histograms, we bitwise
-  // concatenate them here to uniquely distinguish each combination. If the
-  // enums for |DomainType| or |PortType| change, the bitwise arithmetic
-  // below must also change.
-  const int histogram_index =
-      (domain_type << 5) | (port_type << 1) | (status ? 1 : 0);
-  STATIC_HISTOGRAM_POINTER_GROUP(
-      histogram_name, histogram_index, kNumLocalhostHistograms,
-      Add(counts[histogram_name]),
-      base::Histogram::FactoryGet(
-          histogram_name,
-          1,     // min value
-          1000,  // max value
-          50,    // number of buckets
-          base::HistogramBase::kUmaTargetedHistogramFlag));
-}
-
 // TODO(uthakore): Update router regex based on further study.
 // Returns true if the IP address matches the following regular expression for
 // common router IP addresses:
@@ -174,131 +106,6 @@
 
 }  // namespace
 
-namespace internal {
-
-// Definitions of getters for the histogram names maps.
-const std::map<internal::DomainType,
-               std::map<internal::ResourceType, std::map<bool, std::string>>>&
-GetNonlocalhostHistogramNames() {
-  static base::LazyInstance<std::map<
-      internal::DomainType,
-      std::map<internal::ResourceType, std::map<bool, std::string>>>>::Leaky
-      histogram_names = LAZY_INSTANCE_INITIALIZER;
-
-  if (histogram_names.Get().empty()) {
-    histogram_names.Get()[internal::DOMAIN_TYPE_PUBLIC]
-                         [internal::RESOURCE_TYPE_PRIVATE][true] =
-        "LocalNetworkRequests.PublicPage.PrivateRequests.Successful";
-    histogram_names.Get()[internal::DOMAIN_TYPE_PUBLIC]
-                         [internal::RESOURCE_TYPE_PRIVATE][false] =
-        "LocalNetworkRequests.PublicPage.PrivateRequests.Failed";
-    histogram_names.Get()[internal::DOMAIN_TYPE_PUBLIC]
-                         [internal::RESOURCE_TYPE_ROUTER][true] =
-        "LocalNetworkRequests.PublicPage.RouterRequests.Successful";
-    histogram_names.Get()[internal::DOMAIN_TYPE_PUBLIC]
-                         [internal::RESOURCE_TYPE_ROUTER][false] =
-        "LocalNetworkRequests.PublicPage.RouterRequests.Failed";
-
-    histogram_names.Get()[internal::DOMAIN_TYPE_PRIVATE]
-                         [internal::RESOURCE_TYPE_PUBLIC][true] =
-        "LocalNetworkRequests.PrivatePage.PublicRequests.Successful";
-    histogram_names.Get()[internal::DOMAIN_TYPE_PRIVATE]
-                         [internal::RESOURCE_TYPE_PUBLIC][false] =
-        "LocalNetworkRequests.PrivatePage.PublicRequests.Failed";
-    histogram_names.Get()[internal::DOMAIN_TYPE_PRIVATE]
-                         [internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET][true] =
-        "LocalNetworkRequests.PrivatePage.SameSubnetRequests.Successful";
-    histogram_names.Get()[internal::DOMAIN_TYPE_PRIVATE]
-                         [internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET][false] =
-        "LocalNetworkRequests.PrivatePage.SameSubnetRequests.Failed";
-    histogram_names.Get()[internal::DOMAIN_TYPE_PRIVATE]
-                         [internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET][true] =
-        "LocalNetworkRequests.PrivatePage.DifferentSubnetRequests.Successful";
-    histogram_names.Get()[internal::DOMAIN_TYPE_PRIVATE]
-                         [internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET][false] =
-        "LocalNetworkRequests.PrivatePage.DifferentSubnetRequests.Failed";
-  }
-
-  return histogram_names.Get();
-}
-
-const std::map<internal::DomainType,
-               std::map<internal::PortType, std::map<bool, std::string>>>&
-GetLocalhostHistogramNames() {
-  static base::LazyInstance<std::map<
-      internal::DomainType,
-      std::map<internal::PortType, std::map<bool, std::string>>>>::Leaky
-      histogram_names = LAZY_INSTANCE_INITIALIZER;
-
-  if (histogram_names.Get().empty()) {
-    histogram_names
-        .Get()[internal::DOMAIN_TYPE_PUBLIC][internal::PORT_TYPE_WEB][true] =
-        "LocalNetworkRequests.PublicPage.Localhost.WebRequests.Successful";
-    histogram_names
-        .Get()[internal::DOMAIN_TYPE_PUBLIC][internal::PORT_TYPE_WEB][false] =
-        "LocalNetworkRequests.PublicPage.Localhost.WebRequests.Failed";
-    histogram_names
-        .Get()[internal::DOMAIN_TYPE_PUBLIC][internal::PORT_TYPE_DB][true] =
-        "LocalNetworkRequests.PublicPage.Localhost.DbRequests.Successful";
-    histogram_names
-        .Get()[internal::DOMAIN_TYPE_PUBLIC][internal::PORT_TYPE_DB][false] =
-        "LocalNetworkRequests.PublicPage.Localhost.DbRequests.Failed";
-    histogram_names
-        .Get()[internal::DOMAIN_TYPE_PUBLIC][internal::PORT_TYPE_PRINT][true] =
-        "LocalNetworkRequests.PublicPage.Localhost.PrinterRequests.Successful";
-    histogram_names
-        .Get()[internal::DOMAIN_TYPE_PUBLIC][internal::PORT_TYPE_PRINT][false] =
-        "LocalNetworkRequests.PublicPage.Localhost.PrinterRequests.Failed";
-    histogram_names
-        .Get()[internal::DOMAIN_TYPE_PUBLIC][internal::PORT_TYPE_DEV][true] =
-        "LocalNetworkRequests.PublicPage.Localhost.DevRequests.Successful";
-    histogram_names
-        .Get()[internal::DOMAIN_TYPE_PUBLIC][internal::PORT_TYPE_DEV][false] =
-        "LocalNetworkRequests.PublicPage.Localhost.DevRequests.Failed";
-    histogram_names
-        .Get()[internal::DOMAIN_TYPE_PUBLIC][internal::PORT_TYPE_OTHER][true] =
-        "LocalNetworkRequests.PublicPage.Localhost.OtherRequests.Successful";
-    histogram_names
-        .Get()[internal::DOMAIN_TYPE_PUBLIC][internal::PORT_TYPE_OTHER][false] =
-        "LocalNetworkRequests.PublicPage.Localhost.OtherRequests.Failed";
-
-    histogram_names
-        .Get()[internal::DOMAIN_TYPE_PRIVATE][internal::PORT_TYPE_WEB][true] =
-        "LocalNetworkRequests.PrivatePage.Localhost.WebRequests.Successful";
-    histogram_names
-        .Get()[internal::DOMAIN_TYPE_PRIVATE][internal::PORT_TYPE_WEB][false] =
-        "LocalNetworkRequests.PrivatePage.Localhost.WebRequests.Failed";
-    histogram_names
-        .Get()[internal::DOMAIN_TYPE_PRIVATE][internal::PORT_TYPE_DB][true] =
-        "LocalNetworkRequests.PrivatePage.Localhost.DbRequests.Successful";
-    histogram_names
-        .Get()[internal::DOMAIN_TYPE_PRIVATE][internal::PORT_TYPE_DB][false] =
-        "LocalNetworkRequests.PrivatePage.Localhost.DbRequests.Failed";
-    histogram_names
-        .Get()[internal::DOMAIN_TYPE_PRIVATE][internal::PORT_TYPE_PRINT][true] =
-        "LocalNetworkRequests.PrivatePage.Localhost.PrinterRequests.Successful";
-    histogram_names.Get()[internal::DOMAIN_TYPE_PRIVATE]
-                         [internal::PORT_TYPE_PRINT][false] =
-        "LocalNetworkRequests.PrivatePage.Localhost.PrinterRequests.Failed";
-    histogram_names
-        .Get()[internal::DOMAIN_TYPE_PRIVATE][internal::PORT_TYPE_DEV][true] =
-        "LocalNetworkRequests.PrivatePage.Localhost.DevRequests.Successful";
-    histogram_names
-        .Get()[internal::DOMAIN_TYPE_PRIVATE][internal::PORT_TYPE_DEV][false] =
-        "LocalNetworkRequests.PrivatePage.Localhost.DevRequests.Failed";
-    histogram_names
-        .Get()[internal::DOMAIN_TYPE_PRIVATE][internal::PORT_TYPE_OTHER][true] =
-        "LocalNetworkRequests.PrivatePage.Localhost.OtherRequests.Successful";
-    histogram_names.Get()[internal::DOMAIN_TYPE_PRIVATE]
-                         [internal::PORT_TYPE_OTHER][false] =
-        "LocalNetworkRequests.PrivatePage.Localhost.OtherRequests.Failed";
-  }
-
-  return histogram_names.Get();
-}
-
-}  // namespace internal
-
 LocalNetworkRequestsPageLoadMetricsObserver::
     LocalNetworkRequestsPageLoadMetricsObserver() {}
 LocalNetworkRequestsPageLoadMetricsObserver::
@@ -379,7 +186,6 @@
   // The browser may come back, but there is no guarantee. To be safe, we record
   // what we have now and treat changes to this navigation as new page loads.
   if (GetDelegate().DidCommit()) {
-    RecordHistograms();
     RecordUkmMetrics(GetDelegate().GetPageUkmSourceId());
     ClearLocalState();
   }
@@ -421,7 +227,6 @@
 void LocalNetworkRequestsPageLoadMetricsObserver::OnComplete(
     const page_load_metrics::mojom::PageLoadTiming& timing) {
   if (GetDelegate().DidCommit()) {
-    RecordHistograms();
     RecordUkmMetrics(GetDelegate().GetPageUkmSourceId());
   }
 }
@@ -432,61 +237,6 @@
   requested_resource_types_.reset();
 }
 
-void LocalNetworkRequestsPageLoadMetricsObserver::RecordHistograms() {
-  if (page_domain_type_ == internal::DOMAIN_TYPE_LOCALHOST) {
-    return;
-  }
-  ResolveResourceTypes();
-
-  // Compute the number of requests of each resource type for the loaded page.
-  std::map<const std::string, int> counts;
-  for (const auto& entry : resource_request_counts_) {
-    counts[internal::GetNonlocalhostHistogramNames()
-               .at(page_domain_type_)
-               .at(requested_resource_types_->at(entry.first))
-               .at(true)] += entry.second.first;
-    counts[internal::GetNonlocalhostHistogramNames()
-               .at(page_domain_type_)
-               .at(requested_resource_types_->at(entry.first))
-               .at(false)] += entry.second.second;
-  }
-
-  for (const auto& entry : localhost_request_counts_) {
-    counts[internal::GetLocalhostHistogramNames()
-               .at(page_domain_type_)
-               .at(DeterminePortType(entry.first))
-               .at(true)] += entry.second.first;
-    counts[internal::GetLocalhostHistogramNames()
-               .at(page_domain_type_)
-               .at(DeterminePortType(entry.first))
-               .at(false)] += entry.second.second;
-  }
-
-  // Log a histogram for each type of resource depending on the domain type of
-  // the page load.
-  if (page_domain_type_ == internal::DOMAIN_TYPE_PUBLIC) {
-    for (auto resource_type :
-         {internal::RESOURCE_TYPE_PRIVATE, internal::RESOURCE_TYPE_ROUTER}) {
-      CreateHistogram(counts, page_domain_type_, resource_type, true);
-      CreateHistogram(counts, page_domain_type_, resource_type, false);
-    }
-  } else {
-    DCHECK_EQ(page_domain_type_, internal::DOMAIN_TYPE_PRIVATE);
-    for (auto resource_type : {internal::RESOURCE_TYPE_PUBLIC,
-                               internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET,
-                               internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET}) {
-      CreateHistogram(counts, page_domain_type_, resource_type, true);
-      CreateHistogram(counts, page_domain_type_, resource_type, false);
-    }
-  }
-  for (auto port_type : {internal::PORT_TYPE_WEB, internal::PORT_TYPE_DB,
-                         internal::PORT_TYPE_PRINT, internal::PORT_TYPE_DEV,
-                         internal::PORT_TYPE_OTHER}) {
-    CreateHistogram(counts, page_domain_type_, port_type, true);
-    CreateHistogram(counts, page_domain_type_, port_type, false);
-  }
-}
-
 internal::ResourceType
 LocalNetworkRequestsPageLoadMetricsObserver::DetermineResourceType(
     net::IPAddress resource_ip) {
diff --git a/chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer.h
index 3ca7147..407a685c4 100644
--- a/chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer.h
+++ b/chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer.h
@@ -101,7 +101,6 @@
   void ResolveResourceTypes();
 
   void RecordUkmDomainType(ukm::SourceId source_id);
-  void RecordHistograms();
   void RecordUkmMetrics(ukm::SourceId source_id);
 
   // Stores the counts of resource requests for each non-localhost IP address as
diff --git a/chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer_unittest.cc
index 63c6a80..d82f5a6 100644
--- a/chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/observers/local_network_requests_page_load_metrics_observer_unittest.cc
@@ -6,7 +6,6 @@
 
 #include <vector>
 
-#include "base/test/metrics/histogram_tester.h"
 #include "chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.h"
 #include "components/page_load_metrics/browser/page_load_metrics_observer.h"
 #include "components/page_load_metrics/browser/page_load_metrics_util.h"
@@ -137,43 +136,6 @@
     DCHECK(navigation_simulator_);
     return navigation_simulator_->GetGlobalRequestID();
   }
-
-  // Helper functions to verify that particular slices of UMA histograms are
-  // empty.
-  void ExpectEmptyHistograms(internal::DomainType domain_type) {
-    for (const auto& port :
-         internal::GetLocalhostHistogramNames().at(domain_type)) {
-      for (const auto& histogramName : port.second) {
-        tester()->histogram_tester().ExpectUniqueSample(histogramName.second, 0,
-                                                        1);
-      }
-    }
-    for (const auto& resource :
-         internal::GetNonlocalhostHistogramNames().at(domain_type)) {
-      for (const auto& histogramName : resource.second) {
-        tester()->histogram_tester().ExpectUniqueSample(histogramName.second, 0,
-                                                        1);
-      }
-    }
-  }
-
-  void ExpectNoHistograms() {
-    for (const auto& domain : internal::GetLocalhostHistogramNames()) {
-      for (const auto& port : domain.second) {
-        for (const auto& status : port.second) {
-          tester()->histogram_tester().ExpectTotalCount(status.second, 0);
-        }
-      }
-    }
-    for (const auto& domain : internal::GetNonlocalhostHistogramNames()) {
-      for (const auto& resource : domain.second) {
-        for (const auto& status : resource.second) {
-          tester()->histogram_tester().ExpectTotalCount(status.second, 0);
-        }
-      }
-    }
-  }
-
   void ExpectUkmPageDomainMetric(const internal::PageAddressInfo& page,
                                  const internal::DomainType domain_type) {
     auto entries = tester()->test_ukm_recorder().GetEntriesByName(
@@ -188,10 +150,9 @@
     }
   }
 
-  void ExpectMetricsAndHistograms(
+  void ExpectMetrics(
       const internal::PageAddressInfo& page,
-      const std::vector<internal::UkmMetricInfo>& expected_metrics,
-      const std::map<std::string, int>& expected_histograms) {
+      const std::vector<internal::UkmMetricInfo>& expected_metrics) {
     using LocalNetworkRequests = ukm::builders::LocalNetworkRequests;
     auto entries = tester()->test_ukm_recorder().GetEntriesByName(
         LocalNetworkRequests::kEntryName);
@@ -215,12 +176,6 @@
             static_cast<int>(expected_metrics[i].port_type));
       }
     }
-
-    // Should have generated UMA histograms for all requests made.
-    for (auto hist : expected_histograms) {
-      tester()->histogram_tester().ExpectUniqueSample(hist.first, hist.second,
-                                                      1);
-    }
   }
 
  private:
@@ -230,9 +185,6 @@
 TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest, NoMetrics) {
   EXPECT_EQ(0ul, tester()->test_ukm_recorder().sources_count());
   EXPECT_EQ(0ul, tester()->test_ukm_recorder().entries_count());
-
-  // Sanity check
-  ExpectNoHistograms();
 }
 
 TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest,
@@ -244,7 +196,6 @@
 
   // Should generate only a domain type UKM entry and nothing else.
   ExpectUkmPageDomainMetric(page, internal::DOMAIN_TYPE_PUBLIC);
-  ExpectEmptyHistograms(internal::DOMAIN_TYPE_PUBLIC);
 }
 
 TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest,
@@ -257,7 +208,6 @@
 
   // Should generate only a domain type UKM entry and nothing else.
   ExpectUkmPageDomainMetric(page, internal::DOMAIN_TYPE_PUBLIC);
-  ExpectEmptyHistograms(internal::DOMAIN_TYPE_PUBLIC);
 }
 
 TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest,
@@ -271,7 +221,6 @@
 
   // Should generate only a domain type UKM entry and nothing else.
   ExpectUkmPageDomainMetric(page, internal::DOMAIN_TYPE_PRIVATE);
-  ExpectEmptyHistograms(internal::DOMAIN_TYPE_PRIVATE);
 }
 
 TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest, PrivatePageNoRequests) {
@@ -282,7 +231,6 @@
 
   // Should generate only a domain type UKM entry and nothing else.
   ExpectUkmPageDomainMetric(page, internal::DOMAIN_TYPE_PRIVATE);
-  ExpectEmptyHistograms(internal::DOMAIN_TYPE_PRIVATE);
 }
 
 TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest, LocalhostPage) {
@@ -295,7 +243,6 @@
 
   // Should generate only a domain type UKM entry and nothing else.
   ExpectUkmPageDomainMetric(page, internal::DOMAIN_TYPE_LOCALHOST);
-  ExpectNoHistograms();
 }
 
 TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest, LocalhostPageIPv6) {
@@ -309,7 +256,6 @@
 
   // Should generate only a domain type UKM entry and nothing else.
   ExpectUkmPageDomainMetric(page, internal::DOMAIN_TYPE_LOCALHOST);
-  ExpectNoHistograms();
 }
 
 TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest,
@@ -343,73 +289,35 @@
 
   // We should now see UKM entries and UMA histograms for each of the types of
   // resources requested except for public resources.
-  ExpectMetricsAndHistograms(
-      page,
-      // List of expected UKM metric values.
-      {
-          {internal::RESOURCE_TYPE_ROUTER, internal::PORT_TYPE_WEB, 1,
-           0},  // 10.0.0.1:80
-          {internal::RESOURCE_TYPE_PRIVATE, internal::PORT_TYPE_WEB, 1,
-           0},  // 10.0.10.200:80
-          {internal::RESOURCE_TYPE_PRIVATE, internal::PORT_TYPE_WEB, 1,
-           0},  // 172.16.0.85:8181
-          {internal::RESOURCE_TYPE_ROUTER, internal::PORT_TYPE_WEB, 1,
-           0},  // 192.168.10.1:443
-          {internal::RESOURCE_TYPE_PRIVATE, internal::PORT_TYPE_WEB, 1,
-           0},  // 192.168.10.123:80
-          {internal::RESOURCE_TYPE_PRIVATE, internal::PORT_TYPE_WEB, 3,
-           0},  // 192.168.10.200:8000
-          {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_WEB, 2,
-           0},  // 127.0.0.1:80
-          {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_PRINT, 1,
-           0},  // 127.0.2.1:515
-          {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_DB, 1,
-           0},  // 127.0.1.1:3306
-          {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_WEB, 1,
-           0},  // 127.0.0.1:8080
-          {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_DEV, 1,
-           0},  // 127.100.150.200:9000
-          {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_OTHER, 1,
-           0},  // 127.0.0.1:9876
-      },
-      // List of expected nonzero UMA histogram values.
-      {
-          {internal::GetNonlocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PUBLIC)
-               .at(internal::RESOURCE_TYPE_ROUTER)
-               .at(true),
-           2},
-          {internal::GetNonlocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PUBLIC)
-               .at(internal::RESOURCE_TYPE_PRIVATE)
-               .at(true),
-           6},
-          {internal::GetLocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PUBLIC)
-               .at(internal::PORT_TYPE_WEB)
-               .at(true),
-           3},
-          {internal::GetLocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PUBLIC)
-               .at(internal::PORT_TYPE_PRINT)
-               .at(true),
-           1},
-          {internal::GetLocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PUBLIC)
-               .at(internal::PORT_TYPE_DB)
-               .at(true),
-           1},
-          {internal::GetLocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PUBLIC)
-               .at(internal::PORT_TYPE_DEV)
-               .at(true),
-           1},
-          {internal::GetLocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PUBLIC)
-               .at(internal::PORT_TYPE_OTHER)
-               .at(true),
-           1},
-      });
+  ExpectMetrics(page,
+                // List of expected UKM metric values.
+                {
+                    {internal::RESOURCE_TYPE_ROUTER, internal::PORT_TYPE_WEB, 1,
+                     0},  // 10.0.0.1:80
+                    {internal::RESOURCE_TYPE_PRIVATE, internal::PORT_TYPE_WEB,
+                     1, 0},  // 10.0.10.200:80
+                    {internal::RESOURCE_TYPE_PRIVATE, internal::PORT_TYPE_WEB,
+                     1, 0},  // 172.16.0.85:8181
+                    {internal::RESOURCE_TYPE_ROUTER, internal::PORT_TYPE_WEB, 1,
+                     0},  // 192.168.10.1:443
+                    {internal::RESOURCE_TYPE_PRIVATE, internal::PORT_TYPE_WEB,
+                     1, 0},  // 192.168.10.123:80
+                    {internal::RESOURCE_TYPE_PRIVATE, internal::PORT_TYPE_WEB,
+                     3, 0},  // 192.168.10.200:8000
+                    {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_WEB,
+                     2, 0},  // 127.0.0.1:80
+                    {internal::RESOURCE_TYPE_LOCALHOST,
+                     internal::PORT_TYPE_PRINT, 1, 0},  // 127.0.2.1:515
+                    {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_DB,
+                     1, 0},  // 127.0.1.1:3306
+                    {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_WEB,
+                     1, 0},  // 127.0.0.1:8080
+                    {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_DEV,
+                     1, 0},  // 127.100.150.200:9000
+                    {internal::RESOURCE_TYPE_LOCALHOST,
+                     internal::PORT_TYPE_OTHER, 1, 0},  // 127.0.0.1:9876
+
+                });
 }
 
 TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest,
@@ -443,84 +351,40 @@
 
   // We should now see UKM entries and UMA histograms for each of the types of
   // resources requested except for the request to the page itself.
-  ExpectMetricsAndHistograms(
-      page,
-      // List of expected UKM metric values.
-      {
-          {internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET, internal::PORT_TYPE_WEB,
-           1, 0},  // 10.0.0.1:80
-          {internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET, internal::PORT_TYPE_WEB,
-           1, 0},  // 10.0.10.200:80
-          {internal::RESOURCE_TYPE_PUBLIC, internal::PORT_TYPE_WEB, 1,
-           0},  // 100.150.200.250:80
-          {internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET, internal::PORT_TYPE_WEB,
-           1, 0},  // 172.16.0.85:8181
-          {internal::RESOURCE_TYPE_PUBLIC, internal::PORT_TYPE_WEB, 1,
-           0},  // 192.10.20.30:443
-          {internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET, internal::PORT_TYPE_WEB,
-           1, 0},  // 192.168.10.1:443
-          {internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET, internal::PORT_TYPE_WEB,
-           3, 0},  // 192.168.10.200:8000
-          {internal::RESOURCE_TYPE_PUBLIC, internal::PORT_TYPE_WEB, 1,
-           0},  // 216.58.195.78:443
-          {internal::RESOURCE_TYPE_PUBLIC, internal::PORT_TYPE_WEB, 1,
-           0},  // [2607:f8b0:4005:809::200e]:443
-          {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_WEB, 2,
-           0},  // 127.0.0.1:80
-          {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_PRINT, 1,
-           0},  // 127.0.2.1:515
-          {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_DB, 1,
-           0},  // 127.0.1.1:3306
-          {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_WEB, 1,
-           0},  // 127.0.0.1:8080
-          {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_DEV, 1,
-           0},  // 127.100.150.200:9000
-          {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_OTHER, 1,
-           0},  // 127.0.0.1:9876
-      },
-      // List of expected nonzero UMA histogram values.
-      {
-          {internal::GetNonlocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PRIVATE)
-               .at(internal::RESOURCE_TYPE_PUBLIC)
-               .at(true),
-           4},
-          {internal::GetNonlocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PRIVATE)
-               .at(internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET)
-               .at(true),
-           3},
-          {internal::GetNonlocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PRIVATE)
-               .at(internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET)
-               .at(true),
-           4},
-          {internal::GetLocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PRIVATE)
-               .at(internal::PORT_TYPE_WEB)
-               .at(true),
-           3},
-          {internal::GetLocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PRIVATE)
-               .at(internal::PORT_TYPE_PRINT)
-               .at(true),
-           1},
-          {internal::GetLocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PRIVATE)
-               .at(internal::PORT_TYPE_DB)
-               .at(true),
-           1},
-          {internal::GetLocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PRIVATE)
-               .at(internal::PORT_TYPE_DEV)
-               .at(true),
-           1},
-          {internal::GetLocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PRIVATE)
-               .at(internal::PORT_TYPE_OTHER)
-               .at(true),
-           1},
-      });
+  ExpectMetrics(page,
+                // List of expected UKM metric values.
+                {
+                    {internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET,
+                     internal::PORT_TYPE_WEB, 1, 0},  // 10.0.0.1:80
+                    {internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET,
+                     internal::PORT_TYPE_WEB, 1, 0},  // 10.0.10.200:80
+                    {internal::RESOURCE_TYPE_PUBLIC, internal::PORT_TYPE_WEB, 1,
+                     0},  // 100.150.200.250:80
+                    {internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET,
+                     internal::PORT_TYPE_WEB, 1, 0},  // 172.16.0.85:8181
+                    {internal::RESOURCE_TYPE_PUBLIC, internal::PORT_TYPE_WEB, 1,
+                     0},  // 192.10.20.30:443
+                    {internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET,
+                     internal::PORT_TYPE_WEB, 1, 0},  // 192.168.10.1:443
+                    {internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET,
+                     internal::PORT_TYPE_WEB, 3, 0},  // 192.168.10.200:8000
+                    {internal::RESOURCE_TYPE_PUBLIC, internal::PORT_TYPE_WEB, 1,
+                     0},  // 216.58.195.78:443
+                    {internal::RESOURCE_TYPE_PUBLIC, internal::PORT_TYPE_WEB, 1,
+                     0},  // [2607:f8b0:4005:809::200e]:443
+                    {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_WEB,
+                     2, 0},  // 127.0.0.1:80
+                    {internal::RESOURCE_TYPE_LOCALHOST,
+                     internal::PORT_TYPE_PRINT, 1, 0},  // 127.0.2.1:515
+                    {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_DB,
+                     1, 0},  // 127.0.1.1:3306
+                    {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_WEB,
+                     1, 0},  // 127.0.0.1:8080
+                    {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_DEV,
+                     1, 0},  // 127.100.150.200:9000
+                    {internal::RESOURCE_TYPE_LOCALHOST,
+                     internal::PORT_TYPE_OTHER, 1, 0},  // 127.0.0.1:9876
+                });
 }
 
 TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest,
@@ -552,84 +416,40 @@
   // requested except for the public resources.
   ExpectUkmPageDomainMetric(page, internal::DOMAIN_TYPE_PRIVATE);
 
-  ExpectMetricsAndHistograms(
-      page,
-      // List of expected UKM metric values.
-      {
-          {internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET, internal::PORT_TYPE_WEB,
-           0, 1},  // 10.0.0.1:80
-          {internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET, internal::PORT_TYPE_WEB,
-           0, 1},  // 10.0.10.200:80
-          {internal::RESOURCE_TYPE_PUBLIC, internal::PORT_TYPE_WEB, 0,
-           1},  // 100.150.200.250:80
-          {internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET, internal::PORT_TYPE_WEB,
-           0, 1},  // 172.16.0.85:8181
-          {internal::RESOURCE_TYPE_PUBLIC, internal::PORT_TYPE_WEB, 0,
-           1},  // 192.10.20.30:443
-          {internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET, internal::PORT_TYPE_WEB,
-           0, 1},  // 192.168.10.1:443
-          {internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET, internal::PORT_TYPE_WEB,
-           0, 3},  // 192.168.10.200:8000
-          {internal::RESOURCE_TYPE_PUBLIC, internal::PORT_TYPE_WEB, 0,
-           1},  // 216.58.195.78:443
-          {internal::RESOURCE_TYPE_PUBLIC, internal::PORT_TYPE_WEB, 0,
-           1},  // [2607:f8b0:4005:809::200e]:443
-          {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_WEB, 0,
-           2},  // 127.0.0.1:80
-          {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_PRINT, 0,
-           1},  // 127.0.2.1:515
-          {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_DB, 0,
-           1},  // 127.0.1.1:3306
-          {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_WEB, 0,
-           1},  // 127.0.0.1:8080
-          {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_DEV, 0,
-           1},  // 127.100.150.200:9000
-          {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_OTHER, 0,
-           1},  // 127.0.0.1:9876
-      },
-      // List of expected nonzero UMA histogram values.
-      {
-          {internal::GetNonlocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PRIVATE)
-               .at(internal::RESOURCE_TYPE_PUBLIC)
-               .at(false),
-           4},
-          {internal::GetNonlocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PRIVATE)
-               .at(internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET)
-               .at(false),
-           3},
-          {internal::GetNonlocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PRIVATE)
-               .at(internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET)
-               .at(false),
-           4},
-          {internal::GetLocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PRIVATE)
-               .at(internal::PORT_TYPE_WEB)
-               .at(false),
-           3},
-          {internal::GetLocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PRIVATE)
-               .at(internal::PORT_TYPE_PRINT)
-               .at(false),
-           1},
-          {internal::GetLocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PRIVATE)
-               .at(internal::PORT_TYPE_DB)
-               .at(false),
-           1},
-          {internal::GetLocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PRIVATE)
-               .at(internal::PORT_TYPE_DEV)
-               .at(false),
-           1},
-          {internal::GetLocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PRIVATE)
-               .at(internal::PORT_TYPE_OTHER)
-               .at(false),
-           1},
-      });
+  ExpectMetrics(page,
+                // List of expected UKM metric values.
+                {
+                    {internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET,
+                     internal::PORT_TYPE_WEB, 0, 1},  // 10.0.0.1:80
+                    {internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET,
+                     internal::PORT_TYPE_WEB, 0, 1},  // 10.0.10.200:80
+                    {internal::RESOURCE_TYPE_PUBLIC, internal::PORT_TYPE_WEB, 0,
+                     1},  // 100.150.200.250:80
+                    {internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET,
+                     internal::PORT_TYPE_WEB, 0, 1},  // 172.16.0.85:8181
+                    {internal::RESOURCE_TYPE_PUBLIC, internal::PORT_TYPE_WEB, 0,
+                     1},  // 192.10.20.30:443
+                    {internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET,
+                     internal::PORT_TYPE_WEB, 0, 1},  // 192.168.10.1:443
+                    {internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET,
+                     internal::PORT_TYPE_WEB, 0, 3},  // 192.168.10.200:8000
+                    {internal::RESOURCE_TYPE_PUBLIC, internal::PORT_TYPE_WEB, 0,
+                     1},  // 216.58.195.78:443
+                    {internal::RESOURCE_TYPE_PUBLIC, internal::PORT_TYPE_WEB, 0,
+                     1},  // [2607:f8b0:4005:809::200e]:443
+                    {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_WEB,
+                     0, 2},  // 127.0.0.1:80
+                    {internal::RESOURCE_TYPE_LOCALHOST,
+                     internal::PORT_TYPE_PRINT, 0, 1},  // 127.0.2.1:515
+                    {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_DB,
+                     0, 1},  // 127.0.1.1:3306
+                    {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_WEB,
+                     0, 1},  // 127.0.0.1:8080
+                    {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_DEV,
+                     0, 1},  // 127.100.150.200:9000
+                    {internal::RESOURCE_TYPE_LOCALHOST,
+                     internal::PORT_TYPE_OTHER, 0, 1},  // 127.0.0.1:9876
+                });
 }
 
 TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest,
@@ -648,49 +468,20 @@
   // requested except for the public resources.
   ExpectUkmPageDomainMetric(page, internal::DOMAIN_TYPE_PUBLIC);
 
-  ExpectMetricsAndHistograms(
-      page,
-      // List of expected UKM metric values.
-      {
-          {internal::RESOURCE_TYPE_ROUTER, internal::PORT_TYPE_WEB, 1,
-           0},  // 10.0.0.1:80
-          {internal::RESOURCE_TYPE_PRIVATE, internal::PORT_TYPE_WEB, 1,
-           1},  // 172.16.0.85:8181
-          {internal::RESOURCE_TYPE_PRIVATE, internal::PORT_TYPE_DEV, 1,
-           0},  // 192.168.10.200:8000
-          {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_DB, 0,
-           1},  // 127.0.1.1:3306
-          {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_OTHER, 0,
-           1},  // 127.0.0.1:9876
-      },
-      // List of expected nonzero UMA histogram values.
-      {
-          {internal::GetNonlocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PUBLIC)
-               .at(internal::RESOURCE_TYPE_ROUTER)
-               .at(true),
-           1},
-          {internal::GetNonlocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PUBLIC)
-               .at(internal::RESOURCE_TYPE_PRIVATE)
-               .at(true),
-           2},
-          {internal::GetNonlocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PUBLIC)
-               .at(internal::RESOURCE_TYPE_PRIVATE)
-               .at(false),
-           1},
-          {internal::GetLocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PUBLIC)
-               .at(internal::PORT_TYPE_DB)
-               .at(false),
-           1},
-          {internal::GetLocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PUBLIC)
-               .at(internal::PORT_TYPE_OTHER)
-               .at(false),
-           1},
-      });
+  ExpectMetrics(page,
+                // List of expected UKM metric values.
+                {
+                    {internal::RESOURCE_TYPE_ROUTER, internal::PORT_TYPE_WEB, 1,
+                     0},  // 10.0.0.1:80
+                    {internal::RESOURCE_TYPE_PRIVATE, internal::PORT_TYPE_WEB,
+                     1, 1},  // 172.16.0.85:8181
+                    {internal::RESOURCE_TYPE_PRIVATE, internal::PORT_TYPE_DEV,
+                     1, 0},  // 192.168.10.200:8000
+                    {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_DB,
+                     0, 1},  // 127.0.1.1:3306
+                    {internal::RESOURCE_TYPE_LOCALHOST,
+                     internal::PORT_TYPE_OTHER, 0, 1},  // 127.0.0.1:9876
+                });
 }
 
 TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest,
@@ -737,42 +528,18 @@
   // Close the page.
   DeleteContents();
 
-  ExpectMetricsAndHistograms(
-      page,
-      // List of expected UKM metric values.
-      {
-          {internal::RESOURCE_TYPE_PRIVATE, internal::PORT_TYPE_WEB, 1000,
-           0},  // 10.0.10.200:80
-          {internal::RESOURCE_TYPE_PRIVATE, internal::PORT_TYPE_WEB, 0,
-           100},  // 172.16.0.85:8181
-          {internal::RESOURCE_TYPE_PRIVATE, internal::PORT_TYPE_DEV, 0,
-           100},  // 192.168.10.200:9000
-          {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_WEB, 100,
-           100},  // 127.0.0.1:80
-      },
-      // List of expected nonzero UMA histogram values.
-      {
-          {internal::GetNonlocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PUBLIC)
-               .at(internal::RESOURCE_TYPE_PRIVATE)
-               .at(true),
-           1000},
-          {internal::GetNonlocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PUBLIC)
-               .at(internal::RESOURCE_TYPE_PRIVATE)
-               .at(false),
-           200},
-          {internal::GetLocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PUBLIC)
-               .at(internal::PORT_TYPE_WEB)
-               .at(true),
-           100},
-          {internal::GetLocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PUBLIC)
-               .at(internal::PORT_TYPE_WEB)
-               .at(false),
-           100},
-      });
+  ExpectMetrics(page,
+                // List of expected UKM metric values.
+                {
+                    {internal::RESOURCE_TYPE_PRIVATE, internal::PORT_TYPE_WEB,
+                     1000, 0},  // 10.0.10.200:80
+                    {internal::RESOURCE_TYPE_PRIVATE, internal::PORT_TYPE_WEB,
+                     0, 100},  // 172.16.0.85:8181
+                    {internal::RESOURCE_TYPE_PRIVATE, internal::PORT_TYPE_DEV,
+                     0, 100},  // 192.168.10.200:9000
+                    {internal::RESOURCE_TYPE_LOCALHOST, internal::PORT_TYPE_WEB,
+                     100, 100},  // 127.0.0.1:80
+                });
 }
 
 TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest,
@@ -793,13 +560,8 @@
 
   // We should still see a UKM entry and UMA histogram for the resource request.
   ExpectUkmPageDomainMetric(page, internal::DOMAIN_TYPE_PUBLIC);
-  ExpectMetricsAndHistograms(
-      page, {{internal::RESOURCE_TYPE_PRIVATE, internal::PORT_TYPE_WEB, 1, 0}},
-      {{internal::GetNonlocalhostHistogramNames()
-            .at(internal::DOMAIN_TYPE_PUBLIC)
-            .at(internal::RESOURCE_TYPE_PRIVATE)
-            .at(true),
-        1}});
+  ExpectMetrics(
+      page, {{internal::RESOURCE_TYPE_PRIVATE, internal::PORT_TYPE_WEB, 1, 0}});
 }
 
 TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest,
@@ -820,7 +582,6 @@
 
   // We shouldn't see any UKM entries or UMA histograms this time.
   ExpectUkmPageDomainMetric(page, internal::DOMAIN_TYPE_PUBLIC);
-  ExpectEmptyHistograms(internal::DOMAIN_TYPE_PUBLIC);
 }
 
 TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest, PrivatePageSubnet10) {
@@ -834,28 +595,15 @@
 
   // The first two requests should be on the same subnet and the last request
   // should be on a different subnet.
-  ExpectMetricsAndHistograms(
-      page,
-      {
-          {internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET, internal::PORT_TYPE_WEB,
-           0, 1},  // 10.0.10.200:80
-          {internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET, internal::PORT_TYPE_OTHER,
-           0, 1},  // 10.15.20.25:12345
-          {internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET, internal::PORT_TYPE_WEB,
-           0, 1},  // 192.168.10.1:443
-      },
-      {
-          {internal::GetNonlocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PRIVATE)
-               .at(internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET)
-               .at(false),
-           2},
-          {internal::GetNonlocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PRIVATE)
-               .at(internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET)
-               .at(false),
-           1},
-      });
+  ExpectMetrics(page,
+                {
+                    {internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET,
+                     internal::PORT_TYPE_WEB, 0, 1},  // 10.0.10.200:80
+                    {internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET,
+                     internal::PORT_TYPE_OTHER, 0, 1},  // 10.15.20.25:12345
+                    {internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET,
+                     internal::PORT_TYPE_WEB, 0, 1},  // 192.168.10.1:443
+                });
 }
 
 TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest, PrivatePageSubnet172) {
@@ -868,26 +616,13 @@
 
   // The first two requests should be on the same subnet and the last request
   // should be on a different subnet.
-  ExpectMetricsAndHistograms(
-      page,
-      {
-          {internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET, internal::PORT_TYPE_WEB,
-           0, 1},  // 10.0.10.200:80
-          {internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET, internal::PORT_TYPE_PRINT,
-           0, 1},  // 172.31.100.20:515
-      },
-      {
-          {internal::GetNonlocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PRIVATE)
-               .at(internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET)
-               .at(false),
-           1},
-          {internal::GetNonlocalhostHistogramNames()
-               .at(internal::DOMAIN_TYPE_PRIVATE)
-               .at(internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET)
-               .at(false),
-           1},
-      });
+  ExpectMetrics(page,
+                {
+                    {internal::RESOURCE_TYPE_LOCAL_DIFF_SUBNET,
+                     internal::PORT_TYPE_WEB, 0, 1},  // 10.0.10.200:80
+                    {internal::RESOURCE_TYPE_LOCAL_SAME_SUBNET,
+                     internal::PORT_TYPE_PRINT, 0, 1},  // 172.31.100.20:515
+                });
 }
 
 TEST_F(LocalNetworkRequestsPageLoadMetricsObserverTest, PrivatePageFailedLoad) {
@@ -905,5 +640,4 @@
                      ->test_ukm_recorder()
                      .GetEntriesByName("HistoryManipulationIntervention")
                      .size());
-  ExpectNoHistograms();
 }
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn
index 49e3c59d..4fef80e0 100644
--- a/chrome/browser/resources/BUILD.gn
+++ b/chrome/browser/resources/BUILD.gn
@@ -46,6 +46,7 @@
       "profile_internals:resources",
       "settings:resources",
       "side_panel:resources",
+      "side_panel/bookmarks:resources",
       "side_panel/customize_chrome:resources",
       "signin:resources",
       "support_tool:resources",
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js
index 4892db1..9db7870 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background.js
@@ -124,7 +124,6 @@
     ClipboardHandler.init();
     CommandHandler.init();
     DownloadHandler.init();
-    EventStreamLogger.init();
     FindHandler.init();
     FocusAutomationHandler.init();
     GestureCommandHandler.init();
@@ -142,6 +141,7 @@
     // complete before continuing.
     await Promise.all([
       DesktopAutomationHandler.init(),
+      EventStreamLogger.init(),
     ]);
     ChromeVoxState.resolveReadyPromise_();
   }
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/logging/event_stream_logger.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/logging/event_stream_logger.js
index 7f09dff..3712772c 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/logging/event_stream_logger.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/logging/event_stream_logger.js
@@ -5,7 +5,6 @@
 /**
  * @fileoverview Creates event stream logger.
  */
-
 import {LocalStorage} from '../../../common/local_storage.js';
 import {BridgeConstants} from '../../common/bridge_constants.js';
 import {BridgeHelper} from '../../common/bridge_helper.js';
@@ -25,31 +24,57 @@
     this.node_ = node;
 
     /** @private {function(!AutomationEvent): void} */
-    this.watcher_ = event => this.eventStreamLogging(event);
+    this.listener_ = event => this.onEvent_(event);
+  }
+
+  /** Initializes global state for EventStreamLogger. */
+  static async init() {
+    const desktop =
+        await new Promise(resolve => chrome.automation.getDesktop(resolve));
+    EventStreamLogger.instance = new EventStreamLogger(desktop);
+    EventStreamLogger.instance.updateAllFilters(
+        LocalStorage.get('enableEventStreamLogging'));
+
+    BridgeHelper.registerHandler(
+        TARGET, Action.NOTIFY_EVENT_STREAM_FILTER_CHANGED,
+        (name, enabled) =>
+            EventStreamLogger.instance.onFilterChanged_(name, enabled));
+  }
+
+  /** @param {boolean} checked */
+  updateAllFilters(checked) {
+    for (const type of Object.values(EventType)) {
+      if (LocalStorage.get(type)) {
+        this.onFilterChanged_(type, checked);
+      }
+    }
+  }
+
+  // ============ Private methods =============
+
+  /**
+   * Adds onEvent_ to this handler.
+   * @param {EventType} eventType
+   * @private
+   */
+  addListener_(eventType) {
+    this.node_.addEventListener(eventType, this.listener_, false);
   }
 
   /**
-   * Adds eventStreamLogging to this handler.
+   * Removes onEvent_ from this handler.
    * @param {EventType} eventType
-   * @protected
+   * @private
    */
-  addWatcher_(eventType) {
-    this.node_.addEventListener(eventType, this.watcher_, false);
-  }
-
-  /**
-   * Removes eventStreamLogging from this handler.
-   * @param {EventType} eventType
-   * @protected
-   */
-  removeWatcher_(eventType) {
-    this.node_.removeEventListener(eventType, this.watcher_, false);
+  removeListener_(eventType) {
+    this.node_.removeEventListener(eventType, this.listener_, false);
   }
 
   /**
    * @param {!AutomationEvent} evt
+   * @private
    */
-  eventStreamLogging(evt) {
+  onEvent_(evt) {
     const eventLog = new EventLog(evt);
     LogStore.instance.writeLog(eventLog);
     console.log(eventLog.toString());
@@ -58,42 +83,16 @@
   /**
    * @param {EventType} eventType
    * @param {boolean} checked
+   * @private
    */
-  notifyEventStreamFilterChanged(eventType, checked) {
+  onFilterChanged_(eventType, checked) {
     if (checked) {
-      this.addWatcher_(eventType);
+      this.addListener_(eventType);
     } else {
-      this.removeWatcher_(eventType);
+      this.removeListener_(eventType);
     }
   }
-
-  /** @param {boolean} checked */
-  notifyEventStreamFilterChangedAll(checked) {
-    for (const type in EventType) {
-      if (LocalStorage.get(EventType[type])) {
-        this.notifyEventStreamFilterChanged(EventType[type], checked);
-      }
-    }
-  }
-
-  /** Initializes global state for EventStreamLogger. */
-  static init() {
-    chrome.automation.getDesktop(function(desktop) {
-      EventStreamLogger.instance = new EventStreamLogger(desktop);
-      EventStreamLogger.instance.notifyEventStreamFilterChangedAll(
-          LocalStorage.get('enableEventStreamLogging'));
-
-      BridgeHelper.registerHandler(
-          TARGET, Action.NOTIFY_EVENT_STREAM_FILTER_CHANGED,
-          (name, enabled) =>
-              EventStreamLogger.instance.notifyEventStreamFilterChanged(
-                  name, enabled));
-    });
-  }
 }
 
-/**
- * Global instance.
- * @type {EventStreamLogger}
- */
+/** @type {EventStreamLogger} */
 EventStreamLogger.instance;
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output.js
index a7fbe02c..8b8d6cd 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output.js
@@ -1120,17 +1120,7 @@
         continue;
       }
 
-      const parentRole = roleInfo.inherits;
-      if (formatNode.role && eventBlock[formatNode.role] &&
-          eventBlock[formatNode.role][formatName]) {
-        rule.role = formatNode.role;
-      } else if (
-          parentRole && eventBlock[parentRole] &&
-          eventBlock[parentRole][formatName]) {
-        rule.role = parentRole;
-      } else {
-        rule.role = CustomRole.DEFAULT;
-      }
+      rule.populateRole(formatNode.role, roleInfo.inherits, formatName);
 
       if (eventBlock[rule.role][formatName]) {
         rule.navigation = formatName;
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_rules.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_rules.js
index cfd3f9de..d82d7b0 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_rules.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output_rules.js
@@ -56,6 +56,24 @@
     });
   }
 
+  /**
+   * @param {ChromeVoxRole|undefined} role
+   * @param {ChromeVoxRole|undefined} parentRole
+   * @param {string} formatName
+   */
+  populateRole(role, parentRole, formatName) {
+    const eventBlock = OutputRule.RULES[this.event_];
+    if (role && eventBlock[role] && eventBlock[role][formatName]) {
+      this.role_ = role;
+    } else if (
+        parentRole && eventBlock[parentRole] &&
+        eventBlock[parentRole][formatName]) {
+      this.role_ = parentRole;
+    } else {
+      this.role_ = CustomRole.DEFAULT;
+    }
+  }
+
   // The following setter functions are a temporary measure.
   // TODO(anastasi): move the logic for determining the below properties into
   // this class.
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/prefs.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/prefs.js
index fb2fd478..17cf8b219 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/prefs.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/prefs.js
@@ -103,7 +103,7 @@
     if (key === 'enableSpeechLogging') {
       TtsBackground.console.setEnabled(value);
     } else if (key === 'enableEventStreamLogging') {
-      EventStreamLogger.instance.notifyEventStreamFilterChangedAll(value);
+      EventStreamLogger.instance.updateAllFilters(value);
     }
     this.enableOrDisableLogUrlWatcher_();
   }
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/log_page/log.js b/chrome/browser/resources/chromeos/accessibility/chromevox/log_page/log.js
index f4f64f7..adeebeb 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/log_page/log.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/log_page/log.js
@@ -9,11 +9,18 @@
 import {BackgroundBridge} from '../common/background_bridge.js';
 import {BaseLog, LogType, SerializableLog} from '../common/log_types.js';
 
-/**
- * Class to manage the log page.
- */
+/** Class to manage the log page. */
 export class LogPage {
+  constructor() {
+    /**
+     * Store whether each filter type is enabled.
+     * @private {Object<string, boolean>}
+     */
+    this.urlPrefs_ = {};
+  }
+
   static async init() {
+    LogPage.instance = new LogPage();
     /** Create filter checkboxes. */
     for (const type of Object.values(LogType)) {
       const label = document.createElement('label');
@@ -97,7 +104,7 @@
     for (const type of Object.values(LogType)) {
       const typeFilter = type + 'Filter';
       const element = document.getElementById(typeFilter);
-      element.checked = LogPage.urlPrefs_[typeFilter];
+      element.checked = LogPage.instance.urlPrefs_[typeFilter];
     }
 
     const log = await BackgroundBridge.LogStore.getLogs();
@@ -111,7 +118,7 @@
    */
   static updateLog(log, div) {
     for (let i = 0; i < log.length; i++) {
-      if (!LogPage.urlPrefs_[log[i].logType + 'Filter']) {
+      if (!LogPage.instance.urlPrefs_[log[i].logType + 'Filter']) {
         continue;
       }
 
@@ -158,21 +165,21 @@
    */
   static setFilterTypeEnabled(typeFilter, checked) {
     if (checked == null || checked === 'true') {
-      LogPage.urlPrefs_[typeFilter] = true;
+      LogPage.instance.urlPrefs_[typeFilter] = true;
     } else {
-      LogPage.urlPrefs_[typeFilter] = false;
+      LogPage.instance.urlPrefs_[typeFilter] = false;
     }
   }
 
   /**
-   * Create URL parameter based on LogPage.urlPrefs_.
+   * Create URL parameter based on LogPage.instance.urlPrefs_.
    * @return {string}
    */
   static createUrlParams() {
     const urlParams = [];
     for (const type of Object.values(LogType)) {
       const typeFilter = type + 'Filter';
-      urlParams.push(typeFilter + '=' + LogPage.urlPrefs_[typeFilter]);
+      urlParams.push(typeFilter + '=' + LogPage.instance.urlPrefs_[typeFilter]);
     }
     return '?' + urlParams.join('&');
   }
@@ -196,14 +203,9 @@
   }
 }
 
-/**
- * Store the preferences of filters.
- * @type {Object<string, boolean>}
- * @private
- */
-LogPage.urlPrefs_ = {};
-
-
 document.addEventListener('DOMContentLoaded', async function() {
   await LogPage.init();
 }, false);
+
+/** @type {LogPage} */
+LogPage.instance;
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.js b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.js
index ecd4e35..773d282e 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.js
@@ -89,10 +89,6 @@
     this.speechElement_ = $('speech');
 
     /** @private {boolean} */
-    this.disableRestartTutorialNudgesForTesting_ = false;
-    /** @private {boolean} */
-    this.mockTouchGestureSourceForTesting_ = false;
-    /** @private {boolean} */
     this.tutorialReadyForTesting_ = false;
 
     this.initListeners_();
@@ -159,11 +155,6 @@
     this.pendingCallback_ = callback;
   }
 
-  /** Enables touch gesture mode for testing. */
-  static setTouchGestureSourceForTesting() {
-    Panel.instance_.mockTouchGestureSourceForTesting_ = true;
-  }
-
   /** Adds BackgroundBridge to the global object so that tests can mock it. */
   static exportBackgroundBridgeForTesting() {
     window.BackgroundBridge = BackgroundBridge;
@@ -334,9 +325,7 @@
       this.pendingCallback_ = null;
 
       const eventSourceState = await BackgroundBridge.EventSourceState.get();
-      const touchScreen =
-          (eventSourceState === EventSourceType.TOUCH_GESTURE ||
-           this.mockTouchGestureSourceForTesting_);
+      const touchScreen = (eventSourceState === EventSourceType.TOUCH_GESTURE);
 
       // Build the top-level menus.
       const searchMenu = this.addSearchMenu_('panel_search_menu');
@@ -1280,8 +1269,7 @@
   /** @private */
   onCurrentRangeChanged_() {
     if (this.mode_ === PanelMode.FULLSCREEN_TUTORIAL) {
-      if (this.tutorial_ && this.tutorial_.restartNudges &&
-          !this.disableRestartTutorialNudgesForTesting_) {
+      if (this.tutorial_ && this.tutorial_.restartNudges) {
         this.tutorial_.restartNudges();
       }
     }
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel_test.js
index 479ef61..4546d6f8 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel_test.js
@@ -20,6 +20,10 @@
         'CommandHandlerInterface',
         '/chromevox/background/command_handler_interface.js');
     await importModule(
+        'EventSourceState', '/chromevox/background/event_source.js');
+    await importModule(
+        'EventSourceType', '/chromevox/common/event_source_type.js');
+    await importModule(
         'LocaleOutputHelper', '/chromevox/common/locale_output_helper.js');
     await importModule(
         ['PanelCommand', 'PanelCommandType'],
@@ -85,6 +89,10 @@
     assertEquals(menuItemTitle, activeItem.menuItemTitle);
   }
 
+  enableTouchMode() {
+    EventSourceState.set(EventSourceType.TOUCH_GESTURE);
+  }
+
   isMenuTitleMessage(menuTitleMessage) {
     const menu = this.getPanel().instance_.activeMenu_;
     return menuTitleMessage === menu.menuMsg;
@@ -286,7 +294,7 @@
     'ChromeVoxPanelTest', 'TouchGesturesMenuAvailableWhenInTouchMode',
     async function() {
       await this.runWithLoadedTree(this.linksDoc);
-      this.getPanel().setTouchGestureSourceForTesting();
+      this.enableTouchMode();
       new PanelCommand(PanelCommandType.OPEN_MENUS).send();
       await this.waitForMenu('panel_search_menu');
 
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/tutorial_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/tutorial_test.js
index 9024c8d..f7767e3de 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/tutorial_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/tutorial_test.js
@@ -85,6 +85,10 @@
     return this.getPanel().instance_.tutorial_;
   }
 
+  disableRestartNudges() {
+    this.getPanel().instance_.tutorial_.restartNudges = null;
+  }
+
   get simpleDoc() {
     return `
       <p>Some web content</p>
@@ -214,10 +218,10 @@
 // Afterward, general hints will be given about using ChromeVox. Lastly,
 // we will give a hint for exiting the tutorial.
 AX_TEST_F('ChromeVoxTutorialTest', 'GeneralNudgesTest', async function() {
-  this.getPanel().instance_.disableRestartTutorialNudgesForTesting_ = true;
   const mockFeedback = this.createMockFeedback();
   const root = await this.runWithLoadedTree(this.simpleDoc);
   await this.launchAndWaitForTutorial();
+  this.disableRestartNudges();
   const tutorial = this.getTutorial();
   const giveNudge = () => {
     tutorial.giveNudge();
@@ -744,10 +748,10 @@
     });
 
 AX_TEST_F('ChromeVoxTutorialTest', 'GeneralTouchNudges', async function() {
-  this.getPanel().instance_.disableRestartTutorialNudgesForTesting_ = true;
   const mockFeedback = this.createMockFeedback();
   const root = await this.runWithLoadedTree(this.simpleDoc);
   await this.launchAndWaitForTutorial();
+  this.disableRestartNudges();
   const tutorial = this.getTutorial();
   const giveNudge = () => {
     tutorial.giveNudge();
diff --git a/chrome/browser/resources/chromeos/emoji_picker/BUILD.gn b/chrome/browser/resources/chromeos/emoji_picker/BUILD.gn
index 6eab14df..e280462 100644
--- a/chrome/browser/resources/chromeos/emoji_picker/BUILD.gn
+++ b/chrome/browser/resources/chromeos/emoji_picker/BUILD.gn
@@ -9,6 +9,7 @@
 import("//ui/webui/resources/tools/generate_grd.gni")
 
 web_component_files = [
+  "emoji_button.ts",
   "emoji_category_button.ts",
   "emoji_group.ts",
   "emoji_group_button.ts",
diff --git a/chrome/browser/resources/chromeos/emoji_picker/emoji_button.html b/chrome/browser/resources/chromeos/emoji_picker/emoji_button.html
new file mode 100644
index 0000000..e6d2e7e
--- /dev/null
+++ b/chrome/browser/resources/chromeos/emoji_picker/emoji_button.html
@@ -0,0 +1,103 @@
+<style>
+  :host {
+    --emoji-background: transparent;
+    /* Fixed height and width are required for buttons that have variants,
+     * Otherwise, when showing variants, buttons' positions will be moved.
+     */
+    height: var(--emoji-size);
+    position: relative;
+    width:  var(--emoji-size);
+  }
+
+  #emoji-button {
+    background: var(--emoji-background);
+    border: none;
+    border-radius: 50%;
+    cursor: pointer;
+    display: block;
+    font-family: 'Noto Color Emoji';
+    font-size: 19px;
+    height: 100%;
+    line-height: var(--emoji-size);
+    outline: none;
+    padding: 0;
+    text-align: center;
+    user-select: none;
+    width: 100%;
+  }
+
+  #emoji-button:focus,
+  #emoji-button:active {
+    outline-color: var(--cros-focus-ring-color);
+    outline-style: solid;
+    outline-width: 2px;
+  }
+
+  #emoji-button:disabled {
+    /* chrome makes disabled buttons semitransparent.
+     * we set a solid colour here to prevent that
+     * (exactly which colour is not important).
+     */
+    color: red;
+    cursor: default;
+  }
+
+  #emoji-button:hover {
+    background-color: var(--emoji-hover-background);
+  }
+
+  /* Implement has-variants as ::after so that it still works with hover
+   * ripple.
+   */
+  .has-variants::after {
+    /* 4px grey triangle in bottom-right.
+    * 315 degrees means starting at bottom-right towards top-left.
+    * Manual color here because there isn't something easy to use, but fine for
+    * dark mode since dark mode is the same.
+    */
+    background: linear-gradient(
+        315deg, var(--google-grey-500) 4px,
+        var(--emoji-background) 4px, var(--emoji-background));
+    content: '';
+    display: block;
+    height: var(--emoji-size);
+    position: relative;
+    top: calc(0px - var(--emoji-size));
+    width: var(--emoji-size);
+  }
+
+  #tooltip {
+    --paper-tooltip-background: var(--cros-tooltip-background-color);
+    --paper-tooltip-delay-in: var(--emoji-tooltip-delay-in);
+    --paper-tooltip-delay-out: var(--emoji-tooltip-delay-out);
+    --paper-tooltip-duration-in: 0;
+    --paper-tooltip-duration-out: 0;
+    --paper-tooltip-opacity: 1;
+    --paper-tooltip-text-color: var(--cros-tooltip-label-color);
+  }
+
+  #tooltip::part(tooltip) {
+    box-shadow: var(--cr-elevation-1);
+    font-family: 'Roboto', sans-serif;
+    font-size: 12px;
+    margin: 4px;
+    padding: 4px 8px 4px 8px;
+    white-space: nowrap;
+  }
+</style>
+
+<button id="emoji-button" class$="[[calculateClassName()]]"
+    on-click="onClick" on-contextmenu="onContextMenu"
+    disabled="[[disabled]]" aria-label="[[getLabel()]]">
+  [[emoji]]
+</button>
+<template is="dom-if" if="[[!variant]]">
+  <paper-tooltip id="tooltip" for="emoji-button" fit-to-visible-bounds
+      part="tooltip" offset="8">
+    [[tooltip]]
+  </paper-tooltip>
+</template>
+<template is="dom-if" if="[[variantsVisible]]">
+  <emoji-variants variants="[[variants]]" tooltip="[[tooltip]]">
+  </emoji-variants>
+</template>
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/emoji_picker/emoji_button.ts b/chrome/browser/resources/chromeos/emoji_picker/emoji_button.ts
new file mode 100644
index 0000000..521fe45
--- /dev/null
+++ b/chrome/browser/resources/chromeos/emoji_picker/emoji_button.ts
@@ -0,0 +1,135 @@
+// 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.
+
+// TODO(b/264211466): This is only used by emoji_variants.html. The only props
+// that are set seem to be emoji, variant, base, all-variants, tooltip  and
+// disabled.  I can delete the others in a follow up, but not changing this file
+// to make the revert simpler to review.
+// https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/resources/chromeos/emoji_picker/emoji_variants.html
+import './emoji_variants.js';
+import 'chrome://resources/polymer/v3_0/paper-tooltip/paper-tooltip.js';
+
+import {beforeNextRender, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {getTemplate} from './emoji_button.html.js';
+import {createCustomEvent, EMOJI_BUTTON_CLICK, EMOJI_VARIANTS_SHOWN, EmojiButtonClickEvent, EmojiVariantsShownEvent} from './events.js';
+import {CategoryEnum, Emoji} from './types.js';
+
+export class EmojiButton extends PolymerElement {
+  static get is() {
+    return 'emoji-button' as const;
+  }
+
+  static get template() {
+    return getTemplate();
+  }
+
+  static get properties() {
+    return {
+      emoji: {type: String, readonly: true},
+      variants: {type: Array, readonly: true},
+      variantsVisible: {type: Boolean, value: false},
+      variant: {type: Boolean, value: false, readonly: true},
+      disabled: {type: Boolean, value: false, readonly: true},
+      base: {type: String},
+      allVariants: {type: Array, readonly: true},
+      tooltip: {type: String, readonly: true},
+      category: {
+        type: String,
+        value: CategoryEnum.EMOJI,
+        readonly: true,
+      },
+    };
+  }
+  emoji: string;
+  variants?: Emoji[];
+  private variantsVisible: boolean;
+  private variant: boolean;
+  private disabled: boolean;
+  private base?: string;
+  private allVariants?: Emoji[];
+  private tooltip?: string;
+  private category: string;
+
+
+  private onClick(): void {
+    if (this.disabled) {
+      return;
+    }
+    this.dispatchEvent(createCustomEvent(EMOJI_BUTTON_CLICK, {
+      text: this.emoji,
+      isVariant: this.variant,
+      baseEmoji: this.base,
+      allVariants: this.allVariants ? this.allVariants : this.variants,
+      name: this.tooltip,
+      category: this.category,
+    }));
+  }
+
+  private onContextMenu(ev: Event): void {
+    ev.preventDefault();
+
+    if (this.disabled) {
+      return;
+    }
+
+    if (this.variants && this.variants.length) {
+      this.variantsVisible = !this.variantsVisible;
+    }
+
+    // send event so emoji-picker knows to close other variants.
+    // need to defer this until <emoji-variants> is created and sized by
+    // Polymer.
+    beforeNextRender(this, () => {
+      const variants = this.variantsVisible ?
+          // ShadowRoot is guaranteed to exist so ! is safe
+          this.shadowRoot!.querySelector('emoji-variants') :
+          null;
+
+      this.dispatchEvent(createCustomEvent(
+          EMOJI_VARIANTS_SHOWN,
+          {owner: this, variants: variants, baseEmoji: this.emoji}));
+    });
+  }
+
+  /**
+   * Hides emoji variants if any is visible.
+   */
+  hideEmojiVariants(): void {
+    /**
+     * TODO(b/233130994): Remove the function as part of the component removal.
+     * The function is only added to help merging emoji-button into
+     * emoji-group to allow removing emoji-button later.
+     */
+    this.variantsVisible = false;
+  }
+
+  private calculateClassName(): string {
+    return (this.variants && this.variants.length > 0) ? 'has-variants' : '';
+  }
+
+  private getLabel(): string {
+    // TODO(crbug/1227852): Just use emoji as the tooltip once ChromeVox can
+    // announce them properly.
+    const emojiLabel =
+        (navigator.languages.some(lang => lang.startsWith('en')) &&
+         this.tooltip) ?
+        this.tooltip :
+        this.emoji;
+    return this.variants?.length ? emojiLabel + ' with variants.' : emojiLabel;
+  }
+}
+
+declare global {
+  interface HTMLElementTagNameMap {
+    [EmojiButton.is]: EmojiButton;
+  }
+  interface HTMLElementEventMap {
+    [EMOJI_VARIANTS_SHOWN]: EmojiVariantsShownEvent;
+    [EMOJI_BUTTON_CLICK]: EmojiButtonClickEvent;
+  }
+}
+
+
+customElements.define(EmojiButton.is, EmojiButton);
diff --git a/chrome/browser/resources/chromeos/emoji_picker/emoji_picker.ts b/chrome/browser/resources/chromeos/emoji_picker/emoji_picker.ts
index 1258006..b0cf82b 100644
--- a/chrome/browser/resources/chromeos/emoji_picker/emoji_picker.ts
+++ b/chrome/browser/resources/chromeos/emoji_picker/emoji_picker.ts
@@ -119,6 +119,9 @@
         events.EMOJI_CLEAR_RECENTS_CLICK,
         (ev: events.EmojiClearRecentClickEvent) => this.clearRecentEmoji(ev));
     // variant popup related handlers
+    this.addEventListener(
+        events.EMOJI_VARIANTS_SHOWN,
+        (ev: events.EmojiVariantsShownEvent) => this.onShowEmojiVariants(ev));
     this.addEventListener('click', () => this.hideDialogs());
     this.addEventListener(
         events.CATEGORY_BUTTON_CLICK,
@@ -854,6 +857,66 @@
                             this.categoriesHistory[category]!.data.preference;
   }
 
+  onShowEmojiVariants(ev: events.EmojiVariantsShownEvent) {
+    // Hide the currently shown emoji variants if the new one belongs
+    // to a different emoji group.
+    if (this.activeVariant && ev.detail.owner !== this.activeVariant) {
+      this.hideEmojiVariants();
+    }
+
+    this.activeVariant = ev.detail.owner as EmojiGroupComponent;
+
+    // Updates the UI if a variant is shown.
+    if (ev.detail.variants) {
+      const message = this.getMessage();
+      if (message) {
+        message.textContent = ev.detail.baseEmoji + ' variants shown.';
+      }
+      this.positionEmojiVariants(ev.detail.variants);
+    }
+  }
+
+  positionEmojiVariants(variants: HTMLElement) {
+    // TODO(crbug.com/1174311): currently positions horizontally within page.
+    // ideal UI would be overflowing the bounds of the page.
+    // also need to account for vertical positioning.
+
+    // compute width required for the variant popup as: SIZE * columns + 10.
+    // SIZE is emoji width in pixels. number of columns is determined by width
+    // of variantRows, then one column each for the base emoji and skin tone
+    // indicators if present. 10 pixels are added for padding and the shadow.
+
+    // Reset any existing left margin before calculating a new position.
+    variants.style.marginLeft = '0';
+
+    // get size of emoji picker
+    const pickerRect = this.getBoundingClientRect();
+
+    // determine how much overflows the right edge of the window.
+    const rect = variants.getBoundingClientRect();
+    const overflowWidth = rect.x + rect.width - pickerRect.width;
+    // shift left by overflowWidth rounded up to next multiple of EMOJI_SIZE.
+    const shift = constants.EMOJI_ICON_SIZE *
+        Math.ceil(overflowWidth / constants.EMOJI_ICON_SIZE);
+    // negative value means we are already within bounds, so no shift needed.
+    variants.style.marginLeft = `-${Math.max(shift, 0)}px`;
+    // Now, examine vertical scrolling and scroll if needed. Not quire sure why
+    // we need listcontainer.offsetTop, but it makes things work.
+    const groups = this.$['groups'] as HTMLElement | null;
+    const scrollTop = groups?.scrollTop ?? 0;
+    const variantTop = variants?.offsetTop ?? 0;
+    const variantBottom = variantTop + variants.offsetHeight;
+    const listTop =
+        (this.$['list-container'] as HTMLElement | null)?.offsetTop ?? 0;
+    if (variantBottom > scrollTop + (groups?.offsetHeight ?? 0) + listTop) {
+      groups?.scrollTo({
+        top: variantBottom - (groups?.offsetHeight ?? 0) - listTop,
+        left: 0,
+        behavior: 'smooth',
+      });
+    }
+  }
+
   /**
    * Triggers when category property changes
    */
diff --git a/chrome/browser/resources/chromeos/emoji_picker/emoji_variants.ts b/chrome/browser/resources/chromeos/emoji_picker/emoji_variants.ts
index a5a55c9..98d5a8ea 100644
--- a/chrome/browser/resources/chromeos/emoji_picker/emoji_variants.ts
+++ b/chrome/browser/resources/chromeos/emoji_picker/emoji_variants.ts
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import './emoji_button.js';
+
 import {beforeNextRender, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {getTemplate} from './emoji_variants.html.js';
diff --git a/chrome/browser/resources/settings/a11y_page/a11y_page.html b/chrome/browser/resources/settings/a11y_page/a11y_page.html
index 7adf9c7f..813efd9e 100644
--- a/chrome/browser/resources/settings/a11y_page/a11y_page.html
+++ b/chrome/browser/resources/settings/a11y_page/a11y_page.html
@@ -53,6 +53,16 @@
             label="$i18n{accessibleImageLabelsTitle}"
             sub-label="$i18n{accessibleImageLabelsSubtitle}">
         </settings-toggle-button>
+<if expr="not is_chromeos">
+        <settings-toggle-button id="pdfOcrToggle"
+            class="hr"
+            hidden$="[[!showPdfOcrToggle_]]"
+            pref="{{prefs.settings.a11y.pdf_ocr_always_active}}"
+            on-change="onPdfOcrChange_"
+            label="$i18n{pdfOcrTitle}"
+            sub-label="$i18n{pdfOcrSubtitle}">
+        </settings-toggle-button>
+</if>
         <cr-link-row class="hr" label="$i18n{moreFeaturesLink}"
             on-click="onMoreFeaturesLinkClick_" sub-label="$i18n{a11yWebStore}"
             external>
diff --git a/chrome/browser/resources/settings/a11y_page/a11y_page.ts b/chrome/browser/resources/settings/a11y_page/a11y_page.ts
index 9d5663a..876523f 100644
--- a/chrome/browser/resources/settings/a11y_page/a11y_page.ts
+++ b/chrome/browser/resources/settings/a11y_page/a11y_page.ts
@@ -95,6 +95,16 @@
         value: false,
       },
 
+      /**
+       * Whether to show pdf ocr settings.
+       */
+      showPdfOcrToggle_: {
+        type: Boolean,
+        value: function() {
+          return loadTimeData.getBoolean('pdfOcrEnabled');
+        },
+      },
+
       focusConfig_: {
         type: Object,
         value() {
@@ -135,6 +145,7 @@
   private showAccessibilityLabelsSetting_: boolean;
   private captionSettingsOpensExternally_: boolean;
 
+
   override ready() {
     super.ready();
 
@@ -172,6 +183,16 @@
     }
   }
 
+  private onPdfOcrChange_(event: Event) {
+    const pdfOcrOn = (event.target as SettingsToggleButtonElement).checked;
+    if (pdfOcrOn) {
+      // TODO(crbug.com/1393069): Downloads a pdf ocr model if not yet
+      // downloaded.
+      console.error(
+          'Need to check a pdf ocr model and download it if necessary');
+    }
+  }
+
   // <if expr="not is_chromeos">
   private onFocusHighlightChange_(event: Event) {
     chrome.metricsPrivate.recordBoolean(
diff --git a/chrome/browser/resources/settings/chromeos/date_time_page/date_time_page.ts b/chrome/browser/resources/settings/chromeos/date_time_page/date_time_page.ts
index dcb971f..3847f940 100644
--- a/chrome/browser/resources/settings/chromeos/date_time_page/date_time_page.ts
+++ b/chrome/browser/resources/settings/chromeos/date_time_page/date_time_page.ts
@@ -20,9 +20,9 @@
 
 import {I18nMixin, I18nMixinInterface} from 'chrome://resources/cr_elements/i18n_mixin.js';
 import {WebUiListenerMixin, WebUiListenerMixinInterface} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {loadTimeData} from '../../i18n_setup.js';
 import {Setting} from '../../mojom-webui/setting.mojom-webui.js';
 import {PrefsMixin, PrefsMixinInterface} from '../../prefs/prefs_mixin.js';
 import {Constructor} from '../common/types.js';
diff --git a/chrome/browser/resources/settings/chromeos/date_time_page/timezone_selector.ts b/chrome/browser/resources/settings/chromeos/date_time_page/timezone_selector.ts
index 32789b53..fea84a0 100644
--- a/chrome/browser/resources/settings/chromeos/date_time_page/timezone_selector.ts
+++ b/chrome/browser/resources/settings/chromeos/date_time_page/timezone_selector.ts
@@ -9,10 +9,10 @@
 import '../../settings_shared.css.js';
 import '../../controls/settings_dropdown_menu.js';
 
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {DropdownMenuOptionList} from '../../controls/settings_dropdown_menu.js';
+import {loadTimeData} from '../../i18n_setup.js';
 import {PrefsMixin} from '../../prefs/prefs_mixin.js';
 import {CrSettingsPrefs} from '../../prefs/prefs_types.js';
 
diff --git a/chrome/browser/resources/settings/chromeos/device_page/keyboard.ts b/chrome/browser/resources/settings/chromeos/device_page/keyboard.ts
index f8301de..2f4f9d47 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/keyboard.ts
+++ b/chrome/browser/resources/settings/chromeos/device_page/keyboard.ts
@@ -16,11 +16,11 @@
 
 import {focusWithoutInk} from 'chrome://resources/ash/common/focus_without_ink_js.js';
 import {WebUiListenerMixin, WebUiListenerMixinInterface} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {afterNextRender, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {DropdownMenuOptionList} from '../../controls/settings_dropdown_menu.js';
 import {FocusConfig} from '../../focus_config.js';
+import {loadTimeData} from '../../i18n_setup.js';
 import {Setting} from '../../mojom-webui/setting.mojom-webui.js';
 import {castExists} from '../assert_extras.js';
 import {Constructor} from '../common/types.js';
diff --git a/chrome/browser/resources/settings/chromeos/kerberos_page/kerberos_accounts.ts b/chrome/browser/resources/settings/chromeos/kerberos_page/kerberos_accounts.ts
index a935566..89f12d8ac 100644
--- a/chrome/browser/resources/settings/chromeos/kerberos_page/kerberos_accounts.ts
+++ b/chrome/browser/resources/settings/chromeos/kerberos_page/kerberos_accounts.ts
@@ -21,9 +21,9 @@
 import {CrToastElement} from 'chrome://resources/cr_elements/cr_toast/cr_toast.js';
 import {I18nMixin, I18nMixinInterface} from 'chrome://resources/cr_elements/i18n_mixin.js';
 import {WebUiListenerMixin, WebUiListenerMixinInterface} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {DomRepeatEvent, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {loadTimeData} from '../../i18n_setup.js';
 import {Setting} from '../../mojom-webui/setting.mojom-webui.js';
 import {cast, castExists} from '../assert_extras.js';
 import {Constructor} from '../common/types.js';
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.js
index 5768f68..cf36cfe3 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.js
@@ -17,20 +17,20 @@
 import './multidevice_permissions_setup_dialog.js';
 import './multidevice_subpage.js';
 
-import {assert, assertNotReached} from 'chrome://resources/ash/common/assert.js';
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js';
 import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/ash/common/web_ui_listener_behavior.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
+import {assert, assertNotReached} from 'chrome://resources/ash/common/assert.js';
 import {beforeNextRender, html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {loadTimeData} from '../../i18n_setup.js';
 import {Setting} from '../../mojom-webui/setting.mojom-webui.js';
+import {Route, Router} from '../router.js';
 import {NearbyShareSettingsBehavior, NearbyShareSettingsBehaviorInterface} from '../../shared/nearby_share_settings_behavior.js';
 import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.js';
 import {recordSettingChange} from '../metrics_recorder.js';
 import {routes} from '../os_route.js';
 import {PrefsBehavior, PrefsBehaviorInterface} from '../prefs_behavior.js';
 import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js';
-import {Route, Router} from '../router.js';
 
 import {MultiDeviceBrowserProxy, MultiDeviceBrowserProxyImpl} from './multidevice_browser_proxy.js';
 import {MultiDeviceFeature, MultiDeviceFeatureState, MultiDevicePageContentData, MultiDeviceSettingsMode, PhoneHubFeatureAccessStatus, PhoneHubPermissionsSetupAction, PhoneHubPermissionsSetupFlowScreens} from './multidevice_constants.js';
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_smartlock_item.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_smartlock_item.js
index 4733eaff..2e99bc3 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_smartlock_item.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_smartlock_item.js
@@ -15,6 +15,7 @@
 import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/ash/common/web_ui_listener_behavior.js';
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {loadTimeData} from '../../i18n_setup.js';
 import {recordSettingChange} from '../metrics_recorder.js';
 import {routes} from '../os_route.js';
 import {OsSettingsRoutes} from '../os_settings_routes.js';
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_subpage.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_subpage.js
index f0d8caf8..d129afe 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_subpage.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_subpage.js
@@ -23,6 +23,7 @@
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js';
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {loadTimeData} from '../../i18n_setup.js';
 import {Setting} from '../../mojom-webui/setting.mojom-webui.js';
 import {Route} from '../router.js';
 import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.js';
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_tether_item.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_tether_item.js
index 164d614..04c9a71 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_tether_item.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_tether_item.js
@@ -19,11 +19,11 @@
 import {MojoInterfaceProviderImpl} from 'chrome://resources/ash/common/network/mojo_interface_provider.js';
 import {NetworkListenerBehavior, NetworkListenerBehaviorInterface} from 'chrome://resources/ash/common/network/network_listener_behavior.js';
 import {OncMojo} from 'chrome://resources/ash/common/network/onc_mojo.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {CrosNetworkConfigRemote, FilterType, InhibitReason, NetworkStateProperties} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom-webui.js';
 import {DeviceStateType, NetworkType} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/network_types.mojom-webui.js';
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {loadTimeData} from '../../i18n_setup.js';
 import {routes} from '../os_route.js';
 import {OsSettingsRoutes} from '../os_settings_routes.js';
 
diff --git a/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_receive_dialog.js b/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_receive_dialog.js
index 717f302..65f3e8a 100644
--- a/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_receive_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_receive_dialog.js
@@ -30,9 +30,9 @@
 import 'chrome://resources/cr_elements/cr_view_manager/cr_view_manager.js';
 
 import {assert} from 'chrome://resources/ash/common/assert.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {loadTimeData} from '../../i18n_setup.js';
 import {NearbySettings} from '../../shared/nearby_share_settings_behavior.js';
 
 import {getReceiveManager, observeReceiveManager} from './nearby_share_receive_manager.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.html b/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.html
index 949f5e0..98f6663 100644
--- a/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.html
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.html
@@ -66,6 +66,14 @@
     </template>
   </div>
 </iron-collapse>
+<template is="dom-if" if="[[showPdfOcrSetting_]]">
+  <settings-toggle-button id="crosPdfOcrToggle"
+      class="hr"
+      pref="{{prefs.settings.a11y.pdf_ocr_always_active}}"
+      label="$i18n{pdfOcrTitle}"
+      sub-label="$i18n{pdfOcrSubtitle}">
+  </settings-toggle-button>
+</template>
 
 <cr-link-row id="ttsSubpageButton" class="hr"
     label="$i18n{manageTtsSettings}" on-click="onManageTtsSettingsTap_"
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.ts b/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.ts
index 670c6bd3..4d4c739 100644
--- a/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.ts
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/text_to_speech_page.ts
@@ -53,6 +53,16 @@
   static get properties() {
     return {
       /**
+       * Whether to show the toggle button for PDF OCR.
+       */
+      showPdfOcrSetting_: {
+        type: Boolean,
+        value: function() {
+          return loadTimeData.getBoolean('pdfOcrEnabled');
+        },
+      },
+
+      /**
        * |hasKeyboard_| starts undefined so observer doesn't trigger until it
        * has been populated.
        */
@@ -83,6 +93,7 @@
   private hasKeyboard_: boolean;
   private route_: Route;
   private textToSpeechBrowserProxy_: TextToSpeechPageBrowserProxy;
+  private showPdfOcrSetting_: boolean;
 
   constructor() {
     super();
diff --git a/chrome/browser/resources/settings/chromeos/os_about_page/detailed_build_info.ts b/chrome/browser/resources/settings/chromeos/os_about_page/detailed_build_info.ts
index fc47007..c46ea7fc 100644
--- a/chrome/browser/resources/settings/chromeos/os_about_page/detailed_build_info.ts
+++ b/chrome/browser/resources/settings/chromeos/os_about_page/detailed_build_info.ts
@@ -21,9 +21,9 @@
 import {CrPolicyIndicatorType} from 'chrome://resources/cr_elements/policy/cr_policy_indicator_mixin.js';
 import {WebUiListenerMixin, WebUiListenerMixinInterface} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js';
 import {focusWithoutInk} from 'chrome://resources/js/focus_without_ink.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {loadTimeData} from '../../i18n_setup.js';
 import {Setting} from '../../mojom-webui/setting.mojom-webui.js';
 import {PrefsMixin, PrefsMixinInterface} from '../../prefs/prefs_mixin.js';
 import {castExists} from '../assert_extras.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.ts b/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.ts
index 344040ce..f320a18e 100644
--- a/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.ts
+++ b/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.ts
@@ -29,10 +29,10 @@
 import {I18nMixin, I18nMixinInterface} from 'chrome://resources/cr_elements/i18n_mixin.js';
 import {WebUiListenerMixin, WebUiListenerMixinInterface} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js';
 import {assert} from 'chrome://resources/js/assert_ts.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {sanitizeInnerHtml} from 'chrome://resources/js/parse_html_subset.js';
 import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {loadTimeData} from '../../i18n_setup.js';
 import {LifetimeBrowserProxyImpl} from '../../lifetime_browser_proxy.js';
 import {Setting} from '../../mojom-webui/setting.mojom-webui.js';
 import {Constructor} from '../common/types.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_forget_device_dialog.ts b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_forget_device_dialog.ts
index 796f4834..55573fe7 100644
--- a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_forget_device_dialog.ts
+++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_forget_device_dialog.ts
@@ -13,10 +13,11 @@
 import {getDeviceName} from 'chrome://resources/ash/common/bluetooth/bluetooth_utils.js';
 import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js';
 import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {PairedBluetoothDeviceProperties} from 'chrome://resources/mojo/chromeos/ash/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom-webui.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {loadTimeData} from '../../i18n_setup.js';
+
 import {getTemplate} from './os_bluetooth_forget_device_dialog.html.js';
 
 interface SettingsBluetoothForgetDeviceDialogElement {
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_summary.ts b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_summary.ts
index 410a4683..988838d 100644
--- a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_summary.ts
+++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_summary.ts
@@ -16,10 +16,10 @@
 import {getBluetoothConfig} from 'chrome://resources/ash/common/bluetooth/cros_bluetooth_config.js';
 import {getInstance as getAnnouncerInstance} from 'chrome://resources/cr_elements/cr_a11y_announcer/cr_a11y_announcer.js';
 import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {BluetoothSystemProperties, BluetoothSystemState, DeviceConnectionState, PairedBluetoothDeviceProperties} from 'chrome://resources/mojo/chromeos/ash/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom-webui.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {loadTimeData} from '../../i18n_setup.js';
 import {routes} from '../os_route.js';
 import {RouteOriginMixin} from '../route_origin_mixin.js';
 import {Route, Router} from '../router.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_remove_saved_device_dialog.ts b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_remove_saved_device_dialog.ts
index e4dd2bd..40991e89 100644
--- a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_remove_saved_device_dialog.ts
+++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_remove_saved_device_dialog.ts
@@ -14,9 +14,10 @@
 import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js';
 import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js';
 import {WebUiListenerMixin} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {loadTimeData} from '../../i18n_setup.js';
+
 import {getTemplate} from './os_remove_saved_device_dialog.html.js';
 import {FastPairSavedDevice} from './settings_fast_pair_constants.js';
 
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_options_page.js b/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_options_page.js
index 096bf09a..741cfd11 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_options_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_options_page.js
@@ -13,11 +13,11 @@
 import './os_japanese_clear_ime_data_dialog.js';
 import './os_japanese_manage_user_dictionary_page.js';
 
-import {assert, assertNotReached} from 'chrome://resources/ash/common/assert.js';
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
+import {assert, assertNotReached} from 'chrome://resources/ash/common/assert.js';
 import {afterNextRender, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {loadTimeData} from '../../i18n_setup.js';
 import {routes} from '../os_route.js';
 import {PrefsBehavior, PrefsBehaviorInterface} from '../prefs_behavior.js';
 import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_util.js b/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_util.js
index a63a552..176d2770 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_util.js
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_util.js
@@ -2,19 +2,19 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-/**
- * @fileoverview constants related to input method options.
- */
-
 import {assert, assertNotReached} from 'chrome://resources/ash/common/assert.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 
-import {routes} from '../os_route.js';
+import {loadTimeData} from '../../i18n_setup.js';
 import {Route} from '../router.js';
+import {routes} from '../os_route.js';
 
 import {getInputMethodSettings, SettingsType} from './input_method_settings.js';
 import {JAPANESE_INPUT_MODE, JAPANESE_KEYMAP_STYLE, JAPANESE_PUNCTUATION_STYLE, JAPANESE_SECTION_SHORTCUT, JAPANESE_SHIFT_KEY_MODE_STYLE, JAPANESE_SPACE_INPUT_STYLE, JAPANESE_SYMBOL_STYLE} from './input_method_types.js';
 
+
+/**
+ * @fileoverview constants related to input method options.
+ */
 /**
  * The prefix string shared by all first party input method ID.
  * @private @const
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.js b/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.js
index df769ae..95ac4b07 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.js
@@ -20,19 +20,19 @@
 import '../../settings_shared.css.js';
 import '../os_settings_page/os_settings_animated_pages.js';
 
-import {assert} from 'chrome://resources/ash/common/assert.js';
 import {focusWithoutInk} from 'chrome://resources/ash/common/focus_without_ink_js.js';
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
+import {assert} from 'chrome://resources/ash/common/assert.js';
 import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {loadTimeData} from '../../i18n_setup.js';
 import {Setting} from '../../mojom-webui/setting.mojom-webui.js';
+import {Route, Router} from '../router.js';
 import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.js';
 import {recordSettingChange} from '../metrics_recorder.js';
 import {routes} from '../os_route.js';
 import {PrefsBehavior, PrefsBehaviorInterface} from '../prefs_behavior.js';
 import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js';
-import {Route, Router} from '../router.js';
 
 import {hasOptionsPageInSettings} from './input_method_util.js';
 import {getTemplate} from './input_page.html.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_page_v2.js b/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_page_v2.js
index 6ca1d00..3a3092c 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_page_v2.js
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_page_v2.js
@@ -22,19 +22,19 @@
 import '../../controls/settings_toggle_button.js';
 import '../../settings_shared.css.js';
 
-import {assert} from 'chrome://resources/ash/common/assert.js';
 import {focusWithoutInk} from 'chrome://resources/ash/common/focus_without_ink_js.js';
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
+import {assert} from 'chrome://resources/ash/common/assert.js';
 import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {loadTimeData} from '../../i18n_setup.js';
 import {Setting} from '../../mojom-webui/setting.mojom-webui.js';
+import {Route, Router} from '../router.js';
 import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.js';
 import {recordSettingChange} from '../metrics_recorder.js';
 import {routes} from '../os_route.js';
 import {PrefsBehavior, PrefsBehaviorInterface} from '../prefs_behavior.js';
 import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js';
-import {Route, Router} from '../router.js';
 
 import {LanguagesMetricsProxy, LanguagesMetricsProxyImpl, LanguagesPageInteraction} from './languages_metrics_proxy.js';
 import {LanguageHelper, LanguagesModel, LanguageState} from './languages_types.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_section.js b/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_section.js
index cea7449..7466e98 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_section.js
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/os_languages_section.js
@@ -22,15 +22,16 @@
 import '../../settings_vars.css.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
-import {routes} from '../os_route.js';
+import {loadTimeData} from '../../i18n_setup.js';
 import {Router} from '../router.js';
+import {routes} from '../os_route.js';
 
 import {LanguageHelper, LanguagesModel} from './languages_types.js';
 import {getTemplate} from './os_languages_section.html.js';
 
+
 // The IME ID for the Accessibility Common extension used by Dictation.
 /** @type {string} */
 const ACCESSIBILITY_COMMON_IME_ID =
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/smart_inputs_page.js b/chrome/browser/resources/settings/chromeos/os_languages_page/smart_inputs_page.js
index 3934e5e..7628a042 100644
--- a/chrome/browser/resources/settings/chromeos/os_languages_page/smart_inputs_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_languages_page/smart_inputs_page.js
@@ -12,15 +12,15 @@
 import '../../settings_shared.css.js';
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {loadTimeData} from '../../i18n_setup.js';
 import {Setting} from '../../mojom-webui/setting.mojom-webui.js';
+import {Route} from '../router.js';
 import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.js';
 import {routes} from '../os_route.js';
 import {PrefsBehavior, PrefsBehaviorInterface} from '../prefs_behavior.js';
 import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js';
-import {Route} from '../router.js';
 
 import {getTemplate} from './smart_inputs_page.html.js';
 
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/account_manager.js b/chrome/browser/resources/settings/chromeos/os_people_page/account_manager.js
index 4457440e..8f9ec9f 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/account_manager.js
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/account_manager.js
@@ -19,9 +19,9 @@
 
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js';
 import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/ash/common/web_ui_listener_behavior.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {loadTimeData} from '../../i18n_setup.js';
 import {Setting} from '../../mojom-webui/setting.mojom-webui.js';
 import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.js';
 import {getImage} from '../icon.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/lock_screen.js b/chrome/browser/resources/settings/chromeos/os_people_page/lock_screen.js
index bc5f8254..5b3741a1 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/lock_screen.js
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/lock_screen.js
@@ -33,10 +33,10 @@
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js';
 import {LockScreenProgress, recordLockScreenProgress} from 'chrome://resources/ash/common/quick_unlock/lock_screen_constants.js';
 import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/ash/common/web_ui_listener_behavior.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {AuthFactor, FactorObserverInterface, FactorObserverReceiver, ManagementType, RecoveryFactorEditor_ConfigureResult} from 'chrome://resources/mojo/chromeos/ash/services/auth_factor_config/public/mojom/auth_factor_config.mojom-webui.js';
 import {afterNextRender, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {loadTimeData} from '../../i18n_setup.js';
 import {Setting} from '../../mojom-webui/setting.mojom-webui.js';
 import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.js';
 import {routes} from '../os_route.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.js b/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.js
index 6049036c..7a49fa4 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.js
@@ -32,9 +32,9 @@
 import {focusWithoutInk} from 'chrome://resources/ash/common/focus_without_ink_js.js';
 import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js';
 import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/ash/common/web_ui_listener_behavior.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {afterNextRender, flush, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {loadTimeData} from '../../i18n_setup.js';
 import {Setting} from '../../mojom-webui/setting.mojom-webui.js';
 import {ProfileInfoBrowserProxyImpl} from '../../people_page/profile_info_browser_proxy.js';
 import {SyncBrowserProxyImpl} from '../../people_page/sync_browser_proxy.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/os_signout_dialog.ts b/chrome/browser/resources/settings/chromeos/os_people_page/os_signout_dialog.ts
index de454d85..7abd79c 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/os_signout_dialog.ts
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/os_signout_dialog.ts
@@ -17,11 +17,11 @@
 import {WebUiListenerMixin} from '//resources/cr_elements/web_ui_listener_mixin.js';
 import {sanitizeInnerHtml} from '//resources/js/parse_html_subset.js';
 import {microTask, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 
-import {SyncBrowserProxyImpl, SyncStatus} from '../../people_page/sync_browser_proxy.js';
+import {loadTimeData} from '../../i18n_setup.js';
 
 import {getTemplate} from './os_signout_dialog.html.js';
+import {SyncBrowserProxyImpl, SyncStatus} from '../../people_page/sync_browser_proxy.js';
 
 export interface OsSettingsSignoutDialogElement {
   $: {
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_page.ts b/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_page.ts
index 9411851..bbc5df68 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_page.ts
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_page.ts
@@ -33,9 +33,9 @@
 import {IronCollapseElement} from '//resources/polymer/v3_0/iron-collapse/iron-collapse.js';
 import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 
 import {FocusConfig} from '../../focus_config.js';
+import {loadTimeData} from '../../i18n_setup.js';
 import {PageStatus, StatusAction, SyncBrowserProxy, SyncBrowserProxyImpl, SyncPrefs, SyncStatus} from '../../people_page/sync_browser_proxy.js';
 import {RouteObserverMixin} from '../route_observer_mixin.js';
 import {Route, Router} from '../router.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/users_page.js b/chrome/browser/resources/settings/chromeos/os_people_page/users_page.js
index bbe853ab..e2099c3 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/users_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/users_page.js
@@ -18,9 +18,9 @@
 
 import {assert} from 'chrome://resources/ash/common/assert.js';
 import {focusWithoutInk} from 'chrome://resources/ash/common/focus_without_ink_js.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {afterNextRender, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {loadTimeData} from '../../i18n_setup.js';
 import {Setting} from '../../mojom-webui/setting.mojom-webui.js';
 import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.js';
 import {routes} from '../os_route.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_add_printer_manufacturer_model_dialog.ts b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_add_printer_manufacturer_model_dialog.ts
index f909833..6f5153f 100644
--- a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_add_printer_manufacturer_model_dialog.ts
+++ b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_add_printer_manufacturer_model_dialog.ts
@@ -15,9 +15,10 @@
 import './cups_printer_shared.css.js';
 import './cups_printers_browser_proxy.js';
 
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {loadTimeData} from '../../i18n_setup.js';
+
 import {getTemplate} from './cups_add_printer_manufacturer_model_dialog.html.js';
 import {getBaseName, getErrorText, isPPDInfoValid} from './cups_printer_dialog_util.js';
 import {CupsPrinterInfo, CupsPrintersBrowserProxy, CupsPrintersBrowserProxyImpl, ManufacturersInfo, ModelsInfo, PrinterSetupResult} from './cups_printers_browser_proxy.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_entry.ts b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_entry.ts
index 0401d3a1..823504f4 100644
--- a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_entry.ts
+++ b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_entry.ts
@@ -12,9 +12,10 @@
 import './cups_printer_types.js';
 
 import {FocusRowMixin} from 'chrome://resources/js/focus_row_mixin.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {loadTimeData} from '../../i18n_setup.js';
+
 import {PrinterListEntry, PrinterType} from './cups_printer_types.js';
 import {getTemplate} from './cups_printers_entry.html.js';
 
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.js b/chrome/browser/resources/settings/chromeos/os_settings.js
index 0a0c4f9d..6744722 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings.js
+++ b/chrome/browser/resources/settings/chromeos/os_settings.js
@@ -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 '../strings.m.js';
 import '../prefs/prefs.js';
 import './device_page/audio.js';
 import './device_page/cros_audio_config.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_main/os_settings_main.ts b/chrome/browser/resources/settings/chromeos/os_settings_main/os_settings_main.ts
index 58c892d0..742aec5 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_main/os_settings_main.ts
+++ b/chrome/browser/resources/settings/chromeos/os_settings_main/os_settings_main.ts
@@ -17,9 +17,9 @@
 import '../../settings_shared.css.js';
 import '../../settings_vars.css.js';
 
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {loadTimeData} from '../../i18n_setup.js';
 import {assertExists} from '../assert_extras.js';
 import {OSPageVisibility} from '../os_page_visibility.js';
 import {routes} from '../os_route.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_subpage.ts b/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_subpage.ts
index 079ef11..d24a826 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_subpage.ts
+++ b/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_subpage.ts
@@ -25,8 +25,8 @@
 import {IronResizableBehavior} from '//resources/polymer/v3_0/iron-resizable-behavior/iron-resizable-behavior.js';
 import {afterNextRender, mixinBehaviors, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {EventTracker} from 'chrome://resources/js/event_tracker.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 
+import {loadTimeData} from '../../i18n_setup.js';
 import {Constructor} from '../common/types.js';
 import {RouteObserverMixin, RouteObserverMixinInterface} from '../route_observer_mixin.js';
 import {Route, Router} from '../router.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.ts b/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.ts
index 4b6e234..8414780 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.ts
+++ b/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.ts
@@ -26,10 +26,10 @@
 import {CrDrawerElement} from 'chrome://resources/cr_elements/cr_drawer/cr_drawer.js';
 import {FindShortcutMixin} from 'chrome://resources/cr_elements/find_shortcut_mixin.js';
 import {assert} from 'chrome://resources/js/assert_ts.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {listenOnce} from 'chrome://resources/js/util_ts.js';
 import {Debouncer, DomIf, microTask, PolymerElement, timeOut} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {loadTimeData} from '../../i18n_setup.js';
 import {SettingsPrefsElement} from '../../prefs/prefs.js';
 import {castExists} from '../assert_extras.js';
 import {setGlobalScrollTarget} from '../global_scroll_target_behavior.js';
diff --git a/chrome/browser/resources/settings/chromeos/parental_controls_page/parental_controls_page.ts b/chrome/browser/resources/settings/chromeos/parental_controls_page/parental_controls_page.ts
index 641daaa8..bfeba0c 100644
--- a/chrome/browser/resources/settings/chromeos/parental_controls_page/parental_controls_page.ts
+++ b/chrome/browser/resources/settings/chromeos/parental_controls_page/parental_controls_page.ts
@@ -15,9 +15,9 @@
 
 import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.js';
 import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {loadTimeData} from '../../i18n_setup.js';
 import {castExists} from '../assert_extras.js';
 
 import {ParentalControlsBrowserProxy, ParentalControlsBrowserProxyImpl} from './parental_controls_browser_proxy.js';
diff --git a/chrome/browser/resources/settings/chromeos/router.js b/chrome/browser/resources/settings/chromeos/router.js
index 89de8a777..333f476 100644
--- a/chrome/browser/resources/settings/chromeos/router.js
+++ b/chrome/browser/resources/settings/chromeos/router.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 '../i18n_setup.js';
+
 import {assert} from 'chrome://resources/ash/common/assert.js';
 import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js';
 
diff --git a/chrome/browser/resources/side_panel/BUILD.gn b/chrome/browser/resources/side_panel/BUILD.gn
index 6072201..b143bce 100644
--- a/chrome/browser/resources/side_panel/BUILD.gn
+++ b/chrome/browser/resources/side_panel/BUILD.gn
@@ -48,13 +48,6 @@
 mojo_root_folder =
     "$root_gen_dir/mojom-webui/chrome/browser/ui/webui/side_panel"
 
-copy("copy_mojo_bookmarks") {
-  deps = [ "//chrome/browser/ui/webui/side_panel/bookmarks:mojo_bindings_js__generator" ]
-  sources = [ "$mojo_root_folder/bookmarks/bookmarks.mojom-webui.js" ]
-  outputs =
-      [ "$target_gen_dir/$preprocess_folder/bookmarks/{{source_file_part}}" ]
-}
-
 copy("copy_mojo_reading_list") {
   deps = [ "//chrome/browser/ui/webui/side_panel/reading_list:mojo_bindings_js__generator" ]
   sources = [ "$mojo_root_folder/reading_list/reading_list.mojom-webui.js" ]
@@ -62,12 +55,6 @@
       [ "$target_gen_dir/$preprocess_folder/reading_list/{{source_file_part}}" ]
 }
 
-copy("copy_mojo_shopping_list") {
-  deps = [ "//components/commerce/core/mojom:mojo_bindings_js__generator" ]
-  sources = [ "$root_gen_dir/mojom-webui/components/commerce/core/mojom/shopping_list.mojom-webui.js" ]
-  outputs = [ "$target_gen_dir/$preprocess_folder/bookmarks/commerce/{{source_file_part}}" ]
-}
-
 copy("copy_mojo_user_notes") {
   deps = [ "//chrome/browser/ui/webui/side_panel/user_notes:mojo_bindings_js__generator" ]
   sources = [ "$mojo_root_folder/user_notes/user_notes.mojom-webui.js" ]
@@ -83,11 +70,8 @@
   in_files = ts_files + html_wrapper_files + mojo_files
   definitions = [
     "read_anything/read_anything.d.ts",
-    "//tools/typescript/definitions/bookmark_manager_private.d.ts",
-    "//tools/typescript/definitions/bookmarks.d.ts",
     "//tools/typescript/definitions/chrome_event.d.ts",
     "//tools/typescript/definitions/metrics_private.d.ts",
-    "//tools/typescript/definitions/tabs.d.ts",
   ]
   deps = [
     "//third_party/polymer/v3_0:library",
@@ -97,9 +81,7 @@
     "//ui/webui/resources/mojo:library",
   ]
   extra_deps = [
-    ":copy_mojo_bookmarks",
     ":copy_mojo_reading_list",
-    ":copy_mojo_shopping_list",
     ":copy_mojo_user_notes",
     ":preprocess_gen",
     ":preprocess_src",
@@ -109,15 +91,10 @@
 generate_grd("build_grd") {
   input_files = [
     "history_clusters/history_clusters.html",
-    "images/bookmarks_empty_dark.svg",
-    "images/bookmarks_empty.svg",
     "images/read_later_empty_dark.svg",
     "images/read_later_empty.svg",
     "reading_list/reading_list.html",
-    "bookmarks/bookmarks.html",
-    "bookmarks/power_bookmarks.html",
     "read_anything/read_anything.html",
-    "side_panel.html",
     "user_notes/user_notes.html",
   ]
   input_files_base_dir = rebase_path(".", "//")
diff --git a/chrome/browser/resources/side_panel/app.html b/chrome/browser/resources/side_panel/app.html
deleted file mode 100644
index 5ce29e92..0000000
--- a/chrome/browser/resources/side_panel/app.html
+++ /dev/null
@@ -1,86 +0,0 @@
-<style include="mwb-element-shared-style">
-  :host {
-    color: var(--cr-primary-text-color);
-    display: flex;
-    flex-direction: column;
-    height: 100%;
-    overflow: hidden;
-    width: 100%;
-  }
-
-  header {
-    border-bottom: solid 1px var(--google-grey-300);
-    display: flex;
-    padding-block-start: 4px;
-  }
-
-  @media (prefers-color-scheme: dark) {
-    header {
-      border-bottom: solid 1px var(--google-grey-700);
-    }
-  }
-
-  cr-tabs {
-    --cr-tabs-height: 40px;
-    --cr-tabs-font-size: 13px;
-    --cr-tabs-selected-tab-focused-font-weight: auto;
-    --cr-tabs-focus-outline: solid 2px var(--mwb-icon-button-focus-ring-color);
-    cursor: default;
-    flex: 1;
-  }
-
-  #closeButtonContainer {
-    align-items: center;
-    display: flex;
-    height: 40px;
-    justify-content: center;
-    width: 48px;
-  }
-
-  #closeButton {
-    --cr-icon-button-size: 28px;
-    --cr-icon-button-icon-size: 18px;
-    margin: 0;
-  }
-
-  #content {
-    flex: 1;
-    overflow-x: hidden;
-    overflow-y: auto;
-    padding: 8px 0;
-  }
-</style>
-
-<header>
-  <cr-tabs
-      tab-names="[[getTabNames_(tabs_)]]"
-      selected="{{selectedTab_}}"
-      on-selected-changed="onSelectedTabChanged_">
-  </cr-tabs>
-  <div id="closeButtonContainer">
-    <cr-icon-button
-        id="closeButton" iron-icon="cr:close" on-click="onCloseClick_"
-        title="$i18n{tooltipClose}" aria-label="$i18n{tooltipClose}">
-    </cr-icon-button>
-  </div>
-</header>
-
-<div id="content">
-  <iron-pages selected="[[selectedTab_]]">
-    <div>
-      <template is="dom-if" if="[[isSelectedTab_(selectedTab_, 0)]]">
-        <reading-list-app side-panel></reading-list-app>
-      </template>
-    </div>
-    <div>
-      <template is="dom-if" if="[[isSelectedTab_(selectedTab_, 1)]]">
-        <bookmarks-list></bookmarks-list>
-      </template>
-    </div>
-    <div>
-      <template is="dom-if" if="[[isSelectedTab_(selectedTab_, 2)]]">
-        <read-anything-app></read-anything-app>
-      </template>
-    </div>
-  </iron-pages>
-</div>
diff --git a/chrome/browser/resources/side_panel/app.ts b/chrome/browser/resources/side_panel/app.ts
deleted file mode 100644
index 7f450017..0000000
--- a/chrome/browser/resources/side_panel/app.ts
+++ /dev/null
@@ -1,103 +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.
-
-import 'chrome://resources/cr_elements/cr_tabs/cr_tabs.js';
-import 'chrome://resources/cr_elements/cr_shared_vars.css.js';
-import 'chrome://resources/polymer/v3_0/iron-pages/iron-pages.js';
-import './reading_list/app.js'; /* <reading-list-app> */
-import '../strings.m.js';
-import './bookmarks/bookmarks_list.js';
-import './bookmarks/power_bookmarks_list.js';
-import './read_anything/app.js'; /* <read-anything-app> */
-
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
-import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-
-import {getTemplate} from './app.html.js';
-import {ReadingListApiProxy, ReadingListApiProxyImpl} from './reading_list/reading_list_api_proxy.js';
-
-// Key for localStorage object that refers to the last active tab's ID.
-export const LOCAL_STORAGE_TAB_ID_KEY = 'lastActiveTab';
-
-export class SidePanelAppElement extends PolymerElement {
-  static get is() {
-    return 'side-panel-app';
-  }
-
-  static get template() {
-    return getTemplate();
-  }
-
-  static get properties() {
-    return {
-      tabs_: {
-        type: Object,
-        value: () => ({
-          'readingList': loadTimeData.getString('title'),
-          'bookmarks': loadTimeData.getString('bookmarksTabTitle'),
-        }),
-      },
-
-      selectedTab_: {
-        type: Number,
-        value: 0,
-      },
-    };
-  }
-
-  private apiProxy_: ReadingListApiProxy =
-      ReadingListApiProxyImpl.getInstance();
-  private selectedTab_: number;
-  private tabs_: {[key: string]: string};
-
-  override ready() {
-    if (loadTimeData.getBoolean('readAnythingEnabled')) {
-      this.tabs_['readAnything'] =
-          loadTimeData.getString('readAnythingTabTitle');
-    }
-    super.ready();
-  }
-
-  override connectedCallback() {
-    super.connectedCallback();
-    const lastActiveTab = window.localStorage[LOCAL_STORAGE_TAB_ID_KEY];
-    if (loadTimeData.getBoolean('shouldShowBookmark')) {
-      window.localStorage[LOCAL_STORAGE_TAB_ID_KEY] = 'bookmarks';
-      this.selectedTab_ = Object.keys(this.tabs_).indexOf('bookmarks');
-    } else if (loadTimeData.getBoolean('hasUnseenReadingListEntries')) {
-      window.localStorage[LOCAL_STORAGE_TAB_ID_KEY] = 'readingList';
-    } else if (lastActiveTab) {
-      this.selectedTab_ = Object.keys(this.tabs_).indexOf(lastActiveTab) || 0;
-    }
-
-    // Show the UI as soon as the app is connected.
-    this.apiProxy_.showUi();
-  }
-
-  private getTabNames_(): string[] {
-    return Object.values(this.tabs_);
-  }
-
-  private isSelectedTab_(selectedTab: number, index: number): boolean {
-    return selectedTab === index;
-  }
-
-  private onCloseClick_() {
-    this.apiProxy_.closeUi();
-  }
-
-  private onSelectedTabChanged_(event: CustomEvent<{value: number}>) {
-    const tabIndex = event.detail.value;
-    window.localStorage[LOCAL_STORAGE_TAB_ID_KEY] =
-        Object.keys(this.tabs_)[tabIndex];
-  }
-}
-
-declare global {
-  interface HTMLElementTagNameMap {
-    'side-panel-app': SidePanelAppElement;
-  }
-}
-
-customElements.define(SidePanelAppElement.is, SidePanelAppElement);
diff --git a/chrome/browser/resources/side_panel/bookmarks/BUILD.gn b/chrome/browser/resources/side_panel/bookmarks/BUILD.gn
new file mode 100644
index 0000000..293c70bc
--- /dev/null
+++ b/chrome/browser/resources/side_panel/bookmarks/BUILD.gn
@@ -0,0 +1,62 @@
+# Copyright 2022 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//chrome/browser/resources/tools/build_webui.gni")
+
+assert(!is_android)
+
+build_webui("build") {
+  grd_prefix = "side_panel_bookmarks"
+
+  static_files = [
+    "bookmarks.html",
+    "images/bookmarks_empty_dark.svg",
+    "images/bookmarks_empty.svg",
+    "power_bookmarks.html",
+  ]
+
+  # Files holding a Polymer element definition and have an equivalent .html file.
+  web_component_files = [
+    "bookmark_folder.ts",
+    "bookmarks_list.ts",
+    "commerce/shopping_list.ts",
+    "power_bookmark_chip.ts",
+    "power_bookmark_row.ts",
+    "power_bookmarks_context_menu.ts",
+    "power_bookmarks_list.ts",
+  ]
+
+  non_web_component_files = [
+    "bookmarks_api_proxy.ts",
+    "bookmarks_drag_manager.ts",
+    "commerce/shopping_list_api_proxy.ts",
+  ]
+
+  icons_html_files = [
+    "commerce/icons.html",
+    "icons.html",
+  ]
+
+  mojo_files_deps = [
+    "//chrome/browser/ui/webui/side_panel/bookmarks:mojo_bindings_js__generator",
+    "//components/commerce/core/mojom:mojo_bindings_js__generator",
+  ]
+  mojo_files = [
+    "$root_gen_dir/mojom-webui/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks.mojom-webui.js",
+    "$root_gen_dir/mojom-webui/components/commerce/core/mojom/shopping_list.mojom-webui.js",
+  ]
+
+  ts_composite = true
+  ts_definitions = [
+    "//tools/typescript/definitions/bookmark_manager_private.d.ts",
+    "//tools/typescript/definitions/bookmarks.d.ts",
+    "//tools/typescript/definitions/metrics_private.d.ts",
+    "//tools/typescript/definitions/tabs.d.ts",
+  ]
+  ts_deps = [
+    "//third_party/polymer/v3_0:library",
+    "//ui/webui/resources:library",
+    "//ui/webui/resources/mojo:library",
+  ]
+}
diff --git a/chrome/browser/resources/side_panel/bookmarks/bookmarks.html b/chrome/browser/resources/side_panel/bookmarks/bookmarks.html
index a3c1bdb..c6128dc 100644
--- a/chrome/browser/resources/side_panel/bookmarks/bookmarks.html
+++ b/chrome/browser/resources/side_panel/bookmarks/bookmarks.html
@@ -30,6 +30,6 @@
 </head>
 <body>
   <bookmarks-list></bookmarks-list>
-  <script type="module" src="bookmarks/bookmarks_list.js"></script>
+  <script type="module" src="bookmarks_list.js"></script>
 </body>
 </html>
diff --git a/chrome/browser/resources/side_panel/bookmarks/bookmarks_list.ts b/chrome/browser/resources/side_panel/bookmarks/bookmarks_list.ts
index b9093d7d..8861a1a 100644
--- a/chrome/browser/resources/side_panel/bookmarks/bookmarks_list.ts
+++ b/chrome/browser/resources/side_panel/bookmarks/bookmarks_list.ts
@@ -14,8 +14,8 @@
 import {BookmarksApiProxy, BookmarksApiProxyImpl} from './bookmarks_api_proxy.js';
 import {BookmarksDragManager} from './bookmarks_drag_manager.js';
 import {getTemplate} from './bookmarks_list.html.js';
-import {BookmarkProductInfo} from './commerce/shopping_list.mojom-webui.js';
 import {ShoppingListApiProxy, ShoppingListApiProxyImpl} from './commerce/shopping_list_api_proxy.js';
+import {BookmarkProductInfo} from './shopping_list.mojom-webui.js';
 
 // Key for localStorage object that refers to all the open folders.
 export const LOCAL_STORAGE_OPEN_FOLDERS_KEY = 'openFolders';
@@ -86,11 +86,11 @@
   override connectedCallback() {
     super.connectedCallback();
     this.setAttribute('role', 'tree');
-    if (loadTimeData.getBoolean('unifiedSidePanel')) {
-      listenOnce(this.$.bookmarksContainer, 'dom-change', () => {
-        setTimeout(() => this.bookmarksApi_.showUi(), 0);
-      });
-    }
+
+    listenOnce(this.$.bookmarksContainer, 'dom-change', () => {
+      setTimeout(() => this.bookmarksApi_.showUi(), 0);
+    });
+
     this.focusOutlineManager_ = FocusOutlineManager.forDocument(document);
     this.bookmarksApi_.getFolders().then(folders => {
       this.folders_ = folders;
diff --git a/chrome/browser/resources/side_panel/bookmarks/commerce/shopping_list.ts b/chrome/browser/resources/side_panel/bookmarks/commerce/shopping_list.ts
index b6126ed..ab8ea13 100644
--- a/chrome/browser/resources/side_panel/bookmarks/commerce/shopping_list.ts
+++ b/chrome/browser/resources/side_panel/bookmarks/commerce/shopping_list.ts
@@ -14,9 +14,9 @@
 
 import {ActionSource} from '../bookmarks.mojom-webui.js';
 import {BookmarksApiProxy, BookmarksApiProxyImpl} from '../bookmarks_api_proxy.js';
+import {BookmarkProductInfo} from '../shopping_list.mojom-webui.js';
 
 import {getTemplate} from './shopping_list.html.js';
-import {BookmarkProductInfo} from './shopping_list.mojom-webui.js';
 import {ShoppingListApiProxy, ShoppingListApiProxyImpl} from './shopping_list_api_proxy.js';
 
 export const LOCAL_STORAGE_EXPAND_STATUS_KEY = 'shoppingListExpanded';
diff --git a/chrome/browser/resources/side_panel/bookmarks/commerce/shopping_list_api_proxy.ts b/chrome/browser/resources/side_panel/bookmarks/commerce/shopping_list_api_proxy.ts
index 64fbb8c..631a83a 100644
--- a/chrome/browser/resources/side_panel/bookmarks/commerce/shopping_list_api_proxy.ts
+++ b/chrome/browser/resources/side_panel/bookmarks/commerce/shopping_list_api_proxy.ts
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {BookmarkProductInfo, PageCallbackRouter, ShoppingListHandlerFactory, ShoppingListHandlerRemote} from './shopping_list.mojom-webui.js';
+import {BookmarkProductInfo, PageCallbackRouter, ShoppingListHandlerFactory, ShoppingListHandlerRemote} from '../shopping_list.mojom-webui.js';
 
 let instance: ShoppingListApiProxy|null = null;
 
diff --git a/chrome/browser/resources/side_panel/images/bookmarks_empty.svg b/chrome/browser/resources/side_panel/bookmarks/images/bookmarks_empty.svg
similarity index 100%
rename from chrome/browser/resources/side_panel/images/bookmarks_empty.svg
rename to chrome/browser/resources/side_panel/bookmarks/images/bookmarks_empty.svg
diff --git a/chrome/browser/resources/side_panel/images/bookmarks_empty_dark.svg b/chrome/browser/resources/side_panel/bookmarks/images/bookmarks_empty_dark.svg
similarity index 100%
rename from chrome/browser/resources/side_panel/images/bookmarks_empty_dark.svg
rename to chrome/browser/resources/side_panel/bookmarks/images/bookmarks_empty_dark.svg
diff --git a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks.html b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks.html
index 1aed432..a8c4101 100644
--- a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks.html
+++ b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks.html
@@ -30,6 +30,6 @@
 </head>
 <body>
   <power-bookmarks-list></power-bookmarks-list>
-  <script type="module" src="bookmarks/power_bookmarks_list.js"></script>
+  <script type="module" src="power_bookmarks_list.js"></script>
 </body>
 </html>
diff --git a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.html b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.html
index 7b37a1af..3d7a8a4c 100644
--- a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.html
+++ b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.html
@@ -4,7 +4,7 @@
     --border-color: var(--google-grey-300);
     --disabled-text-color: var(--google-grey-600);
     --edit-footer-background: var(--google-grey-50);
-    --empty-state-image: url(../images/bookmarks_empty.svg);
+    --empty-state-image: url(./images/bookmarks_empty.svg);
     --label-selected-color: var(--google-blue-50);
     --price-tracking-chip-background: var(--google-green-50);
     --price-tracking-discount-color: var(--google-green-800);
@@ -16,7 +16,7 @@
       --border-color: var(--google-grey-700);
       --disabled-text-color: var(--google-grey-500);
       --edit-footer-background: var(--google-grey-900-white-4-percent);
-      --empty-state-image: url(../images/bookmarks_empty_dark.svg);
+      --empty-state-image: url(./images/bookmarks_empty_dark.svg);
       --price-tracking-chip-background: var(--google-green-900);
       --price-tracking-discount-color: white;
       --price-tracking-original-color: var(--google-green-200);
diff --git a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.ts b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.ts
index 3d872d9..844b73a 100644
--- a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.ts
+++ b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.ts
@@ -25,10 +25,10 @@
 
 import {ActionSource} from './bookmarks.mojom-webui.js';
 import {BookmarksApiProxy, BookmarksApiProxyImpl} from './bookmarks_api_proxy.js';
-import {BookmarkProductInfo} from './commerce/shopping_list.mojom-webui.js';
 import {ShoppingListApiProxy, ShoppingListApiProxyImpl} from './commerce/shopping_list_api_proxy.js';
 import {PowerBookmarksContextMenuElement} from './power_bookmarks_context_menu.js';
 import {getTemplate} from './power_bookmarks_list.html.js';
+import {BookmarkProductInfo} from './shopping_list.mojom-webui.js';
 
 function getBookmarkName(bookmark: chrome.bookmarks.BookmarkTreeNode): string {
   return bookmark.title || bookmark.url || '';
diff --git a/chrome/browser/resources/side_panel/bookmarks/tsconfig_base.json b/chrome/browser/resources/side_panel/bookmarks/tsconfig_base.json
new file mode 100644
index 0000000..5ea1ac6
--- /dev/null
+++ b/chrome/browser/resources/side_panel/bookmarks/tsconfig_base.json
@@ -0,0 +1,9 @@
+{
+   "extends": "../../../../../tools/typescript/tsconfig_base.json",
+   "compilerOptions": {
+      "allowJs": true,
+      "noUncheckedIndexedAccess": false,
+      "noUnusedLocals": false,
+      "strictPropertyInitialization": false
+   }
+}
diff --git a/chrome/browser/resources/side_panel/reading_list/app.ts b/chrome/browser/resources/side_panel/reading_list/app.ts
index 1597abf..edb847e 100644
--- a/chrome/browser/resources/side_panel/reading_list/app.ts
+++ b/chrome/browser/resources/side_panel/reading_list/app.ts
@@ -79,11 +79,6 @@
         type: Boolean,
         value: true,
       },
-
-      unifiedSidePanel_: {
-        type: Boolean,
-        value: () => loadTimeData.getBoolean('unifiedSidePanel'),
-      },
     };
   }
 
@@ -92,7 +87,6 @@
   private currentPageActionButtonState_: CurrentPageActionButtonState;
   buttonRipples: boolean;
   private loadingContent_: boolean;
-  private unifiedSidePanel_: boolean;
   private apiProxy_: ReadingListApiProxy =
       ReadingListApiProxyImpl.getInstance();
   private listenerIds_: number[] = [];
@@ -125,14 +119,8 @@
             (state: CurrentPageActionButtonState) =>
                 this.updateCurrentPageActionButton_(state)));
 
-    // If added in a visible state update current reading list items.
-    // If UnifiedSidePanel is enabled do this immediately. This is only
-    // undesirable when UnifiedSidePanel is not enabled since previously reading
-    // list and bookmarks shared a webview.
-    if (document.visibilityState === 'visible' || this.unifiedSidePanel_) {
-      this.updateReadLaterEntries_();
-      this.apiProxy_.updateCurrentPageActionButtonState();
-    }
+    this.updateReadLaterEntries_();
+    this.apiProxy_.updateCurrentPageActionButtonState();
 
     this.readingListEventTracker_.add(
         this.root!, MARKED_AS_READ_UI_EVENT, this.onMarkedAsRead.bind(this));
diff --git a/chrome/browser/resources/side_panel/side_panel.gni b/chrome/browser/resources/side_panel/side_panel.gni
index 1ecb7159..2b230a4 100644
--- a/chrome/browser/resources/side_panel/side_panel.gni
+++ b/chrome/browser/resources/side_panel/side_panel.gni
@@ -2,24 +2,11 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-non_web_component_files = [
-  "bookmarks/bookmarks_api_proxy.ts",
-  "bookmarks/bookmarks_drag_manager.ts",
-  "bookmarks/commerce/shopping_list_api_proxy.ts",
-  "reading_list/reading_list_api_proxy.ts",
-]
+non_web_component_files = [ "reading_list/reading_list_api_proxy.ts" ]
 
 # Files holding a Polymer element definition and have an equivalent .html file.
 web_component_files = [
-  "app.ts",
-  "bookmarks/bookmark_folder.ts",
-  "bookmarks/bookmarks_list.ts",
-  "bookmarks/power_bookmark_chip.ts",
-  "bookmarks/power_bookmark_row.ts",
-  "bookmarks/power_bookmarks_context_menu.ts",
-  "bookmarks/power_bookmarks_list.ts",
   "history_clusters/app.ts",
-  "bookmarks/commerce/shopping_list.ts",
   "read_anything/app.ts",
   "reading_list/app.ts",
   "reading_list/reading_list_item.ts",
@@ -31,11 +18,7 @@
   html_files += [ string_replace(f, ".ts", ".html") ]
 }
 
-icons_html_files = [
-  "reading_list/icons.html",
-  "bookmarks/commerce/icons.html",
-  "bookmarks/icons.html",
-]
+icons_html_files = [ "reading_list/icons.html" ]
 
 # Files that are generated by html_to_wrapper().
 html_wrapper_files = []
@@ -45,8 +28,4 @@
 
 ts_files = web_component_files + non_web_component_files
 
-mojo_files = [
-  "bookmarks/bookmarks.mojom-webui.js",
-  "bookmarks/commerce/shopping_list.mojom-webui.js",
-  "reading_list/reading_list.mojom-webui.js",
-]
+mojo_files = [ "reading_list/reading_list.mojom-webui.js" ]
diff --git a/chrome/browser/resources/side_panel/side_panel.html b/chrome/browser/resources/side_panel/side_panel.html
deleted file mode 100644
index 8675d22..0000000
--- a/chrome/browser/resources/side_panel/side_panel.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!doctype html>
-<html dir="$i18n{textdirection}" lang="$i18n{language}">
-<head>
-  <meta charset="utf-8">
-  <title>$i18n{sidePanelTitle}</title>
-  <meta name="color-scheme" content="light dark">
-  <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
-  <link rel="stylesheet" href="chrome://resources/css/md_colors.css">
-  <style>
-    html,
-    body {
-      height: 100%;
-      margin: 0;
-      padding: 0;
-      width: 100%;
-    }
-
-    body {
-      background: white;
-      overflow: auto;
-    }
-
-    @media (prefers-color-scheme: dark) {
-      body {
-        background: var(--google-grey-900);
-      }
-    }
-  </style>
-</head>
-<body>
-  <side-panel-app></side-panel-app>
-  <script type="module" src="app.js"></script>
-  </script>
-</body>
-</html>
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 96f7e2ac..beb7e566 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -2523,6 +2523,8 @@
       "views/borealis/borealis_installer_view.h",
       "views/borealis/borealis_splash_screen_view.cc",
       "views/borealis/borealis_splash_screen_view.h",
+      "views/bruschetta/bruschetta_installer_view.cc",
+      "views/bruschetta/bruschetta_installer_view.h",
       "views/chrome_views_delegate_chromeos.cc",
       "views/crostini/crostini_ansible_software_config_view.cc",
       "views/crostini/crostini_ansible_software_config_view.h",
@@ -5314,8 +5316,8 @@
       "//components/payments/content",
       "//components/payments/content:utils",
       "//components/payments/core",
+      "//components/power_bookmarks/common",
       "//components/power_bookmarks/core:core",
-      "//components/power_bookmarks/core:powers",
       "//components/power_bookmarks/storage",
       "//components/qr_code_generator",
       "//components/reading_list/features:flags",
diff --git a/chrome/browser/ui/ash/app_list/app_list_with_recent_apps_browsertest.cc b/chrome/browser/ui/ash/app_list/app_list_with_recent_apps_browsertest.cc
index fa942c2..04a807d 100644
--- a/chrome/browser/ui/ash/app_list/app_list_with_recent_apps_browsertest.cc
+++ b/chrome/browser/ui/ash/app_list/app_list_with_recent_apps_browsertest.cc
@@ -34,13 +34,6 @@
     // Ensure async callbacks are run.
     base::RunLoop().RunUntilIdle();
 
-    // In release builds (without DCHECKs) this test sometimes fails because the
-    // search ranking subsystem filters out all the recent app items due to a
-    // race between zero state search request and initialization of the ranker
-    // for removed results. Work around this by disabling ranking.
-    // https://crbug.com/1371600
-    client->search_controller()->disable_ranking_for_test();
-
     // Install enough apps to show the recent apps view.
     LoadExtension(test_data_dir_.AppendASCII("app1"));
     LoadExtension(test_data_dir_.AppendASCII("app2"));
diff --git a/chrome/browser/ui/ash/wallpaper_controller_client_impl.cc b/chrome/browser/ui/ash/wallpaper_controller_client_impl.cc
index c5e5de2..9245f73 100644
--- a/chrome/browser/ui/ash/wallpaper_controller_client_impl.cc
+++ b/chrome/browser/ui/ash/wallpaper_controller_client_impl.cc
@@ -83,10 +83,6 @@
 
 // Known user keys.
 const char kWallpaperFilesId[] = "wallpaper-files-id";
-constexpr char kDriveFsWallpaperDirName[] = "Chromebook Wallpaper";
-// Encoded in |WallpaperControllerImpl.ResizeAndEncodeImage|.
-constexpr char kDriveFsWallpaperFileName[] = "wallpaper.jpg";
-constexpr char kDriveFsTempWallpaperFileName[] = "wallpaper-tmp.jpg";
 
 WallpaperControllerClientImpl* g_wallpaper_controller_client_instance = nullptr;
 
@@ -182,47 +178,6 @@
   return nullptr;
 }
 
-base::FilePath GetDriveFsWallpaperDir(Profile* profile) {
-  CHECK(profile);
-
-  drive::DriveIntegrationService* drive_integration_service =
-      drive::util::GetIntegrationServiceByProfile(profile);
-  if (!drive_integration_service) {
-    return base::FilePath();
-  }
-  return drive_integration_service->GetMountPointPath()
-      .Append(drive::util::kDriveMyDriveRootDirName)
-      .Append(kDriveFsWallpaperDirName);
-}
-
-bool SaveWallpaperToDriveFsIOTaskRunner(
-    const base::FilePath& origin,
-    const base::FilePath& destination_directory) {
-  if (destination_directory.empty())
-    return false;
-
-  if (!base::DirectoryExists(destination_directory) &&
-      !base::CreateDirectory(destination_directory)) {
-    return false;
-  }
-
-  std::string temp_file_name =
-      base::UnguessableToken::Create().ToString().append(
-          kDriveFsTempWallpaperFileName);
-  base::FilePath temp_destination =
-      destination_directory.Append(temp_file_name);
-  if (!base::CopyFile(origin, temp_destination)) {
-    base::DeleteFile(temp_destination);
-    return false;
-  }
-
-  base::FilePath destination =
-      destination_directory.Append(kDriveFsWallpaperFileName);
-  bool success = base::ReplaceFile(temp_destination, destination, nullptr);
-  base::DeleteFile(temp_destination);
-  return success;
-}
-
 }  // namespace
 
 WallpaperControllerClientImpl::WallpaperControllerClientImpl() {
@@ -241,10 +196,6 @@
   // SessionManager might not exist in unit tests.
   if (session_manager)
     session_observation_.Observe(session_manager);
-
-  io_task_runner_ = base::ThreadPool::CreateSequencedTaskRunner(
-      {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
-       base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
 }
 
 WallpaperControllerClientImpl::~WallpaperControllerClientImpl() {
@@ -483,28 +434,6 @@
   return wallpaper_controller_->ShouldShowWallpaperSetting();
 }
 
-void WallpaperControllerClientImpl::SaveWallpaperToDriveFs(
-    const AccountId& account_id,
-    const base::FilePath& origin,
-    base::OnceCallback<void(bool)> wallpaper_saved_callback) {
-  Profile* profile = ProfileHelper::Get()->GetProfileByAccountId(account_id);
-  base::FilePath destination_directory = GetDriveFsWallpaperDir(profile);
-  io_task_runner_->PostTaskAndReplyWithResult(
-      FROM_HERE,
-      base::BindOnce(&SaveWallpaperToDriveFsIOTaskRunner, origin,
-                     destination_directory),
-      std::move(wallpaper_saved_callback));
-}
-
-base::FilePath WallpaperControllerClientImpl::GetWallpaperPathFromDriveFs(
-    const AccountId& account_id) {
-  Profile* profile = ProfileHelper::Get()->GetProfileByAccountId(account_id);
-  base::FilePath wallpaper_directory = GetDriveFsWallpaperDir(profile);
-  if (wallpaper_directory.empty())
-    return wallpaper_directory;
-  return wallpaper_directory.Append(kDriveFsWallpaperFileName);
-}
-
 void WallpaperControllerClientImpl::GetFilesId(
     const AccountId& account_id,
     base::OnceCallback<void(const std::string&)> files_id_callback) const {
diff --git a/chrome/browser/ui/ash/wallpaper_controller_client_impl.h b/chrome/browser/ui/ash/wallpaper_controller_client_impl.h
index e912620..18fc083 100644
--- a/chrome/browser/ui/ash/wallpaper_controller_client_impl.h
+++ b/chrome/browser/ui/ash/wallpaper_controller_client_impl.h
@@ -26,10 +26,6 @@
 
 class AccountId;
 
-namespace base {
-class SequencedTaskRunner;
-}  // namespace base
-
 namespace {
 class WallpaperControllerClientImplTest;
 }
@@ -82,12 +78,6 @@
   void FetchGooglePhotosAccessToken(
       const AccountId& account_id,
       FetchGooglePhotosAccessTokenCallback callback) override;
-  void SaveWallpaperToDriveFs(
-      const AccountId& account_id,
-      const base::FilePath& origin,
-      base::OnceCallback<void(bool)> wallpaper_saved_callback) override;
-  base::FilePath GetWallpaperPathFromDriveFs(
-      const AccountId& account_id) override;
   void GetFilesId(const AccountId& account_id,
                   base::OnceCallback<void(const std::string&)>
                       files_id_callback) const override;
@@ -230,11 +220,7 @@
                           session_manager::SessionManagerObserver>
       session_observation_{this};
 
-  scoped_refptr<base::SequencedTaskRunner> io_task_runner_;
-
   base::WeakPtrFactory<WallpaperControllerClientImpl> weak_factory_{this};
-  base::WeakPtrFactory<WallpaperControllerClientImpl> storage_weak_factory_{
-      this};
 };
 
 #endif  // CHROME_BROWSER_UI_ASH_WALLPAPER_CONTROLLER_CLIENT_IMPL_H_
diff --git a/chrome/browser/ui/views/bruschetta/DIR_METADATA b/chrome/browser/ui/views/bruschetta/DIR_METADATA
new file mode 100644
index 0000000..06e627f
--- /dev/null
+++ b/chrome/browser/ui/views/bruschetta/DIR_METADATA
@@ -0,0 +1 @@
+mixins: "//chrome/browser/ash/guest_os/COMMON_METADATA"
diff --git a/chrome/browser/ui/views/bruschetta/OWNERS b/chrome/browser/ui/views/bruschetta/OWNERS
new file mode 100644
index 0000000..a33be2b
--- /dev/null
+++ b/chrome/browser/ui/views/bruschetta/OWNERS
@@ -0,0 +1 @@
+file://chrome/browser/ash/guest_os/OWNERS
diff --git a/chrome/browser/ui/views/bruschetta/bruschetta_installer_view.cc b/chrome/browser/ui/views/bruschetta/bruschetta_installer_view.cc
new file mode 100644
index 0000000..2afa4c4
--- /dev/null
+++ b/chrome/browser/ui/views/bruschetta/bruschetta_installer_view.cc
@@ -0,0 +1,360 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/bruschetta/bruschetta_installer_view.h"
+
+#include <memory>
+
+#include "ash/public/cpp/style/color_mode_observer.h"
+#include "ash/public/cpp/style/dark_light_mode_controller.h"
+#include "base/check_is_test.h"
+#include "base/functional/bind.h"
+#include "base/strings/string_number_conversions.h"
+#include "chrome/browser/ash/bruschetta/bruschetta_installer.h"
+#include "chrome/browser/ash/bruschetta/bruschetta_installer_impl.h"
+#include "chrome/browser/ui/views/chrome_typography.h"
+#include "chrome/grit/generated_resources.h"
+#include "content/public/browser/browser_thread.h"
+#include "ui/accessibility/ax_node_data.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/base/ui_base_types.h"
+#include "ui/gfx/geometry/insets.h"
+#include "ui/strings/grit/ui_strings.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/controls/progress_bar.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/view_class_properties.h"
+
+namespace {
+
+BruschettaInstallerView* g_bruschetta_installer_view = nullptr;
+
+constexpr auto kButtonRowInsets = gfx::Insets::TLBR(0, 64, 32, 64);
+constexpr int kWindowWidth = 768;
+constexpr int kWindowHeight = 636;
+
+}  // namespace
+
+// static
+void BruschettaInstallerView::Show(Profile* profile,
+                                   const guest_os::GuestId& guest_id) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  if (!g_bruschetta_installer_view) {
+    g_bruschetta_installer_view =
+        new BruschettaInstallerView(profile, guest_id);
+    views::DialogDelegate::CreateDialogWidget(g_bruschetta_installer_view,
+                                              nullptr, nullptr);
+  }
+  g_bruschetta_installer_view->SetButtonRowInsets(kButtonRowInsets);
+
+  g_bruschetta_installer_view->GetWidget()->Show();
+}
+
+// static
+BruschettaInstallerView* BruschettaInstallerView::GetActiveViewForTesting() {
+  return g_bruschetta_installer_view;
+}
+
+// We need a separate class so that we can alert screen readers appropriately
+// when the text changes.
+class BruschettaInstallerView::TitleLabel : public views::Label {
+ public:
+  using Label::Label;
+
+  METADATA_HEADER(TitleLabel);
+
+  TitleLabel() = default;
+  ~TitleLabel() override = default;
+
+  void GetAccessibleNodeData(ui::AXNodeData* node_data) override {
+    node_data->role = ax::mojom::Role::kStatus;
+    node_data->SetNameChecked(GetText());
+  }
+};
+
+BEGIN_METADATA(BruschettaInstallerView, TitleLabel, views::Label)
+END_METADATA
+
+BruschettaInstallerView::BruschettaInstallerView(Profile* profile,
+                                                 guest_os::GuestId guest_id)
+    : profile_(profile), observation_(this), guest_id_(guest_id) {
+  // Layout constants from the spec used for the plugin vm installer.
+  constexpr auto kDialogInsets = gfx::Insets::TLBR(60, 64, 0, 64);
+  const int kPrimaryMessageHeight = views::style::GetLineHeight(
+      CONTEXT_HEADLINE, views::style::STYLE_PRIMARY);
+  const int kSecondaryMessageHeight = views::style::GetLineHeight(
+      views::style::CONTEXT_DIALOG_BODY_TEXT, views::style::STYLE_SECONDARY);
+  constexpr int kProgressBarHeight = 5;
+  constexpr int kProgressBarTopMargin = 32;
+
+  SetCanMinimize(true);
+  set_draggable(true);
+  // Removed margins so dialog insets specify it instead.
+  set_margins(gfx::Insets());
+
+  views::BoxLayout* layout =
+      SetLayoutManager(std::make_unique<views::BoxLayout>(
+          views::BoxLayout::Orientation::kVertical, kDialogInsets));
+
+  views::View* upper_container_view =
+      AddChildView(std::make_unique<views::View>());
+  upper_container_view->SetLayoutManager(std::make_unique<views::BoxLayout>(
+      views::BoxLayout::Orientation::kVertical, gfx::Insets()));
+  AddChildView(upper_container_view);
+
+  views::View* lower_container_view =
+      AddChildView(std::make_unique<views::View>());
+  lower_container_layout_ =
+      lower_container_view->SetLayoutManager(std::make_unique<views::BoxLayout>(
+          views::BoxLayout::Orientation::kVertical));
+  AddChildView(lower_container_view);
+
+  primary_message_label_ = new TitleLabel(GetPrimaryMessage(), CONTEXT_HEADLINE,
+                                          views::style::STYLE_PRIMARY);
+  primary_message_label_->SetProperty(
+      views::kMarginsKey, gfx::Insets::TLBR(kPrimaryMessageHeight, 0, 0, 0));
+  primary_message_label_->SetMultiLine(false);
+  primary_message_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+  upper_container_view->AddChildView(primary_message_label_.get());
+
+  views::View* secondary_message_container_view =
+      AddChildView(std::make_unique<views::View>());
+  secondary_message_container_view->SetLayoutManager(
+      std::make_unique<views::BoxLayout>(
+          views::BoxLayout::Orientation::kVertical,
+          gfx::Insets::TLBR(kSecondaryMessageHeight, 0, 0, 0)));
+  upper_container_view->AddChildView(secondary_message_container_view);
+  secondary_message_label_ = new views::Label(
+      GetSecondaryMessage(), views::style::CONTEXT_DIALOG_BODY_TEXT,
+      views::style::STYLE_SECONDARY);
+  secondary_message_label_->SetMultiLine(true);
+  secondary_message_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+  secondary_message_container_view->AddChildView(
+      secondary_message_label_.get());
+
+  progress_bar_ = new views::ProgressBar(kProgressBarHeight);
+  progress_bar_->SetProperty(
+      views::kMarginsKey,
+      gfx::Insets::TLBR(kProgressBarTopMargin - kProgressBarHeight, 0, 0, 0));
+  upper_container_view->AddChildView(progress_bar_.get());
+
+  // Make sure the lower_container_view is pinned to the bottom of the dialog.
+  lower_container_layout_->set_main_axis_alignment(
+      views::BoxLayout::MainAxisAlignment::kEnd);
+  layout->SetFlexForView(lower_container_view, 1, true);
+
+  ash::DarkLightModeController* dark_light_controller =
+      ash::DarkLightModeController::Get();
+  if (dark_light_controller) {
+    dark_light_controller->AddObserver(this);
+  }
+}
+
+BruschettaInstallerView::~BruschettaInstallerView() {
+  // installer_->Cancel calls back into us, so remember that we're being
+  // destroyed now to avoid doing work (that crashes us) in the callback.
+  is_destroying_ = true;
+  if (installer_) {
+    installer_->Cancel();
+  }
+  g_bruschetta_installer_view = nullptr;
+}
+
+bool BruschettaInstallerView::Accept() {
+  if (state_ == State::kConfirmInstall) {
+    StartInstallation();
+    return false;
+  }
+
+  // If we're not on the confirmation page then we're on the end page.
+  return true;
+}
+
+bool BruschettaInstallerView::Cancel() {
+  observation_.Reset();
+  if (state_ == State::kInstalling) {
+    installer_->Cancel();
+  }
+  return true;
+}
+
+void BruschettaInstallerView::StartInstallation() {
+  state_ = State::kInstalling;
+  progress_bar_->SetValue(-1);
+
+  if (!installer_) {
+    installer_ = std::make_unique<bruschetta::BruschettaInstallerImpl>(
+        profile_, base::BindOnce(&BruschettaInstallerView::OnInstallationEnded,
+                                 weak_factory_.GetWeakPtr()));
+  } else {
+    // Only test code should have an existing installer, non-test-code should
+    // always be hitting the above branch to create an instance since we have a
+    // singleton view and no way of going back to a previous page.
+    CHECK_IS_TEST();
+  }
+  observation_.Observe(installer_.get());
+  installer_->Install(guest_id_.vm_name, guest_id_.vm_name);
+
+  OnStateUpdated();
+}
+
+void BruschettaInstallerView::StateChanged(InstallerState new_state) {
+  VLOG(2) << "State changed: " << static_cast<int>(installing_state_) << " -> "
+          << static_cast<int>(new_state);
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  DCHECK_EQ(state_, State::kInstalling);
+  installing_state_ = new_state;
+  OnStateUpdated();
+}
+
+void BruschettaInstallerView::Error() {
+  VLOG(2) << "Error";
+  error_ = true;
+  state_ = State::kFailed;
+  OnStateUpdated();
+}
+
+void BruschettaInstallerView::OnInstallationEnded() {
+  if (is_destroying_) {
+    return;
+  }
+  observation_.Reset();
+  installer_.reset();
+  GetWidget()->CloseWithReason(views::Widget::ClosedReason::kUnspecified);
+}
+
+bool BruschettaInstallerView::ShouldShowCloseButton() const {
+  return true;
+}
+
+bool BruschettaInstallerView::ShouldShowWindowTitle() const {
+  return false;
+}
+
+gfx::Size BruschettaInstallerView::CalculatePreferredSize() const {
+  return gfx::Size(kWindowWidth, kWindowHeight);
+}
+
+std::u16string BruschettaInstallerView::GetPrimaryMessage() const {
+  switch (state_) {
+    case State::kConfirmInstall:
+      return l10n_util::GetStringUTF16(
+          IDS_BRUSCHETTA_INSTALLER_CONFIRMATION_TITLE);
+    case State::kInstalling:
+      return l10n_util::GetStringUTF16(IDS_BRUSCHETTA_INSTALLER_ONGOING_TITLE);
+    case State::kFailed:
+      return l10n_util::GetStringUTF16(IDS_BRUSCHETTA_INSTALLER_ERROR_TITLE);
+  }
+}
+
+std::u16string BruschettaInstallerView::GetSecondaryMessage() const {
+  if (state_ == State::kInstalling) {
+    switch (installing_state_) {
+      case InstallerState::kBootDiskDownload:
+      case InstallerState::kInstallStarted:
+      case InstallerState::kDlcInstall:
+      case InstallerState::kFirmwareDownload:
+      case InstallerState::kFirmwareMount:
+      case InstallerState::kBootDiskMount:
+      case InstallerState::kOpenFiles:
+      case InstallerState::kCreateVmDisk:
+      case InstallerState::kStartVm:
+      case InstallerState::kLaunchTerminal:
+        return u"state=" +
+               base::NumberToString16(static_cast<int>(installing_state_));
+    }
+  } else if (state_ == State::kFailed) {
+    // TODO(b/231899688): expose errors from installer and expose them via the
+    // UI.
+    return l10n_util::GetStringFUTF16(IDS_BRUSCHETTA_INSTALLER_ERROR_MESSAGE,
+                                      u"UNKNOWN_ERROR");
+  }
+  return {};
+}
+
+int BruschettaInstallerView::GetCurrentDialogButtons() const {
+  switch (state_) {
+    case State::kInstalling:
+      return ui::DIALOG_BUTTON_CANCEL;
+    case State::kConfirmInstall:
+      return ui::DIALOG_BUTTON_CANCEL | ui::DIALOG_BUTTON_OK;
+    case State::kFailed:
+      return ui::DIALOG_BUTTON_CANCEL;
+  }
+}
+
+std::u16string BruschettaInstallerView::GetCurrentDialogButtonLabel(
+    ui::DialogButton button) const {
+  switch (state_) {
+    case State::kConfirmInstall:
+      return l10n_util::GetStringUTF16(
+          button == ui::DIALOG_BUTTON_OK
+              ? IDS_BRUSCHETTA_INSTALLER_INSTALL_BUTTON
+              : IDS_APP_CANCEL);
+    case State::kInstalling:
+      DCHECK_EQ(button, ui::DIALOG_BUTTON_CANCEL);
+      return l10n_util::GetStringUTF16(IDS_APP_CANCEL);
+    case State::kFailed:
+      return l10n_util::GetStringUTF16(IDS_APP_CLOSE);
+  }
+}
+
+void BruschettaInstallerView::OnStateUpdated() {
+  SetPrimaryMessageLabel();
+  SetSecondaryMessageLabel();
+
+  int buttons = GetCurrentDialogButtons();
+  SetButtons(buttons);
+  if (buttons & ui::DIALOG_BUTTON_OK) {
+    SetButtonLabel(ui::DIALOG_BUTTON_OK,
+                   GetCurrentDialogButtonLabel(ui::DIALOG_BUTTON_OK));
+    SetDefaultButton(ui::DIALOG_BUTTON_OK);
+  } else {
+    SetDefaultButton(ui::DIALOG_BUTTON_NONE);
+  }
+  if (buttons & ui::DIALOG_BUTTON_CANCEL) {
+    SetButtonLabel(ui::DIALOG_BUTTON_CANCEL,
+                   GetCurrentDialogButtonLabel(ui::DIALOG_BUTTON_CANCEL));
+  }
+
+  const bool progress_bar_visible = state_ == State::kInstalling;
+  progress_bar_->SetVisible(progress_bar_visible);
+
+  DialogModelChanged();
+  primary_message_label_->NotifyAccessibilityEvent(
+      ax::mojom::Event::kLiveRegionChanged,
+      /* send_native_event = */ true);
+}
+
+void BruschettaInstallerView::AddedToWidget() {
+  // At this point GetWidget() is guaranteed to return non-null.
+  OnStateUpdated();
+}
+
+void BruschettaInstallerView::OnColorModeChanged(bool dark_mode_enabled) {
+  // We check dark-mode ourselves, so no need to propagate the param.
+  OnStateUpdated();
+}
+
+void BruschettaInstallerView::SetPrimaryMessageLabel() {
+  primary_message_label_->SetText(GetPrimaryMessage());
+  primary_message_label_->SetVisible(true);
+  primary_message_label_->NotifyAccessibilityEvent(
+      ax::mojom::Event::kTextChanged, true);
+}
+
+void BruschettaInstallerView::SetSecondaryMessageLabel() {
+  secondary_message_label_->SetText(GetSecondaryMessage());
+  secondary_message_label_->SetVisible(true);
+  secondary_message_label_->NotifyAccessibilityEvent(
+      ax::mojom::Event::kTextChanged, true);
+}
+
+BEGIN_METADATA(BruschettaInstallerView, views::DialogDelegateView)
+ADD_READONLY_PROPERTY_METADATA(std::u16string, PrimaryMessage)
+ADD_READONLY_PROPERTY_METADATA(std::u16string, SecondaryMessage)
+ADD_READONLY_PROPERTY_METADATA(int, CurrentDialogButtons)
+END_METADATA
diff --git a/chrome/browser/ui/views/bruschetta/bruschetta_installer_view.h b/chrome/browser/ui/views/bruschetta/bruschetta_installer_view.h
new file mode 100644
index 0000000..1c30798
--- /dev/null
+++ b/chrome/browser/ui/views/bruschetta/bruschetta_installer_view.h
@@ -0,0 +1,120 @@
+// 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_UI_VIEWS_BRUSCHETTA_BRUSCHETTA_INSTALLER_VIEW_H_
+#define CHROME_BROWSER_UI_VIEWS_BRUSCHETTA_BRUSCHETTA_INSTALLER_VIEW_H_
+
+#include "ash/public/cpp/style/color_mode_observer.h"
+#include "base/memory/weak_ptr.h"
+#include "base/scoped_observation.h"
+#include "chrome/browser/ash/bruschetta/bruschetta_installer.h"
+#include "chrome/browser/ash/guest_os/guest_id.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/views/window/dialog_delegate.h"
+
+class Profile;
+
+namespace views {
+class BoxLayout;
+class Label;
+class ProgressBar;
+}  // namespace views
+
+// The front end for the Bruschetta installation process, works closely with
+// "chrome/browser/ash/bruschetta/bruschetta_installer.h".
+class BruschettaInstallerView
+    : public views::DialogDelegateView,
+      public bruschetta::BruschettaInstaller::Observer,
+      public ash::ColorModeObserver {
+ public:
+  METADATA_HEADER(BruschettaInstallerView);
+
+  using InstallerState = bruschetta::BruschettaInstaller::State;
+
+  static void Show(Profile* profile, const guest_os::GuestId& guest_id);
+
+  explicit BruschettaInstallerView(Profile* profile,
+                                   guest_os::GuestId guest_id);
+
+  // Disallow copy and assign.
+  BruschettaInstallerView(const BruschettaInstallerView&) = delete;
+  BruschettaInstallerView& operator=(const BruschettaInstallerView&) = delete;
+
+  static BruschettaInstallerView* GetActiveViewForTesting();
+
+  // views::DialogDelegateView implementation.
+  bool ShouldShowCloseButton() const override;
+  bool ShouldShowWindowTitle() const override;
+  bool Accept() override;
+  bool Cancel() override;
+  gfx::Size CalculatePreferredSize() const override;
+
+  // bruschetta::BruschettaInstaller::Observer implementation.
+  void StateChanged(InstallerState state) override;
+  void Error() override;
+
+  // Public for testing purposes.
+  std::u16string GetPrimaryMessage() const;
+  std::u16string GetSecondaryMessage() const;
+  void OnInstallationEnded();
+
+  // Instead of creating a real one the view will use this one, letting tests
+  // inject an installer.
+  void set_installer_for_testing(
+      std::unique_ptr<bruschetta::BruschettaInstaller> installer) {
+    installer_ = std::move(installer);
+  }
+
+ private:
+  class TitleLabel;
+  enum class State {
+    kConfirmInstall,  // Waiting for user to start installation.
+    kInstalling,      // Installation in progress.
+    kFailed,          // Installation process failed.
+    // Note: No succeeded state since we close the installer upon success.
+  };
+
+  ~BruschettaInstallerView() override;
+
+  // Returns the dialog buttons that should be displayed, based on the current
+  // |state_|.
+  int GetCurrentDialogButtons() const;
+
+  // Returns the label for a dialog |button|, based on the current |state_|.
+  std::u16string GetCurrentDialogButtonLabel(ui::DialogButton button) const;
+
+  // views::DialogDelegateView implementation.
+  void AddedToWidget() override;
+
+  // ash::ColorModeObserver overrides.
+  void OnColorModeChanged(bool dark_mode_enabled) override;
+
+  void SetPrimaryMessageLabel();
+  void SetSecondaryMessageLabel();
+
+  void StartInstallation();
+  void OnStateUpdated();
+
+  raw_ptr<Profile> profile_ = nullptr;
+  raw_ptr<views::Label> primary_message_label_ = nullptr;
+  raw_ptr<views::Label> secondary_message_label_ = nullptr;
+  raw_ptr<views::ProgressBar> progress_bar_ = nullptr;
+  raw_ptr<views::BoxLayout> lower_container_layout_ = nullptr;
+
+  State state_ = State::kConfirmInstall;
+  InstallerState installing_state_ = InstallerState::kInstallStarted;
+
+  base::ScopedObservation<bruschetta::BruschettaInstaller,
+                          bruschetta::BruschettaInstaller::Observer>
+      observation_;
+
+  std::unique_ptr<bruschetta::BruschettaInstaller> installer_;
+  guest_os::GuestId guest_id_;
+  bool error_ = false;
+  bool is_destroying_ = false;
+
+  base::WeakPtrFactory<BruschettaInstallerView> weak_factory_{this};
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_BRUSCHETTA_BRUSCHETTA_INSTALLER_VIEW_H_
diff --git a/chrome/browser/ui/views/bruschetta/bruschetta_installer_view_browsertest.cc b/chrome/browser/ui/views/bruschetta/bruschetta_installer_view_browsertest.cc
new file mode 100644
index 0000000..e1d248a
--- /dev/null
+++ b/chrome/browser/ui/views/bruschetta/bruschetta_installer_view_browsertest.cc
@@ -0,0 +1,153 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/bruschetta/bruschetta_installer_view.h"
+
+#include <memory>
+
+#include "chrome/browser/ash/bruschetta/bruschetta_installer.h"
+#include "chrome/browser/ash/bruschetta/bruschetta_util.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/test/test_browser_dialog.h"
+#include "chrome/grit/generated_resources.h"
+#include "content/public/test/browser_test.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/l10n/l10n_util.h"
+
+using testing::AnyNumber;
+using testing::AtLeast;
+
+namespace bruschetta {
+namespace {
+
+class BruschettaInstallerMock : public bruschetta::BruschettaInstaller {
+ public:
+  MOCK_METHOD(void, Cancel, ());
+  MOCK_METHOD(void, Install, (std::string, std::string));
+  MOCK_METHOD(void, AddObserver, (Observer*));
+  MOCK_METHOD(void, RemoveObserver, (Observer*));
+
+  MOCK_METHOD(const base::GUID&, GetDownloadGuid, (), (const));
+
+  MOCK_METHOD(void,
+              DownloadStarted,
+              (const std::string& guid,
+               download::DownloadParams::StartResult result));
+  MOCK_METHOD(void, DownloadFailed, ());
+  MOCK_METHOD(void,
+              DownloadSucceeded,
+              (const download::CompletionInfo& completion_info));
+};
+
+class BruschettaInstallerViewBrowserTest : public DialogBrowserTest {
+ public:
+  BruschettaInstallerViewBrowserTest() = default;
+
+  // Disallow copy and assign.
+  BruschettaInstallerViewBrowserTest(
+      const BruschettaInstallerViewBrowserTest&) = delete;
+  BruschettaInstallerViewBrowserTest& operator=(
+      const BruschettaInstallerViewBrowserTest&) = delete;
+
+  void SetUpOnMainThread() override {}
+
+  void ShowUi(const std::string& name) override {
+    BruschettaInstallerView::Show(browser()->profile(), GetBruschettaAlphaId());
+    view_ = BruschettaInstallerView::GetActiveViewForTesting();
+
+    ASSERT_NE(nullptr, view_);
+    ASSERT_FALSE(view_->GetWidget()->IsClosed());
+    auto mock_installer = std::make_unique<BruschettaInstallerMock>();
+    installer_ = mock_installer.get();
+    view_->set_installer_for_testing(std::move(mock_installer));
+    EXPECT_CALL(*installer_, AddObserver).Times(AnyNumber());
+  }
+
+  BruschettaInstallerView* view_;
+  BruschettaInstallerMock* installer_;
+};
+
+IN_PROC_BROWSER_TEST_F(BruschettaInstallerViewBrowserTest, Show) {
+  ShowUi("default");
+  EXPECT_NE(nullptr, view_->GetOkButton());
+  EXPECT_NE(nullptr, view_->GetCancelButton());
+  EXPECT_EQ(
+      view_->GetPrimaryMessage(),
+      l10n_util::GetStringUTF16(IDS_BRUSCHETTA_INSTALLER_CONFIRMATION_TITLE));
+}
+
+IN_PROC_BROWSER_TEST_F(BruschettaInstallerViewBrowserTest,
+                       CancelOnPromptScreen) {
+  ShowUi("default");
+  view_->CancelDialog();
+  ASSERT_TRUE(view_->GetWidget()->IsClosed());
+}
+
+IN_PROC_BROWSER_TEST_F(BruschettaInstallerViewBrowserTest, InstallThenCancel) {
+  ShowUi("default");
+  EXPECT_CALL(*installer_, Install);
+  EXPECT_CALL(*installer_, Cancel).Times(AtLeast(1));
+
+  view_->AcceptDialog();
+  EXPECT_EQ(nullptr, view_->GetOkButton());
+  EXPECT_NE(nullptr, view_->GetCancelButton());
+  EXPECT_EQ(view_->GetPrimaryMessage(),
+            l10n_util::GetStringUTF16(IDS_BRUSCHETTA_INSTALLER_ONGOING_TITLE));
+
+  view_->CancelDialog();
+  ASSERT_TRUE(view_->GetWidget()->IsClosed());
+}
+
+IN_PROC_BROWSER_TEST_F(BruschettaInstallerViewBrowserTest, InstallThenError) {
+  ShowUi("default");
+  EXPECT_CALL(*installer_, Install);
+
+  view_->AcceptDialog();
+  EXPECT_EQ(nullptr, view_->GetOkButton());
+  EXPECT_NE(nullptr, view_->GetCancelButton());
+  EXPECT_EQ(view_->GetPrimaryMessage(),
+            l10n_util::GetStringUTF16(IDS_BRUSCHETTA_INSTALLER_ONGOING_TITLE));
+
+  view_->Error();
+  EXPECT_EQ(nullptr, view_->GetOkButton());
+  EXPECT_NE(nullptr, view_->GetCancelButton());
+  EXPECT_EQ(view_->GetPrimaryMessage(),
+            l10n_util::GetStringUTF16(IDS_BRUSCHETTA_INSTALLER_ERROR_TITLE));
+
+  EXPECT_CALL(*installer_, Cancel).Times(AtLeast(1));
+  view_->CancelDialog();
+  ASSERT_TRUE(view_->GetWidget()->IsClosed());
+}
+
+IN_PROC_BROWSER_TEST_F(BruschettaInstallerViewBrowserTest, InstallThenSuccess) {
+  ShowUi("default");
+  EXPECT_CALL(*installer_, Install);
+  EXPECT_CALL(*installer_, Cancel).Times(0);
+
+  view_->AcceptDialog();
+  EXPECT_EQ(nullptr, view_->GetOkButton());
+  EXPECT_NE(nullptr, view_->GetCancelButton());
+  EXPECT_EQ(view_->GetPrimaryMessage(),
+            l10n_util::GetStringUTF16(IDS_BRUSCHETTA_INSTALLER_ONGOING_TITLE));
+  auto first_message = view_->GetSecondaryMessage();
+
+  // Check that state changes update the progress message.
+  view_->StateChanged(bruschetta::BruschettaInstaller::State::kDlcInstall);
+  EXPECT_EQ(nullptr, view_->GetOkButton());
+  EXPECT_NE(nullptr, view_->GetCancelButton());
+  EXPECT_EQ(view_->GetPrimaryMessage(),
+            l10n_util::GetStringUTF16(IDS_BRUSCHETTA_INSTALLER_ONGOING_TITLE));
+  EXPECT_NE(first_message, view_->GetSecondaryMessage());
+
+  view_->OnInstallationEnded();
+
+  // We close the installer upon completion since we switch to a terminal
+  // window to complete the install.
+  ASSERT_TRUE(view_->GetWidget()->IsClosed());
+}
+
+}  // namespace
+}  // namespace bruschetta
diff --git a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_linux.cc b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_linux.cc
index 20a6b07a..f0eeced 100644
--- a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_linux.cc
+++ b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_linux.cc
@@ -19,6 +19,7 @@
 #include "chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view.h"
 #include "chrome/browser/ui/views/tabs/tab_strip.h"
 #include "third_party/skia/include/core/SkRRect.h"
+#include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/rect_conversions.h"
 #include "ui/gfx/geometry/skia_conversions.h"
 #include "ui/linux/linux_ui.h"
@@ -238,15 +239,22 @@
         region.op(corner_rect, SkRegion::kDifference_Op);
       }
 
+      auto translucent_top_area_rect = SkIRect::MakeXYWH(
+          rect.x(), rect.y(), rect.width(),
+          std::ceil(view->GetTranslucentTopAreaHeight() * scale - rect.y()));
+      region.op(translucent_top_area_rect, SkRegion::kDifference_Op);
+
       // Convert the region to a list of rectangles.
       for (SkRegion::Iterator i(region); !i.done(); i.next())
         opaque_region.push_back(gfx::SkIRectToRect(i.rect()));
     } else {
-      gfx::Rect widget_size_px =
-          gfx::ScaleToEnclosingRect(gfx::Rect(widget_size), scale);
-
-      // Set the entire window as opaque.
-      opaque_region.push_back(widget_size_px);
+      // The entire window except for the translucent top is opaque.
+      gfx::Rect opaque_region_dip(widget_size);
+      gfx::Insets insets;
+      insets.set_top(view->GetTranslucentTopAreaHeight());
+      opaque_region_dip.Inset(insets);
+      opaque_region.push_back(
+          gfx::ScaleToEnclosingRect(opaque_region_dip, scale));
     }
     window->SetOpaqueRegion(&opaque_region);
   }
diff --git a/chrome/browser/ui/views/frame/browser_frame_view_layout_linux_native_unittest.cc b/chrome/browser/ui/views/frame/browser_frame_view_layout_linux_native_unittest.cc
index b801d84c..6c9b2042 100644
--- a/chrome/browser/ui/views/frame/browser_frame_view_layout_linux_native_unittest.cc
+++ b/chrome/browser/ui/views/frame/browser_frame_view_layout_linux_native_unittest.cc
@@ -141,6 +141,7 @@
 
   // ui::WindowFrameProvider:
   int GetTopCornerRadiusDip() override { return 0; }
+  bool IsTopFrameTranslucent() override { return false; }
   gfx::Insets GetFrameThicknessDip() override { return {}; }
   void PaintWindowFrame(gfx::Canvas* canvas,
                         const gfx::Rect& rect,
diff --git a/chrome/browser/ui/views/frame/browser_frame_view_linux.cc b/chrome/browser/ui/views/frame/browser_frame_view_linux.cc
index 257ced2..d9d620b1 100644
--- a/chrome/browser/ui/views/frame/browser_frame_view_linux.cc
+++ b/chrome/browser/ui/views/frame/browser_frame_view_linux.cc
@@ -99,3 +99,7 @@
   return ChromeLayoutProvider::Get()->GetCornerRadiusMetric(
       views::Emphasis::kHigh);
 }
+
+int BrowserFrameViewLinux::GetTranslucentTopAreaHeight() const {
+  return 0;
+}
diff --git a/chrome/browser/ui/views/frame/browser_frame_view_linux.h b/chrome/browser/ui/views/frame/browser_frame_view_linux.h
index ee761b5..b6b6047e 100644
--- a/chrome/browser/ui/views/frame/browser_frame_view_linux.h
+++ b/chrome/browser/ui/views/frame/browser_frame_view_linux.h
@@ -34,6 +34,7 @@
   gfx::Insets MirroredFrameBorderInsets() const override;
   gfx::Insets GetInputInsets() const override;
   SkRRect GetRestoredClipRegion() const override;
+  int GetTranslucentTopAreaHeight() const override;
 
   // Gets the shadow metrics (radius, offset, and number of shadows).  This will
   // always return shadow values, even if shadows are not actually drawn.
diff --git a/chrome/browser/ui/views/frame/browser_frame_view_linux_native.cc b/chrome/browser/ui/views/frame/browser_frame_view_linux_native.cc
index 08b80c7..ef65e539 100644
--- a/chrome/browser/ui/views/frame/browser_frame_view_linux_native.cc
+++ b/chrome/browser/ui/views/frame/browser_frame_view_linux_native.cc
@@ -55,6 +55,11 @@
   return window_frame_provider_->GetTopCornerRadiusDip();
 }
 
+int BrowserFrameViewLinuxNative::GetTranslucentTopAreaHeight() const {
+  return window_frame_provider_->IsTopFrameTranslucent() ? GetTopAreaHeight()
+                                                         : 0;
+}
+
 void BrowserFrameViewLinuxNative::Layout() {
   // Calling MaybeUpdateCachedFrameButtonImages() from Layout() is sufficient to
   // catch all cases that could update the appearance, since
diff --git a/chrome/browser/ui/views/frame/browser_frame_view_linux_native.h b/chrome/browser/ui/views/frame/browser_frame_view_linux_native.h
index 35005eb..58f0aa66 100644
--- a/chrome/browser/ui/views/frame/browser_frame_view_linux_native.h
+++ b/chrome/browser/ui/views/frame/browser_frame_view_linux_native.h
@@ -30,6 +30,7 @@
  protected:
   // BrowserFrameViewLinux:
   float GetRestoredCornerRadiusDip() const override;
+  int GetTranslucentTopAreaHeight() const override;
 
   // OpaqueBrowserFrameView:
   void Layout() override;
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
index d5c900b..82a7a7e 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
@@ -269,6 +269,10 @@
   return SkRRect();
 }
 
+int BrowserNonClientFrameView::GetTranslucentTopAreaHeight() const {
+  return 0;
+}
+
 void BrowserNonClientFrameView::PaintAsActiveChanged() {
   if (web_app_frame_toolbar_)
     web_app_frame_toolbar_->SetPaintAsActive(ShouldPaintAsActive());
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
index fa0d024..d3279ce 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
@@ -161,6 +161,11 @@
   // view coordinates.
   virtual SkRRect GetRestoredClipRegion() const;
 
+  // Returns the height of the top frame.  This value will be 0 if the
+  // compositor doesn't support translucency, if the top frame is not
+  // translucent, or if the window is in full screen mode.
+  virtual int GetTranslucentTopAreaHeight() const;
+
  protected:
   // Called when |frame_|'s "paint as active" state has changed.
   virtual void PaintAsActiveChanged();
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
index ce8fe8af..492019e 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
@@ -3163,8 +3163,9 @@
 
 }  // namespace
 
-#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX)
+#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)
 // TODO(mukai): enable this test on Windows and Linux.
+// TODO(crbug.com/979013): flaky on Mac
 #define MAYBE_OffsetForDraggingTab DISABLED_OffsetForDraggingTab
 #else
 #define MAYBE_OffsetForDraggingTab OffsetForDraggingTab
diff --git a/chrome/browser/ui/views/web_apps/file_handler_launch_dialog_browsertest.cc b/chrome/browser/ui/views/web_apps/file_handler_launch_dialog_browsertest.cc
index ed8f73f..c8d0ad0 100644
--- a/chrome/browser/ui/views/web_apps/file_handler_launch_dialog_browsertest.cc
+++ b/chrome/browser/ui/views/web_apps/file_handler_launch_dialog_browsertest.cc
@@ -27,7 +27,6 @@
 #include "chrome/browser/web_applications/web_app_provider.h"
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/browser/web_applications/web_app_registry_update.h"
-#include "chrome/common/chrome_features.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
@@ -35,7 +34,6 @@
 #include "content/public/test/browser_test.h"
 #include "content/public/test/test_navigation_observer.h"
 #include "content/public/test/test_utils.h"
-#include "third_party/blink/public/common/features.h"
 #include "ui/views/widget/any_widget_observer.h"
 #include "ui/views/widget/widget.h"
 
@@ -166,9 +164,6 @@
 
  protected:
   AppId app_id_;
-
-  base::test::ScopedFeatureList feature_list_{
-      blink::features::kFileHandlingAPI};
 };
 
 IN_PROC_BROWSER_TEST_F(FileHandlerLaunchDialogTest,
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
index ca14d17..59e4586 100644
--- a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
@@ -117,7 +117,6 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h"
 #include "third_party/re2/src/re2/re2.h"
 #include "ui/accessibility/ax_action_data.h"
@@ -3416,7 +3415,6 @@
   enabled_features.push_back(features::kPwaUpdateDialogForName);
   enabled_features.push_back(features::kDesktopPWAsEnforceWebAppSettingsPolicy);
   enabled_features.push_back(features::kRecordWebAppDebugInfo);
-  enabled_features.push_back(blink::features::kFileHandlingAPI);
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   disabled_features.push_back(features::kWebAppsCrosapi);
   disabled_features.push_back(ash::features::kLacrosPrimary);
diff --git a/chrome/browser/ui/web_applications/web_app_browsertest.cc b/chrome/browser/ui/web_applications/web_app_browsertest.cc
index 1546f39..b2f84b3 100644
--- a/chrome/browser/ui/web_applications/web_app_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_browsertest.cc
@@ -132,13 +132,6 @@
 
 constexpr char kLaunchWebAppDisplayModeHistogram[] = "Launch.WebAppDisplayMode";
 
-// Represents the variety of states that can exist and which control the page
-// info bubble's app settings link.
-enum class WebAppSettingsState {
-  kFileHandlingDisabled = 1,
-  kFileHandlingEnabled,
-};
-
 // Opens |url| in a new popup window with the dimensions |popup_size|.
 Browser* OpenPopupAndWait(Browser* browser,
                           const GURL& url,
@@ -2168,9 +2161,7 @@
 #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
 class WebAppBrowserTest_FileHandler : public WebAppBrowserTest {
  public:
-  WebAppBrowserTest_FileHandler() {
-    feature_list_.InitAndEnableFeature(blink::features::kFileHandlingAPI);
-  }
+  WebAppBrowserTest_FileHandler() {}
 
 #if BUILDFLAG(IS_WIN)
  protected:
@@ -2182,9 +2173,6 @@
 
   registry_util::RegistryOverrideManager registry_override_manager_;
 #endif  // BUILDFLAG(IS_WIN)
-
- private:
-  base::test::ScopedFeatureList feature_list_;
 };
 
 // TODO(crbug.com/1320285): Flaky on Mac.
@@ -2419,32 +2407,17 @@
 }
 
 // Verifies the behavior of the App/site settings link in the page info bubble.
-class WebAppBrowserTest_PageInfoManagementLink
-    : public WebAppBrowserTest,
-      public testing::WithParamInterface<WebAppSettingsState> {
+class WebAppBrowserTest_PageInfoManagementLink : public WebAppBrowserTest {
  public:
-  WebAppBrowserTest_PageInfoManagementLink() {
-    file_handling_feature_list_.InitWithFeatureState(
-        blink::features::kFileHandlingAPI,
-        GetParam() == WebAppSettingsState::kFileHandlingEnabled);
-  }
-
   bool ShowingAppManagementLink(Browser* browser) {
     int unused_id, unused_id2;
     return GetLabelIdsForAppManagementLinkInPageInfo(
         browser->tab_strip_model()->GetActiveWebContents(), &unused_id,
         &unused_id2);
   }
-
-  static bool ShowsAppSettingsLinkInTabbedBrowser() {
-    return base::FeatureList::IsEnabled(blink::features::kFileHandlingAPI);
-  }
-
- private:
-  base::test::ScopedFeatureList file_handling_feature_list_;
 };
 
-IN_PROC_BROWSER_TEST_P(WebAppBrowserTest_PageInfoManagementLink, Reparenting) {
+IN_PROC_BROWSER_TEST_F(WebAppBrowserTest_PageInfoManagementLink, Reparenting) {
   const GURL app_url = GetSecureAppURL();
   InstallPWA(app_url);
 
@@ -2465,13 +2438,12 @@
 
   // Move back into tabbed browser: should keep showing the app settings link.
   Browser* tabbed_browser = chrome::OpenInChrome(app_browser);
-  EXPECT_EQ(ShowsAppSettingsLinkInTabbedBrowser(),
-            ShowingAppManagementLink(tabbed_browser));
+  EXPECT_TRUE(ShowingAppManagementLink(tabbed_browser));
 }
 
 // Verifies behavior when an app window is opened by navigating with
 // `open_pwa_window_if_possible` set to true.
-IN_PROC_BROWSER_TEST_P(WebAppBrowserTest_PageInfoManagementLink,
+IN_PROC_BROWSER_TEST_F(WebAppBrowserTest_PageInfoManagementLink,
                        OpenAppWindowIfPossible) {
   const GURL app_url = GetSecureAppURL();
   InstallPWA(app_url);
@@ -2490,7 +2462,7 @@
   EXPECT_TRUE(ShowingAppManagementLink(params.browser));
 }
 
-IN_PROC_BROWSER_TEST_P(WebAppBrowserTest_PageInfoManagementLink, LaunchAsTab) {
+IN_PROC_BROWSER_TEST_F(WebAppBrowserTest_PageInfoManagementLink, LaunchAsTab) {
   const GURL app_url = GetSecureAppURL();
   const AppId app_id = InstallPWA(app_url);
 
@@ -2501,18 +2473,11 @@
   // should be visible.
   Browser* tabbed_browser = LaunchBrowserForWebAppInTab(app_id);
   EXPECT_EQ(browser(), tabbed_browser);
-  EXPECT_EQ(ShowsAppSettingsLinkInTabbedBrowser(),
-            ShowingAppManagementLink(tabbed_browser));
+  EXPECT_TRUE(ShowingAppManagementLink(tabbed_browser));
 }
 
 INSTANTIATE_TEST_SUITE_P(
     All,
-    WebAppBrowserTest_PageInfoManagementLink,
-    ::testing::Values(WebAppSettingsState::kFileHandlingDisabled,
-                      WebAppSettingsState::kFileHandlingEnabled));
-
-INSTANTIATE_TEST_SUITE_P(
-    All,
     WebAppBrowserTest_ExternalPrefMigration,
     ::testing::Values(
         test::ExternalPrefMigrationTestCases::kDisableMigrationReadPref,
diff --git a/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc b/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc
index 5dceaa41..b5502a0 100644
--- a/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc
@@ -261,8 +261,6 @@
   }
 
   TestServerRedirectHandle redirect_handle_;
-  base::test::ScopedFeatureList feature_list_{
-      blink::features::kFileHandlingAPI};
   raw_ptr<content::WebContents, DanglingUntriaged> web_contents_;
   std::unique_ptr<content::WebContentsDestroyedWatcher> destroyed_watcher_;
 };
@@ -501,28 +499,6 @@
   // is removed, this test should work the same as IsFileHandlerOnChromeOS.
   EXPECT_EQ(0u, tasks.size());
 }
-
-class WebAppFileHandlingDisabledTest : public WebAppFileHandlingBrowserTest {
- public:
-  WebAppFileHandlingDisabledTest() {
-    feature_list_.InitWithFeatures({}, {blink::features::kFileHandlingAPI});
-  }
-
- private:
-  base::test::ScopedFeatureList feature_list_;
-};
-
-// Check that the web app is not returned as a file handler task when
-// the flag kFileHandlingAPI is disabled.
-IN_PROC_BROWSER_TEST_F(WebAppFileHandlingDisabledTest,
-                       NoFileHandlerOnChromeOS) {
-  InstallFileHandlingPWA();
-
-  base::FilePath test_file_path = CreateTestFileWithExtension("txt");
-  std::vector<file_manager::file_tasks::FullTaskDescriptor> tasks =
-      file_manager::test::GetTasksForFile(profile(), test_file_path);
-  EXPECT_EQ(0u, tasks.size());
-}
 #endif
 
 class WebAppFileHandlingIconBrowserTest
@@ -530,9 +506,7 @@
       public testing::WithParamInterface<bool> {
  public:
   WebAppFileHandlingIconBrowserTest() {
-    feature_list_.InitWithFeatures({blink::features::kFileHandlingAPI,
-                                    blink::features::kFileHandlingIcons},
-                                   {});
+    feature_list_.InitWithFeatures({blink::features::kFileHandlingIcons}, {});
     WebAppFileHandlerManager::SetIconsSupportedByOsForTesting(GetParam());
   }
   ~WebAppFileHandlingIconBrowserTest() override = default;
diff --git a/chrome/browser/ui/web_applications/web_app_launch_handler_browsertest.cc b/chrome/browser/ui/web_applications/web_app_launch_handler_browsertest.cc
index b56dbe3d..d8c9bb2 100644
--- a/chrome/browser/ui/web_applications/web_app_launch_handler_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_launch_handler_browsertest.cc
@@ -464,9 +464,8 @@
 class WebAppLaunchHandlerDisabledBrowserTest : public InProcessBrowserTest {
  public:
   WebAppLaunchHandlerDisabledBrowserTest() {
-    feature_list_.InitWithFeatures({},
-                                   {blink::features::kWebAppEnableLaunchHandler,
-                                    blink::features::kFileHandlingAPI});
+    feature_list_.InitWithFeatures(
+        {}, {blink::features::kWebAppEnableLaunchHandler});
   }
   ~WebAppLaunchHandlerDisabledBrowserTest() override = default;
 
@@ -485,7 +484,8 @@
   OsIntegrationManager::ScopedSuppressForTesting os_hooks_suppress_;
 };
 
-IN_PROC_BROWSER_TEST_F(WebAppLaunchHandlerDisabledBrowserTest, NoLaunchQueue) {
+IN_PROC_BROWSER_TEST_F(WebAppLaunchHandlerDisabledBrowserTest,
+                       LaunchQueueNoLaunchHandlers) {
   base::HistogramTester histogram_tester;
   AppId app_id = InstallWebAppFromPage(
       browser(), embedded_test_server()->GetURL("/web_apps/basic.html"));
@@ -494,9 +494,9 @@
   content::WebContents* web_contents =
       app_browser->tab_strip_model()->GetActiveWebContents();
 
-  EXPECT_FALSE(EvalJs(web_contents, "!!window.LaunchQueue").ExtractBool());
-  EXPECT_FALSE(EvalJs(web_contents, "!!window.launchQueue").ExtractBool());
-  EXPECT_FALSE(EvalJs(web_contents, "!!window.LaunchParams").ExtractBool());
+  EXPECT_TRUE(EvalJs(web_contents, "!!window.LaunchQueue").ExtractBool());
+  EXPECT_TRUE(EvalJs(web_contents, "!!window.launchQueue").ExtractBool());
+  EXPECT_TRUE(EvalJs(web_contents, "!!window.LaunchParams").ExtractBool());
 
   histogram_tester.ExpectTotalCount(kLaunchHandlerHistogram, 0);
 }
diff --git a/chrome/browser/ui/web_applications/web_app_ui_utils.cc b/chrome/browser/ui/web_applications/web_app_ui_utils.cc
index 950b783..0a93a8b 100644
--- a/chrome/browser/ui/web_applications/web_app_ui_utils.cc
+++ b/chrome/browser/ui/web_applications/web_app_ui_utils.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/ui/web_applications/web_app_ui_utils.h"
 
-#include "base/feature_list.h"
 #include "build/chromeos_buildflags.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
@@ -15,10 +14,8 @@
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/browser/web_applications/web_app_tab_helper.h"
 #include "chrome/browser/web_applications/web_app_utils.h"
-#include "chrome/common/chrome_features.h"
 #include "chrome/grit/generated_resources.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/blink/public/common/features.h"
 
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
 #include "chromeos/crosapi/mojom/app_service.mojom.h"
@@ -31,18 +28,10 @@
 
 absl::optional<AppId> GetAppIdForManagementLinkInWebContents(
     content::WebContents* web_contents) {
-  bool show_app_link_in_tabbed_browser =
-      base::FeatureList::IsEnabled(blink::features::kFileHandlingAPI);
-
   Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
   if (!browser)
     return absl::nullopt;
 
-  if (!web_app::AppBrowserController::IsWebApp(browser) &&
-      !show_app_link_in_tabbed_browser) {
-    return absl::nullopt;
-  }
-
   const web_app::AppId* app_id =
       web_app::WebAppTabHelper::GetAppId(web_contents);
   if (!app_id)
diff --git a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_notification_manager.cc b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_notification_manager.cc
index 165d017f..01dd27c 100644
--- a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_notification_manager.cc
+++ b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_notification_manager.cc
@@ -5,6 +5,8 @@
 #include "chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_notification_manager.h"
 
 #include "ash/public/cpp/notification_utils.h"
+#include "base/check.h"
+#include "base/functional/callback_helpers.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
@@ -17,12 +19,12 @@
 namespace ash::cloud_upload {
 namespace {
 
-// Minimum amount of time, in seconds, for which the notification should be
+// The minimum amount of time for which the "in progress" state should be
 // displayed.
-const base::TimeDelta kMinNotificationTime = base::Seconds(5);
+const base::TimeDelta kMinInProgressTime = base::Seconds(5);
 
-// Time, in seconds, for which the "Complete" notification should display.
-const base::TimeDelta kCompleteNotificationTimeout = base::Seconds(2);
+// Time for which the "Complete" notification should display.
+const base::TimeDelta kCompleteNotificationTime = base::Seconds(5);
 
 // If no other class instance holds a reference to the notification manager, the
 // notification manager goes out of scope.
@@ -65,9 +67,10 @@
 
 std::unique_ptr<message_center::Notification>
 CloudUploadNotificationManager::CreateUploadProgressNotification() {
-  std::string title = "Moving \"" + file_name_ + "\"";
-  std::string message = "Moving to " + cloud_provider_name_ +
-                        ". Your file will open automatically when completed.";
+  std::string title =
+      "Moving \"" + file_name_ + "\" to " + cloud_provider_name_;
+  std::string message =
+      "Your file will open in " + target_app_name_ + " when completed.";
 
   return ash::CreateSystemNotificationPtr(
       /*type=*/message_center::NOTIFICATION_TYPE_PROGRESS,
@@ -87,9 +90,8 @@
 std::unique_ptr<message_center::Notification>
 CloudUploadNotificationManager::CreateUploadCompleteNotification() {
   std::string title = "Move completed";
-  std::string message =
-      "1 item moved to \"from Chromebook\" folder. Opening in " +
-      target_app_name_;
+  std::string message = "1 item moved to " + cloud_provider_name_ +
+                        ". Opening in " + target_app_name_;
   return ash::CreateSystemNotificationPtr(
       /*type=*/message_center::NOTIFICATION_TYPE_SIMPLE,
       /*id=*/notification_id_, base::UTF8ToUTF16(title),
@@ -137,19 +139,19 @@
                                            *notification,
                                            /*metadata=*/nullptr);
 
-  // Start the "min time" notification timer when the first progress
-  // notification is shown.
-  if (!first_notification_shown) {
-    first_notification_shown = true;
-    notification_timer_.Start(
-        FROM_HERE, kMinNotificationTime,
+  // Make sure we display the "in progress" state for a minimum amount of time.
+  if (state_ == State::kUninitialized) {
+    state_ = State::kInProgress;
+    in_progress_timer_.Start(
+        FROM_HERE, kMinInProgressTime,
         base::BindOnce(
-            &CloudUploadNotificationManager::OnMinNotificationTimeReached,
+            &CloudUploadNotificationManager::OnMinInProgressTimeReached,
             weak_ptr_factory_.GetWeakPtr()));
   }
 }
 
-void CloudUploadNotificationManager::ShowUploadComplete() {
+void CloudUploadNotificationManager::ShowCompleteNotification() {
+  DCHECK_EQ(state_, State::kComplete);
   std::unique_ptr<message_center::Notification> notification =
       CreateUploadCompleteNotification();
   notification->set_never_timeout(true);
@@ -157,26 +159,28 @@
                                            *notification,
                                            /*metadata=*/nullptr);
 
-  // If the complete notification is shown before any progress notifications,
-  // start the `kMinNotificationTime` timer.
-  if (!first_notification_shown) {
-    first_notification_shown = true;
-    notification_timer_.Start(
-        FROM_HERE, kMinNotificationTime,
-        base::BindOnce(
-            &CloudUploadNotificationManager::OnMinNotificationTimeReached,
-            weak_ptr_factory_.GetWeakPtr()));
-  }
-
   // Start the timer to automatically dismiss the "Complete" notification.
   complete_notification_timer_.Start(
-      FROM_HERE, kCompleteNotificationTimeout,
-      base::BindOnce(
-          &CloudUploadNotificationManager::OnCompleteNotificationTimeout,
-          weak_ptr_factory_.GetWeakPtr()));
+      FROM_HERE, kCompleteNotificationTime,
+      base::BindOnce(&CloudUploadNotificationManager::CloseNotification,
+                     weak_ptr_factory_.GetWeakPtr()));
 }
 
-void CloudUploadNotificationManager::ShowUploadError(std::string message) {
+void CloudUploadNotificationManager::MarkUploadComplete() {
+  // Check if the "in progress" timeout has happened yet or not.
+  if (state_ == State::kInProgress) {
+    state_ = State::kWaitingForInProgressTimeout;
+  } else if (state_ == State::kUninitialized ||
+             state_ == State::kInProgressTimedOut) {
+    // If the complete notification is shown before any progress notifications,
+    // we don't run the kMinInProgressTime timeout.
+    state_ = State::kComplete;
+    ShowCompleteNotification();
+  }
+}
+
+void CloudUploadNotificationManager::ShowUploadError(
+    const std::string& message) {
   std::unique_ptr<message_center::Notification> notification =
       CreateUploadErrorNotification(message);
   notification->set_never_timeout(true);
@@ -185,32 +189,27 @@
                                            /*metadata=*/nullptr);
 }
 
-void CloudUploadNotificationManager::OnMinNotificationTimeReached() {
-  // Close the notification only if the "Complete notification" has timed out.
-  // Error notifications can only be dismissed by users.
-  if (completed_) {
-    CloseNotification();
-  }
-}
-
-void CloudUploadNotificationManager::OnCompleteNotificationTimeout() {
-  completed_ = true;
-
-  // If `kMinNotificationTime` hasn't been reached yet, do not close the
-  // notification.
-  if (!notification_timer_.IsRunning()) {
-    CloseNotification();
+void CloudUploadNotificationManager::OnMinInProgressTimeReached() {
+  if (state_ == State::kInProgress) {
+    state_ = State::kInProgressTimedOut;
+  } else if (state_ == State::kWaitingForInProgressTimeout) {
+    state_ = State::kComplete;
+    ShowCompleteNotification();
   }
 }
 
 void CloudUploadNotificationManager::CloseNotification() {
   GetNotificationDisplayService()->Close(NotificationHandler::Type::TRANSIENT,
                                          notification_id_);
-  notification_timer_.Stop();
+  in_progress_timer_.Stop();
   complete_notification_timer_.Stop();
   if (callback_) {
     std::move(callback_).Run();
   }
 }
 
+void CloudUploadNotificationManager::CloseForTest() {
+  CloseNotification();
+}
+
 }  // namespace ash::cloud_upload
diff --git a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_notification_manager.h b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_notification_manager.h
index 8c4ab919..9190cd0 100644
--- a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_notification_manager.h
+++ b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_notification_manager.h
@@ -5,7 +5,6 @@
 #ifndef CHROME_BROWSER_UI_WEBUI_ASH_CLOUD_UPLOAD_CLOUD_UPLOAD_NOTIFICATION_MANAGER_H_
 #define CHROME_BROWSER_UI_WEBUI_ASH_CLOUD_UPLOAD_CLOUD_UPLOAD_NOTIFICATION_MANAGER_H_
 
-#include "base/files/file_path.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/timer/timer.h"
@@ -17,7 +16,10 @@
 
 namespace ash::cloud_upload {
 
-// Manages creation/deletion and update of cloud upload system notifications.
+// Creates, updates and deletes cloud upload system notifications. Ensures that
+// notifications stay in the "in progress" state for a minimum of 5 seconds, and
+// a minimum of 5 seconds for the 'complete' state. For the error state,
+// notifications stay open until the user closes them.
 class CloudUploadNotificationManager
     : public base::RefCounted<CloudUploadNotificationManager> {
  public:
@@ -26,14 +28,25 @@
                                  const std::string& cloud_provider_name,
                                  const std::string& target_app_name);
 
-  // Shows the upload progress notification. |progress| within the 0-100 range.
+  // Creates the notification with "in progress" state if it doesn't exist, or
+  // updates the progress bar if it does. |progress| is within the 0-100 range.
+  // The notification will stay in the "in progress" state for a minimum of 5
+  // seconds, even at 100% progress.
   void ShowUploadProgress(int progress);
 
-  // Shows the upload complete notification for 2s if the upload was successful.
-  void ShowUploadComplete();
+  // Shows the upload complete notification for 5 seconds, but only once the
+  // minimum 5 seconds from the "in progress" state has finished.
+  void MarkUploadComplete();
 
-  // Shows the upload error notification.
-  void ShowUploadError(std::string message);
+  // Shows the error state for the notification indefinitely, until closed by
+  // the user. Does not wait for the progress notification to show for a minimum
+  // time.
+  void ShowUploadError(const std::string& message);
+
+  // This class owns a reference to itself that is only deleted once the
+  // notification life cycle has completed. Tests can use this method to avoid
+  // leaking instances of this class.
+  void CloseForTest();
 
  private:
   friend base::RefCounted<CloudUploadNotificationManager>;
@@ -54,17 +67,29 @@
   std::unique_ptr<message_center::Notification> CreateUploadErrorNotification(
       std::string message);
 
-  // Called when the minimum amount of time to display the notification is
-  // reached.
-  void OnMinNotificationTimeReached();
+  // Called when the minimum amount of time to display the "in progress"
+  // notification is reached.
+  void OnMinInProgressTimeReached();
 
-  // Called when the "Complete" notification times out.
-  void OnCompleteNotificationTimeout();
+  // Updates the notification immediately to show the complete state.
+  void ShowCompleteNotification();
 
   // Called when the upload flow is complete: Ensures that notifications are
   // closed, timers are interrupted and the completion callback has been called.
   void CloseNotification();
 
+  // A state machine and the possible transitions. The state of showing the
+  // error notification is not explicit because it is never used to determine
+  // later logic.
+  enum class State {
+    kUninitialized,  // --> kInProgress, kComplete
+    kInProgress,     // --> kInProgressTimedOut, kWaitingForInProgressTimeout,
+                     // (error)
+    kInProgressTimedOut,           // --> kComplete, (error)
+    kWaitingForInProgressTimeout,  // --> kComplete
+    kComplete
+  };
+
   // Counts the total number of notification manager instances. This counter is
   // never decremented.
   static inline int notification_manager_counter_ = 0;
@@ -76,10 +101,9 @@
   std::string notification_id_;
   std::string target_app_name_;
   base::OnceClosure callback_;
-  base::OneShotTimer notification_timer_;
+  base::OneShotTimer in_progress_timer_;
   base::OneShotTimer complete_notification_timer_;
-  bool first_notification_shown = false;
-  bool completed_ = false;
+  State state_ = State::kUninitialized;
   base::WeakPtrFactory<CloudUploadNotificationManager> weak_ptr_factory_{this};
 };
 
diff --git a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_notification_manager_unittest.cc b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_notification_manager_unittest.cc
new file mode 100644
index 0000000..4e21bce
--- /dev/null
+++ b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_notification_manager_unittest.cc
@@ -0,0 +1,168 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_notification_manager.h"
+
+#include "base/time/time.h"
+#include "chrome/browser/notifications/notification_display_service_factory.h"
+#include "chrome/browser/notifications/stub_notification_display_service.h"
+#include "chrome/test/base/testing_profile.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace ash::cloud_upload {
+
+class CloudUploadNotificationManagerTest : public testing::Test {
+ public:
+  CloudUploadNotificationManagerTest() = default;
+
+  CloudUploadNotificationManagerTest(
+      const CloudUploadNotificationManagerTest&) = delete;
+  CloudUploadNotificationManagerTest& operator=(
+      const CloudUploadNotificationManagerTest&) = delete;
+
+  // testing::Test:
+  void SetUp() override {
+    profile_ = std::make_unique<TestingProfile>();
+
+    display_service_ = static_cast<StubNotificationDisplayService*>(
+        NotificationDisplayServiceFactory::GetInstance()
+            ->SetTestingFactoryAndUse(
+                profile_.get(),
+                base::BindRepeating(
+                    &StubNotificationDisplayService::FactoryForTests)));
+  }
+
+ protected:
+  Profile* profile() { return profile_.get(); }
+
+  absl::optional<message_center::Notification> notification() {
+    auto notifications = display_service_->GetDisplayedNotificationsForType(
+        NotificationHandler::Type::TRANSIENT);
+    if (notifications.size()) {
+      return notifications[0];
+    }
+    return absl::nullopt;
+  }
+
+  bool HaveProgressNotification() {
+    return notification().has_value() &&
+           notification()->type() ==
+               message_center::NotificationType::NOTIFICATION_TYPE_PROGRESS;
+  }
+
+  bool HaveCompleteNotification() {
+    return notification().has_value() &&
+           notification()->type() ==
+               message_center::NotificationType::NOTIFICATION_TYPE_SIMPLE &&
+           notification()->title().starts_with(u"Move completed");
+  }
+
+  bool HaveErrorNotification() {
+    return notification().has_value() &&
+           notification()->type() ==
+               message_center::NotificationType::NOTIFICATION_TYPE_SIMPLE &&
+           notification()->title().starts_with(u"Failed");
+  }
+
+  content::BrowserTaskEnvironment task_environment_{
+      base::test::TaskEnvironment::TimeSource::MOCK_TIME};
+  std::unique_ptr<TestingProfile> profile_;
+  StubNotificationDisplayService* display_service_;
+};
+
+TEST_F(CloudUploadNotificationManagerTest,
+       ShowUploadProgressCreatesNotification) {
+  scoped_refptr<CloudUploadNotificationManager> manager =
+      base::MakeRefCounted<CloudUploadNotificationManager>(
+          profile(), "foo.docx", "Google Drive", "Google Docs");
+
+  ASSERT_EQ(absl::nullopt, notification());
+  manager->ShowUploadProgress(1);
+  ASSERT_TRUE(HaveProgressNotification());
+
+  manager->CloseForTest();
+}
+
+TEST_F(CloudUploadNotificationManagerTest, MinimumTiming) {
+  scoped_refptr<CloudUploadNotificationManager> manager =
+      base::MakeRefCounted<CloudUploadNotificationManager>(
+          profile(), "foo.docx", "Google Drive", "Google Docs");
+
+  manager->ShowUploadProgress(1);
+  manager->ShowUploadProgress(100);
+  manager->MarkUploadComplete();
+  ASSERT_TRUE(HaveProgressNotification());
+
+  // The progress notification should still be showing.
+  task_environment_.FastForwardBy(base::Milliseconds(4900));
+  ASSERT_TRUE(HaveProgressNotification());
+
+  // Now we see the Complete nofication after 5s.
+  task_environment_.FastForwardBy(base::Milliseconds(500));
+  ASSERT_TRUE(HaveCompleteNotification());
+
+  // Now we're at 9900 ms total - we still expect the Complete notification.
+  task_environment_.FastForwardBy(base::Milliseconds(4500));
+  ASSERT_TRUE(HaveCompleteNotification());
+
+  // After > 10s total, the notification should be closed.
+  task_environment_.FastForwardBy(base::Milliseconds(500));
+  ASSERT_EQ(absl::nullopt, notification());
+}
+
+TEST_F(CloudUploadNotificationManagerTest, CompleteWithoutProgress) {
+  scoped_refptr<CloudUploadNotificationManager> manager =
+      base::MakeRefCounted<CloudUploadNotificationManager>(
+          profile(), "foo.docx", "Google Drive", "Google Docs");
+
+  manager->MarkUploadComplete();
+  ASSERT_TRUE(HaveCompleteNotification());
+
+  // The complete notification should still be showing.
+  task_environment_.FastForwardBy(base::Milliseconds(4900));
+  ASSERT_TRUE(HaveCompleteNotification());
+
+  // After > 5s total, the notification should be closed.
+  task_environment_.FastForwardBy(base::Milliseconds(500));
+  ASSERT_EQ(absl::nullopt, notification());
+}
+
+TEST_F(CloudUploadNotificationManagerTest, ErrorStaysOpen) {
+  scoped_refptr<CloudUploadNotificationManager> manager =
+      base::MakeRefCounted<CloudUploadNotificationManager>(
+          profile(), "foo.docx", "Google Drive", "Google Docs");
+
+  manager->ShowUploadProgress(1);
+  manager->ShowUploadProgress(100);
+  manager->ShowUploadError("error");
+  // The error is shown straight away.
+  ASSERT_TRUE(HaveErrorNotification());
+
+  // The error notification should still be showing.
+  task_environment_.FastForwardBy(base::Seconds(60));
+  ASSERT_TRUE(HaveErrorNotification());
+
+  manager->CloseForTest();
+}
+
+TEST_F(CloudUploadNotificationManagerTest, ManagerLifetime) {
+  {
+    scoped_refptr<CloudUploadNotificationManager> manager =
+        base::MakeRefCounted<CloudUploadNotificationManager>(
+            profile(), "foo.docx", "Google Drive", "Google Docs");
+
+    manager->ShowUploadProgress(1);
+    manager->ShowUploadError("error");
+    ASSERT_TRUE(HaveErrorNotification());
+  }
+  // We still have a ref to manager until the notification is dismissed.
+  ASSERT_TRUE(HaveErrorNotification());
+
+  notification()->delegate()->Click(absl::nullopt, absl::nullopt);
+  ASSERT_EQ(absl::nullopt, notification());
+}
+
+}  // namespace ash::cloud_upload
diff --git a/chrome/browser/ui/webui/ash/cloud_upload/drive_upload_handler.cc b/chrome/browser/ui/webui/ash/cloud_upload/drive_upload_handler.cc
index 1957cec..dccbf26 100644
--- a/chrome/browser/ui/webui/ash/cloud_upload/drive_upload_handler.cc
+++ b/chrome/browser/ui/webui/ash/cloud_upload/drive_upload_handler.cc
@@ -164,7 +164,7 @@
   // Resolve notifications.
   if (notification_manager_) {
     if (hosted_url.is_valid()) {
-      notification_manager_->ShowUploadComplete();
+      notification_manager_->MarkUploadComplete();
     } else if (!error_message.empty()) {
       LOG(ERROR) << "Cloud upload: " << error_message;
       notification_manager_->ShowUploadError(error_message);
diff --git a/chrome/browser/ui/webui/ash/cloud_upload/one_drive_upload_handler.cc b/chrome/browser/ui/webui/ash/cloud_upload/one_drive_upload_handler.cc
index 24ca79b..b27e1a9d 100644
--- a/chrome/browser/ui/webui/ash/cloud_upload/one_drive_upload_handler.cc
+++ b/chrome/browser/ui/webui/ash/cloud_upload/one_drive_upload_handler.cc
@@ -131,7 +131,7 @@
   // Resolve notifications.
   if (notification_manager_) {
     if (uploaded_file_url.is_valid()) {
-      notification_manager_->ShowUploadComplete();
+      notification_manager_->MarkUploadComplete();
     } else if (!error_message.empty()) {
       LOG(ERROR) << "Upload to OneDrive: " << error_message;
       notification_manager_->ShowUploadError(error_message);
diff --git a/chrome/browser/ui/webui/settings/ash/accessibility_section.cc b/chrome/browser/ui/webui/settings/ash/accessibility_section.cc
index 74dac4a..5897e82 100644
--- a/chrome/browser/ui/webui/settings/ash/accessibility_section.cc
+++ b/chrome/browser/ui/webui/settings/ash/accessibility_section.cc
@@ -686,6 +686,8 @@
       {"onScreenKeyboardLabel", IDS_SETTINGS_ON_SCREEN_KEYBOARD_LABEL},
       {"optionsInMenuDescription", IDS_SETTINGS_OPTIONS_IN_MENU_DESCRIPTION},
       {"optionsInMenuLabel", IDS_SETTINGS_OPTIONS_IN_MENU_LABEL},
+      {"pdfOcrSubtitle", IDS_SETTINGS_PDF_OCR_SUBTITLE},
+      {"pdfOcrTitle", IDS_SETTINGS_PDF_OCR_TITLE},
       {"percentage", IDS_SETTINGS_PERCENTAGE},
       {"saturationLabel", IDS_SETTINGS_SATURATION_LABEL},
       {"screenMagnifierDescriptionOff",
@@ -972,6 +974,9 @@
       "areExperimentalAccessibilityColorEnhancementSettingsEnabled",
       AreExperimentalAccessibilityColorEnhancementSettingsEnabled());
 
+  html_source->AddBoolean("pdfOcrEnabled",
+                          base::FeatureList::IsEnabled(::features::kPdfOcr));
+
   ::settings::AddCaptionSubpageStrings(html_source);
 }
 
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
index 30349d4..a4aba00 100644
--- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -91,6 +91,7 @@
 #include "net/net_buildflags.h"
 #include "services/device/public/cpp/device_features.h"
 #include "third_party/blink/public/common/features_generated.h"
+#include "ui/accessibility/accessibility_features.h"
 #include "ui/accessibility/accessibility_switches.h"
 #include "ui/base/accelerators/accelerator.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -115,7 +116,6 @@
 #include "ui/chromeos/devicetype_utils.h"
 #else  // !BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/ui/webui/settings/system_handler.h"
-#include "ui/accessibility/accessibility_features.h"
 #endif
 
 #if BUILDFLAG(IS_CHROMEOS)
@@ -247,6 +247,8 @@
     {"accessibleImageLabelsTitle", IDS_SETTINGS_ACCESSIBLE_IMAGE_LABELS_TITLE},
     {"accessibleImageLabelsSubtitle",
      IDS_SETTINGS_ACCESSIBLE_IMAGE_LABELS_SUBTITLE},
+    {"pdfOcrTitle", IDS_SETTINGS_PDF_OCR_TITLE},
+    {"pdfOcrSubtitle", IDS_SETTINGS_PDF_OCR_SUBTITLE},
     {"settingsSliderRoleDescription",
      IDS_SETTINGS_SLIDER_MIN_MAX_ARIA_ROLE_DESCRIPTION},
     {"caretBrowsingTitle", IDS_SETTINGS_ENABLE_CARET_BROWSING_TITLE},
@@ -270,6 +272,8 @@
       "showFocusHighlightOption",
       base::FeatureList::IsEnabled(features::kAccessibilityFocusHighlight));
 #endif
+  html_source->AddBoolean("pdfOcrEnabled",
+                          base::FeatureList::IsEnabled(features::kPdfOcr));
 
   AddCaptionSubpageStrings(html_source);
 }
diff --git a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.cc b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.cc
index 2015205..2088dec 100644
--- a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.cc
+++ b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.cc
@@ -21,8 +21,8 @@
 #include "chrome/browser/ui/webui/webui_util.h"
 #include "chrome/common/webui_url_constants.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/side_panel_resources.h"
-#include "chrome/grit/side_panel_resources_map.h"
+#include "chrome/grit/side_panel_bookmarks_resources.h"
+#include "chrome/grit/side_panel_bookmarks_resources_map.h"
 #include "components/bookmarks/browser/bookmark_model.h"
 #include "components/bookmarks/common/bookmark_pref_names.h"
 #include "components/commerce/core/shopping_service.h"
@@ -49,7 +49,6 @@
       {"bookmarkCreated", IDS_BOOKMARK_SCREEN_READER_CREATED},
       {"bookmarkReordered", IDS_BOOKMARK_SCREEN_READER_REORDERED},
       {"bookmarkMoved", IDS_BOOKMARK_SCREEN_READER_MOVED},
-      {"sidePanelTitle", IDS_SIDE_PANEL_TITLE},
       {"tooltipClose", IDS_CLOSE},
       {"tooltipDelete", IDS_DELETE},
       {"tooltipMore", IDS_BOOKMARKS_EDIT_MORE},
@@ -102,8 +101,6 @@
       "bookmarksDragAndDropEnabled",
       prefs->GetBoolean(bookmarks::prefs::kEditBookmarksEnabled));
 
-  source->AddBoolean("unifiedSidePanel", true);
-
   source->AddBoolean("guestMode", profile->IsGuestSession());
   source->AddBoolean("incognitoMode", profile->IsIncognitoProfile());
 
@@ -125,9 +122,10 @@
       base::FeatureList::IsEnabled(features::kPowerBookmarksSidePanel)
           ? IDR_SIDE_PANEL_BOOKMARKS_POWER_BOOKMARKS_HTML
           : IDR_SIDE_PANEL_BOOKMARKS_BOOKMARKS_HTML;
-  webui::SetupWebUIDataSource(
-      source, base::make_span(kSidePanelResources, kSidePanelResourcesSize),
-      resource);
+  webui::SetupWebUIDataSource(source,
+                              base::make_span(kSidePanelBookmarksResources,
+                                              kSidePanelBookmarksResourcesSize),
+                              resource);
 
   // Add a handler to provide pluralized strings.
   auto plural_string_handler = std::make_unique<PluralStringHandler>();
diff --git a/chrome/browser/ui/webui/side_panel/reading_list/reading_list_ui.cc b/chrome/browser/ui/webui/side_panel/reading_list/reading_list_ui.cc
index 3e44122b..106345f0 100644
--- a/chrome/browser/ui/webui/side_panel/reading_list/reading_list_ui.cc
+++ b/chrome/browser/ui/webui/side_panel/reading_list/reading_list_ui.cc
@@ -51,7 +51,6 @@
       profile, chrome::kChromeUIReadLaterHost);
   static constexpr webui::LocalizedString kLocalizedStrings[] = {
       {"addCurrentTab", IDS_READ_LATER_ADD_CURRENT_TAB},
-      {"bookmarksTabTitle", IDS_BOOKMARK_MANAGER_TITLE},
       {"bookmarkCopied", IDS_BOOKMARK_MANAGER_TOAST_ITEM_COPIED},
       {"bookmarkDeleted", IDS_BOOKMARK_MANAGER_TOAST_ITEM_DELETED},
       {"bookmarkCreated", IDS_BOOKMARK_SCREEN_READER_CREATED},
@@ -65,8 +64,6 @@
       {"readAnythingTabTitle", IDS_READ_ANYTHING_TITLE},
       {"readHeader", IDS_READ_LATER_MENU_READ_HEADER},
       {"title", IDS_READ_LATER_TITLE},
-      {"sidePanelTitle", IDS_SIDE_PANEL_TITLE},
-      {"tooltipClose", IDS_CLOSE},
       {"tooltipDelete", IDS_DELETE},
       {"tooltipMore", IDS_BOOKMARKS_EDIT_MORE},
       {"tooltipMarkAsRead", IDS_READ_LATER_MENU_TOOLTIP_MARK_AS_READ},
@@ -138,7 +135,6 @@
       reading_list_model->loaded() ? reading_list_model->unseen_size() : false);
 
   source->AddBoolean("readAnythingEnabled", features::IsReadAnythingEnabled());
-  source->AddBoolean("unifiedSidePanel", true);
 
   source->AddBoolean("guestMode", profile->IsGuestSession());
   source->AddBoolean("incognitoMode", profile->IsIncognitoProfile());
diff --git a/chrome/browser/ui/webui/side_panel/user_notes/user_notes_page_handler.cc b/chrome/browser/ui/webui/side_panel/user_notes/user_notes_page_handler.cc
index 5cdb678da..293b905 100644
--- a/chrome/browser/ui/webui/side_panel/user_notes/user_notes_page_handler.cc
+++ b/chrome/browser/ui/webui/side_panel/user_notes/user_notes_page_handler.cc
@@ -9,8 +9,9 @@
 #include "chrome/browser/power_bookmarks/power_bookmark_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/webui/side_panel/user_notes/user_notes_side_panel_ui.h"
-#include "components/power_bookmarks/core/powers/power.h"
-#include "components/power_bookmarks/core/powers/power_overview.h"
+#include "components/power_bookmarks/common/power.h"
+#include "components/power_bookmarks/common/power_overview.h"
+#include "components/power_bookmarks/core/power_bookmark_service.h"
 #include "components/sync/protocol/power_bookmark_specifics.pb.h"
 #include "ui/base/l10n/time_format.h"
 
diff --git a/chrome/browser/web_applications/app_service/lacros_web_apps_controller_browsertest.cc b/chrome/browser/web_applications/app_service/lacros_web_apps_controller_browsertest.cc
index 9e83a994..4905fb19 100644
--- a/chrome/browser/web_applications/app_service/lacros_web_apps_controller_browsertest.cc
+++ b/chrome/browser/web_applications/app_service/lacros_web_apps_controller_browsertest.cc
@@ -20,7 +20,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/single_thread_task_runner.h"
 #include "base/test/bind.h"
-#include "base/test/scoped_feature_list.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/values.h"
 #include "chrome/browser/apps/app_service/app_icon/app_icon_factory.h"
@@ -72,7 +71,6 @@
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "testing/gmock/include/gmock/gmock-matchers.h"
 #include "third_party/abseil-cpp/absl/types/variant.h"
-#include "third_party/blink/public/common/features.h"
 #include "ui/display/types/display_constants.h"
 #include "ui/message_center/public/cpp/notification.h"
 #include "ui/message_center/public/cpp/notification_types.h"
@@ -186,10 +184,6 @@
  public:
   LacrosWebAppsControllerBrowserTest() = default;
   ~LacrosWebAppsControllerBrowserTest() override = default;
-
- private:
-  base::test::ScopedFeatureList feature_list_{
-      blink::features::kFileHandlingAPI};
 };
 
 IN_PROC_BROWSER_TEST_F(LacrosWebAppsControllerBrowserTest, PublishApps) {
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 bfd9902..216b0957 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
@@ -1960,9 +1960,6 @@
     apps::AppLaunchParams params,
     base::OnceCallback<void(const std::vector<content::WebContents*>&)>
         callback) {
-  DCHECK(
-      provider_->os_integration_manager().IsFileHandlingAPIAvailable(app_id));
-
   std::vector<base::FilePath> file_paths = params.launch_files;
   auto launch_callback =
       base::BindOnce(&WebAppPublisherHelper::OnFileHandlerDialogCompleted,
diff --git a/chrome/browser/web_applications/commands/update_file_handler_command.cc b/chrome/browser/web_applications/commands/update_file_handler_command.cc
index ad50b97..0d112755 100644
--- a/chrome/browser/web_applications/commands/update_file_handler_command.cc
+++ b/chrome/browser/web_applications/commands/update_file_handler_command.cc
@@ -51,29 +51,19 @@
       new UpdateFileHandlerCommand(app_id, allowed, std::move(callback)));
 }
 
-// static
-std::unique_ptr<UpdateFileHandlerCommand>
-UpdateFileHandlerCommand::CreateForUpdate(const AppId& app_id,
-                                          base::OnceClosure callback) {
-  return base::WrapUnique(new UpdateFileHandlerCommand(
-      app_id, /*user_choice_to_remember=*/absl::nullopt, std::move(callback)));
-}
-
-UpdateFileHandlerCommand::UpdateFileHandlerCommand(
-    const AppId& app_id,
-    absl::optional<bool> user_choice_to_remember,
-    base::OnceClosure callback)
+UpdateFileHandlerCommand::UpdateFileHandlerCommand(const AppId& app_id,
+                                                   bool user_choice_to_remember,
+                                                   base::OnceClosure callback)
     : WebAppCommandTemplate<AppLock>("UpdateFileHandlerCommand"),
       lock_description_(
           std::make_unique<AppLockDescription, base::flat_set<AppId>>(
               {app_id})),
       app_id_(app_id),
-      user_choice_to_remember_(std::move(user_choice_to_remember)),
+      user_choice_to_remember_(user_choice_to_remember),
       callback_(std::move(callback)) {
   debug_info_.Set("app_id", app_id_);
-  if (user_choice_to_remember_)
-    debug_info_.Set("user_choice_to_remember",
-                    user_choice_to_remember_.value() ? "allow" : "disallow");
+  debug_info_.Set("user_choice_to_remember",
+                  user_choice_to_remember_ ? "allow" : "disallow");
 }
 
 UpdateFileHandlerCommand::~UpdateFileHandlerCommand() = default;
@@ -88,17 +78,13 @@
     return;
   }
 
-  if (user_choice_to_remember_) {
-    lock_->sync_bridge().SetAppFileHandlerApprovalState(
-        app_id_, user_choice_to_remember_.value()
-                     ? ApiApprovalState::kAllowed
-                     : ApiApprovalState::kDisallowed);
-  }
+  lock_->sync_bridge().SetAppFileHandlerApprovalState(
+      app_id_, user_choice_to_remember_ ? ApiApprovalState::kAllowed
+                                        : ApiApprovalState::kDisallowed);
 
   // File handling could have been disabled via origin trial as well as user
   // choice, so check both here.
   bool file_handling_enabled =
-      lock_->os_integration_manager().IsFileHandlingAPIAvailable(app_id_) &&
       !lock_->registrar().IsAppFileHandlerPermissionBlocked(app_id_);
 
   // This checks whether the current enabled state matches what we expect
diff --git a/chrome/browser/web_applications/commands/update_file_handler_command.h b/chrome/browser/web_applications/commands/update_file_handler_command.h
index 0e7125c..11e2be27 100644
--- a/chrome/browser/web_applications/commands/update_file_handler_command.h
+++ b/chrome/browser/web_applications/commands/update_file_handler_command.h
@@ -10,7 +10,6 @@
 #include "base/functional/callback.h"
 #include "chrome/browser/web_applications/commands/web_app_command.h"
 #include "chrome/browser/web_applications/web_app_id.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace web_app {
 
@@ -20,7 +19,7 @@
 enum class Result;
 
 // UpdateFileHandlerCommand updates file handler registration to match with the
-// app's setting or user choice.
+// user choice.
 class UpdateFileHandlerCommand : public WebAppCommandTemplate<AppLock> {
  public:
   // Updates the File Handling API approval state for the given app. If
@@ -30,19 +29,6 @@
       bool allowed,
       base::OnceClosure callback);
 
-  // Updates the file handler registration with the OS to match the app's
-  // settings. Note that this tries to avoid extra work by no-oping if the
-  // current OS state matches what is calculated to be the desired stated. For
-  // example, if Chromium has already registered file handlers with the OS, and
-  // finds that file handlers *should* be registered with the OS, this function
-  // will no-op. This will not account for what the current file handlers
-  // actually are. The actual set of file handlers can only change on app
-  // update, and that path must go through
-  // `OsIntegrationManager::UpdateOsHooks()`, which always clobbers and renews
-  // the entire set of OS-registered file handlers (and other OS hooks).
-  static std::unique_ptr<UpdateFileHandlerCommand> CreateForUpdate(
-      const AppId& app_id,
-      base::OnceClosure callback);
   ~UpdateFileHandlerCommand() override;
 
   void StartWithLock(std::unique_ptr<AppLock> lock) override;
@@ -56,7 +42,7 @@
 
  private:
   UpdateFileHandlerCommand(const AppId& app_id,
-                           absl::optional<bool> user_choice_to_remember,
+                           bool user_choice_to_remember,
                            base::OnceClosure callback);
   void OnFileHandlerUpdated(bool file_handling_enabled, Result result);
   void ReportResultAndDestroy(CommandResult result);
@@ -65,7 +51,7 @@
   std::unique_ptr<AppLock> lock_;
 
   const AppId app_id_;
-  absl::optional<bool> user_choice_to_remember_;
+  const bool user_choice_to_remember_;
   base::OnceClosure callback_;
 
   base::Value::Dict debug_info_;
diff --git a/chrome/browser/web_applications/commands/update_file_handler_command_unittest.cc b/chrome/browser/web_applications/commands/update_file_handler_command_unittest.cc
index bda0497..7f69e69 100644
--- a/chrome/browser/web_applications/commands/update_file_handler_command_unittest.cc
+++ b/chrome/browser/web_applications/commands/update_file_handler_command_unittest.cc
@@ -15,7 +15,6 @@
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/common/chrome_features.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/features.h"
 #include "url/gurl.h"
 
 namespace web_app {
@@ -31,13 +30,11 @@
   UpdateFileHandlerCommandTest() {
     if (GetParam() == OsIntegrationSubManagersState::kSaveStateToDB) {
       scoped_feature_list_.InitWithFeaturesAndParameters(
-          {{features::kOsIntegrationSubManagers, {{"stage", "write_config"}}},
-           {blink::features::kFileHandlingAPI, {}}},
+          {{features::kOsIntegrationSubManagers, {{"stage", "write_config"}}}},
           /*disabled_features=*/{});
     } else {
       scoped_feature_list_.InitWithFeatures(
-          {blink::features::kFileHandlingAPI},
-          {features::kOsIntegrationSubManagers});
+          {}, {features::kOsIntegrationSubManagers});
     }
   }
 
@@ -65,18 +62,6 @@
 
   WebAppProvider* provider() { return provider_; }
 
-  void EnableFileHandlingAPI() {
-    scoped_feature_list_.Reset();
-    scoped_feature_list_.InitAndEnableFeature(
-        blink::features::kFileHandlingAPI);
-  }
-
-  void DisableFileHandlingAPI() {
-    scoped_feature_list_.Reset();
-    scoped_feature_list_.InitAndDisableFeature(
-        blink::features::kFileHandlingAPI);
-  }
-
  private:
   raw_ptr<FakeWebAppProvider> provider_;
   base::test::ScopedFeatureList scoped_feature_list_;
@@ -122,38 +107,6 @@
           app_id));
 }
 
-TEST_P(UpdateFileHandlerCommandTest, UpdateFileHandler) {
-  const AppId app_id =
-      test::InstallDummyWebApp(profile(), kTestAppName, kTestAppUrl);
-  EXPECT_EQ(
-      provider()->registrar_unsafe().GetAppFileHandlerApprovalState(app_id),
-      ApiApprovalState::kRequiresPrompt);
-
-  DisableFileHandlingAPI();
-
-  base::RunLoop run_loop;
-  provider()->scheduler().UpdateFileHandlerOsIntegration(
-      app_id, run_loop.QuitClosure());
-  run_loop.Run();
-
-  EXPECT_EQ(
-      provider()->registrar_unsafe().GetAppFileHandlerApprovalState(app_id),
-      ApiApprovalState::kRequiresPrompt);
-  EXPECT_FALSE(
-      provider()->registrar_unsafe().ExpectThatFileHandlersAreRegisteredWithOs(
-          app_id));
-
-  EnableFileHandlingAPI();
-
-  base::RunLoop run_loop_2;
-  provider()->scheduler().UpdateFileHandlerOsIntegration(
-      app_id, run_loop_2.QuitClosure());
-  run_loop_2.Run();
-  EXPECT_TRUE(
-      provider()->registrar_unsafe().ExpectThatFileHandlersAreRegisteredWithOs(
-          app_id));
-}
-
 INSTANTIATE_TEST_SUITE_P(
     All,
     UpdateFileHandlerCommandTest,
diff --git a/chrome/browser/web_applications/manifest_update_manager_browsertest.cc b/chrome/browser/web_applications/manifest_update_manager_browsertest.cc
index a0d5d379..0974aff 100644
--- a/chrome/browser/web_applications/manifest_update_manager_browsertest.cc
+++ b/chrome/browser/web_applications/manifest_update_manager_browsertest.cc
@@ -2299,8 +2299,6 @@
   ManifestUpdateManagerBrowserTestWithFileHandling() = default;
 
  private:
-  base::test::ScopedFeatureList feature_list_{
-      blink::features::kFileHandlingAPI};
 };
 
 IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerBrowserTestWithFileHandling,
diff --git a/chrome/browser/web_applications/os_integration/os_integration_manager.cc b/chrome/browser/web_applications/os_integration/os_integration_manager.cc
index 4a926d0..eec305b 100644
--- a/chrome/browser/web_applications/os_integration/os_integration_manager.cc
+++ b/chrome/browser/web_applications/os_integration/os_integration_manager.cc
@@ -424,8 +424,7 @@
 }
 
 bool OsIntegrationManager::IsFileHandlingAPIAvailable(const AppId& app_id) {
-  DCHECK(file_handler_manager_);
-  return file_handler_manager_->IsFileHandlingAPIAvailable(app_id);
+  return true;
 }
 
 const apps::FileHandlers* OsIntegrationManager::GetEnabledFileHandlers(
@@ -791,12 +790,6 @@
     return;
   }
 
-  if (file_handlers_need_os_update == FileHandlerUpdateAction::kUpdate &&
-      !IsFileHandlingAPIAvailable(app_id)) {
-    std::move(finished_callback).Run(Result::kOk);
-    return;
-  }
-
   ResultCallback callback_after_removal;
   if (file_handlers_need_os_update == FileHandlerUpdateAction::kUpdate) {
     callback_after_removal = base::BindOnce(
diff --git a/chrome/browser/web_applications/os_integration/web_app_file_handler_manager.cc b/chrome/browser/web_applications/os_integration/web_app_file_handler_manager.cc
index 854cd4f..0b8bd3d 100644
--- a/chrome/browser/web_applications/os_integration/web_app_file_handler_manager.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_file_handler_manager.cc
@@ -76,11 +76,6 @@
 void WebAppFileHandlerManager::EnableAndRegisterOsFileHandlers(
     const AppId& app_id,
     ResultCallback callback) {
-  if (!IsFileHandlingAPIAvailable(app_id)) {
-    std::move(callback).Run(Result::kOk);
-    return;
-  }
-
   SetOsIntegrationState(app_id, OsIntegrationState::kEnabled);
 
   if (GetOsIntegrationCallback()) {
@@ -136,7 +131,6 @@
 const apps::FileHandlers* WebAppFileHandlerManager::GetEnabledFileHandlers(
     const AppId& app_id) const {
   if (ShouldOsIntegrationBeEnabled(app_id) &&
-      IsFileHandlingAPIAvailable(app_id) &&
       !GetRegistrar()->IsAppFileHandlerPermissionBlocked(app_id)) {
     return GetAllFileHandlers(app_id);
   }
@@ -144,20 +138,6 @@
   return nullptr;
 }
 
-bool WebAppFileHandlerManager::IsFileHandlingAPIAvailable(
-    const AppId& app_id) const {
-  if (base::FeatureList::IsEnabled(blink::features::kFileHandlingAPI))
-    return true;
-
-  // May be null in unit tests.
-  if (GetRegistrar()) {
-    const WebApp* web_app = GetRegistrar()->GetAppById(app_id);
-    return web_app && web_app->IsSystemApp();
-  }
-
-  return false;
-}
-
 // static
 bool WebAppFileHandlerManager::IconsEnabled() {
   return g_icons_supported_by_os_override.value_or(
@@ -165,10 +145,6 @@
          base::FeatureList::IsEnabled(blink::features::kFileHandlingIcons);
 }
 
-void WebAppFileHandlerManager::SyncOsIntegrationStateForTesting() {
-  SyncOsIntegrationState();
-}
-
 const apps::FileHandlers* WebAppFileHandlerManager::GetAllFileHandlers(
     const AppId& app_id) const {
   const WebApp* web_app = GetRegistrar()->GetAppById(app_id);
@@ -182,7 +158,7 @@
     const AppId& app_id,
     const std::vector<base::FilePath>& launch_files) {
   LaunchInfos launch_infos;
-  if (!IsFileHandlingAPIAvailable(app_id) || launch_files.empty() ||
+  if (launch_files.empty() ||
       GetRegistrar()->IsAppFileHandlerPermissionBlocked(app_id)) {
     return launch_infos;
   }
@@ -244,14 +220,4 @@
   return sync_bridge_ ? &sync_bridge_->registrar() : nullptr;
 }
 
-void WebAppFileHandlerManager::SyncOsIntegrationState() {
-  if (GetRegistrar()) {
-    for (AppId& id : GetRegistrar()->GetAppIds()) {
-      WebAppProvider::GetForLocalAppsUnchecked(profile_)
-          ->scheduler()
-          .UpdateFileHandlerOsIntegration(id, base::DoNothing());
-    }
-  }
-}
-
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/os_integration/web_app_file_handler_manager.h b/chrome/browser/web_applications/os_integration/web_app_file_handler_manager.h
index e0f38ea..4bccd36 100644
--- a/chrome/browser/web_applications/os_integration/web_app_file_handler_manager.h
+++ b/chrome/browser/web_applications/os_integration/web_app_file_handler_manager.h
@@ -72,14 +72,9 @@
   // the app they belong to.
   const apps::FileHandlers* GetEnabledFileHandlers(const AppId& app_id) const;
 
-  // Determines whether file handling is allowed for |app_id|.
-  bool IsFileHandlingAPIAvailable(const AppId& app_id) const;
-
   // Returns true when the system supports file type association icons.
   static bool IconsEnabled();
 
-  void SyncOsIntegrationStateForTesting();
-
  protected:
   // Gets all file handlers for |app_id|. |nullptr| if the app has no file
   // handlers or if app_id was uninstalled.
@@ -100,11 +95,6 @@
   // registry.
   bool ShouldOsIntegrationBeEnabled(const AppId& app_id) const;
 
-  // Refreshes the OS integration state for all apps. This is useful to handle
-  // the case where the File Handling feature became enabled or disabled since
-  // the last time Chromium ran.
-  void SyncOsIntegrationState();
-
   const WebAppRegistrar* GetRegistrar() const;
 
   static bool disable_automatic_file_handler_cleanup_for_testing_;
diff --git a/chrome/browser/web_applications/os_integration/web_app_file_handler_manager_unittest.cc b/chrome/browser/web_applications/os_integration/web_app_file_handler_manager_unittest.cc
index bee558b..1a2d29b29 100644
--- a/chrome/browser/web_applications/os_integration/web_app_file_handler_manager_unittest.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_file_handler_manager_unittest.cc
@@ -11,7 +11,6 @@
 #include "base/callback_helpers.h"
 #include "base/run_loop.h"
 #include "base/test/bind.h"
-#include "base/test/scoped_feature_list.h"
 #include "chrome/browser/web_applications/os_integration/web_app_file_handler_registration.h"
 #include "chrome/browser/web_applications/test/fake_web_app_file_handler_manager.h"
 #include "chrome/browser/web_applications/test/fake_web_app_provider.h"
@@ -24,7 +23,6 @@
 #include "components/services/app_service/public/cpp/file_handler.h"
 #include "testing/gmock/include/gmock/gmock-matchers.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/features.h"
 #include "url/gurl.h"
 
 namespace web_app {
@@ -161,13 +159,6 @@
 }
 
 class WebAppFileHandlerManagerTest : public WebAppTest {
- public:
-  WebAppFileHandlerManagerTest() {
-    // |features_| needs to be initialized before SetUp kicks off tasks that
-    // check if a feature is enabled.
-    features_.InitAndEnableFeature(blink::features::kFileHandlingAPI);
-  }
-
  protected:
   void SetUp() override {
     WebAppTest::SetUp();
@@ -203,7 +194,6 @@
   raw_ptr<FakeWebAppProvider> provider_;
   std::unique_ptr<FakeWebAppFileHandlerManager> file_handler_manager_;
 
-  base::test::ScopedFeatureList features_;
   AppId app_id_;
 };
 
diff --git a/chrome/browser/web_applications/os_integration/web_app_file_handler_registration_linux_browsertest.cc b/chrome/browser/web_applications/os_integration/web_app_file_handler_registration_linux_browsertest.cc
index 7cac167..3ac81f833 100644
--- a/chrome/browser/web_applications/os_integration/web_app_file_handler_registration_linux_browsertest.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_file_handler_registration_linux_browsertest.cc
@@ -11,7 +11,6 @@
 #include "base/files/file_path.h"
 #include "base/run_loop.h"
 #include "base/test/bind.h"
-#include "base/test/scoped_feature_list.h"
 #include "chrome/browser/shell_integration_linux.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h"
@@ -24,7 +23,6 @@
 #include "content/public/test/browser_test.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/blink/public/common/features.h"
 #include "url/gurl.h"
 
 namespace web_app {
@@ -51,11 +49,6 @@
 class WebAppFileHandlerRegistrationLinuxBrowserTest
     : public InProcessBrowserTest {
  protected:
-  WebAppFileHandlerRegistrationLinuxBrowserTest() {
-    scoped_feature_list_.InitAndEnableFeature(
-        blink::features::kFileHandlingAPI);
-  }
-
   WebAppRegistrar& registrar() {
     return WebAppProvider::GetForTest(browser()->profile())->registrar_unsafe();
   }
@@ -66,7 +59,6 @@
     result_code_ = result.code;
   }
 
-  base::test::ScopedFeatureList scoped_feature_list_;
   absl::optional<webapps::InstallResultCode> result_code_;
 };
 
diff --git a/chrome/browser/web_applications/web_app_command_scheduler.cc b/chrome/browser/web_applications/web_app_command_scheduler.cc
index b25b252..3c2b3da 100644
--- a/chrome/browser/web_applications/web_app_command_scheduler.cc
+++ b/chrome/browser/web_applications/web_app_command_scheduler.cc
@@ -174,19 +174,6 @@
           app_id, allowed, std::move(callback)));
 }
 
-void WebAppCommandScheduler::UpdateFileHandlerOsIntegration(
-    const AppId& app_id,
-    base::OnceClosure callback) {
-  if (IsShuttingDown()) {
-    base::SequencedTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::BindOnce(std::move(callback)));
-    return;
-  }
-
-  provider_->command_manager().ScheduleCommand(
-      UpdateFileHandlerCommand::CreateForUpdate(app_id, std::move(callback)));
-}
-
 void WebAppCommandScheduler::ScheduleManifestUpdateDataFetch(
     const GURL& url,
     const AppId& app_id,
diff --git a/chrome/browser/web_applications/web_app_command_scheduler.h b/chrome/browser/web_applications/web_app_command_scheduler.h
index ea2fa61..225c174 100644
--- a/chrome/browser/web_applications/web_app_command_scheduler.h
+++ b/chrome/browser/web_applications/web_app_command_scheduler.h
@@ -96,9 +96,6 @@
                                      bool allowed,
                                      base::OnceClosure callback);
 
-  void UpdateFileHandlerOsIntegration(const AppId& app_id,
-                                      base::OnceClosure callback);
-
   // Schedule a command that performs fetching data from the manifest
   // for a manifest update.
   void ScheduleManifestUpdateDataFetch(
diff --git a/chrome/browser/web_applications/web_app_command_scheduler_unittest.cc b/chrome/browser/web_applications/web_app_command_scheduler_unittest.cc
index 823800a..8b44a66 100644
--- a/chrome/browser/web_applications/web_app_command_scheduler_unittest.cc
+++ b/chrome/browser/web_applications/web_app_command_scheduler_unittest.cc
@@ -85,32 +85,5 @@
   EXPECT_EQ(provider()->command_manager().GetCommandCountForTesting(), 0u);
 }
 
-TEST_F(WebAppCommandSchedulerTest, UpdateFileHandlerOsIntegration) {
-  EXPECT_FALSE(provider()->is_registry_ready());
-  provider()->scheduler().UpdateFileHandlerOsIntegration("app id",
-                                                         base::DoNothing());
-
-  provider()->StartWithSubsystems();
-  EXPECT_EQ(provider()->command_manager().GetCommandCountForTesting(), 0u);
-
-  WaitForProviderReady();
-  EXPECT_EQ(provider()->command_manager().GetCommandCountForTesting(), 1u);
-  base::Value::Dict log =
-      provider()->command_manager().ToDebugValue().TakeDict();
-  base::Value::List* command_queue = log.FindList("command_queue");
-
-  EXPECT_EQ(command_queue->size(), 1u);
-
-  const base::Value::Dict& command_log = command_queue->front().GetDict();
-  EXPECT_EQ(*command_log.FindString("name"), "UpdateFileHandlerCommand");
-  provider()->command_manager().AwaitAllCommandsCompleteForTesting();
-
-  provider()->Shutdown();
-  // commands don't get scheduled after shutdown.
-  provider()->scheduler().PersistFileHandlersUserChoice(
-      "app id", /*allowed=*/true, base::DoNothing());
-  EXPECT_EQ(provider()->command_manager().GetCommandCountForTesting(), 0u);
-}
-
 }  // namespace
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_install_finalizer.cc b/chrome/browser/web_applications/web_app_install_finalizer.cc
index 2548f13..0b84bfd 100644
--- a/chrome/browser/web_applications/web_app_install_finalizer.cc
+++ b/chrome/browser/web_applications/web_app_install_finalizer.cc
@@ -681,9 +681,6 @@
 FileHandlerUpdateAction WebAppInstallFinalizer::GetFileHandlerUpdateAction(
     const AppId& app_id,
     const WebAppInstallInfo& new_web_app_info) {
-  if (!os_integration_manager_->IsFileHandlingAPIAvailable(app_id))
-    return FileHandlerUpdateAction::kNoUpdate;
-
   if (GetWebAppRegistrar().GetAppFileHandlerApprovalState(app_id) ==
       ApiApprovalState::kDisallowed) {
     return FileHandlerUpdateAction::kNoUpdate;
diff --git a/chrome/browser/web_applications/web_app_install_finalizer_unittest.cc b/chrome/browser/web_applications/web_app_install_finalizer_unittest.cc
index 51b65aa..acc9dc3 100644
--- a/chrome/browser/web_applications/web_app_install_finalizer_unittest.cc
+++ b/chrome/browser/web_applications/web_app_install_finalizer_unittest.cc
@@ -38,7 +38,6 @@
 #include "mojo/public/cpp/bindings/struct_ptr.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/mojom/manifest/manifest.mojom-forward.h"
 #include "third_party/blink/public/mojom/manifest/manifest.mojom.h"
 #include "url/gurl.h"
@@ -83,13 +82,11 @@
   WebAppInstallFinalizerUnitTest() {
     if (GetParam() == OsIntegrationSubManagersState::kSaveStateToDB) {
       scoped_feature_list_.InitWithFeaturesAndParameters(
-          {{blink::features::kFileHandlingAPI, {}},
-           {features::kOsIntegrationSubManagers, {{"stage", "write_config"}}}},
+          {{features::kOsIntegrationSubManagers, {{"stage", "write_config"}}}},
           /*disabled_features=*/{});
     } else {
       scoped_feature_list_.InitWithFeatures(
-          {blink::features::kFileHandlingAPI},
-          {features::kOsIntegrationSubManagers});
+          {}, {features::kOsIntegrationSubManagers});
     }
   }
   WebAppInstallFinalizerUnitTest(const WebAppInstallFinalizerUnitTest&) =
diff --git a/chrome/browser/web_applications/web_app_install_task_unittest.cc b/chrome/browser/web_applications/web_app_install_task_unittest.cc
index f26118a..41a9235c 100644
--- a/chrome/browser/web_applications/web_app_install_task_unittest.cc
+++ b/chrome/browser/web_applications/web_app_install_task_unittest.cc
@@ -60,7 +60,6 @@
 #include "net/http/http_status_code.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/mojom/manifest/manifest.mojom.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkColor.h"
@@ -1252,11 +1251,6 @@
 
 class WebAppInstallTaskTestWithFileHandlers : public WebAppInstallTaskTest {
  public:
-  WebAppInstallTaskTestWithFileHandlers() {
-    scoped_feature_list_.InitWithFeatures({blink::features::kFileHandlingAPI},
-                                          {});
-  }
-
   blink::mojom::ManifestPtr CreateManifest(const GURL& url) {
     auto manifest = blink::mojom::Manifest::New();
     manifest->start_url = url;
@@ -1333,9 +1327,6 @@
     EXPECT_TRUE(callback_called);
     return result;
   }
-
- private:
-  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
 TEST_F(WebAppInstallTaskTestWithFileHandlers,
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index e916854..79e0ac16 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1672768604-02e07768de6f9e782be0bff18efe56f271ef18f2.profdata
+chrome-linux-main-1672790328-d0f218a0dbfdd315a7c4768d830d648a50b0b16c.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index 167fa6a..717da84 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1672768604-17d1d9682a1b10df8e779c979c79ac2169f9dfe2.profdata
+chrome-mac-arm-main-1672811657-c57826f8793da42014c144341f2b40e11c956a5b.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 596edc9..7518663c 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1672768604-f7f43286d8b833779c2cf3cb6baf8dcb15abcb77.profdata
+chrome-mac-main-1672790328-242ff39a3d24b4789e5db398b7c35acf54533a57.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 00ed62c..4906c08 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1672768604-0184dbab237a45944e284e084332b3a92d758063.profdata
+chrome-win32-main-1672801140-3b5d5298b1072bc9ce893820996409e1da8daf42.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 7add4ef..5fa9ad041 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1672768604-8da543c818b6aea3eae2ad5cb80cfe61abd454a1.profdata
+chrome-win64-main-1672801140-ff6b40af5d8b7c3e4fd9cbf4a516c16516598ef7.profdata
diff --git a/chrome/chrome_paks.gni b/chrome/chrome_paks.gni
index 592f3e3..11bd811e 100644
--- a/chrome/chrome_paks.gni
+++ b/chrome/chrome_paks.gni
@@ -167,6 +167,7 @@
         "$root_gen_dir/chrome/privacy_sandbox_resources.pak",
         "$root_gen_dir/chrome/profile_internals_resources.pak",
         "$root_gen_dir/chrome/settings_resources.pak",
+        "$root_gen_dir/chrome/side_panel_bookmarks_resources.pak",
         "$root_gen_dir/chrome/side_panel_customize_chrome_resources.pak",
         "$root_gen_dir/chrome/side_panel_resources.pak",
         "$root_gen_dir/chrome/signin_resources.pak",
@@ -203,6 +204,7 @@
         "//chrome/browser/resources/profile_internals:resources",
         "//chrome/browser/resources/settings:resources",
         "//chrome/browser/resources/side_panel:resources",
+        "//chrome/browser/resources/side_panel/bookmarks:resources",
         "//chrome/browser/resources/side_panel/customize_chrome:resources",
         "//chrome/browser/resources/signin:resources",
         "//chrome/browser/resources/support_tool:resources",
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index 48e31803..3e35626c 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -44,6 +44,12 @@
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
+BASE_FEATURE(kAppDeduplicationServiceFondue,
+             "AppDeduplicationServiceFondue",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 BASE_FEATURE(kAppPreloadService,
              "AppPreloadService",
              base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h
index 0305aa8..f2cc02b 100644
--- a/chrome/common/chrome_features.h
+++ b/chrome/common/chrome_features.h
@@ -43,6 +43,11 @@
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 COMPONENT_EXPORT(CHROME_FEATURES)
+BASE_DECLARE_FEATURE(kAppDeduplicationServiceFondue);
+#endif
+
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+COMPONENT_EXPORT(CHROME_FEATURES)
 BASE_DECLARE_FEATURE(kAppManagementAppDetails);
 #endif
 
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index a2fd936..37527c34 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -4096,6 +4096,7 @@
         "../browser/ui/views/arc_app_dialog_view_browsertest.cc",
         "../browser/ui/views/borealis/borealis_installer_view_browsertest.cc",
         "../browser/ui/views/borealis/borealis_splash_screen_view_browsertest.cc",
+        "../browser/ui/views/bruschetta/bruschetta_installer_view_browsertest.cc",
         "../browser/ui/views/crostini/crostini_ansible_software_config_view_browsertest.cc",
         "../browser/ui/views/crostini/crostini_dialogue_browser_test_util.cc",
         "../browser/ui/views/crostini/crostini_dialogue_browser_test_util.h",
diff --git a/chrome/test/data/webui/bluetooth_internals/bluetooth_internals_browsertest.js b/chrome/test/data/webui/bluetooth_internals/bluetooth_internals_browsertest.js
index f900910..7e64f46 100644
--- a/chrome/test/data/webui/bluetooth_internals/bluetooth_internals_browsertest.js
+++ b/chrome/test/data/webui/bluetooth_internals/bluetooth_internals_browsertest.js
@@ -32,7 +32,10 @@
   ],
 };
 
-TEST_F('BluetoothInternalsTest', 'Startup_BluetoothInternals', function() {
-  // Run all registered tests.
-  mocha.run();
-});
+// TODO(crbug.com/1399475): Flaky on all platforms.
+TEST_F(
+    'BluetoothInternalsTest', 'DISABLED_Startup_BluetoothInternals',
+    function() {
+      // Run all registered tests.
+      mocha.run();
+    });
diff --git a/chrome/test/data/webui/chromeos/shortcut_customization/accelerator_lookup_manager_test.ts b/chrome/test/data/webui/chromeos/shortcut_customization/accelerator_lookup_manager_test.ts
index 19f4f079..48aa433 100644
--- a/chrome/test/data/webui/chromeos/shortcut_customization/accelerator_lookup_manager_test.ts
+++ b/chrome/test/data/webui/chromeos/shortcut_customization/accelerator_lookup_manager_test.ts
@@ -161,26 +161,6 @@
     });
   });
 
-  test('GetLayoutInfoDefaultFakeNoAccelerators', () => {
-    // TODO(jimmyxgong): Remove this test once real data is ready.
-    getProvider().setFakeAcceleratorLayoutInfos(fakeLayoutInfo);
-    return getProvider().getAcceleratorLayoutInfos().then((result) => {
-      assertDeepEquals(fakeLayoutInfo, result.layoutInfos);
-
-      getManager().setAcceleratorLayoutLookup(result.layoutInfos);
-
-      // If accelerators have not been initialized into the
-      // AcceleratorLookupManager, we expect the subcategories to be undefined.
-      assertEquals(
-          undefined,
-          getManager().getSubcategories(AcceleratorCategory.kTabsAndWindows));
-      assertEquals(
-          undefined,
-          getManager().getSubcategories(
-              AcceleratorCategory.kPageAndWebBrowser));
-    });
-  });
-
   test('ReplaceBasicAccelerator', () => {
     getProvider().setFakeAcceleratorConfig(fakeAcceleratorConfig);
     return getProvider().getAccelerators().then((result) => {
diff --git a/chrome/test/data/webui/settings/chromeos/app_management/app_details_item_test.js b/chrome/test/data/webui/settings/chromeos/app_management/app_details_item_test.js
index f69e22e..406927e 100644
--- a/chrome/test/data/webui/settings/chromeos/app_management/app_details_item_test.js
+++ b/chrome/test/data/webui/settings/chromeos/app_management/app_details_item_test.js
@@ -22,14 +22,13 @@
     flushTasks();
   });
 
-  test('PWA type from unknown source', async function() {
-    const options = {
-      type: AppType.kWeb,
-      installSource: InstallSource.kUnknown,
-    };
-
-    // Add PWA app, and make it the currently selected app.
-    const app = await fakeHandler.addApp('app', options);
+  /**
+   * @param {Object} appOptions
+   * @param {string} [appName="app"]
+   **/
+  async function addApp(appOptions, appName = 'app') {
+    // Add an app, and make it the currently selected app.
+    const app = await fakeHandler.addApp(appName, appOptions);
 
     AppManagementStore.getInstance().dispatch(updateSelectedAppId(app.id));
 
@@ -42,6 +41,13 @@
     replaceBody(appDetailsItem);
     fakeHandler.flushPipesForTesting();
     flushTasks();
+  }
+
+  test('PWA type from unknown source', async function() {
+    await addApp({
+      type: AppType.kWeb,
+      installSource: InstallSource.kUnknown,
+    });
 
     assertTrue(!!appDetailsItem.shadowRoot.querySelector('#typeAndSource'));
     assertEquals(
@@ -51,26 +57,12 @@
   });
 
   test('PWA type from browser', async function() {
-    const options = {
+    const publisherId = 'https://google.com/';
+    await addApp({
       type: AppType.kWeb,
       installSource: InstallSource.kBrowser,
-      publisherId: 'https://google.com/',
-    };
-
-    // Add PWA app, and make it the currently selected app.
-    const app = await fakeHandler.addApp('app', options);
-
-    AppManagementStore.getInstance().dispatch(updateSelectedAppId(app.id));
-
-    await fakeHandler.flushPipesForTesting();
-
-    assertTrue(!!AppManagementStore.getInstance().data.apps[app.id]);
-
-    appDetailsItem.app = app;
-
-    replaceBody(appDetailsItem);
-    fakeHandler.flushPipesForTesting();
-    flushTasks();
+      publisherId,
+    });
 
     assertTrue(!!appDetailsItem.shadowRoot.querySelector('#typeAndSourceText'));
     assertEquals(
@@ -84,29 +76,14 @@
         appDetailsItem.shadowRoot.querySelector('#infoIconTooltip')
             .querySelector('#tooltipText')
             .textContent.trim(),
-        options.publisherId);
+        publisherId);
   });
 
   test('Android type', async function() {
-    const options = {
+    await addApp({
       type: AppType.kArc,
       installSource: InstallSource.kUnknown,
-    };
-
-    // Add Android app, and make it the currently selected app.
-    const app = await fakeHandler.addApp('app', options);
-
-    AppManagementStore.getInstance().dispatch(updateSelectedAppId(app.id));
-
-    await fakeHandler.flushPipesForTesting();
-
-    assertTrue(!!AppManagementStore.getInstance().data.apps[app.id]);
-
-    appDetailsItem.app = app;
-
-    replaceBody(appDetailsItem);
-    fakeHandler.flushPipesForTesting();
-    flushTasks();
+    });
 
     assertTrue(!!appDetailsItem.shadowRoot.querySelector('#typeAndSource'));
     assertEquals(
@@ -116,25 +93,10 @@
   });
 
   test('Chrome type', async function() {
-    const options = {
+    await addApp({
       type: AppType.kChromeApp,
       installSource: InstallSource.kUnknown,
-    };
-
-    // Add Chrome app, and make it the currently selected app.
-    const app = await fakeHandler.addApp('app', options);
-
-    AppManagementStore.getInstance().dispatch(updateSelectedAppId(app.id));
-
-    await fakeHandler.flushPipesForTesting();
-
-    assertTrue(!!AppManagementStore.getInstance().data.apps[app.id]);
-
-    appDetailsItem.app = app;
-
-    replaceBody(appDetailsItem);
-    fakeHandler.flushPipesForTesting();
-    flushTasks();
+    });
 
     assertTrue(!!appDetailsItem.shadowRoot.querySelector('#typeAndSource'));
     assertEquals(
@@ -144,25 +106,10 @@
   });
 
   test('Chrome App from web store', async function() {
-    const options = {
+    await addApp({
       type: AppType.kChromeApp,
       installSource: InstallSource.kChromeWebStore,
-    };
-
-    // Add Chrome app, and make it the currently selected app.
-    const app = await fakeHandler.addApp('app', options);
-
-    AppManagementStore.getInstance().dispatch(updateSelectedAppId(app.id));
-
-    await fakeHandler.flushPipesForTesting();
-
-    assertTrue(!!AppManagementStore.getInstance().data.apps[app.id]);
-
-    appDetailsItem.app = app;
-
-    replaceBody(appDetailsItem);
-    fakeHandler.flushPipesForTesting();
-    flushTasks();
+    });
 
     assertTrue(!!appDetailsItem.shadowRoot.querySelector('#typeAndSource'));
     assertEquals(
@@ -172,25 +119,10 @@
   });
 
   test('Android App from play store', async function() {
-    const options = {
+    await addApp({
       type: AppType.kArc,
       installSource: InstallSource.kPlayStore,
-    };
-
-    // Add Chrome app, and make it the currently selected app.
-    const app = await fakeHandler.addApp('app', options);
-
-    AppManagementStore.getInstance().dispatch(updateSelectedAppId(app.id));
-
-    await fakeHandler.flushPipesForTesting();
-
-    assertTrue(!!AppManagementStore.getInstance().data.apps[app.id]);
-
-    appDetailsItem.app = app;
-
-    replaceBody(appDetailsItem);
-    fakeHandler.flushPipesForTesting();
-    flushTasks();
+    });
 
     assertTrue(!!appDetailsItem.shadowRoot.querySelector('#typeAndSource'));
     assertEquals(
@@ -200,24 +132,9 @@
   });
 
   test('System type', async function() {
-    const options = {
+    await addApp({
       type: AppType.kSystemWeb,
-    };
-
-    // Add System app, and make it the currently selected app.
-    const app = await fakeHandler.addApp('app', options);
-
-    AppManagementStore.getInstance().dispatch(updateSelectedAppId(app.id));
-
-    await fakeHandler.flushPipesForTesting();
-
-    assertTrue(!!AppManagementStore.getInstance().data.apps[app.id]);
-
-    appDetailsItem.app = app;
-
-    replaceBody(appDetailsItem);
-    fakeHandler.flushPipesForTesting();
-    flushTasks();
+    });
 
     assertTrue(!!appDetailsItem.shadowRoot.querySelector('#typeAndSource'));
     assertEquals(
@@ -226,25 +143,10 @@
         'System App');
   });
 
-  test('system install source', async function() {
-    const options = {
+  test('System install source', async function() {
+    await addApp({
       installSource: InstallSource.kSystem,
-    };
-
-    // Add System app, and make it the currently selected app.
-    const app = await fakeHandler.addApp('app', options);
-
-    AppManagementStore.getInstance().dispatch(updateSelectedAppId(app.id));
-
-    await fakeHandler.flushPipesForTesting();
-
-    assertTrue(!!AppManagementStore.getInstance().data.apps[app.id]);
-
-    appDetailsItem.app = app;
-
-    replaceBody(appDetailsItem);
-    fakeHandler.flushPipesForTesting();
-    flushTasks();
+    });
 
     assertTrue(!!appDetailsItem.shadowRoot.querySelector('#typeAndSource'));
     assertEquals(
@@ -254,25 +156,10 @@
   });
 
   test('Chrome app version', async function() {
-    const options = {
+    await addApp({
       type: AppType.kChromeApp,
       version: '17.2',
-    };
-
-    // Add Chrome app, and make it the currently selected app.
-    const app = await fakeHandler.addApp('app', options);
-
-    AppManagementStore.getInstance().dispatch(updateSelectedAppId(app.id));
-
-    await fakeHandler.flushPipesForTesting();
-
-    assertTrue(!!AppManagementStore.getInstance().data.apps[app.id]);
-
-    appDetailsItem.app = app;
-
-    replaceBody(appDetailsItem);
-    fakeHandler.flushPipesForTesting();
-    flushTasks();
+    });
 
     assertEquals(
         appDetailsItem.shadowRoot.querySelector('#version').textContent.trim(),
@@ -280,25 +167,10 @@
   });
 
   test('Android app version', async function() {
-    const options = {
+    await addApp({
       type: AppType.kArc,
       version: '13.1.52',
-    };
-
-    // Add Android app, and make it the currently selected app.
-    const app = await fakeHandler.addApp('app', options);
-
-    AppManagementStore.getInstance().dispatch(updateSelectedAppId(app.id));
-
-    await fakeHandler.flushPipesForTesting();
-
-    assertTrue(!!AppManagementStore.getInstance().data.apps[app.id]);
-
-    appDetailsItem.app = app;
-
-    replaceBody(appDetailsItem);
-    fakeHandler.flushPipesForTesting();
-    flushTasks();
+    });
 
     assertEquals(
         appDetailsItem.shadowRoot.querySelector('#version').innerText.trim(),
@@ -306,34 +178,11 @@
   });
 
   test('Android type storage', async function() {
-    const options = {
+    await addApp({
       type: AppType.kArc,
       installSource: InstallSource.kUnknown,
       appSize: '17 MB',
-    };
-
-    const options2 = {
-      type: AppType.kArc,
-      installSource: InstallSource.kUnknown,
-      appSize: '17 MB',
-      dataSize: '124.6 GB',
-    };
-
-    // Add Android app, and make it the currently selected app.
-    const app = await fakeHandler.addApp('app', options);
-    const app2 = await fakeHandler.addApp('app2', options2);
-
-    AppManagementStore.getInstance().dispatch(updateSelectedAppId(app.id));
-
-    await fakeHandler.flushPipesForTesting();
-
-    assertTrue(!!AppManagementStore.getInstance().data.apps[app.id]);
-
-    appDetailsItem.app = app;
-
-    replaceBody(appDetailsItem);
-    fakeHandler.flushPipesForTesting();
-    flushTasks();
+    });
 
     assertTrue(!!appDetailsItem.shadowRoot.querySelector('#storageTitle'));
     assertTrue(!!appDetailsItem.shadowRoot.querySelector('#appSize'));
@@ -343,17 +192,14 @@
         appDetailsItem.shadowRoot.querySelector('#appSize').textContent.trim(),
         'App size: 17 MB');
 
-    AppManagementStore.getInstance().dispatch(updateSelectedAppId(app2.id));
-
-    await fakeHandler.flushPipesForTesting();
-
-    assertTrue(!!AppManagementStore.getInstance().data.apps[app2.id]);
-
-    appDetailsItem.app = app2;
-
-    replaceBody(appDetailsItem);
-    fakeHandler.flushPipesForTesting();
-    flushTasks();
+    await addApp(
+        {
+          type: AppType.kArc,
+          installSource: InstallSource.kUnknown,
+          appSize: '17 MB',
+          dataSize: '124.6 GB',
+        },
+        'app2');
 
     assertTrue(!!appDetailsItem.shadowRoot.querySelector('#storageTitle'));
     assertTrue(!!appDetailsItem.shadowRoot.querySelector('#appSize'));
diff --git a/chrome/test/data/webui/settings/chromeos/text_to_speech_page_tests.js b/chrome/test/data/webui/settings/chromeos/text_to_speech_page_tests.js
index 15a07159..1397a7a 100644
--- a/chrome/test/data/webui/settings/chromeos/text_to_speech_page_tests.js
+++ b/chrome/test/data/webui/settings/chromeos/text_to_speech_page_tests.js
@@ -86,4 +86,21 @@
       }
     });
   });
+
+  test('pdf ocr pref enabled when pdf ocr enabled', async function() {
+    loadTimeData.overrideValues({pdfOcrEnabled: true});
+    await initPage();
+
+    const pdfOcrToggle = page.shadowRoot.querySelector('#crosPdfOcrToggle');
+    assertTrue(!!pdfOcrToggle);
+    assertTrue(isVisible(pdfOcrToggle));
+    assertFalse(pdfOcrToggle.checked);
+    assertFalse(page.prefs.settings.a11y.pdf_ocr_always_active.value);
+    pdfOcrToggle.click();
+
+    await waitBeforeNextRender(page);
+    flush();
+    assertTrue(pdfOcrToggle.checked);
+    assertTrue(page.prefs.settings.a11y.pdf_ocr_always_active.value);
+  });
 });
diff --git a/chrome/test/data/webui/side_panel/BUILD.gn b/chrome/test/data/webui/side_panel/BUILD.gn
index 45862a12..55c8403 100644
--- a/chrome/test/data/webui/side_panel/BUILD.gn
+++ b/chrome/test/data/webui/side_panel/BUILD.gn
@@ -10,6 +10,10 @@
   out_dir = "$target_gen_dir/tsc"
   tsconfig_base = "tsconfig_base.json"
   path_mappings = [
+    "chrome://bookmarks-side-panel.top-chrome/*|" +
+        rebase_path(
+            "$root_gen_dir/chrome/browser/resources/side_panel/bookmarks/tsc/*",
+            target_gen_dir),
     "chrome://read-later.top-chrome/*|" +
         rebase_path("$root_gen_dir/chrome/browser/resources/side_panel/tsc/*",
                     target_gen_dir),
@@ -29,7 +33,6 @@
     "reading_list/reading_list_app_test.ts",
     "reading_list/test_reading_list_api_proxy.ts",
     "read_anything/read_anything_app_test.ts",
-    "side_panel_app_test.ts",
   ]
   definitions = [
     "//chrome/browser/resources/side_panel/read_anything/read_anything.d.ts",
@@ -40,6 +43,7 @@
   deps = [
     "..:build_ts",
     "//chrome/browser/resources/side_panel:build_ts",
+    "//chrome/browser/resources/side_panel/bookmarks:build_ts",
   ]
 }
 
diff --git a/chrome/test/data/webui/side_panel/bookmarks/bookmark_folder_test.ts b/chrome/test/data/webui/side_panel/bookmarks/bookmark_folder_test.ts
index 872735f..e6a01258 100644
--- a/chrome/test/data/webui/side_panel/bookmarks/bookmark_folder_test.ts
+++ b/chrome/test/data/webui/side_panel/bookmarks/bookmark_folder_test.ts
@@ -3,11 +3,11 @@
 // found in the LICENSE file.
 
 import 'chrome://webui-test/mojo_webui_test_support.js';
-import 'chrome://read-later.top-chrome/bookmarks/bookmark_folder.js';
+import 'chrome://bookmarks-side-panel.top-chrome/bookmark_folder.js';
 
-import {BookmarkFolderElement, FOLDER_OPEN_CHANGED_EVENT, getBookmarkFromElement} from 'chrome://read-later.top-chrome/bookmarks/bookmark_folder.js';
-import {ActionSource} from 'chrome://read-later.top-chrome/bookmarks/bookmarks.mojom-webui.js';
-import {BookmarksApiProxyImpl} from 'chrome://read-later.top-chrome/bookmarks/bookmarks_api_proxy.js';
+import {BookmarkFolderElement, FOLDER_OPEN_CHANGED_EVENT, getBookmarkFromElement} from 'chrome://bookmarks-side-panel.top-chrome/bookmark_folder.js';
+import {ActionSource} from 'chrome://bookmarks-side-panel.top-chrome/bookmarks.mojom-webui.js';
+import {BookmarksApiProxyImpl} from 'chrome://bookmarks-side-panel.top-chrome/bookmarks_api_proxy.js';
 import {getFaviconForPageURL} from 'chrome://resources/js/icon.js';
 import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
 import {flushTasks, waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
diff --git a/chrome/test/data/webui/side_panel/bookmarks/bookmarks_drag_manager_test.ts b/chrome/test/data/webui/side_panel/bookmarks/bookmarks_drag_manager_test.ts
index 15be32a..fe26f1d 100644
--- a/chrome/test/data/webui/side_panel/bookmarks/bookmarks_drag_manager_test.ts
+++ b/chrome/test/data/webui/side_panel/bookmarks/bookmarks_drag_manager_test.ts
@@ -4,10 +4,10 @@
 
 import 'chrome://webui-test/mojo_webui_test_support.js';
 
-import {BookmarksApiProxyImpl} from 'chrome://read-later.top-chrome/bookmarks/bookmarks_api_proxy.js';
-import {BookmarksDragManager, DROP_POSITION_ATTR, DropPosition, overrideFolderOpenerTimeoutDelay} from 'chrome://read-later.top-chrome/bookmarks/bookmarks_drag_manager.js';
-import {BookmarksListElement, LOCAL_STORAGE_OPEN_FOLDERS_KEY} from 'chrome://read-later.top-chrome/bookmarks/bookmarks_list.js';
-import {ShoppingListApiProxyImpl} from 'chrome://read-later.top-chrome/bookmarks/commerce/shopping_list_api_proxy.js';
+import {BookmarksApiProxyImpl} from 'chrome://bookmarks-side-panel.top-chrome/bookmarks_api_proxy.js';
+import {BookmarksDragManager, DROP_POSITION_ATTR, DropPosition, overrideFolderOpenerTimeoutDelay} from 'chrome://bookmarks-side-panel.top-chrome/bookmarks_drag_manager.js';
+import {BookmarksListElement, LOCAL_STORAGE_OPEN_FOLDERS_KEY} from 'chrome://bookmarks-side-panel.top-chrome/bookmarks_list.js';
+import {ShoppingListApiProxyImpl} from 'chrome://bookmarks-side-panel.top-chrome/commerce/shopping_list_api_proxy.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
diff --git a/chrome/test/data/webui/side_panel/bookmarks/bookmarks_list_interactive_ui_test.ts b/chrome/test/data/webui/side_panel/bookmarks/bookmarks_list_interactive_ui_test.ts
index c15ac3b..22bbfa2f6 100644
--- a/chrome/test/data/webui/side_panel/bookmarks/bookmarks_list_interactive_ui_test.ts
+++ b/chrome/test/data/webui/side_panel/bookmarks/bookmarks_list_interactive_ui_test.ts
@@ -3,12 +3,12 @@
 // found in the LICENSE file.
 
 import 'chrome://webui-test/mojo_webui_test_support.js';
-import 'chrome://read-later.top-chrome/bookmarks/bookmarks_list.js';
+import 'chrome://bookmarks-side-panel.top-chrome/bookmarks_list.js';
 
-import {BookmarkFolderElement} from 'chrome://read-later.top-chrome/bookmarks/bookmark_folder.js';
-import {BookmarksApiProxyImpl} from 'chrome://read-later.top-chrome/bookmarks/bookmarks_api_proxy.js';
-import {BookmarksListElement} from 'chrome://read-later.top-chrome/bookmarks/bookmarks_list.js';
-import {ShoppingListApiProxyImpl} from 'chrome://read-later.top-chrome/bookmarks/commerce/shopping_list_api_proxy.js';
+import {BookmarkFolderElement} from 'chrome://bookmarks-side-panel.top-chrome/bookmark_folder.js';
+import {BookmarksApiProxyImpl} from 'chrome://bookmarks-side-panel.top-chrome/bookmarks_api_proxy.js';
+import {BookmarksListElement} from 'chrome://bookmarks-side-panel.top-chrome/bookmarks_list.js';
+import {ShoppingListApiProxyImpl} from 'chrome://bookmarks-side-panel.top-chrome/commerce/shopping_list_api_proxy.js';
 import {FocusOutlineManager} from 'chrome://resources/js/focus_outline_manager.js';
 import {down, keyDownOn} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js';
 import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
diff --git a/chrome/test/data/webui/side_panel/bookmarks/bookmarks_list_test.ts b/chrome/test/data/webui/side_panel/bookmarks/bookmarks_list_test.ts
index edacbf7..f67ceea 100644
--- a/chrome/test/data/webui/side_panel/bookmarks/bookmarks_list_test.ts
+++ b/chrome/test/data/webui/side_panel/bookmarks/bookmarks_list_test.ts
@@ -3,13 +3,13 @@
 // found in the LICENSE file.
 
 import 'chrome://webui-test/mojo_webui_test_support.js';
-import 'chrome://read-later.top-chrome/bookmarks/bookmarks_list.js';
+import 'chrome://bookmarks-side-panel.top-chrome/bookmarks_list.js';
 
-import {BookmarkFolderElement, FOLDER_OPEN_CHANGED_EVENT} from 'chrome://read-later.top-chrome/bookmarks/bookmark_folder.js';
-import {BookmarksApiProxyImpl} from 'chrome://read-later.top-chrome/bookmarks/bookmarks_api_proxy.js';
-import {BookmarksListElement, LOCAL_STORAGE_OPEN_FOLDERS_KEY} from 'chrome://read-later.top-chrome/bookmarks/bookmarks_list.js';
-import {BookmarkProductInfo} from 'chrome://read-later.top-chrome/bookmarks/commerce/shopping_list.mojom-webui.js';
-import {ShoppingListApiProxyImpl} from 'chrome://read-later.top-chrome/bookmarks/commerce/shopping_list_api_proxy.js';
+import {BookmarkFolderElement, FOLDER_OPEN_CHANGED_EVENT} from 'chrome://bookmarks-side-panel.top-chrome/bookmark_folder.js';
+import {BookmarksApiProxyImpl} from 'chrome://bookmarks-side-panel.top-chrome/bookmarks_api_proxy.js';
+import {BookmarksListElement, LOCAL_STORAGE_OPEN_FOLDERS_KEY} from 'chrome://bookmarks-side-panel.top-chrome/bookmarks_list.js';
+import {ShoppingListApiProxyImpl} from 'chrome://bookmarks-side-panel.top-chrome/commerce/shopping_list_api_proxy.js';
+import {BookmarkProductInfo} from 'chrome://bookmarks-side-panel.top-chrome/shopping_list.mojom-webui.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
diff --git a/chrome/test/data/webui/side_panel/bookmarks/commerce/shopping_list_test.ts b/chrome/test/data/webui/side_panel/bookmarks/commerce/shopping_list_test.ts
index f22da4f..7caccc8 100644
--- a/chrome/test/data/webui/side_panel/bookmarks/commerce/shopping_list_test.ts
+++ b/chrome/test/data/webui/side_panel/bookmarks/commerce/shopping_list_test.ts
@@ -3,14 +3,14 @@
 // found in the LICENSE file.
 
 import 'chrome://webui-test/mojo_webui_test_support.js';
-import 'chrome://read-later.top-chrome/bookmarks/commerce/shopping_list.js';
-import 'chrome://read-later.top-chrome/bookmarks/bookmarks_list.js';
+import 'chrome://bookmarks-side-panel.top-chrome/commerce/shopping_list.js';
+import 'chrome://bookmarks-side-panel.top-chrome/bookmarks_list.js';
 
-import {ActionSource} from 'chrome://read-later.top-chrome/bookmarks/bookmarks.mojom-webui.js';
-import {BookmarksApiProxyImpl} from 'chrome://read-later.top-chrome/bookmarks/bookmarks_api_proxy.js';
-import {ACTION_BUTTON_TRACK_IMAGE, ACTION_BUTTON_UNTRACK_IMAGE, LOCAL_STORAGE_EXPAND_STATUS_KEY, ShoppingListElement} from 'chrome://read-later.top-chrome/bookmarks/commerce/shopping_list.js';
-import {BookmarkProductInfo} from 'chrome://read-later.top-chrome/bookmarks/commerce/shopping_list.mojom-webui.js';
-import {ShoppingListApiProxyImpl} from 'chrome://read-later.top-chrome/bookmarks/commerce/shopping_list_api_proxy.js';
+import {ActionSource} from 'chrome://bookmarks-side-panel.top-chrome/bookmarks.mojom-webui.js';
+import {BookmarksApiProxyImpl} from 'chrome://bookmarks-side-panel.top-chrome/bookmarks_api_proxy.js';
+import {ACTION_BUTTON_TRACK_IMAGE, ACTION_BUTTON_UNTRACK_IMAGE, LOCAL_STORAGE_EXPAND_STATUS_KEY, ShoppingListElement} from 'chrome://bookmarks-side-panel.top-chrome/commerce/shopping_list.js';
+import {ShoppingListApiProxyImpl} from 'chrome://bookmarks-side-panel.top-chrome/commerce/shopping_list_api_proxy.js';
+import {BookmarkProductInfo} from 'chrome://bookmarks-side-panel.top-chrome/shopping_list.mojom-webui.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
 import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
diff --git a/chrome/test/data/webui/side_panel/bookmarks/commerce/test_shopping_list_api_proxy.ts b/chrome/test/data/webui/side_panel/bookmarks/commerce/test_shopping_list_api_proxy.ts
index 2f472c3..d4b0e82 100644
--- a/chrome/test/data/webui/side_panel/bookmarks/commerce/test_shopping_list_api_proxy.ts
+++ b/chrome/test/data/webui/side_panel/bookmarks/commerce/test_shopping_list_api_proxy.ts
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {BookmarkProductInfo, PageCallbackRouter, PageRemote} from 'chrome://read-later.top-chrome/bookmarks/commerce/shopping_list.mojom-webui.js';
-import {ShoppingListApiProxy} from 'chrome://read-later.top-chrome/bookmarks/commerce/shopping_list_api_proxy.js';
+import {ShoppingListApiProxy} from 'chrome://bookmarks-side-panel.top-chrome/commerce/shopping_list_api_proxy.js';
+import {BookmarkProductInfo, PageCallbackRouter, PageRemote} from 'chrome://bookmarks-side-panel.top-chrome/shopping_list.mojom-webui.js';
 import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js';
 
 export class TestShoppingListApiProxy extends TestBrowserProxy implements
diff --git a/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_list_test.ts b/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_list_test.ts
index 9636b9d..dcf48a6 100644
--- a/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_list_test.ts
+++ b/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_list_test.ts
@@ -3,12 +3,12 @@
 // found in the LICENSE file.
 
 import 'chrome://webui-test/mojo_webui_test_support.js';
-import 'chrome://read-later.top-chrome/bookmarks/power_bookmarks_list.js';
+import 'chrome://bookmarks-side-panel.top-chrome/power_bookmarks_list.js';
 
-import {BookmarksApiProxyImpl} from 'chrome://read-later.top-chrome/bookmarks/bookmarks_api_proxy.js';
-import {ShoppingListApiProxyImpl} from 'chrome://read-later.top-chrome/bookmarks/commerce/shopping_list_api_proxy.js';
-import {PowerBookmarkRowElement} from 'chrome://read-later.top-chrome/bookmarks/power_bookmark_row.js';
-import {PowerBookmarksListElement} from 'chrome://read-later.top-chrome/bookmarks/power_bookmarks_list.js';
+import {BookmarksApiProxyImpl} from 'chrome://bookmarks-side-panel.top-chrome/bookmarks_api_proxy.js';
+import {ShoppingListApiProxyImpl} from 'chrome://bookmarks-side-panel.top-chrome/commerce/shopping_list_api_proxy.js';
+import {PowerBookmarkRowElement} from 'chrome://bookmarks-side-panel.top-chrome/power_bookmark_row.js';
+import {PowerBookmarksListElement} from 'chrome://bookmarks-side-panel.top-chrome/power_bookmarks_list.js';
 import {PluralStringProxyImpl} from 'chrome://resources/js/plural_string_proxy.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {assertEquals, assertNotEquals} from 'chrome://webui-test/chai_assert.js';
diff --git a/chrome/test/data/webui/side_panel/bookmarks/test_bookmarks_api_proxy.ts b/chrome/test/data/webui/side_panel/bookmarks/test_bookmarks_api_proxy.ts
index 50ffed4f..655ead0 100644
--- a/chrome/test/data/webui/side_panel/bookmarks/test_bookmarks_api_proxy.ts
+++ b/chrome/test/data/webui/side_panel/bookmarks/test_bookmarks_api_proxy.ts
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {ActionSource} from 'chrome://read-later.top-chrome/bookmarks/bookmarks.mojom-webui.js';
-import {BookmarksApiProxy} from 'chrome://read-later.top-chrome/bookmarks/bookmarks_api_proxy.js';
+import {ActionSource} from 'chrome://bookmarks-side-panel.top-chrome/bookmarks.mojom-webui.js';
+import {BookmarksApiProxy} from 'chrome://bookmarks-side-panel.top-chrome/bookmarks_api_proxy.js';
 import {ClickModifiers} from 'chrome://resources/mojo/ui/base/mojom/window_open_disposition.mojom-webui.js';
 import {FakeChromeEvent} from 'chrome://webui-test/fake_chrome_event.js';
 import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js';
diff --git a/chrome/test/data/webui/side_panel/side_panel_app_test.ts b/chrome/test/data/webui/side_panel/side_panel_app_test.ts
deleted file mode 100644
index 3ba8fe1b..0000000
--- a/chrome/test/data/webui/side_panel/side_panel_app_test.ts
+++ /dev/null
@@ -1,70 +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.
-
-import 'chrome://webui-test/mojo_webui_test_support.js';
-import 'chrome://read-later.top-chrome/app.js';
-
-import {LOCAL_STORAGE_TAB_ID_KEY, SidePanelAppElement} from 'chrome://read-later.top-chrome/app.js';
-import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
-import {assertEquals} from 'chrome://webui-test/chai_assert.js';
-import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';
-
-suite('SidePanelAppElementTest', () => {
-  let sidePanelApp: SidePanelAppElement;
-
-  setup(() => {
-    document.body.innerHTML = window.trustedTypes!.emptyHTML;
-    sidePanelApp = document.createElement('side-panel-app');
-    document.body.appendChild(sidePanelApp);
-  });
-
-  test('RemembersLastActiveTab', () => {
-    const tabs = sidePanelApp.shadowRoot!.querySelector('cr-tabs')!;
-
-    // Remove the app, change localStorage to select the Bookmarks tab, and add
-    // the app back to the DOM to see if the app changes tabs on
-    // connectedCallback.
-    sidePanelApp.remove();
-    window.localStorage[LOCAL_STORAGE_TAB_ID_KEY] = 'bookmarks';
-    document.body.appendChild(sidePanelApp);
-    assertEquals(1, tabs.selected);
-
-    // Change the selected tab to Reading List and confirm localStorage has
-    // changed.
-    tabs.selected = 0;
-    assertEquals('readingList', window.localStorage[LOCAL_STORAGE_TAB_ID_KEY]);
-  });
-
-  test('LazilyLoadsTabContents', async () => {
-    const tabs = sidePanelApp.shadowRoot!.querySelector('cr-tabs')!;
-    tabs.selected = 0;
-    await flushTasks();
-    assertEquals(
-        1,
-        sidePanelApp.shadowRoot!.querySelectorAll('reading-list-app').length);
-    assertEquals(
-        0, sidePanelApp.shadowRoot!.querySelectorAll('bookmarks-list').length);
-
-    tabs.selected = 1;
-    await flushTasks();
-    assertEquals(
-        1, sidePanelApp.shadowRoot!.querySelectorAll('bookmarks-list').length);
-  });
-
-  test('ForceShowBookmarkTab', async () => {
-    const tabs = sidePanelApp.shadowRoot!.querySelector('cr-tabs')!;
-
-    // Remove the app, change localStorage to select the ReadList tab while
-    // force showing Bookmarks tab, and add the app back to the DOM to see if
-    // the app changes tabs on connectedCallback.
-    sidePanelApp.remove();
-    window.localStorage[LOCAL_STORAGE_TAB_ID_KEY] = 'readingList';
-    loadTimeData.overrideValues({
-      shouldShowBookmark: true,
-    });
-
-    document.body.appendChild(sidePanelApp);
-    assertEquals(1, tabs.selected);
-  });
-});
diff --git a/chrome/test/data/webui/side_panel/side_panel_browsertest.js b/chrome/test/data/webui/side_panel/side_panel_browsertest.js
index 31bae101..fd3822e 100644
--- a/chrome/test/data/webui/side_panel/side_panel_browsertest.js
+++ b/chrome/test/data/webui/side_panel/side_panel_browsertest.js
@@ -16,22 +16,10 @@
   }
 }
 
-var SidePanelAppTest = class extends SidePanelBrowserTest {
-  /** @override */
-  get browsePreload() {
-    return 'chrome://read-later.top-chrome/test_loader.html?module=side_panel/side_panel_app_test.js';
-  }
-};
-
-// TODO(crbug.com/1401515): Test no longer works, delete as part of the cleanup.
-TEST_F('SidePanelAppTest', 'DISABLED_All', function() {
-  mocha.run();
-});
-
 var SidePanelBookmarksListTest = class extends SidePanelBrowserTest {
   /** @override */
   get browsePreload() {
-    return 'chrome://read-later.top-chrome/test_loader.html?module=side_panel/bookmarks/bookmarks_list_test.js';
+    return 'chrome://bookmarks-side-panel.top-chrome/test_loader.html?module=side_panel/bookmarks/bookmarks_list_test.js';
   }
 };
 
@@ -42,7 +30,7 @@
 var SidePanelPowerBookmarksListTest = class extends SidePanelBrowserTest {
   /** @override */
   get browsePreload() {
-    return 'chrome://read-later.top-chrome/test_loader.html?module=side_panel/bookmarks/power_bookmarks_list_test.js';
+    return 'chrome://bookmarks-side-panel.top-chrome/test_loader.html?module=side_panel/bookmarks/power_bookmarks_list_test.js';
   }
 };
 
@@ -60,7 +48,7 @@
 var ShoppingListTest = class extends SidePanelBrowserTest {
   /** @override */
   get browsePreload() {
-    return 'chrome://read-later.top-chrome/test_loader.html?module=side_panel/bookmarks/commerce/shopping_list_test.js';
+    return 'chrome://bookmarks-side-panel.top-chrome/test_loader.html?module=side_panel/bookmarks/commerce/shopping_list_test.js';
   }
 };
 
@@ -71,7 +59,7 @@
 var SidePanelBookmarkFolderTest = class extends SidePanelBrowserTest {
   /** @override */
   get browsePreload() {
-    return 'chrome://read-later.top-chrome/test_loader.html?module=side_panel/bookmarks/bookmark_folder_test.js';
+    return 'chrome://bookmarks-side-panel.top-chrome/test_loader.html?module=side_panel/bookmarks/bookmark_folder_test.js';
   }
 };
 
@@ -83,7 +71,7 @@
 var SidePanelBookmarksDragManagerTest = class extends SidePanelBrowserTest {
   /** @override */
   get browsePreload() {
-    return 'chrome://read-later.top-chrome/test_loader.html?module=side_panel/bookmarks/bookmarks_drag_manager_test.js';
+    return 'chrome://bookmarks-side-panel.top-chrome/test_loader.html?module=side_panel/bookmarks/bookmarks_drag_manager_test.js';
   }
 };
 
diff --git a/chrome/test/data/webui/side_panel/side_panel_interactive_ui_tests.js b/chrome/test/data/webui/side_panel/side_panel_interactive_ui_tests.js
index a028788..8fc97a9 100644
--- a/chrome/test/data/webui/side_panel/side_panel_interactive_ui_tests.js
+++ b/chrome/test/data/webui/side_panel/side_panel_interactive_ui_tests.js
@@ -13,7 +13,7 @@
     class extends PolymerInteractiveUITest {
   /** @override */
   get browsePreload() {
-    return 'chrome://read-later.top-chrome/test_loader.html?module=side_panel/bookmarks/bookmarks_list_interactive_ui_test.js';
+    return 'chrome://bookmarks-side-panel.top-chrome/test_loader.html?module=side_panel/bookmarks/bookmarks_list_interactive_ui_test.js';
   }
 };
 
diff --git a/chrome/updater/util/unittest_util.cc b/chrome/updater/util/unittest_util.cc
index d8ee74e..c802c21 100644
--- a/chrome/updater/util/unittest_util.cc
+++ b/chrome/updater/util/unittest_util.cc
@@ -20,6 +20,7 @@
 #include "base/strings/strcat.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
 #include "base/threading/platform_thread.h"
 #include "base/time/time.h"
 #include "chrome/updater/constants.h"
@@ -33,6 +34,7 @@
 #if BUILDFLAG(IS_WIN)
 #include <shlobj.h>
 
+#include "base/strings/string_number_conversions_win.h"
 #include "base/win/windows_version.h"
 #include "chrome/test/base/process_inspector_win.h"
 #include "chrome/updater/util/win_util.h"
@@ -347,41 +349,37 @@
     LOG(ERROR) << __func__ << ": failed to backup pml file";
 }
 
+const base::ProcessIterator::ProcessEntries FindProcesses(
+    const base::FilePath::StringType& executable_name) {
+  return base::NamedProcessIterator(executable_name, nullptr).Snapshot();
+}
+
 base::FilePath::StringType PrintProcesses(
     const base::FilePath::StringType& executable_name) {
-  class ExeNameProcessFilter : public base::ProcessFilter {
-   public:
-    explicit ExeNameProcessFilter(
-        const base::FilePath::StringType& executable_name)
-        : executable_name_(executable_name) {}
-
-    bool Includes(const base::ProcessEntry& entry) const override {
-      return base::EqualsCaseInsensitiveASCII(entry.exe_file(),
-                                              executable_name_);
-    }
-
-   private:
-    const base::FilePath::StringType executable_name_;
-  };
-
-  base::FilePath::StringType message(FILE_PATH_LITERAL("Found processes:"));
-  const base::FilePath::StringType demarcation(72, FILE_PATH_LITERAL('='));
+  base::FilePath::StringType message(L"Found processes:\n");
+  base::FilePath::StringType demarcation(72, L'=');
+  demarcation += L'\n';
   message += demarcation;
 
-  ExeNameProcessFilter exe_name_filter(executable_name);
-  base::ProcessIterator process_iterator(&exe_name_filter);
-  const base::ProcessIterator::ProcessEntries& process_entries =
-      process_iterator.Snapshot();
-  for (const base::ProcessEntry& entry : process_entries) {
+  for (const base::ProcessEntry& entry : FindProcesses(executable_name)) {
     message += base::StrCat(
-        {entry.exe_file(), FILE_PATH_LITERAL(", cmdline="),
+        {entry.exe_file(), L", pid=", base::NumberToWString(entry.pid()),
+         L", creation time=",
+         [](base::ProcessId pid) {
+           const base::Process process = base::Process::Open(pid);
+           return process.IsValid() ? base::ASCIIToWide(base::TimeFormatHTTP(
+                                          process.CreationTime()))
+                                    : L"n/a";
+         }(entry.pid()),
+         L", cmdline=",
          [](base::ProcessId pid) {
            std::unique_ptr<ProcessInspector> process_inspector =
                ProcessInspector::Create(base::Process::OpenWithAccess(
                    pid, PROCESS_ALL_ACCESS | PROCESS_VM_READ));
            return process_inspector ? process_inspector->command_line()
-                                    : FILE_PATH_LITERAL("n/a");
-         }(entry.pid())});
+                                    : L"n/a";
+         }(entry.pid()),
+         L"\n"});
   }
 
   return message + demarcation;
diff --git a/chrome/updater/util/unittest_util.h b/chrome/updater/util/unittest_util.h
index 42d1035..05127de 100644
--- a/chrome/updater/util/unittest_util.h
+++ b/chrome/updater/util/unittest_util.h
@@ -9,6 +9,7 @@
 
 #include "base/files/file_path.h"
 #include "base/memory/scoped_refptr.h"
+#include "base/process/process_iterator.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace base {
@@ -85,6 +86,10 @@
 // procmon PML file returned from `StartProcmonLogging`.
 void StopProcmonLogging(const base::FilePath& pml_file);
 
+// Returns a list of processes matching `executable_name`.
+const base::ProcessIterator::ProcessEntries FindProcesses(
+    const base::FilePath::StringType& executable_name);
+
 // Returns a log string of processes matching `executable_name`.
 base::FilePath::StringType PrintProcesses(
     const base::FilePath::StringType& executable_name);
diff --git a/chrome/updater/util/unittest_util_unittest.cc b/chrome/updater/util/unittest_util_unittest.cc
index 9f620b7..82a81f0ae 100644
--- a/chrome/updater/util/unittest_util_unittest.cc
+++ b/chrome/updater/util/unittest_util_unittest.cc
@@ -5,19 +5,31 @@
 #include "chrome/updater/util/unittest_util.h"
 
 #include "base/base_paths.h"
+#include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/logging.h"
 #include "base/path_service.h"
+#include "base/process/launch.h"
+#include "base/process/process.h"
+#include "base/strings/strcat.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/test/bind.h"
 #include "base/test/test_timeouts.h"
 #include "build/build_config.h"
+#include "chrome/updater/test/integration_tests_impl.h"
 #include "chrome/updater/test_scope.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 #if BUILDFLAG(IS_WIN)
+#include <windows.h>
+
+#include "base/strings/string_number_conversions_win.h"
+#include "chrome/updater/util/win_util.h"
 #include "chrome/updater/win/test/test_executables.h"
+#include "chrome/updater/win/test/test_strings.h"
 #endif
 
 namespace updater::test {
@@ -110,4 +122,38 @@
   EXPECT_TRUE(base::DirectoryExists(temp_path));
 }
 
+#if BUILDFLAG(IS_WIN)
+TEST(UnitTestUtil, FindProcesses) {
+  base::CommandLine command_line =
+      GetTestProcessCommandLine(GetTestScope(), test::GetTestName());
+
+  // Create a unique name for a shared event to be waited for in the test
+  // process and signaled in this test.
+  const std::wstring event_name =
+      base::StrCat({kTestProcessExecutableName, L"-",
+                    base::NumberToWString(::GetCurrentProcessId())});
+  NamedObjectAttributes attr =
+      GetNamedObjectAttributes(event_name.c_str(), GetTestScope());
+
+  base::WaitableEvent event(base::win::ScopedHandle(
+      ::CreateEvent(&attr.sa, FALSE, FALSE, attr.name.c_str())));
+  ASSERT_NE(event.handle(), nullptr);
+
+  command_line.AppendSwitchNative(kTestEventToWaitOn, attr.name);
+
+  const base::Process process = base::LaunchProcess(command_line, {});
+  ASSERT_TRUE(process.IsValid());
+
+  EXPECT_TRUE(test::WaitFor(
+      base::BindLambdaForTesting([&]() { return process.IsRunning(); })));
+  EXPECT_EQ(test::FindProcesses(kTestProcessExecutableName).size(), 1U);
+
+  event.Signal();
+
+  EXPECT_TRUE(test::WaitFor(
+      base::BindLambdaForTesting([&]() { return !process.IsRunning(); })));
+  EXPECT_TRUE(test::FindProcesses(kTestProcessExecutableName).empty());
+}
+#endif  // BUILDFLAG(IS_WIN)
+
 }  // namespace updater::test
diff --git a/chrome/updater/win/task_scheduler_unittest.cc b/chrome/updater/win/task_scheduler_unittest.cc
index 4676903..ad43430 100644
--- a/chrome/updater/win/task_scheduler_unittest.cc
+++ b/chrome/updater/win/task_scheduler_unittest.cc
@@ -267,11 +267,13 @@
 
   EXPECT_TRUE(test::WaitFor(base::BindLambdaForTesting(
       [&]() { return task_scheduler_->IsTaskRunning(kTaskName1); })));
+  EXPECT_EQ(test::FindProcesses(kTestProcessExecutableName).size(), 1U);
 
   event.Signal();
 
   EXPECT_TRUE(test::WaitFor(base::BindLambdaForTesting(
       [&]() { return !task_scheduler_->IsTaskRunning(kTaskName1); })));
+  EXPECT_TRUE(test::FindProcesses(kTestProcessExecutableName).empty());
 }
 
 TEST_F(TaskSchedulerTests, GetTaskNameList) {
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index b7efdc6a..ec51362 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-15300.0.0
\ No newline at end of file
+15301.0.0
\ No newline at end of file
diff --git a/chromeos/ash/components/drivefs/drivefs_pin_manager.cc b/chromeos/ash/components/drivefs/drivefs_pin_manager.cc
index c367f61..50d29442 100644
--- a/chromeos/ash/components/drivefs/drivefs_pin_manager.cc
+++ b/chromeos/ash/components/drivefs/drivefs_pin_manager.cc
@@ -5,6 +5,7 @@
 #include "chromeos/ash/components/drivefs/drivefs_pin_manager.h"
 
 #include <locale>
+#include <type_traits>
 #include <utility>
 #include <vector>
 
@@ -12,11 +13,11 @@
 #include "base/functional/callback_forward.h"
 #include "base/logging.h"
 #include "base/no_destructor.h"
-#include "base/ranges/algorithm.h"
 #include "base/strings/stringprintf.h"
 #include "base/system/sys_info.h"
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool.h"
+#include "chromeos/ash/components/drivefs/mojom/drivefs.mojom.h"
 #include "components/drive/file_errors.h"
 
 namespace drivefs::pinning {
@@ -62,6 +63,87 @@
   std::string do_grouping() const override { return "\3"; }
 };
 
+template <typename T>
+struct Quoter {
+  const T& value;
+};
+
+template <typename T>
+Quoter<T> Quote(const T& value) {
+  return {value};
+}
+
+std::ostream& operator<<(std::ostream& out, Quoter<base::FilePath> q) {
+  return out << "'" << q.value << "'";
+}
+
+std::ostream& operator<<(std::ostream& out, Quoter<std::string> q) {
+  return out << "'" << q.value << "'";
+}
+
+template <typename T>
+std::ostream& operator<<(std::ostream& out, Quoter<absl::optional<T>> q) {
+  if (!q.value.has_value()) {
+    return out << "(nullopt)";
+  }
+
+  return out << Quote(*q.value);
+}
+
+std::ostream& operator<<(std::ostream& out,
+                         Quoter<mojom::FileMetadata::Type> q) {
+  using Type = mojom::FileMetadata::Type;
+  switch (q.value) {
+#define PRINT(s)   \
+  case Type::k##s: \
+    return out << #s;
+    PRINT(File)
+    PRINT(Hosted)
+    PRINT(Directory)
+#undef PRINT
+  }
+
+  return out << "Type(" << static_cast<std::underlying_type_t<Type>>(q.value)
+             << ")";
+}
+
+std::ostream& operator<<(std::ostream& out, Quoter<mojom::ItemEvent::State> q) {
+  using State = mojom::ItemEvent::State;
+  switch (q.value) {
+#define PRINT(s)    \
+  case State::k##s: \
+    return out << #s;
+    PRINT(Queued)
+    PRINT(InProgress)
+    PRINT(Completed)
+    PRINT(Failed)
+#undef PRINT
+  }
+
+  return out << "State(" << static_cast<std::underlying_type_t<State>>(q.value)
+             << ")";
+}
+
+std::ostream& operator<<(std::ostream& out, Quoter<mojom::FileMetadata> q) {
+  const mojom::FileMetadata& md = q.value;
+  return out << "{type: " << Quote(md.type)
+             << ", size: " << HumanReadableSize(md.size)
+             << ", pinned: " << md.pinned << ", can_pin: "
+             << (md.can_pin == mojom::FileMetadata::CanPinStatus::kOk)
+             << ", available_offline: " << md.available_offline
+             << ", shared: " << md.shared << ", starred: " << md.starred
+             << ", item_id = " << Quote(md.item_id) << "}";
+}
+
+std::ostream& operator<<(std::ostream& out, Quoter<mojom::ItemEvent> q) {
+  const mojom::ItemEvent& e = q.value;
+  return out << "{state: " << Quote(e.state) << ", path: " << Quote(e.path)
+             << ", bytes_transferred: " << e.bytes_transferred
+             << ", bytes_to_transfer: " << e.bytes_to_transfer << "}";
+}
+
+constexpr int64_t kAverageHostedFileSizeInBytes = 7800;
+
 }  // namespace
 
 std::ostream& operator<<(std::ostream& out, HumanReadableSize size) {
@@ -114,11 +196,8 @@
 #undef PRINT
   }
 
-  return out
-         << "SetupError("
-         << static_cast<std::underlying_type_t<drivefs::pinning::SetupError>>(
-                error)
-         << ")";
+  return out << "SetupError("
+             << static_cast<std::underlying_type_t<SetupError>>(error) << ")";
 }
 
 std::ostream& operator<<(std::ostream& out, const SetupStage stage) {
@@ -135,11 +214,8 @@
 #undef PRINT
   }
 
-  return out
-         << "SetupStage("
-         << static_cast<std::underlying_type_t<drivefs::pinning::SetupStage>>(
-                stage)
-         << ")";
+  return out << "SetupStage("
+             << static_cast<std::underlying_type_t<SetupStage>>(stage) << ")";
 }
 
 // TODO(b/261530666): This was chosen arbitrarily, this should be experimented
@@ -159,8 +235,8 @@
   // Emplace an item with no progress (yet). The progress values will get
   // updated in the `OnSyncingStatusUpdate`.
   const auto [it, ok] = in_progress_items_.try_emplace(path);
-  LOG_IF(ERROR, !ok) << "Cannot add item '" << path
-                     << "': There is already an item with progress "
+  LOG_IF(ERROR, !ok) << "Cannot add item " << Quote(path)
+                     << ": There is already an item with progress "
                      << HumanReadableSize(it->second.transferred) << " / "
                      << HumanReadableSize(it->second.total);
   DCHECK_EQ(path, it->first);
@@ -170,7 +246,7 @@
     const std::string& path,
     const int64_t total_bytes) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK_GE(total_bytes, 0) << " for '" << path << "'";
+  DCHECK_GE(total_bytes, 0) << " for " << Quote(path);
 
   const auto it = in_progress_items_.find(path);
   if (it == in_progress_items_.end()) {
@@ -179,7 +255,7 @@
     // In this case, gracefully degrade by responding with the total bytes
     // transferred. This should ideally fail as all syncing operations should be
     // identified as they affect disk space.
-    LOG(ERROR) << "Cannot remove '" << path << "'";
+    VLOG(2) << "Cannot remove " << Quote(path);
     return total_bytes_transferred_;
   }
 
@@ -188,7 +264,7 @@
   LOG_IF(ERROR, progress.transferred > total_bytes)
       << "Progress went backwards from "
       << HumanReadableSize(progress.transferred) << " to "
-      << HumanReadableSize(total_bytes) << " for '" << path << "'";
+      << HumanReadableSize(total_bytes) << " for " << Quote(path);
   total_bytes_transferred_ += total_bytes - progress.transferred;
   in_progress_items_.erase(it);
   return total_bytes_transferred_;
@@ -196,38 +272,23 @@
 
 int64_t DriveFsPinManager::InProgressSyncingItems::UpdateItem(
     const std::string& path,
-    int64_t bytes_transferred,
-    int64_t bytes_to_transfer) {
+    const int64_t bytes_transferred,
+    const int64_t bytes_to_transfer) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK_GE(bytes_to_transfer, 0) << " for '" << path << "'";
+  DCHECK_GE(bytes_to_transfer, 0) << " for " << Quote(path);
 
   if (bytes_transferred < 0) {
     LOG(ERROR) << "Negative bytes_transferred = "
-               << HumanReadableSize(bytes_transferred) << " for '" << path
-               << "'";
+               << HumanReadableSize(bytes_transferred) << " for "
+               << Quote(path);
     return total_bytes_transferred_;
   }
 
-  const auto it = in_progress_items_.find(path);
-  if (it == in_progress_items_.end()) {
-    // TODO(b/261530520): Items can end up in this flow when an update is
-    // attempted on an item that wasn't tracked via an explicit pin operation.
-    // In this case, gracefully degrade by responding with the total bytes
-    // transferred. This should ideally fail as all syncing operations should be
-    // identified as they affect disk space.
-    LOG(ERROR) << "Cannot update '" << path << "' with bytes_transferred = "
-               << HumanReadableSize(bytes_transferred)
-               << " and bytes_to_transfer = "
-               << HumanReadableSize(bytes_to_transfer);
-    return total_bytes_transferred_;
-  }
-
-  DCHECK_EQ(it->first, path);
-  Progress& progress = it->second;
+  Progress& progress = in_progress_items_[path];
   LOG_IF(ERROR, progress.transferred > bytes_transferred)
       << "Progress went backwards from "
       << HumanReadableSize(progress.transferred) << " to "
-      << HumanReadableSize(bytes_transferred) << " for '" << path << "'";
+      << HumanReadableSize(bytes_transferred) << " for " << Quote(path);
   total_bytes_transferred_ += bytes_transferred - progress.transferred;
   progress.transferred = bytes_transferred;
   progress.total = bytes_to_transfer;
@@ -328,7 +389,7 @@
 
 void DriveFsPinManager::OnSearchResultForSizeCalculation(
     const drive::FileError error,
-    const absl::optional<std::vector<drivefs::mojom::QueryItemPtr>> items) {
+    const absl::optional<std::vector<mojom::QueryItemPtr>> items) {
   if (error != drive::FILE_ERROR_OK || !items) {
     LOG(ERROR) << "Cannot list files for size calculation: " << error;
     return Complete(SetupError::kCannotRetrieveSearchResults);
@@ -346,23 +407,30 @@
 
   VLOG(2) << "Iterating over " << items->size()
           << " items for space calculation";
-  for (const drivefs::mojom::QueryItemPtr& item : *items) {
+  for (const mojom::QueryItemPtr& item : *items) {
     DCHECK(item);
     DCHECK(item->metadata);
 
-    VLOG(2) << "path: '" << item->path
-            << "', size: " << HumanReadableSize(item->metadata->size)
-            << ", pinned: " << item->metadata->pinned
-            << ", available_offline: " << item->metadata->available_offline;
-    if (item->metadata->pinned) {
-      VLOG(2) << "Skipped '" << item->path << "': Already pinned";
+    const mojom::FileMetadata& md = *item->metadata;
+    VLOG(2) << "path: " << Quote(item->path) << ", metadata: " << Quote(md);
+
+    if (md.pinned) {
+      VLOG(2) << "Skipped " << Quote(item->path) << ": Already pinned";
       continue;
     }
 
-    DCHECK_GE(item->metadata->size, 0)
-        << "Negative size " << HumanReadableSize(item->metadata->size)
-        << "for '" << item->path << "'";
-    state_.progress.required_disk_space += item->metadata->size;
+    if (md.can_pin != mojom::FileMetadata::CanPinStatus::kOk) {
+      VLOG(2) << "Skipped " << Quote(item->path) << ": Cannot be pinned";
+      continue;
+    }
+
+    if (md.type == mojom::FileMetadata::Type::kHosted) {
+      state_.progress.required_disk_space += kAverageHostedFileSizeInBytes;
+      continue;
+    }
+
+    DCHECK_GE(md.size, 0) << " for " << Quote(item->path);
+    state_.progress.required_disk_space += md.size;
   }
 
   // TODO(b/259454320): This should really not use up all free space but instead
@@ -429,7 +497,7 @@
 
 void DriveFsPinManager::OnSearchResultsForPinning(
     const drive::FileError error,
-    const absl::optional<std::vector<drivefs::mojom::QueryItemPtr>> items) {
+    const absl::optional<std::vector<mojom::QueryItemPtr>> items) {
   if (error != drive::FILE_ERROR_OK || !items) {
     LOG(ERROR) << "Cannot list files to pin: " << error;
     return Complete(SetupError::kCannotRetrieveSearchResults);
@@ -452,17 +520,21 @@
   // operations writing to disk might cause cause the free space to get used
   // faster than anticipated.
   bool processed = false;
-  for (const drivefs::mojom::QueryItemPtr& item : *items) {
+  for (const mojom::QueryItemPtr& item : *items) {
     DCHECK(item);
     const base::FilePath& path = item->path;
-
     DCHECK(item->metadata);
-    if (item->metadata->pinned) {
-      VLOG(2) << "Skipped '" << path << "': Already pinned";
+    const mojom::FileMetadata& md = *item->metadata;
+    VLOG(2) << "path: " << Quote(path) << ", metadata: " << Quote(md);
+    if (md.pinned) {
+      VLOG(2) << "Skipped " << Quote(md.type) << " " << Quote(path)
+              << ": Already pinned";
       continue;
     }
 
-    VLOG(2) << "Pinning '" << path << "'...";
+    VLOG(2) << "Pinning " << Quote(md.type) << " " << Quote(path) << "...";
+    syncing_items_.AsyncCall(&InProgressSyncingItems::AddItem)
+        .WithArgs(path.value());
     drivefs_interface_->SetPinned(
         path, /*pinned=*/true,
         base::BindOnce(&DriveFsPinManager::OnFilePinned,
@@ -488,13 +560,12 @@
 void DriveFsPinManager::OnFilePinned(const std::string& path,
                                      const drive::FileError status) {
   if (status != drive::FILE_ERROR_OK) {
-    LOG(ERROR) << "Cannot pin '" << path << "': " << status;
+    LOG(ERROR) << "Cannot pin " << Quote(path) << ": " << status;
     state_.progress.error_count++;
     return;
   }
 
-  VLOG(2) << "Pinned '" << path << "'";
-  syncing_items_.AsyncCall(&InProgressSyncingItems::AddItem).WithArgs(path);
+  VLOG(2) << "Pinned " << Quote(path);
 }
 
 void DriveFsPinManager::OnSyncingStatusUpdate(
@@ -503,29 +574,42 @@
     return;
   }
 
-  for (const mojom::ItemEventPtr& item : status.item_events) {
-    DCHECK(item);
+  for (const mojom::ItemEventPtr& event : status.item_events) {
+    DCHECK(event);
+    VLOG(2) << "Got event: " << Quote(*event);
 
-    // TODO(b/259454320): Hosted files (e.g. gdoc) do not send an update via the
-    // `OnSyncingStatusUpdate` method. Need to add a method to cleanse the
-    // `in_progress_items_` map to ensure any values that are small enough or
-    // optimistically pinned get removed.
-    if (item->state == mojom::ItemEvent::State::kCompleted) {
-      VLOG(2) << "Synced '" << item->path << "'";
-      GetMetadataForPath(base::FilePath(item->path));
-      continue;
+    using State = mojom::ItemEvent::State;
+
+    switch (event->state) {
+      case State::kQueued:
+        VLOG(2) << "Queued " << Quote(event->path);
+        continue;
+
+      case State::kCompleted:
+        VLOG(2) << "Synced " << Quote(event->path);
+        GetMetadataForPath(event->path);
+        continue;
+
+      case State::kFailed:
+        LOG(ERROR) << "Cannot sync " << Quote(event->path);
+        state_.progress.error_count++;
+        continue;
+
+      case State::kInProgress:
+        LOG_IF(ERROR, event->bytes_transferred < 0)
+            << "Negative bytes_transferred " << event->bytes_transferred
+            << " for " << Quote(event->path);
+        LOG_IF(ERROR, event->bytes_to_transfer < 0)
+            << "Negative bytes_to_transfer " << event->bytes_to_transfer
+            << " for " << Quote(event->path);
+        syncing_items_.AsyncCall(&InProgressSyncingItems::UpdateItem)
+            .WithArgs(event->path, event->bytes_transferred,
+                      event->bytes_to_transfer)
+            .Then(
+                base::BindOnce(&DriveFsPinManager::ReportTotalBytesTransferred,
+                               weak_ptr_factory_.GetWeakPtr()));
+        continue;
     }
-
-    if (item->state == mojom::ItemEvent::State::kFailed) {
-      LOG(ERROR) << "Cannot sync '" << item->path << "'";
-      state_.progress.error_count++;
-      continue;
-    }
-
-    syncing_items_.AsyncCall(&InProgressSyncingItems::UpdateItem)
-        .WithArgs(item->path, item->bytes_transferred, item->bytes_to_transfer)
-        .Then(base::BindOnce(&DriveFsPinManager::ReportTotalBytesTransferred,
-                             weak_ptr_factory_.GetWeakPtr()));
   }
 
   syncing_items_.AsyncCall(&InProgressSyncingItems::GetItemCount)
@@ -560,8 +644,7 @@
     const std::vector<mojom::FileChange>& changes) {}
 
 void DriveFsPinManager::OnError(const mojom::DriveError& error) {
-  LOG(ERROR) << "DriveFS error " << error.type << " with '" << error.path
-             << "'";
+  LOG(ERROR) << "DriveFS error " << error.type << " with " << Quote(error.path);
 }
 
 void DriveFsPinManager::NotifyProgress() {
@@ -569,11 +652,11 @@
     return;
   }
 
-  VLOG(2) << "Notifying observers...";
+  VLOG(3) << "Notifying observers...";
   for (DriveFsBulkPinObserver& observer : observers_) {
     observer.OnSetupProgress(state_.progress);
   }
-  VLOG(2) << "Notified observers";
+  VLOG(3) << "Notified observers";
 }
 
 void DriveFsPinManager::AddObserver(DriveFsBulkPinObserver* observer) {
@@ -612,10 +695,11 @@
                            weak_ptr_factory_.GetWeakPtr()));
 }
 
-void DriveFsPinManager::GetMetadataForPath(const base::FilePath& path) {
+void DriveFsPinManager::GetMetadataForPath(const std::string& path) {
   drivefs_interface_->GetMetadata(
-      path, base::BindOnce(&DriveFsPinManager::OnMetadataRetrieved,
-                           weak_ptr_factory_.GetWeakPtr(), path.value()));
+      base::FilePath(path),
+      base::BindOnce(&DriveFsPinManager::OnMetadataRetrieved,
+                     weak_ptr_factory_.GetWeakPtr(), path));
 }
 
 void DriveFsPinManager::OnMetadataRetrieved(
@@ -623,22 +707,25 @@
     const drive::FileError error,
     const mojom::FileMetadataPtr metadata) {
   if (error != drive::FILE_ERROR_OK) {
-    LOG(ERROR) << "Cannot get metadata of '" << path << "': " << error;
+    LOG(ERROR) << "Cannot get metadata of " << Quote(path) << ": " << error;
     return;
   }
 
   DCHECK(metadata);
-  VLOG(2) << "Got metadata of path: '" << path
-          << "', size: " << HumanReadableSize(metadata->size)
-          << ", pinned: " << metadata->pinned
-          << ", available_offline: " << metadata->available_offline;
+  VLOG(2) << "path: " << Quote(path) << ", metadata: " << Quote(*metadata);
 
   if (metadata->available_offline || metadata->size == 0) {
+    const int64_t file_size =
+        (metadata->type == mojom::FileMetadata::Type::kHosted)
+            ? kAverageHostedFileSizeInBytes
+            : metadata->size;
+
     VLOG_IF(2, metadata->available_offline)
-        << "Skipped '" << path << "': Already available offline";
-    VLOG_IF(2, metadata->size == 0) << "Skipped '" << path << "': Empty file";
+        << "Skipped " << Quote(path) << ": Already available offline";
+    VLOG_IF(2, metadata->size == 0)
+        << "Skipped " << Quote(path) << ": Empty file";
     syncing_items_.AsyncCall(&InProgressSyncingItems::RemoveItem)
-        .WithArgs(std::move(path), metadata->size)
+        .WithArgs(std::move(path), file_size)
         .Then(base::BindOnce(&DriveFsPinManager::ReportTotalBytesTransferred,
                              weak_ptr_factory_.GetWeakPtr()));
   }
diff --git a/chromeos/ash/components/drivefs/drivefs_pin_manager.h b/chromeos/ash/components/drivefs/drivefs_pin_manager.h
index 1984f87b..59df693 100644
--- a/chromeos/ash/components/drivefs/drivefs_pin_manager.h
+++ b/chromeos/ash/components/drivefs/drivefs_pin_manager.h
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "base/component_export.h"
+#include "base/files/file_path.h"
 #include "base/functional/callback.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
@@ -189,8 +190,8 @@
     // removal. Returns the total bytes transferred on every removal.
     int64_t RemoveItem(const std::string& path, int64_t total_bytes);
 
-    // Update the item keyed at `path` with the new progress bytes. Returns the
-    // total bytes transferred on every update.
+    // Adds or updates the item keyed at `path` with the new progress bytes.
+    // Returns the total bytes transferred on every update.
     int64_t UpdateItem(const std::string& path,
                        int64_t bytes_transferred,
                        int64_t bytes_to_transfer);
@@ -266,7 +267,7 @@
   // When an item goes to completed, it doesn't emit the final chunk of progress
   // nor it's final size, to ensure progress is adequately retrieved, this
   // method is used to get the total size to keep track of.
-  void GetMetadataForPath(const base::FilePath& path);
+  void GetMetadataForPath(const std::string& path);
   void OnMetadataRetrieved(const std::string& path,
                            drive::FileError error,
                            mojom::FileMetadataPtr metadata);
diff --git a/chromeos/components/quick_answers/search_result_parsers/unit_conversion_result_parser.cc b/chromeos/components/quick_answers/search_result_parsers/unit_conversion_result_parser.cc
index 37249a4..7249ecd 100644
--- a/chromeos/components/quick_answers/search_result_parsers/unit_conversion_result_parser.cc
+++ b/chromeos/components/quick_answers/search_result_parsers/unit_conversion_result_parser.cc
@@ -35,16 +35,16 @@
     if (ratio.has_value() && ratio.value() > kPreferredRatioRange) {
       const auto* rule = result->FindListPath(kRuleSetPath);
       if (rule) {
-        UnitConverter converter(*rule);
+        UnitConverter converter(rule->GetList());
 
         const auto* src_unit = result->FindPath(kSourceUnitPath);
         if (src_unit) {
-          const auto* dst_unit =
-              converter.FindProperDestinationUnit(*src_unit, ratio.value());
+          const auto* dst_unit = converter.FindProperDestinationUnit(
+              src_unit->GetDict(), ratio.value());
 
           if (dst_unit) {
-            result_string =
-                converter.Convert(src_amount.value(), *src_unit, *dst_unit);
+            result_string = converter.Convert(src_amount.value(),
+                                              src_unit->GetDict(), *dst_unit);
           }
         }
       }
diff --git a/chromeos/components/quick_answers/utils/unit_converter.cc b/chromeos/components/quick_answers/utils/unit_converter.cc
index e22ce35..71537fc 100644
--- a/chromeos/components/quick_answers/utils/unit_converter.cc
+++ b/chromeos/components/quick_answers/utils/unit_converter.cc
@@ -22,21 +22,22 @@
 
 }  // namespace
 
-UnitConverter::UnitConverter(const Value& rule_set) : rule_set_(rule_set) {}
+UnitConverter::UnitConverter(const Value::List& rule_set)
+    : rule_set_(rule_set) {}
 
 UnitConverter::~UnitConverter() = default;
 
 const std::string UnitConverter::Convert(const double src_value,
-                                         const base::Value& src_unit,
-                                         const base::Value& dst_unit) {
+                                         const base::Value::Dict& src_unit,
+                                         const base::Value::Dict& dst_unit) {
   // Validate the inputs.
-  const auto* src_name = src_unit.FindStringPath(kNamePath);
-  const auto src_rate_a = src_unit.FindDoublePath(kConversionRateAPath);
+  const auto* src_name = src_unit.FindStringByDottedPath(kNamePath);
+  const auto src_rate_a = src_unit.FindDoubleByDottedPath(kConversionRateAPath);
   if (!src_name || !IsLinearFormula(src_rate_a)) {
     return std::string();
   }
-  const auto* dst_name = dst_unit.FindStringPath(kNamePath);
-  const auto dst_rate_a = dst_unit.FindDoublePath(kConversionRateAPath);
+  const auto* dst_name = dst_unit.FindStringByDottedPath(kNamePath);
+  const auto dst_rate_a = dst_unit.FindDoubleByDottedPath(kConversionRateAPath);
   if (!dst_name || !IsLinearFormula(dst_rate_a)) {
     return std::string();
   }
@@ -49,12 +50,12 @@
       GetUnitDisplayText(*dst_name));
 }
 
-const Value* UnitConverter::FindProperDestinationUnit(
-    const Value& src_unit,
+const Value::Dict* UnitConverter::FindProperDestinationUnit(
+    const Value::Dict& src_unit,
     const double preferred_range) {
-  const auto* src_category = src_unit.FindStringPath(kCategoryPath);
-  const auto* src_name = src_unit.FindStringPath(kNamePath);
-  const auto src_rate_a = src_unit.FindDoublePath(kConversionRateAPath);
+  const auto* src_category = src_unit.FindStringByDottedPath(kCategoryPath);
+  const auto* src_name = src_unit.FindStringByDottedPath(kNamePath);
+  const auto src_rate_a = src_unit.FindDoubleByDottedPath(kConversionRateAPath);
   // Make sure the input source unit is valid.
   if (!src_category || !src_name || !IsLinearFormula(src_rate_a))
     return nullptr;
@@ -65,11 +66,12 @@
 
   // Find the unit with closest conversion rate within the preferred range. If
   // no proper unit found, return nullptr.
-  const Value* dst_unit = nullptr;
+  const Value::Dict* dst_unit = nullptr;
   double min_rate = preferred_range;
-  for (const Value& unit : units->GetList()) {
-    const auto* name = unit.FindStringPath(kNamePath);
-    const auto rate_a = unit.FindDoublePath(kConversionRateAPath);
+  for (const Value& unit_value : *units) {
+    const base::Value::Dict& unit = unit_value.GetDict();
+    const auto* name = unit.FindStringByDottedPath(kNamePath);
+    const auto rate_a = unit.FindDoubleByDottedPath(kConversionRateAPath);
     if (*name == *src_name || !rate_a.has_value() || rate_a.value() == 0)
       continue;
     auto rate = GetRatio(rate_a.value(), src_rate_a.value());
@@ -82,26 +84,26 @@
   return dst_unit;
 }
 
-const Value* UnitConverter::GetConversionForCategory(
+const Value::Dict* UnitConverter::GetConversionForCategory(
     const std::string& target_category) {
-  if (rule_set_.GetList().empty())
-    return nullptr;
-  for (const Value& conversion : rule_set_.GetList()) {
-    const auto* category = conversion.FindStringPath(kCategoryPath);
+  for (const Value& conversion : rule_set_) {
+    const base::Value::Dict& conversion_dict = conversion.GetDict();
+    const auto* category =
+        conversion_dict.FindStringByDottedPath(kCategoryPath);
     if (category && *category == target_category)
-      return &conversion;
+      return &conversion_dict;
   }
   return nullptr;
 }
 
-const Value* UnitConverter::GetPossibleUnitsForCategory(
+const Value::List* UnitConverter::GetPossibleUnitsForCategory(
     const std::string& target_category) {
   // Get the list of conversion rate for the category.
   const auto* conversion = GetConversionForCategory(target_category);
   if (!conversion)
     return nullptr;
 
-  return conversion->FindListPath(kUnitsPath);
+  return conversion->FindListByDottedPath(kUnitsPath);
 }
 
 }  // namespace quick_answers
diff --git a/chromeos/components/quick_answers/utils/unit_converter.h b/chromeos/components/quick_answers/utils/unit_converter.h
index 3558266..632b1a0 100644
--- a/chromeos/components/quick_answers/utils/unit_converter.h
+++ b/chromeos/components/quick_answers/utils/unit_converter.h
@@ -14,7 +14,7 @@
 // Utility class for unit conversion.
 class UnitConverter {
  public:
-  explicit UnitConverter(const base::Value& rule_set);
+  explicit UnitConverter(const base::Value::List& rule_set);
 
   UnitConverter(const UnitConverter&) = delete;
   UnitConverter& operator=(const UnitConverter&) = delete;
@@ -23,25 +23,26 @@
 
   // Convert the |src_value| from |src_unit| to |dst_unit|.
   const std::string Convert(const double src_value,
-                            const base::Value& src_unit,
-                            const base::Value& dst_unit);
+                            const base::Value::Dict& src_unit,
+                            const base::Value::Dict& dst_unit);
 
   // Find the unit with the closest conversion rate within the preferred range.
   // Return nullptr if no proper unit type found.
-  const base::Value* FindProperDestinationUnit(const base::Value& src_unit,
-                                               const double preferred_range);
+  const base::Value::Dict* FindProperDestinationUnit(
+      const base::Value::Dict& src_unit,
+      const double preferred_range);
 
   // Get the list of conversion rates for the given category.
-  const base::Value* GetConversionForCategory(
+  const base::Value::Dict* GetConversionForCategory(
       const std::string& target_category);
 
-  const base::Value* GetPossibleUnitsForCategory(
+  const base::Value::List* GetPossibleUnitsForCategory(
       const std::string& target_category);
 
  private:
   // Conversion rule set for supported unit types.
   // |rules_set_| needs to outlive the converter.
-  const base::Value& rule_set_;
+  const base::Value::List& rule_set_;
 };
 
 }  // namespace quick_answers
diff --git a/chromeos/components/quick_answers/utils/unit_converter_unittest.cc b/chromeos/components/quick_answers/utils/unit_converter_unittest.cc
index 42be056..9b102e88 100644
--- a/chromeos/components/quick_answers/utils/unit_converter_unittest.cc
+++ b/chromeos/components/quick_answers/utils/unit_converter_unittest.cc
@@ -17,7 +17,6 @@
 namespace {
 
 using base::Value;
-using Type = base::Value::Type;
 
 constexpr char kMassCategory[] = "Mass";
 constexpr char kLengthCategory[] = "Length";
@@ -34,14 +33,14 @@
 constexpr double kStrictPreferredRange = 1.001;
 constexpr double kConvertSouceValue = 100;
 
-Value CreateUnit(double rate_a,
-                 const std::string& name,
-                 const std::string& category = std::string()) {
-  Value unit(Type::DICTIONARY);
-  unit.SetDoubleKey(kConversionRateAPath, rate_a);
-  unit.SetStringKey(kNamePath, name);
+Value::Dict CreateUnit(double rate_a,
+                       const std::string& name,
+                       const std::string& category = std::string()) {
+  Value::Dict unit;
+  unit.Set(kConversionRateAPath, rate_a);
+  unit.Set(kNamePath, name);
   if (!category.empty())
-    unit.SetStringKey(kCategoryPath, category);
+    unit.Set(kCategoryPath, category);
 
   return unit;
 }
@@ -50,7 +49,7 @@
 
 class UnitConverterTest : public testing::Test {
  public:
-  UnitConverterTest() : rule_set_(Type::LIST) {}
+  UnitConverterTest() = default;
 
   UnitConverterTest(const UnitConverterTest&) = delete;
   UnitConverterTest& operator=(const UnitConverterTest&) = delete;
@@ -62,15 +61,15 @@
   }
 
   void AddConversion(const std::string& category, Value units) {
-    Value conversion(Type::DICTIONARY);
-    conversion.SetStringKey(kCategoryPath, category);
-    conversion.SetKey(kUnitsPath, std::move(units));
+    Value::Dict conversion;
+    conversion.Set(kCategoryPath, category);
+    conversion.Set(kUnitsPath, std::move(units));
 
     rule_set_.Append(std::move(conversion));
   }
 
  private:
-  Value rule_set_;
+  Value::List rule_set_;
   std::unique_ptr<UnitConverter> converter_;
 };
 
@@ -93,7 +92,7 @@
   auto* converter = CreateUnitConverter();
 
   auto* conversion = converter->GetConversionForCategory(kMassCategory);
-  auto* category_name = conversion->FindStringPath(kCategoryPath);
+  auto* category_name = conversion->FindStringByDottedPath(kCategoryPath);
   EXPECT_EQ(*category_name, kMassCategory);
 }
 
@@ -105,17 +104,17 @@
 }
 
 TEST_F(UnitConverterTest, GetPossibleUnitsWithKnownCategoryShouldSuccess) {
-  Value input_units(Type::LIST);
+  Value::List input_units;
   input_units.Append(CreateUnit(kKilogramRateA, kKilogramName));
 
-  AddConversion(kMassCategory, std::move(input_units));
+  AddConversion(kMassCategory, Value(std::move(input_units)));
   auto* converter = CreateUnitConverter();
 
   auto* units = converter->GetPossibleUnitsForCategory(kMassCategory);
-  EXPECT_EQ(units->GetList().size(), 1u);
-  auto* unit = &units->GetList()[0];
-  EXPECT_EQ(unit->FindDoublePath(kConversionRateAPath), kKilogramRateA);
-  EXPECT_EQ(*unit->FindStringPath(kNamePath), kKilogramName);
+  EXPECT_EQ(units->size(), 1u);
+  auto& unit = (*units)[0].GetDict();
+  EXPECT_EQ(unit.FindDoubleByDottedPath(kConversionRateAPath), kKilogramRateA);
+  EXPECT_EQ(*unit.FindStringByDottedPath(kNamePath), kKilogramName);
 }
 
 TEST_F(UnitConverterTest,
@@ -130,10 +129,10 @@
 
 TEST_F(UnitConverterTest,
        FindProperDestinationUnitForSameUnitShouldReturnNullptr) {
-  Value input_units(Type::LIST);
+  Value::List input_units;
   input_units.Append(CreateUnit(kKilogramRateA, kKilogramName));
 
-  AddConversion(kMassCategory, std::move(input_units));
+  AddConversion(kMassCategory, Value(std::move(input_units)));
   auto* converter = CreateUnitConverter();
 
   // Should ignore the source unit itself in the ruleset.
@@ -145,42 +144,42 @@
 
 TEST_F(UnitConverterTest,
        FindProperDestinationUnitWithProperUnitsShouldSuccess) {
-  Value input_units(Type::LIST);
+  Value::List input_units;
   input_units.Append(CreateUnit(kKilogramRateA, kKilogramName));
   input_units.Append(CreateUnit(kPoundRateA, kPoundName));
 
-  AddConversion(kMassCategory, std::move(input_units));
+  AddConversion(kMassCategory, Value(std::move(input_units)));
   auto* converter = CreateUnitConverter();
 
   auto* unit = converter->FindProperDestinationUnit(
       CreateUnit(kKilogramRateA, kKilogramName, kMassCategory),
       kSamplePreferredRange);
-  EXPECT_EQ(unit->FindDoublePath(kConversionRateAPath), kPoundRateA);
-  EXPECT_EQ(*unit->FindStringPath(kNamePath), kPoundName);
+  EXPECT_EQ(unit->FindDoubleByDottedPath(kConversionRateAPath), kPoundRateA);
+  EXPECT_EQ(*unit->FindStringByDottedPath(kNamePath), kPoundName);
 }
 
 TEST_F(UnitConverterTest,
        FindProperDestinationUnitForEmptySourceUnitShouldReturnNullptr) {
-  Value input_units(Type::LIST);
+  Value::List input_units;
   input_units.Append(CreateUnit(kKilogramRateA, kKilogramName));
   input_units.Append(CreateUnit(kPoundRateA, kPoundName));
 
-  AddConversion(kMassCategory, std::move(input_units));
+  AddConversion(kMassCategory, Value(std::move(input_units)));
   auto* converter = CreateUnitConverter();
 
   // Should find nothing for empty source unit.
-  auto* unit = converter->FindProperDestinationUnit(Value(Type::DICTIONARY),
+  auto* unit = converter->FindProperDestinationUnit(Value::Dict(),
                                                     kSamplePreferredRange);
   EXPECT_EQ(unit, nullptr);
 }
 
 TEST_F(UnitConverterTest,
        FindProperDestinationUnitForStrictRangeShouldReturnNullptr) {
-  Value input_units(Type::LIST);
+  Value::List input_units;
   input_units.Append(CreateUnit(kKilogramRateA, kKilogramName));
   input_units.Append(CreateUnit(kPoundRateA, kPoundName));
 
-  AddConversion(kMassCategory, std::move(input_units));
+  AddConversion(kMassCategory, Value(std::move(input_units)));
   auto* converter = CreateUnitConverter();
 
   // No unit within the preferred conversion rate found.
@@ -192,19 +191,19 @@
 
 TEST_F(UnitConverterTest,
        FindProperDestinationUnitBetweenMultipleUnitsShouldReturnClosestRate) {
-  Value input_units(Type::LIST);
+  Value::List input_units;
   input_units.Append(CreateUnit(kKilogramRateA, kKilogramName));
   input_units.Append(CreateUnit(kPoundRateA, kPoundName));
   input_units.Append(CreateUnit(kOunceRateA, kOunceName));
 
-  AddConversion(kMassCategory, std::move(input_units));
+  AddConversion(kMassCategory, Value(std::move(input_units)));
   auto* converter = CreateUnitConverter();
 
   // Should return the unit with closest conversion rate, which is Pound.
   auto* unit = converter->FindProperDestinationUnit(
       CreateUnit(kKilogramRateA, kKilogramName, kMassCategory), 100);
-  EXPECT_EQ(unit->FindDoublePath(kConversionRateAPath), kPoundRateA);
-  EXPECT_EQ(*unit->FindStringPath(kNamePath), kPoundName);
+  EXPECT_EQ(unit->FindDoubleByDottedPath(kConversionRateAPath), kPoundRateA);
+  EXPECT_EQ(*unit->FindStringByDottedPath(kNamePath), kPoundName);
 }
 
 TEST_F(UnitConverterTest, ConvertWithProperInputShouldSuccess) {
diff --git a/components/autofill/core/browser/autofill_suggestion_generator_unittest.cc b/components/autofill/core/browser/autofill_suggestion_generator_unittest.cc
index 503f155..74ba8696 100644
--- a/components/autofill/core/browser/autofill_suggestion_generator_unittest.cc
+++ b/components/autofill/core/browser/autofill_suggestion_generator_unittest.cc
@@ -490,185 +490,6 @@
   }
 }
 
-// Verify that the suggestion's texts are populated correctly for a virtual card
-// suggestion when the cardholder name field is focused.
-TEST_F(AutofillSuggestionGeneratorTest,
-       CreateCreditCardSuggestion_VirtualCardMetadata_NameField) {
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitWithFeatures(
-      /*enabled_features=*/{features::kAutofillEnableVirtualCardMetadata,
-                            features::kAutofillEnableCardProductName},
-      /*disabled_features=*/{});
-
-  // Create a server card.
-  CreditCard server_card = CreateServerCard();
-
-  // Name field suggestion for virtual cards.
-  Suggestion virtual_card_name_field_suggestion =
-      suggestion_generator()->CreateCreditCardSuggestion(
-          server_card, AutofillType(CREDIT_CARD_NAME_FULL),
-          /*virtual_card_option=*/true,
-          /*card_linked_offer_available=*/false);
-
-  EXPECT_EQ(virtual_card_name_field_suggestion.main_text.value,
-            u"Elvis Presley");
-  EXPECT_EQ(virtual_card_name_field_suggestion.minor_text.value, u"");
-
-  ASSERT_EQ(virtual_card_name_field_suggestion.labels.size(), 2U);
-
-#if BUILDFLAG(IS_IOS)
-  // For IOS, the label is "....1234".
-  ASSERT_EQ(virtual_card_name_field_suggestion.labels[0].size(), 1U);
-  EXPECT_EQ(virtual_card_name_field_suggestion.labels[0][0].value,
-            internal::GetObfuscatedStringForCardDigits(u"1111", 4));
-#else
-  // For Desktop/Android, the label is "CardName  ....1234". Card name and last
-  // four are shown separately.
-  ASSERT_EQ(virtual_card_name_field_suggestion.labels[0].size(), 2U);
-  EXPECT_EQ(virtual_card_name_field_suggestion.labels[0][0].value, u"Visa");
-  EXPECT_EQ(virtual_card_name_field_suggestion.labels[0][1].value,
-            internal::GetObfuscatedStringForCardDigits(u"1111", 4));
-#endif
-  // The virtual card text should be populated in the labels to be shown in a
-  // new line.
-  ASSERT_EQ(virtual_card_name_field_suggestion.labels[1].size(), 1U);
-  EXPECT_EQ(virtual_card_name_field_suggestion.labels[1][0].value,
-            u"Virtual card");
-}
-
-// Verify that the suggestion's texts are populated correctly for a virtual card
-// suggestion when the card number field is focused.
-TEST_F(AutofillSuggestionGeneratorTest,
-       CreateCreditCardSuggestion_VirtualCardMetadata_NumberField) {
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitWithFeatures(
-      /*enabled_features=*/{features::kAutofillEnableVirtualCardMetadata,
-                            features::kAutofillEnableCardProductName},
-      /*disabled_features=*/{});
-
-  // Create a server card.
-  CreditCard server_card = CreateServerCard();
-
-  // Card number field suggestion for virtual cards.
-  Suggestion virtual_card_number_field_suggestion =
-      suggestion_generator()->CreateCreditCardSuggestion(
-          server_card, AutofillType(CREDIT_CARD_NUMBER),
-          /*virtual_card_option=*/true,
-          /*card_linked_offer_available=*/false);
-
-#if BUILDFLAG(IS_IOS)
-  // Only card number is displayed on the first line.
-  EXPECT_EQ(virtual_card_number_field_suggestion.main_text.value,
-            base::StrCat({u"Visa  ", internal::GetObfuscatedStringForCardDigits(
-                                         u"1111", 4)}));
-  EXPECT_EQ(virtual_card_number_field_suggestion.minor_text.value, u"");
-#else
-  // Card name and the obfuscated last four digits are shown separately.
-  EXPECT_EQ(virtual_card_number_field_suggestion.main_text.value, u"Visa");
-  EXPECT_EQ(virtual_card_number_field_suggestion.minor_text.value,
-            internal::GetObfuscatedStringForCardDigits(u"1111", 4));
-#endif
-
-  // "Virtual card" is the label.
-  ASSERT_EQ(virtual_card_number_field_suggestion.labels.size(), 1U);
-  ASSERT_EQ(virtual_card_number_field_suggestion.labels[0].size(), 1U);
-  EXPECT_EQ(virtual_card_number_field_suggestion.labels[0][0].value,
-            u"Virtual card");
-}
-
-// Verify that the suggestion's texts are populated correctly for a masked
-// server card suggestion when the cardholder name field is focused.
-TEST_F(AutofillSuggestionGeneratorTest,
-       CreateCreditCardSuggestion_MaskedServerCardMetadata_NameField) {
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitWithFeatures(
-      /*enabled_features=*/{features::kAutofillEnableVirtualCardMetadata,
-                            features::kAutofillEnableCardProductName},
-      /*disabled_features=*/{});
-
-  // Create a server card.
-  CreditCard server_card = CreateServerCard();
-
-  // Name field suggestion for non-virtual cards.
-  Suggestion real_card_name_field_suggestion =
-      suggestion_generator()->CreateCreditCardSuggestion(
-          server_card, AutofillType(CREDIT_CARD_NAME_FULL),
-          /*virtual_card_option=*/false,
-          /*card_linked_offer_available=*/false);
-
-  // Only the name is displayed on the first line.
-  EXPECT_EQ(real_card_name_field_suggestion.main_text.value, u"Elvis Presley");
-  EXPECT_EQ(real_card_name_field_suggestion.minor_text.value, u"");
-
-#if BUILDFLAG(IS_IOS)
-  // For IOS, the label is "....1234".
-  ASSERT_EQ(real_card_name_field_suggestion.labels.size(), 1U);
-  ASSERT_EQ(real_card_name_field_suggestion.labels[0].size(), 1U);
-  EXPECT_EQ(real_card_name_field_suggestion.labels[0][0].value,
-            internal::GetObfuscatedStringForCardDigits(u"1111", 4));
-#else
-  // For Desktop/Android, the label is "CardName  ....1234". Card name and last
-  // four are shown separately.
-  ASSERT_EQ(real_card_name_field_suggestion.labels.size(), 1U);
-  ASSERT_EQ(real_card_name_field_suggestion.labels[0].size(), 2U);
-  EXPECT_EQ(real_card_name_field_suggestion.labels[0][0].value, u"Visa");
-  EXPECT_EQ(real_card_name_field_suggestion.labels[0][1].value,
-            internal::GetObfuscatedStringForCardDigits(u"1111", 4));
-#endif
-}
-
-// Verify that the suggestion's texts are populated correctly for a masked
-// server card suggestion when the card number field is focused.
-TEST_F(AutofillSuggestionGeneratorTest,
-       CreateCreditCardSuggestion_MaskedServerCardMetadata_NumberField) {
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitWithFeatures(
-      /*enabled_features=*/{features::kAutofillEnableVirtualCardMetadata,
-                            features::kAutofillEnableCardProductName},
-      /*disabled_features=*/{});
-
-  // Create a server card.
-  CreditCard server_card = CreateServerCard();
-
-  // Card number field suggestion for non-virtual cards.
-  Suggestion real_card_number_field_suggestion =
-      suggestion_generator()->CreateCreditCardSuggestion(
-          server_card, AutofillType(CREDIT_CARD_NUMBER),
-          /*virtual_card_option=*/false,
-          /*card_linked_offer_available=*/false);
-
-#if BUILDFLAG(IS_IOS)
-  // Only the card number is displayed on the first line.
-  EXPECT_EQ(real_card_number_field_suggestion.main_text.value,
-            base::StrCat({u"Visa  ", internal::GetObfuscatedStringForCardDigits(
-                                         u"1111", 4)}));
-  EXPECT_EQ(real_card_number_field_suggestion.minor_text.value, u"");
-#else
-  // For Desktop/Android, split the first line and populate card name, last 4
-  // digits separately.
-  EXPECT_EQ(real_card_number_field_suggestion.main_text.value, u"Visa");
-  EXPECT_EQ(real_card_number_field_suggestion.minor_text.value,
-            internal::GetObfuscatedStringForCardDigits(u"1111", 4));
-#endif
-
-#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
-  // For mobile devices, the label is the expiration date formatted as mm/yy.
-  ASSERT_EQ(real_card_number_field_suggestion.labels.size(), 1U);
-  ASSERT_EQ(real_card_number_field_suggestion.labels[0].size(), 1U);
-  EXPECT_EQ(real_card_number_field_suggestion.labels[0][0].value,
-            base::StrCat({base::UTF8ToUTF16(test::NextMonth()), u"/",
-                          base::UTF8ToUTF16(test::NextYear().substr(2))}));
-#else
-  // For Desktop, the label is the descriptive expiration date formatted as
-  // "Expires on mm/yy".
-  ASSERT_EQ(real_card_number_field_suggestion.labels.size(), 1U);
-  ASSERT_EQ(real_card_number_field_suggestion.labels[0].size(), 1U);
-  EXPECT_EQ(real_card_number_field_suggestion.labels[0][0].value,
-            base::StrCat({base::UTF8ToUTF16(test::NextMonth()), u"/",
-                          base::UTF8ToUTF16(test::NextYear().substr(2))}));
-#endif
-}
-
 TEST_F(AutofillSuggestionGeneratorTest, ShouldShowVirtualCardOption) {
   // Create a complete form.
   FormData credit_card_form;
@@ -917,6 +738,256 @@
   }
 }
 
+// This class helps test the credit card contents that are displayed in Autofill
+// suggestions. It covers suggestions on Desktop/Android dropdown, and on
+// Android keyboard accessory.
+class AutofillCreditCardSuggestionContentTest
+    : public AutofillSuggestionGeneratorTest,
+      public testing::WithParamInterface<bool> {
+ public:
+  AutofillCreditCardSuggestionContentTest() {
+#if BUILDFLAG(IS_ANDROID)
+    keyboard_accessory_enabled_ = GetParam();
+    feature_list_keyboard_accessory_.InitWithFeatureState(
+        features::kAutofillKeyboardAccessory, keyboard_accessory_enabled_);
+#endif
+    feature_list_metadata_.InitWithFeatures(
+        /*enabled_features=*/{features::kAutofillEnableVirtualCardMetadata,
+                              features::kAutofillEnableCardProductName},
+        /*disabled_features=*/{});
+  }
+
+  ~AutofillCreditCardSuggestionContentTest() override = default;
+
+  bool keyboard_accessory_enabled() const {
+#if BUILDFLAG(IS_ANDROID)
+    return keyboard_accessory_enabled_;
+#else
+    return false;
+#endif
+  }
+
+ private:
+#if BUILDFLAG(IS_ANDROID)
+  bool keyboard_accessory_enabled_;
+  base::test::ScopedFeatureList feature_list_keyboard_accessory_;
+#endif
+  base::test::ScopedFeatureList feature_list_metadata_;
+};
+
+INSTANTIATE_TEST_SUITE_P(All,
+                         AutofillCreditCardSuggestionContentTest,
+                         testing::Bool());
+
+// Verify that the suggestion's texts are populated correctly for a virtual card
+// suggestion when the cardholder name field is focused.
+TEST_P(AutofillCreditCardSuggestionContentTest,
+       CreateCreditCardSuggestion_VirtualCardMetadata_NameField) {
+  CreditCard server_card = CreateServerCard();
+
+  // Name field suggestion for virtual cards.
+  Suggestion virtual_card_name_field_suggestion =
+      suggestion_generator()->CreateCreditCardSuggestion(
+          server_card, AutofillType(CREDIT_CARD_NAME_FULL),
+          /*virtual_card_option=*/true,
+          /*card_linked_offer_available=*/false);
+
+  if (keyboard_accessory_enabled()) {
+    // For the keyboard accessory, the main text is "Virtual card" and the minor
+    // text is the cardholder name. An example suggestion: "Virtual card  Elvis
+    // Presley".
+    EXPECT_EQ(virtual_card_name_field_suggestion.main_text.value,
+              u"Virtual card");
+    EXPECT_EQ(virtual_card_name_field_suggestion.minor_text.value,
+              u"Elvis Presley");
+
+    // There should be only 1 line of label: obfuscated last 4 digits. The label
+    // is not shown.
+    ASSERT_EQ(virtual_card_name_field_suggestion.labels.size(), 1U);
+  } else {
+    // On other platforms, the cardholder name is shown on the first line.
+    EXPECT_EQ(virtual_card_name_field_suggestion.main_text.value,
+              u"Elvis Presley");
+    EXPECT_EQ(virtual_card_name_field_suggestion.minor_text.value, u"");
+
+    // There should be 2 lines of labels:
+    // 1. Card name + obfuscated last 4 digits for the dropdowns, only
+    // obfuscated last 4 digits for iOS.
+    // 2. Virtual card label.
+    ASSERT_EQ(virtual_card_name_field_suggestion.labels.size(), 2U);
+  }
+
+#if BUILDFLAG(IS_IOS)
+  // For IOS, the label is "....1111".
+  ASSERT_EQ(virtual_card_name_field_suggestion.labels[0].size(), 1U);
+  EXPECT_EQ(virtual_card_name_field_suggestion.labels[0][0].value,
+            internal::GetObfuscatedStringForCardDigits(u"1111", 4));
+#else
+  if (keyboard_accessory_enabled()) {
+    // For the keyboard accessory, the label is "..1111".
+    ASSERT_EQ(virtual_card_name_field_suggestion.labels[0].size(), 1U);
+    EXPECT_EQ(virtual_card_name_field_suggestion.labels[0][0].value,
+              internal::GetObfuscatedStringForCardDigits(u"1111", 2));
+  } else {
+    // For Desktop/Android dropdown, the label is "CardName  ....1111". Card
+    // name and last four are shown separately.
+    ASSERT_EQ(virtual_card_name_field_suggestion.labels[0].size(), 2U);
+    EXPECT_EQ(virtual_card_name_field_suggestion.labels[0][0].value, u"Visa");
+    EXPECT_EQ(virtual_card_name_field_suggestion.labels[0][1].value,
+              internal::GetObfuscatedStringForCardDigits(u"1111", 4));
+  }
+#endif
+
+  if (!keyboard_accessory_enabled()) {
+    // The virtual card text should be populated in the labels to be shown in a
+    // new line.
+    ASSERT_EQ(virtual_card_name_field_suggestion.labels[1].size(), 1U);
+    EXPECT_EQ(virtual_card_name_field_suggestion.labels[1][0].value,
+              u"Virtual card");
+  }
+}
+
+// Verify that the suggestion's texts are populated correctly for a virtual card
+// suggestion when the card number field is focused.
+TEST_P(AutofillCreditCardSuggestionContentTest,
+       CreateCreditCardSuggestion_VirtualCardMetadata_NumberField) {
+  CreditCard server_card = CreateServerCard();
+
+  // Card number field suggestion for virtual cards.
+  Suggestion virtual_card_number_field_suggestion =
+      suggestion_generator()->CreateCreditCardSuggestion(
+          server_card, AutofillType(CREDIT_CARD_NUMBER),
+          /*virtual_card_option=*/true,
+          /*card_linked_offer_available=*/false);
+
+#if BUILDFLAG(IS_IOS)
+  // Only card number is displayed on the first line.
+  EXPECT_EQ(virtual_card_number_field_suggestion.main_text.value,
+            base::StrCat({u"Visa  ", internal::GetObfuscatedStringForCardDigits(
+                                         u"1111", 4)}));
+  EXPECT_EQ(virtual_card_number_field_suggestion.minor_text.value, u"");
+#else
+  if (keyboard_accessory_enabled()) {
+    // For the keyboard accessory, the "Virtual card" label is added as a prefix
+    // to the card number. The obfuscated last four digits are shown as suffix.
+    EXPECT_EQ(virtual_card_number_field_suggestion.main_text.value,
+              u"Virtual card");
+    EXPECT_EQ(
+        virtual_card_number_field_suggestion.minor_text.value,
+        base::StrCat({u"Visa  ",
+                      internal::GetObfuscatedStringForCardDigits(u"1111", 2)}));
+  } else {
+    // Card name and the obfuscated last four digits are shown separately.
+    EXPECT_EQ(virtual_card_number_field_suggestion.main_text.value, u"Visa");
+    EXPECT_EQ(virtual_card_number_field_suggestion.minor_text.value,
+              internal::GetObfuscatedStringForCardDigits(u"1111", 4));
+  }
+#endif
+
+  if (keyboard_accessory_enabled()) {
+    // For the keyboard accessory, the label is the expiration date formatted as
+    // mm/yy.
+    ASSERT_EQ(virtual_card_number_field_suggestion.labels.size(), 1U);
+    ASSERT_EQ(virtual_card_number_field_suggestion.labels[0].size(), 1U);
+    EXPECT_EQ(virtual_card_number_field_suggestion.labels[0][0].value,
+              base::StrCat({base::UTF8ToUTF16(test::NextMonth()), u"/",
+                            base::UTF8ToUTF16(test::NextYear().substr(2))}));
+  } else {
+    // For Desktop/Android dropdown, and on iOS, "Virtual card" is the label.
+    ASSERT_EQ(virtual_card_number_field_suggestion.labels.size(), 1U);
+    ASSERT_EQ(virtual_card_number_field_suggestion.labels[0].size(), 1U);
+    EXPECT_EQ(virtual_card_number_field_suggestion.labels[0][0].value,
+              u"Virtual card");
+  }
+}
+
+// Verify that the suggestion's texts are populated correctly for a masked
+// server card suggestion when the cardholder name field is focused.
+TEST_P(AutofillCreditCardSuggestionContentTest,
+       CreateCreditCardSuggestion_MaskedServerCardMetadata_NameField) {
+  CreditCard server_card = CreateServerCard();
+
+  // Name field suggestion for non-virtual cards.
+  Suggestion real_card_name_field_suggestion =
+      suggestion_generator()->CreateCreditCardSuggestion(
+          server_card, AutofillType(CREDIT_CARD_NAME_FULL),
+          /*virtual_card_option=*/false,
+          /*card_linked_offer_available=*/false);
+
+  // Only the name is displayed on the first line.
+  EXPECT_EQ(real_card_name_field_suggestion.main_text.value, u"Elvis Presley");
+  EXPECT_EQ(real_card_name_field_suggestion.minor_text.value, u"");
+
+#if BUILDFLAG(IS_IOS)
+  // For IOS, the label is "....1111".
+  ASSERT_EQ(real_card_name_field_suggestion.labels.size(), 1U);
+  ASSERT_EQ(real_card_name_field_suggestion.labels[0].size(), 1U);
+  EXPECT_EQ(real_card_name_field_suggestion.labels[0][0].value,
+            internal::GetObfuscatedStringForCardDigits(u"1111", 4));
+#else
+  if (keyboard_accessory_enabled()) {
+    // For the keyboard accessory, the label is "..1111".
+    ASSERT_EQ(real_card_name_field_suggestion.labels.size(), 1U);
+    ASSERT_EQ(real_card_name_field_suggestion.labels[0].size(), 1U);
+    EXPECT_EQ(real_card_name_field_suggestion.labels[0][0].value,
+              internal::GetObfuscatedStringForCardDigits(u"1111", 2));
+  } else {
+    // For Desktop/Android, the label is "CardName  ....1111". Card name and
+    // last four are shown separately.
+    ASSERT_EQ(real_card_name_field_suggestion.labels.size(), 1U);
+    ASSERT_EQ(real_card_name_field_suggestion.labels[0].size(), 2U);
+    EXPECT_EQ(real_card_name_field_suggestion.labels[0][0].value, u"Visa");
+    EXPECT_EQ(real_card_name_field_suggestion.labels[0][1].value,
+              internal::GetObfuscatedStringForCardDigits(u"1111", 4));
+  }
+#endif
+}
+
+// Verify that the suggestion's texts are populated correctly for a masked
+// server card suggestion when the card number field is focused.
+TEST_P(AutofillCreditCardSuggestionContentTest,
+       CreateCreditCardSuggestion_MaskedServerCardMetadata_NumberField) {
+  CreditCard server_card = CreateServerCard();
+
+  // Card number field suggestion for non-virtual cards.
+  Suggestion real_card_number_field_suggestion =
+      suggestion_generator()->CreateCreditCardSuggestion(
+          server_card, AutofillType(CREDIT_CARD_NUMBER),
+          /*virtual_card_option=*/false,
+          /*card_linked_offer_available=*/false);
+
+#if BUILDFLAG(IS_IOS)
+  // Only the card number is displayed on the first line.
+  EXPECT_EQ(real_card_number_field_suggestion.main_text.value,
+            base::StrCat({u"Visa  ", internal::GetObfuscatedStringForCardDigits(
+                                         u"1111", 4)}));
+  EXPECT_EQ(real_card_number_field_suggestion.minor_text.value, u"");
+#else
+  // For the keyboard accessory, the card name and the last 4 digits appear in
+  // the same view.
+  if (keyboard_accessory_enabled()) {
+    EXPECT_EQ(
+        real_card_number_field_suggestion.main_text.value,
+        base::StrCat({u"Visa  ",
+                      internal::GetObfuscatedStringForCardDigits(u"1111", 2)}));
+    EXPECT_EQ(real_card_number_field_suggestion.minor_text.value, u"");
+  } else {
+    // For Desktop/Android dropdown, split the first line and populate card
+    // name, last 4 digits separately.
+    EXPECT_EQ(real_card_number_field_suggestion.main_text.value, u"Visa");
+    EXPECT_EQ(real_card_number_field_suggestion.minor_text.value,
+              internal::GetObfuscatedStringForCardDigits(u"1111", 4));
+  }
+#endif
+
+  // The label is the expiration date formatted as mm/yy.
+  ASSERT_EQ(real_card_number_field_suggestion.labels.size(), 1U);
+  ASSERT_EQ(real_card_number_field_suggestion.labels[0].size(), 1U);
+  EXPECT_EQ(real_card_number_field_suggestion.labels[0][0].value,
+            base::StrCat({base::UTF8ToUTF16(test::NextMonth()), u"/",
+                          base::UTF8ToUTF16(test::NextYear().substr(2))}));
+}
+
 class AutofillSuggestionGeneratorTestForMetadata
     : public AutofillSuggestionGeneratorTest,
       public testing::WithParamInterface<std::tuple<bool, bool, bool>> {
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/ExperimentalOptionsTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/ExperimentalOptionsTest.java
index 28ec76f6..b07f4ce 100644
--- a/components/cronet/android/test/javatests/src/org/chromium/net/ExperimentalOptionsTest.java
+++ b/components/cronet/android/test/javatests/src/org/chromium/net/ExperimentalOptionsTest.java
@@ -22,6 +22,7 @@
 import androidx.test.filters.LargeTest;
 import androidx.test.filters.MediumTest;
 
+import org.json.JSONException;
 import org.json.JSONObject;
 import org.junit.After;
 import org.junit.Before;
@@ -49,6 +50,8 @@
 import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
@@ -277,18 +280,13 @@
     @OnlyRunNativeCronet
     @DisabledTest(message = "https://crbug.com/1404719")
     // Experimental options should be specified through a JSON compliant string. When that is not
-    // the case building a Cronet engine should fail when it is allowed to do so.
+    // the case building a Cronet engine should fail.
     public void testWrongJsonExperimentalOptions() throws Exception {
         try {
             mBuilder.setExperimentalOptions("Not a serialized JSON object");
             CronetEngine cronetEngine = mBuilder.build();
-            if (nativeExperimentalOptionsParsingIsAllowedToFail()) {
-                fail();
-            }
+            fail("Setting invalid JSON should have thrown an exception.");
         } catch (IllegalArgumentException e) {
-            if (!nativeExperimentalOptionsParsingIsAllowedToFail()) {
-                fail();
-            }
             assertTrue(e.getMessage().contains("Experimental options parsing failed"));
         }
     }
@@ -363,7 +361,7 @@
         mBuilder.build();
 
         assertNull(mockBuilderImpl.mConnectionMigrationOptions);
-        assertEquals(EXPECTED_CONNECTION_MIGRATION_ENABLED_STRING,
+        assertJsonEquals(EXPECTED_CONNECTION_MIGRATION_ENABLED_STRING,
                 mockBuilderImpl.mEffectiveExperimentalOptions);
     }
 
@@ -399,7 +397,7 @@
         mBuilder.build();
 
         assertNull(mockBuilderImpl.mConnectionMigrationOptions);
-        assertEquals(EXPECTED_CONNECTION_MIGRATION_ENABLED_STRING,
+        assertJsonEquals(EXPECTED_CONNECTION_MIGRATION_ENABLED_STRING,
                 mockBuilderImpl.mEffectiveExperimentalOptions);
     }
 
@@ -416,7 +414,7 @@
         mBuilder.build();
 
         assertNull(mockBuilderImpl.mConnectionMigrationOptions);
-        assertEquals("{\"QUIC\":{}}", mockBuilderImpl.mEffectiveExperimentalOptions);
+        assertJsonEquals("{\"QUIC\":{}}", mockBuilderImpl.mEffectiveExperimentalOptions);
     }
 
     @Test
@@ -432,7 +430,7 @@
         mBuilder.build();
 
         assertNull(mockBuilderImpl.mConnectionMigrationOptions);
-        assertEquals("{\"QUIC\":{\"allow_port_migration\":true}}",
+        assertJsonEquals("{\"QUIC\":{\"allow_port_migration\":true}}",
                 mockBuilderImpl.mEffectiveExperimentalOptions);
     }
 
@@ -450,11 +448,10 @@
         mBuilder.build();
 
         assertNull(mockBuilderImpl.mConnectionMigrationOptions);
-        assertEquals("{\"QUIC\":{\"migrate_sessions_early_v2\":true}}",
+        assertJsonEquals("{\"QUIC\":{\"migrate_sessions_early_v2\":true}}",
                 mockBuilderImpl.mEffectiveExperimentalOptions);
     }
 
-    @DisabledTest(message = "crbug.com/1403204")
     @Test
     @MediumTest
     @Feature({"Cronet"})
@@ -469,7 +466,7 @@
         mBuilder.build();
 
         assertNull(mockBuilderImpl.mConnectionMigrationOptions);
-        assertEquals(
+        assertJsonEquals(
                 "{\"QUIC\":{\"migrate_sessions_early_v2\":false,\"allow_port_migration\":true}}",
                 mockBuilderImpl.mEffectiveExperimentalOptions);
     }
@@ -496,7 +493,6 @@
         }
     }
 
-    @DisabledTest(message = "crbug.com/1403204")
     @Test
     @MediumTest
     @Feature({"Cronet"})
@@ -628,14 +624,9 @@
                 + "  }"
                 + "}";
 
-        // The generated experimental options aren't prettified. There's no whitespace
-        // in expected values.
-        String expected = formattedJson.replaceAll("\\s", "");
-
-        assertEquals(expected, mockBuilderImpl.mEffectiveExperimentalOptions);
+        assertJsonEquals(formattedJson, mockBuilderImpl.mEffectiveExperimentalOptions);
     }
 
-    @DisabledTest(message = "crbug.com/1403204")
     @Test
     @MediumTest
     @Feature({"Cronet"})
@@ -649,7 +640,7 @@
                 .setDnsOptions(DnsOptions.builder().build());
 
         mBuilder.build();
-        assertEquals("{\"QUIC\":{},\"AsyncDNS\":{},\"StaleDNS\":{}}",
+        assertJsonEquals("{\"QUIC\":{},\"AsyncDNS\":{},\"StaleDNS\":{}}",
                 mockBuilderImpl.mEffectiveExperimentalOptions);
     }
 
@@ -686,6 +677,53 @@
         return result;
     }
 
+    private static void assertJsonEquals(String expected, String actual) {
+        try {
+            JSONObject expectedJson = new JSONObject(expected);
+            JSONObject actualJson = new JSONObject(actual);
+
+            assertJsonEquals(expectedJson, actualJson);
+        } catch (JSONException e) {
+            throw new AssertionError(e);
+        }
+    }
+
+    private static void assertJsonEquals(JSONObject expected, JSONObject actual)
+            throws JSONException {
+        assertEquals(jsonKeys(expected), jsonKeys(actual));
+
+        for (String key : jsonKeys(expected)) {
+            Object expectedValue = expected.get(key);
+            Object actualValue = actual.get(key);
+            if (expectedValue == actualValue) {
+                continue;
+            }
+            if (expectedValue instanceof JSONObject) {
+                if (actualValue instanceof JSONObject) {
+                    assertJsonEquals((JSONObject) expectedValue, (JSONObject) actualValue);
+                } else {
+                    fail("key [" + key + "]: expected [" + expectedValue + "] but got ["
+                            + actualValue + "]");
+                }
+            } else {
+                assertEquals(expectedValue, actualValue);
+            }
+        }
+    }
+
+    private static Set<String> jsonKeys(JSONObject json) throws JSONException {
+        Set<String> result = new HashSet<>();
+
+        Iterator<String> keys = json.keys();
+
+        while (keys.hasNext()) {
+            String key = keys.next();
+            result.add(key);
+        }
+
+        return result;
+    }
+
     // Mocks make life downstream miserable so use a custom mock-like class.
     private static class MockCronetBuilderImpl extends ICronetEngineBuilder {
         private ConnectionMigrationOptions mConnectionMigrationOptions;
diff --git a/components/history/core/browser/history_backend.cc b/components/history/core/browser/history_backend.cc
index 32dd57ac..3a9a070 100644
--- a/components/history/core/browser/history_backend.cc
+++ b/components/history/core/browser/history_backend.cc
@@ -2157,6 +2157,16 @@
   db_->AddVisitsToCluster(cluster_id, visits);
 }
 
+void HistoryBackend::UpdateClusterTriggerability(
+    const std::vector<Cluster>& clusters) {
+  TRACE_EVENT0("browser", "HistoryBackend::UpdateClusterTriggerability");
+  if (!db_) {
+    return;
+  }
+
+  db_->UpdateClusterTriggerability(clusters);
+}
+
 std::vector<Cluster> HistoryBackend::GetMostRecentClusters(
     base::Time inclusive_min_time,
     base::Time exclusive_max_time,
diff --git a/components/history/core/browser/history_backend.h b/components/history/core/browser/history_backend.h
index ba2fe87..dbdb05b 100644
--- a/components/history/core/browser/history_backend.h
+++ b/components/history/core/browser/history_backend.h
@@ -521,6 +521,8 @@
   void AddVisitsToCluster(int64_t cluster_id,
                           const std::vector<ClusterVisit>& visits);
 
+  void UpdateClusterTriggerability(const std::vector<Cluster>& clusters);
+
   std::vector<Cluster> GetMostRecentClusters(
       base::Time inclusive_min_time,
       base::Time exclusive_max_time,
diff --git a/components/history/core/browser/history_backend_unittest.cc b/components/history/core/browser/history_backend_unittest.cc
index 03e38c8..91206962 100644
--- a/components/history/core/browser/history_backend_unittest.cc
+++ b/components/history/core/browser/history_backend_unittest.cc
@@ -4082,6 +4082,35 @@
   VerifyCluster(backend_->GetCluster(cluster_id, false), {cluster_id, {2, 1}});
 }
 
+TEST_F(
+    HistoryBackendTest,
+    ReserveNextClusterId_AddVisitsToCluster_UpdateClusterTriggerability_GetCluster) {
+  int64_t cluster_id = backend_->ReserveNextClusterId();
+
+  AddAnnotatedVisit(1);
+  AddAnnotatedVisit(2);
+  ClusterVisit visit_1;
+  visit_1.annotated_visit.visit_row.visit_id = 1;
+  // Verify the cluster visits are being flushed out.
+  visit_1.url_for_display = u"url_for_display";
+  ClusterVisit visit_2;
+  visit_2.annotated_visit.visit_row.visit_id = 2;
+  backend_->AddVisitsToCluster(cluster_id, {visit_1, visit_2});
+  Cluster cluster;
+  cluster.cluster_id = cluster_id;
+  cluster.should_show_on_prominent_ui_surfaces = true;
+  cluster.triggerability_calculated = true;
+  cluster.keyword_to_data_map[u"keyword1"];
+  backend_->UpdateClusterTriggerability({cluster});
+
+  Cluster out_cluster = backend_->GetCluster(cluster_id, true);
+  VerifyCluster(out_cluster, {cluster_id, {2, 1}});
+  EXPECT_TRUE(out_cluster.should_show_on_prominent_ui_surfaces);
+  EXPECT_TRUE(out_cluster.triggerability_calculated);
+  EXPECT_EQ(out_cluster.keyword_to_data_map.size(), 1u);
+  EXPECT_TRUE(out_cluster.keyword_to_data_map.contains(u"keyword1"));
+}
+
 TEST_F(HistoryBackendTest, GetRedirectChainStart) {
   auto last_visit_time = base::Time::Now();
   const auto add_visit = [&](std::string url, VisitID referring_visit,
diff --git a/components/history/core/browser/history_service.cc b/components/history/core/browser/history_service.cc
index cef765a..13bbab40 100644
--- a/components/history/core/browser/history_service.cc
+++ b/components/history/core/browser/history_service.cc
@@ -324,6 +324,19 @@
                      cluster_id, visits));
 }
 
+base::CancelableTaskTracker::TaskId HistoryService::UpdateClusterTriggerability(
+    const std::vector<history::Cluster>& clusters,
+    base::OnceClosure callback,
+    base::CancelableTaskTracker* tracker) {
+  DCHECK(backend_task_runner_) << "History service being called after cleanup";
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return tracker->PostTaskAndReply(
+      backend_task_runner_.get(), FROM_HERE,
+      base::BindOnce(&HistoryBackend::UpdateClusterTriggerability,
+                     history_backend_, clusters),
+      std::move(callback));
+}
+
 base::CancelableTaskTracker::TaskId HistoryService::GetMostRecentClusters(
     base::Time inclusive_min_time,
     base::Time exclusive_max_time,
diff --git a/components/history/core/browser/history_service.h b/components/history/core/browser/history_service.h
index c48bffd..3ca9674 100644
--- a/components/history/core/browser/history_service.h
+++ b/components/history/core/browser/history_service.h
@@ -605,6 +605,12 @@
       const std::vector<ClusterVisit>& visits,
       base::CancelableTaskTracker* tracker);
 
+  // Updates the triggerability attributes for `clusters`.
+  base::CancelableTaskTracker::TaskId UpdateClusterTriggerability(
+      const std::vector<history::Cluster>& clusters,
+      base::OnceClosure callback,
+      base::CancelableTaskTracker* tracker);
+
   // Get the most recent `Cluster`s within the constraints. The most recent
   // visit of a cluster represents the cluster's time. `max_clusters` is a hard
   // cap. `max_visits_soft_cap` is a soft cap; `GetMostRecentClusters()` will
diff --git a/components/history/core/browser/visit_annotations_database.cc b/components/history/core/browser/visit_annotations_database.cc
index 9d86bbe..bcb9ac7 100644
--- a/components/history/core/browser/visit_annotations_database.cc
+++ b/components/history/core/browser/visit_annotations_database.cc
@@ -724,6 +724,67 @@
   });
 }
 
+void VisitAnnotationsDatabase::UpdateClusterTriggerability(
+    const std::vector<history::Cluster>& clusters) {
+  sql::Statement clusters_statement(GetDB().GetCachedStatement(
+      SQL_FROM_HERE,
+      "UPDATE clusters "
+      "SET should_show_on_prominent_ui_surfaces=?, triggerability_calculated=? "
+      "WHERE cluster_id=?"));
+
+  sql::Statement delete_cluster_keywords_statement(GetDB().GetCachedStatement(
+      SQL_FROM_HERE, "DELETE FROM cluster_keywords WHERE cluster_id=?"));
+
+  sql::Statement cluster_keywords_statement(
+      GetDB().GetCachedStatement(SQL_FROM_HERE,
+                                 "INSERT INTO cluster_keywords"
+                                 "(cluster_id,keyword,type,score,collections)"
+                                 "VALUES(?,?,?,?,?)"));
+
+  base::ranges::for_each(clusters, [&](const auto& cluster) {
+    DCHECK_GT(cluster.cluster_id, 0);
+
+    // Update cluster visibility.
+    clusters_statement.Reset(true);
+    clusters_statement.BindBool(0,
+                                cluster.should_show_on_prominent_ui_surfaces);
+    clusters_statement.BindBool(1, cluster.triggerability_calculated);
+    clusters_statement.BindInt64(2, cluster.cluster_id);
+    if (!clusters_statement.Run()) {
+      DVLOG(0) << "Failed to execute clusters update statement:  "
+               << "cluster_id = " << cluster.cluster_id;
+    }
+
+    // Delete all previously persisted keywords.
+    delete_cluster_keywords_statement.Reset(true);
+    delete_cluster_keywords_statement.BindInt64(0, cluster.cluster_id);
+    if (!delete_cluster_keywords_statement.Run()) {
+      DVLOG(0) << "Failed to execute 'cluster_keywords' delete statement in "
+                  "`UpdateClusterTriggerability()`:  cluster_id = "
+               << cluster.cluster_id;
+    }
+
+    // Add each keyword into 'cluster_keywords'.
+    for (const auto& [keyword, keyword_data] : cluster.keyword_to_data_map) {
+      cluster_keywords_statement.Reset(true);
+      cluster_keywords_statement.BindInt64(0, cluster.cluster_id);
+      cluster_keywords_statement.BindString16(1, keyword);
+      cluster_keywords_statement.BindInt(2, keyword_data.type);
+      cluster_keywords_statement.BindDouble(3, keyword_data.score);
+      cluster_keywords_statement.BindString(
+          4, keyword_data.entity_collections.empty()
+                 ? ""
+                 : keyword_data.entity_collections[0]);
+      if (!cluster_keywords_statement.Run()) {
+        DVLOG(0) << "Failed to execute 'cluster_keywords' insert statement in "
+                    "`UpdateClusterTriggerability()`:  "
+                 << "cluster_id = " << cluster.cluster_id
+                 << ", keyword = " << keyword;
+      }
+    }
+  });
+}
+
 Cluster VisitAnnotationsDatabase::GetCluster(int64_t cluster_id) {
   DCHECK_GT(cluster_id, 0);
   sql::Statement statement(GetDB().GetCachedStatement(
diff --git a/components/history/core/browser/visit_annotations_database.h b/components/history/core/browser/visit_annotations_database.h
index 6b4ea1dd..6b57549 100644
--- a/components/history/core/browser/visit_annotations_database.h
+++ b/components/history/core/browser/visit_annotations_database.h
@@ -90,6 +90,10 @@
   void AddVisitsToCluster(int64_t cluster_id,
                           const std::vector<ClusterVisit>& visits);
 
+  // Updates the triggerability attributes for each cluster in `clusters`.
+  void UpdateClusterTriggerability(
+      const std::vector<history::Cluster>& clusters);
+
   // Get a `Cluster`. Does not include the cluster's `visits` or
   // `keyword_to_data_map`.
   Cluster GetCluster(int64_t cluster_id);
diff --git a/components/history/core/browser/visit_annotations_database_unittest.cc b/components/history/core/browser/visit_annotations_database_unittest.cc
index 7d65383..084f6b8 100644
--- a/components/history/core/browser/visit_annotations_database_unittest.cc
+++ b/components/history/core/browser/visit_annotations_database_unittest.cc
@@ -456,6 +456,70 @@
   EXPECT_EQ(GetClusterIdContainingVisit(7), 3);
 }
 
+TEST_F(VisitAnnotationsDatabaseTest,
+       ReserveNextClusterId_AddVisitsToCluster_UpdateClusterTriggerability) {
+  // Add an initial cluster with multiple visits.
+  VisitID visit_id1 = AddVisitWithTime(IntToTime(0));
+  VisitID visit_id2 = AddVisitWithTime(IntToTime(1));
+  int64_t cluster_id1 = ReserveNextClusterId();
+  int64_t cluster_id2 = ReserveNextClusterId();
+  Cluster cluster1 = CreateCluster({visit_id1, visit_id2});
+  cluster1.cluster_id = cluster_id1;
+  AddVisitsToCluster(cluster_id1, cluster1.visits);
+
+  // Add a second cluster.
+  VisitID visit_id3 = AddVisitWithTime(IntToTime(2));
+  Cluster cluster2 = CreateCluster({visit_id3});
+  cluster2.cluster_id = cluster_id2;
+  AddVisitsToCluster(cluster_id2, {cluster2.visits});
+
+  // Update cluster triggerability initially.
+  cluster1.should_show_on_prominent_ui_surfaces = true;
+  cluster1.triggerability_calculated = true;
+  cluster1.keyword_to_data_map[u"keyword1"];
+  cluster1.keyword_to_data_map[u"keyword2"];
+  cluster2.should_show_on_prominent_ui_surfaces = false;
+  cluster2.triggerability_calculated = true;
+  cluster2.keyword_to_data_map[u"keyword3"];
+  UpdateClusterTriggerability({cluster1, cluster2});
+
+  Cluster out_cluster1 = GetCluster(cluster_id1);
+  out_cluster1.keyword_to_data_map = GetClusterKeywords(cluster_id1);
+  EXPECT_TRUE(out_cluster1.should_show_on_prominent_ui_surfaces);
+  EXPECT_TRUE(out_cluster1.triggerability_calculated);
+  EXPECT_EQ(out_cluster1.keyword_to_data_map.size(), 2u);
+  EXPECT_THAT(GetVisitIdsInCluster(cluster_id1),
+              UnorderedElementsAre(visit_id1, visit_id2));
+
+  Cluster out_cluster2 = GetCluster(cluster_id2);
+  out_cluster2.keyword_to_data_map = GetClusterKeywords(cluster_id2);
+  EXPECT_FALSE(out_cluster2.should_show_on_prominent_ui_surfaces);
+  EXPECT_TRUE(out_cluster2.triggerability_calculated);
+  EXPECT_EQ(out_cluster2.keyword_to_data_map.size(), 1u);
+  EXPECT_TRUE(out_cluster2.keyword_to_data_map.contains(u"keyword3"));
+  EXPECT_THAT(GetVisitIdsInCluster(cluster_id2),
+              UnorderedElementsAre(visit_id3));
+
+  // Update cluster triggerability again for one of the clusters.
+  VisitID visit_id4 = AddVisitWithTime(IntToTime(4));
+  ClusterVisit cluster_visit4;
+  cluster_visit4.annotated_visit.visit_row.visit_id = visit_id4;
+  AddVisitsToCluster(cluster_id2, {cluster_visit4});
+  cluster2.should_show_on_prominent_ui_surfaces = true;
+  cluster2.keyword_to_data_map.clear();
+  cluster2.keyword_to_data_map[u"keyword4"];
+  UpdateClusterTriggerability({cluster2});
+
+  out_cluster2 = GetCluster(cluster_id2);
+  out_cluster2.keyword_to_data_map = GetClusterKeywords(cluster_id2);
+  EXPECT_TRUE(out_cluster2.should_show_on_prominent_ui_surfaces);
+  EXPECT_TRUE(out_cluster2.triggerability_calculated);
+  EXPECT_EQ(out_cluster2.keyword_to_data_map.size(), 1u);
+  EXPECT_TRUE(out_cluster2.keyword_to_data_map.contains(u"keyword4"));
+  EXPECT_THAT(GetVisitIdsInCluster(cluster_id2),
+              UnorderedElementsAre(visit_id3, visit_id4));
+}
+
 TEST_F(VisitAnnotationsDatabaseTest, DeleteAnnotationsForVisit) {
   // Add a cluster with 2 visits.
   AddContentAnnotationsForVisit(1, {});
diff --git a/components/power_bookmarks/common/BUILD.gn b/components/power_bookmarks/common/BUILD.gn
new file mode 100644
index 0000000..2e81cb0a
--- /dev/null
+++ b/components/power_bookmarks/common/BUILD.gn
@@ -0,0 +1,34 @@
+# Copyright 2022 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+static_library("common") {
+  sources = [
+    "power.cc",
+    "power.h",
+    "power_bookmark_metrics.cc",
+    "power_bookmark_metrics.h",
+    "power_overview.cc",
+    "power_overview.h",
+    "search_params.h",
+  ]
+
+  public_deps = [ "//components/sync/protocol" ]
+
+  deps = [
+    "//base",
+    "//components/sync/protocol",
+    "//url",
+  ]
+}
+
+source_set("unit_tests") {
+  testonly = true
+
+  sources = [ "power_unittest.cc" ]
+
+  deps = [
+    ":common",
+    "//base/test:test_support",
+  ]
+}
diff --git a/components/power_bookmarks/metrics/DEPS b/components/power_bookmarks/common/DEPS
similarity index 100%
rename from components/power_bookmarks/metrics/DEPS
rename to components/power_bookmarks/common/DEPS
diff --git a/components/power_bookmarks/core/powers/power.cc b/components/power_bookmarks/common/power.cc
similarity index 97%
rename from components/power_bookmarks/core/powers/power.cc
rename to components/power_bookmarks/common/power.cc
index b6f4778..aebb15d 100644
--- a/components/power_bookmarks/core/powers/power.cc
+++ b/components/power_bookmarks/common/power.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/power_bookmarks/core/powers/power.h"
+#include "components/power_bookmarks/common/power.h"
 
 namespace power_bookmarks {
 
diff --git a/components/power_bookmarks/core/powers/power.h b/components/power_bookmarks/common/power.h
similarity index 93%
rename from components/power_bookmarks/core/powers/power.h
rename to components/power_bookmarks/common/power.h
index 30d396c..56905ae 100644
--- a/components/power_bookmarks/core/powers/power.h
+++ b/components/power_bookmarks/common/power.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_POWER_BOOKMARKS_CORE_POWERS_POWER_H_
-#define COMPONENTS_POWER_BOOKMARKS_CORE_POWERS_POWER_H_
+#ifndef COMPONENTS_POWER_BOOKMARKS_COMMON_POWER_H_
+#define COMPONENTS_POWER_BOOKMARKS_COMMON_POWER_H_
 
 #include "base/guid.h"
 #include "base/time/time.h"
@@ -81,4 +81,4 @@
 
 }  // namespace power_bookmarks
 
-#endif  // COMPONENTS_POWER_BOOKMARKS_CORE_POWERS_POWER_H_
\ No newline at end of file
+#endif  // COMPONENTS_POWER_BOOKMARKS_COMMON_POWER_H_
\ No newline at end of file
diff --git a/components/power_bookmarks/metrics/power_bookmark_metrics.cc b/components/power_bookmarks/common/power_bookmark_metrics.cc
similarity index 96%
rename from components/power_bookmarks/metrics/power_bookmark_metrics.cc
rename to components/power_bookmarks/common/power_bookmark_metrics.cc
index baaebe8..1776a29d 100644
--- a/components/power_bookmarks/metrics/power_bookmark_metrics.cc
+++ b/components/power_bookmarks/common/power_bookmark_metrics.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/power_bookmarks/metrics/power_bookmark_metrics.h"
+#include "components/power_bookmarks/common/power_bookmark_metrics.h"
 
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
diff --git a/components/power_bookmarks/metrics/power_bookmark_metrics.h b/components/power_bookmarks/common/power_bookmark_metrics.h
similarity index 78%
rename from components/power_bookmarks/metrics/power_bookmark_metrics.h
rename to components/power_bookmarks/common/power_bookmark_metrics.h
index 1382058..f726d69 100644
--- a/components/power_bookmarks/metrics/power_bookmark_metrics.h
+++ b/components/power_bookmarks/common/power_bookmark_metrics.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_POWER_BOOKMARKS_METRICS_POWER_BOOKMARK_METRICS_H_
-#define COMPONENTS_POWER_BOOKMARKS_METRICS_POWER_BOOKMARK_METRICS_H_
+#ifndef COMPONENTS_POWER_BOOKMARKS_COMMON_POWER_BOOKMARK_METRICS_H_
+#define COMPONENTS_POWER_BOOKMARKS_COMMON_POWER_BOOKMARK_METRICS_H_
 
 #include "components/sync/protocol/power_bookmark_specifics.pb.h"
 
@@ -27,4 +27,4 @@
 
 }  // namespace power_bookmarks::metrics
 
-#endif  // COMPONENTS_POWER_BOOKMARKS_METRICS_POWER_BOOKMARK_METRICS_H_
\ No newline at end of file
+#endif  // COMPONENTS_POWER_BOOKMARKS_COMMON_POWER_BOOKMARK_METRICS_H_
\ No newline at end of file
diff --git a/components/power_bookmarks/core/powers/power_overview.cc b/components/power_bookmarks/common/power_overview.cc
similarity index 74%
rename from components/power_bookmarks/core/powers/power_overview.cc
rename to components/power_bookmarks/common/power_overview.cc
index 7de00c203..ccd29a6f 100644
--- a/components/power_bookmarks/core/powers/power_overview.cc
+++ b/components/power_bookmarks/common/power_overview.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/power_bookmarks/core/powers/power_overview.h"
+#include "components/power_bookmarks/common/power_overview.h"
 
-#include "components/power_bookmarks/core/powers/power.h"
+#include "components/power_bookmarks/common/power.h"
 
 namespace power_bookmarks {
 
diff --git a/components/power_bookmarks/core/powers/power_overview.h b/components/power_bookmarks/common/power_overview.h
similarity index 80%
rename from components/power_bookmarks/core/powers/power_overview.h
rename to components/power_bookmarks/common/power_overview.h
index b6bc7513..8242226b 100644
--- a/components/power_bookmarks/core/powers/power_overview.h
+++ b/components/power_bookmarks/common/power_overview.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_POWER_BOOKMARKS_CORE_POWERS_POWER_OVERVIEW_H_
-#define COMPONENTS_POWER_BOOKMARKS_CORE_POWERS_POWER_OVERVIEW_H_
+#ifndef COMPONENTS_POWER_BOOKMARKS_COMMON_POWER_OVERVIEW_H_
+#define COMPONENTS_POWER_BOOKMARKS_COMMON_POWER_OVERVIEW_H_
 
 #include <memory>
 
@@ -32,4 +32,4 @@
 
 }  // namespace power_bookmarks
 
-#endif  // COMPONENTS_POWER_BOOKMARKS_CORE_POWERS_POWER_OVERVIEW_H_
+#endif  // COMPONENTS_POWER_BOOKMARKS_COMMON_POWER_OVERVIEW_H_
diff --git a/components/power_bookmarks/core/powers/power_unittest.cc b/components/power_bookmarks/common/power_unittest.cc
similarity index 97%
rename from components/power_bookmarks/core/powers/power_unittest.cc
rename to components/power_bookmarks/common/power_unittest.cc
index 76625557..be25d07e 100644
--- a/components/power_bookmarks/core/powers/power_unittest.cc
+++ b/components/power_bookmarks/common/power_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/power_bookmarks/core/powers/power.h"
+#include "components/power_bookmarks/common/power.h"
 
 #include "base/guid.h"
 #include "base/time/time.h"
diff --git a/components/power_bookmarks/core/powers/search_params.h b/components/power_bookmarks/common/search_params.h
similarity index 72%
rename from components/power_bookmarks/core/powers/search_params.h
rename to components/power_bookmarks/common/search_params.h
index dffe3994..033bbbd 100644
--- a/components/power_bookmarks/core/powers/search_params.h
+++ b/components/power_bookmarks/common/search_params.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_POWER_BOOKMARKS_CORE_POWERS_SEARCH_PARAMS_H_
-#define COMPONENTS_POWER_BOOKMARKS_CORE_POWERS_SEARCH_PARAMS_H_
+#ifndef COMPONENTS_POWER_BOOKMARKS_COMMON_SEARCH_PARAMS_H_
+#define COMPONENTS_POWER_BOOKMARKS_COMMON_SEARCH_PARAMS_H_
 
 #include <string>
 
@@ -19,4 +19,4 @@
 
 }  // namespace power_bookmarks
 
-#endif  // COMPONENTS_POWER_BOOKMARKS_CORE_POWERS_SEARCH_PARAMS_H_
+#endif  // COMPONENTS_POWER_BOOKMARKS_COMMON_SEARCH_PARAMS_H_
diff --git a/components/power_bookmarks/core/BUILD.gn b/components/power_bookmarks/core/BUILD.gn
index 7fcd5ef..44b98e269 100644
--- a/components/power_bookmarks/core/BUILD.gn
+++ b/components/power_bookmarks/core/BUILD.gn
@@ -24,13 +24,12 @@
 
   deps = [
     ":features",
-    ":powers",
     "//base",
     "//base:i18n",
     "//components/bookmarks/browser",
     "//components/commerce/core:proto",
     "//components/keyed_service/core:core",
-    "//components/power_bookmarks/metrics",
+    "//components/power_bookmarks/common",
     "//components/power_bookmarks/storage",
     "//ui/base",
     "//url",
@@ -46,23 +45,6 @@
   deps = [ "//base" ]
 }
 
-static_library("powers") {
-  sources = [
-    "powers/power.cc",
-    "powers/power.h",
-    "powers/power_overview.cc",
-    "powers/power_overview.h",
-    "powers/search_params.h",
-  ]
-
-  public_deps = [ "//components/sync/protocol" ]
-
-  deps = [
-    "//base",
-    "//url",
-  ]
-}
-
 proto_library("proto") {
   proto_in_dir = "//"
   sources = [
@@ -89,16 +71,15 @@
   sources = [
     "power_bookmark_service_unittest.cc",
     "power_bookmark_utils_unittest.cc",
-    "powers/power_unittest.cc",
   ]
 
   deps = [
     ":core",
     ":features",
-    ":powers",
     "//base/test:test_support",
     "//components/bookmarks/browser",
     "//components/bookmarks/test",
+    "//components/power_bookmarks/common",
     "//testing/gmock",
     "//testing/gtest",
   ]
diff --git a/components/power_bookmarks/core/power_bookmark_service.cc b/components/power_bookmarks/core/power_bookmark_service.cc
index daafd682..e470407 100644
--- a/components/power_bookmarks/core/power_bookmark_service.cc
+++ b/components/power_bookmarks/core/power_bookmark_service.cc
@@ -7,14 +7,14 @@
 #include "base/feature_list.h"
 #include "base/ranges/algorithm.h"
 #include "components/bookmarks/browser/bookmark_model.h"
+#include "components/power_bookmarks/common/power.h"
+#include "components/power_bookmarks/common/power_bookmark_metrics.h"
+#include "components/power_bookmarks/common/power_overview.h"
+#include "components/power_bookmarks/common/search_params.h"
 #include "components/power_bookmarks/core/power_bookmark_data_provider.h"
 #include "components/power_bookmarks/core/power_bookmark_features.h"
 #include "components/power_bookmarks/core/power_bookmark_utils.h"
-#include "components/power_bookmarks/core/powers/power.h"
-#include "components/power_bookmarks/core/powers/power_overview.h"
-#include "components/power_bookmarks/core/powers/search_params.h"
 #include "components/power_bookmarks/core/proto/power_bookmark_meta.pb.h"
-#include "components/power_bookmarks/metrics/power_bookmark_metrics.h"
 #include "components/power_bookmarks/storage/power_bookmark_backend.h"
 #include "components/sync/protocol/power_bookmark_specifics.pb.h"
 
diff --git a/components/power_bookmarks/core/power_bookmark_service_unittest.cc b/components/power_bookmarks/core/power_bookmark_service_unittest.cc
index c223cff6..ec1dce27 100644
--- a/components/power_bookmarks/core/power_bookmark_service_unittest.cc
+++ b/components/power_bookmarks/core/power_bookmark_service_unittest.cc
@@ -15,12 +15,12 @@
 #include "base/test/task_environment.h"
 #include "components/bookmarks/browser/bookmark_model.h"
 #include "components/bookmarks/test/test_bookmark_client.h"
+#include "components/power_bookmarks/common/power.h"
+#include "components/power_bookmarks/common/power_overview.h"
+#include "components/power_bookmarks/common/search_params.h"
 #include "components/power_bookmarks/core/power_bookmark_data_provider.h"
 #include "components/power_bookmarks/core/power_bookmark_features.h"
 #include "components/power_bookmarks/core/power_bookmark_service.h"
-#include "components/power_bookmarks/core/powers/power.h"
-#include "components/power_bookmarks/core/powers/power_overview.h"
-#include "components/power_bookmarks/core/powers/search_params.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/components/power_bookmarks/metrics/BUILD.gn b/components/power_bookmarks/metrics/BUILD.gn
deleted file mode 100644
index 42765a75..0000000
--- a/components/power_bookmarks/metrics/BUILD.gn
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright 2022 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-static_library("metrics") {
-  sources = [
-    "power_bookmark_metrics.cc",
-    "power_bookmark_metrics.h",
-  ]
-
-  deps = [
-    "//base",
-    "//components/sync/protocol",
-  ]
-}
diff --git a/components/power_bookmarks/storage/BUILD.gn b/components/power_bookmarks/storage/BUILD.gn
index 9cefe7e..5b42a52 100644
--- a/components/power_bookmarks/storage/BUILD.gn
+++ b/components/power_bookmarks/storage/BUILD.gn
@@ -19,8 +19,7 @@
 
   deps = [
     "//base",
-    "//components/power_bookmarks/core:powers",
-    "//components/power_bookmarks/metrics",
+    "//components/power_bookmarks/common",
     "//components/sync",
     "//components/sync/model",
     "//components/sync/protocol",
@@ -42,7 +41,7 @@
     ":storage",
     "//base",
     "//base/test:test_support",
-    "//components/power_bookmarks/core:powers",
+    "//components/power_bookmarks/common",
     "//components/sync/model",
     "//components/sync/protocol",
     "//sql",
diff --git a/components/power_bookmarks/storage/empty_power_bookmark_database.cc b/components/power_bookmarks/storage/empty_power_bookmark_database.cc
index c48da799..fecb418 100644
--- a/components/power_bookmarks/storage/empty_power_bookmark_database.cc
+++ b/components/power_bookmarks/storage/empty_power_bookmark_database.cc
@@ -4,7 +4,7 @@
 
 #include "components/power_bookmarks/storage/empty_power_bookmark_database.h"
 
-#include "components/power_bookmarks/core/powers/search_params.h"
+#include "components/power_bookmarks/common/search_params.h"
 #include "components/sync/protocol/power_bookmark_specifics.pb.h"
 #include "url/gurl.h"
 
diff --git a/components/power_bookmarks/storage/empty_power_bookmark_database.h b/components/power_bookmarks/storage/empty_power_bookmark_database.h
index 94b6ae6..9c45632 100644
--- a/components/power_bookmarks/storage/empty_power_bookmark_database.h
+++ b/components/power_bookmarks/storage/empty_power_bookmark_database.h
@@ -5,8 +5,8 @@
 #ifndef COMPONENTS_POWER_BOOKMARKS_STORAGE_EMPTY_POWER_BOOKMARK_DATABASE_H_
 #define COMPONENTS_POWER_BOOKMARKS_STORAGE_EMPTY_POWER_BOOKMARK_DATABASE_H_
 
-#include "components/power_bookmarks/core/powers/power.h"
-#include "components/power_bookmarks/core/powers/power_overview.h"
+#include "components/power_bookmarks/common/power.h"
+#include "components/power_bookmarks/common/power_overview.h"
 #include "components/power_bookmarks/storage/power_bookmark_database.h"
 #include "url/gurl.h"
 
diff --git a/components/power_bookmarks/storage/power_bookmark_backend.cc b/components/power_bookmarks/storage/power_bookmark_backend.cc
index c8141ff9..7b86a1bf 100644
--- a/components/power_bookmarks/storage/power_bookmark_backend.cc
+++ b/components/power_bookmarks/storage/power_bookmark_backend.cc
@@ -4,7 +4,7 @@
 
 #include "components/power_bookmarks/storage/power_bookmark_backend.h"
 
-#include "components/power_bookmarks/core/powers/search_params.h"
+#include "components/power_bookmarks/common/search_params.h"
 #include "components/power_bookmarks/storage/empty_power_bookmark_database.h"
 #include "components/power_bookmarks/storage/power_bookmark_database_impl.h"
 #include "components/power_bookmarks/storage/power_bookmark_sync_bridge.h"
diff --git a/components/power_bookmarks/storage/power_bookmark_database.h b/components/power_bookmarks/storage/power_bookmark_database.h
index d9a4d91..1a1d5d2 100644
--- a/components/power_bookmarks/storage/power_bookmark_database.h
+++ b/components/power_bookmarks/storage/power_bookmark_database.h
@@ -8,8 +8,8 @@
 #include <memory>
 #include <vector>
 
-#include "components/power_bookmarks/core/powers/power.h"
-#include "components/power_bookmarks/core/powers/power_overview.h"
+#include "components/power_bookmarks/common/power.h"
+#include "components/power_bookmarks/common/power_overview.h"
 #include "components/power_bookmarks/storage/power_bookmark_sync_bridge.h"
 #include "url/gurl.h"
 
diff --git a/components/power_bookmarks/storage/power_bookmark_database_impl.cc b/components/power_bookmarks/storage/power_bookmark_database_impl.cc
index 896f140d..da56645 100644
--- a/components/power_bookmarks/storage/power_bookmark_database_impl.cc
+++ b/components/power_bookmarks/storage/power_bookmark_database_impl.cc
@@ -9,8 +9,8 @@
 #include "base/strings/pattern.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_util.h"
-#include "components/power_bookmarks/core/powers/search_params.h"
-#include "components/power_bookmarks/metrics/power_bookmark_metrics.h"
+#include "components/power_bookmarks/common/power_bookmark_metrics.h"
+#include "components/power_bookmarks/common/search_params.h"
 #include "components/power_bookmarks/storage/power_bookmark_sync_metadata_database.h"
 #include "components/sync/protocol/power_bookmark_specifics.pb.h"
 #include "sql/error_delegate_util.h"
diff --git a/components/power_bookmarks/storage/power_bookmark_database_impl.h b/components/power_bookmarks/storage/power_bookmark_database_impl.h
index 525b23d..ee5b514 100644
--- a/components/power_bookmarks/storage/power_bookmark_database_impl.h
+++ b/components/power_bookmarks/storage/power_bookmark_database_impl.h
@@ -6,8 +6,8 @@
 #define COMPONENTS_POWER_BOOKMARKS_STORAGE_POWER_BOOKMARK_DATABASE_IMPL_H_
 
 #include "base/files/file_path.h"
-#include "components/power_bookmarks/core/powers/power.h"
-#include "components/power_bookmarks/core/powers/power_overview.h"
+#include "components/power_bookmarks/common/power.h"
+#include "components/power_bookmarks/common/power_overview.h"
 #include "components/power_bookmarks/storage/power_bookmark_database.h"
 #include "sql/database.h"
 #include "sql/meta_table.h"
diff --git a/components/power_bookmarks/storage/power_bookmark_database_impl_unittest.cc b/components/power_bookmarks/storage/power_bookmark_database_impl_unittest.cc
index 9ef5c208..bc0243bf 100644
--- a/components/power_bookmarks/storage/power_bookmark_database_impl_unittest.cc
+++ b/components/power_bookmarks/storage/power_bookmark_database_impl_unittest.cc
@@ -13,7 +13,7 @@
 #include "base/ranges/algorithm.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "build/build_config.h"
-#include "components/power_bookmarks/core/powers/search_params.h"
+#include "components/power_bookmarks/common/search_params.h"
 #include "components/sync/protocol/power_bookmark_specifics.pb.h"
 #include "sql/database.h"
 #include "sql/meta_table.h"
diff --git a/components/power_bookmarks/storage/power_bookmark_sync_bridge.cc b/components/power_bookmarks/storage/power_bookmark_sync_bridge.cc
index 8b40fed8..b708d19 100644
--- a/components/power_bookmarks/storage/power_bookmark_sync_bridge.cc
+++ b/components/power_bookmarks/storage/power_bookmark_sync_bridge.cc
@@ -4,7 +4,7 @@
 
 #include "components/power_bookmarks/storage/power_bookmark_sync_bridge.h"
 
-#include "components/power_bookmarks/core/powers/power.h"
+#include "components/power_bookmarks/common/power.h"
 #include "components/power_bookmarks/storage/power_bookmark_sync_metadata_database.h"
 #include "components/sync/model/metadata_batch.h"
 #include "components/sync/model/metadata_change_list.h"
diff --git a/components/ukm/content/source_url_recorder_browsertest.cc b/components/ukm/content/source_url_recorder_browsertest.cc
index ba4d640..669e4d38 100644
--- a/components/ukm/content/source_url_recorder_browsertest.cc
+++ b/components/ukm/content/source_url_recorder_browsertest.cc
@@ -246,7 +246,7 @@
       ExecJs(shell()->web_contents(),
              base::StringPrintf("document.querySelector('portal').src = '%s';",
                                 portal_url.spec().c_str())));
-  portal_nav_manager.WaitForNavigationFinished();
+  ASSERT_TRUE(portal_nav_manager.WaitForNavigationFinished());
   EXPECT_TRUE(portal_nav_observer.has_committed());
   EXPECT_FALSE(portal_nav_observer.is_error());
 
diff --git a/content/browser/accessibility/accessibility_win_browsertest.cc b/content/browser/accessibility/accessibility_win_browsertest.cc
index 8d48b30..2d784236 100644
--- a/content/browser/accessibility/accessibility_win_browsertest.cc
+++ b/content/browser/accessibility/accessibility_win_browsertest.cc
@@ -2303,6 +2303,57 @@
   EXPECT_LT(1, height);
 }
 
+IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
+                       TestBasicMSAAAccessibilityModeChange) {
+  LoadInitialAccessibilityTreeFromHtml(R"HTML(
+      <p>Hello world.</p>
+      )HTML");
+  // Get the accessibility object for the window tree host.
+  aura::Window* window = shell()->window();
+  CHECK(window);
+  aura::WindowTreeHost* window_tree_host = window->GetHost();
+  CHECK(window_tree_host);
+  HWND hwnd = window_tree_host->GetAcceleratedWidget();
+  CHECK(hwnd);
+  Microsoft::WRL::ComPtr<IAccessible> browser_accessible;
+  HRESULT hr = AccessibleObjectFromWindow(hwnd, OBJID_WINDOW,
+                                          IID_PPV_ARGS(&browser_accessible));
+  ASSERT_EQ(S_OK, hr);
+
+  // Ensure that we can find accessibility nodes in web contents.
+  bool found = false;
+  FindNodeInAccessibilityTree(browser_accessible.Get(), ROLE_SYSTEM_STATICTEXT,
+                              L"Hello world.", 0, &found);
+  EXPECT_TRUE(found);
+
+  // Remove all accessibility modes.
+  content::BrowserAccessibilityStateImpl::GetInstance()
+      ->RemoveAccessibilityModeFlags(ui::kAXModeComplete);
+
+  // Ensure accessibility is not enabled before we begin the test.
+  EXPECT_TRUE(content::BrowserAccessibilityStateImpl::GetInstance()
+                  ->GetAccessibilityMode()
+                  .is_mode_off());
+
+  // Search for the document, we should be able to find it.
+  found = false;
+  FindNodeInAccessibilityTree(browser_accessible.Get(), ROLE_SYSTEM_DOCUMENT,
+                              L"", 0, &found);
+  EXPECT_TRUE(found);
+
+  // The act of searching for the document should enable kNativeAPIs
+  EXPECT_EQ(ui::AXMode(ui::AXMode::kNativeAPIs),
+            content::BrowserAccessibilityStateImpl::GetInstance()
+                ->GetAccessibilityMode());
+
+  // Even with kNativeAPIs, we still shouldn't be able to find the node in web
+  // contents.
+  found = false;
+  FindNodeInAccessibilityTree(browser_accessible.Get(), ROLE_SYSTEM_STATICTEXT,
+                              L"Hello world.", 0, &found);
+  EXPECT_FALSE(found);
+}
+
 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestScrollToPoint) {
   Microsoft::WRL::ComPtr<IAccessibleText> accessible_text;
   SetUpSampleParagraphInScrollableDocument(&accessible_text);
diff --git a/content/browser/accessibility/browser_accessibility_state_impl_win.cc b/content/browser/accessibility/browser_accessibility_state_impl_win.cc
index 97c1bc05..57197f4c 100644
--- a/content/browser/accessibility/browser_accessibility_state_impl_win.cc
+++ b/content/browser/accessibility/browser_accessibility_state_impl_win.cc
@@ -39,13 +39,21 @@
 
  private:
   // WinAccessibilityAPIUsageObserver
+  void OnMSAAUsed() override {
+    // When only basic MSAA functionality is used, just enable kNativeAPIs.
+    // Enabling kNativeAPIs gives little perf impact, but allows these APIs to
+    // interact with the BrowserAccessibilityManager allowing ATs to be able at
+    // least find the document without using any advanced APIs.
+    BrowserAccessibilityStateImpl::GetInstance()->AddAccessibilityModeFlags(
+        ui::AXMode::kNativeAPIs);
+  }
+
   void OnIAccessible2Used() override {
     // When IAccessible2 APIs have been used elsewhere in the codebase,
     // enable basic web accessibility support. (Full screen reader support is
     // detected later when specific more advanced APIs are accessed.)
     BrowserAccessibilityStateImpl::GetInstance()->AddAccessibilityModeFlags(
         ui::kAXModeBasic);
-    BrowserAccessibilityStateImpl::GetInstance()->OnAccessibilityApiUsage();
   }
 
   void OnScreenReaderHoneyPotQueried() override {
@@ -59,7 +67,6 @@
       BrowserAccessibilityStateImpl::GetInstance()->AddAccessibilityModeFlags(
           ui::kAXModeBasic);
     }
-    BrowserAccessibilityStateImpl::GetInstance()->OnAccessibilityApiUsage();
   }
 
   void OnAccNameCalled() override {
@@ -71,7 +78,6 @@
       BrowserAccessibilityStateImpl::GetInstance()->AddAccessibilityModeFlags(
           ui::kAXModeBasic);
     }
-    BrowserAccessibilityStateImpl::GetInstance()->OnAccessibilityApiUsage();
   }
 
   void OnBasicUIAutomationUsed() override {
@@ -116,7 +122,6 @@
       mode = ui::kAXModeComplete;
     BrowserAccessibilityStateImpl::GetInstance()->AddAccessibilityModeFlags(
         mode);
-    BrowserAccessibilityStateImpl::GetInstance()->OnAccessibilityApiUsage();
   }
 
   void StartFiringUIAEvents() override { firing_uia_events_ = true; }
diff --git a/content/browser/child_process_security_policy_impl.cc b/content/browser/child_process_security_policy_impl.cc
index e8a69656..da665921 100644
--- a/content/browser/child_process_security_policy_impl.cc
+++ b/content/browser/child_process_security_policy_impl.cc
@@ -1582,7 +1582,7 @@
   if (ShouldRestrictCanAccessDataForOriginToUIThread()) {
     // Ensure this is only called on the UI thread, which is the only thread
     // with sufficient information to do the full set of checks.
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   } else {
     // For legacy cases, this may be called on multiple threads.
     DCHECK(IsRunningOnExpectedThread());
@@ -1627,7 +1627,7 @@
   if (ShouldRestrictCanAccessDataForOriginToUIThread()) {
     // Ensure this is only called on the UI thread, which is the only thread
     // with sufficient information to do the full set of checks.
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   } else {
     // For legacy cases, this may be called on multiple threads.
     DCHECK(IsRunningOnExpectedThread());
diff --git a/content/browser/renderer_host/frame_tree_node.cc b/content/browser/renderer_host/frame_tree_node.cc
index aef8bba..9d1bd693 100644
--- a/content/browser/renderer_host/frame_tree_node.cc
+++ b/content/browser/renderer_host/frame_tree_node.cc
@@ -1012,6 +1012,10 @@
   return render_manager_;
 }
 
+FrameTreeNode* FrameTreeNode::GetOpener() const {
+  return opener_;
+}
+
 void FrameTreeNode::SetFocusedFrame(SiteInstanceGroup* source) {
   frame_tree_->delegate()->SetFocusedFrame(this, source);
 }
diff --git a/content/browser/renderer_host/frame_tree_node.h b/content/browser/renderer_host/frame_tree_node.h
index 85413a9..28a0788 100644
--- a/content/browser/renderer_host/frame_tree_node.h
+++ b/content/browser/renderer_host/frame_tree_node.h
@@ -583,6 +583,7 @@
   bool Reload() override;
   Navigator& GetCurrentNavigator() override;
   RenderFrameHostManager& GetRenderFrameHostManager() override;
+  FrameTreeNode* GetOpener() const override;
   void SetFocusedFrame(SiteInstanceGroup* source) override;
   void DidChangeReferrerPolicy(
       network::mojom::ReferrerPolicy referrer_policy) override;
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index 4260b51..298581c 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -2885,6 +2885,8 @@
     return;
   }
 
+  CHECK(owner_);
+
   // The initial empty document inherits its policy container from its creator.
   // The creator is either its parent for subframes and embedded frames, or its
   // opener for new windows.
@@ -2920,12 +2922,12 @@
             network::mojom::WebSandboxFlags::kNone,
             /*is_credentialless=*/false,
             /*can_navigate_top_without_user_gesture=*/true)));
-  } else if (frame_tree_node_->opener()) {
+  } else if (owner_->GetOpener()) {
     // During a `window.open(...)` without `noopener`, a new popup is created
     // and always starts from the initial empty document. The opener has
     // synchronous access toward its openee. So they must both share the same
     // policies.
-    SetPolicyContainerHost(frame_tree_node_->opener()
+    SetPolicyContainerHost(owner_->GetOpener()
                                ->current_frame_host()
                                ->policy_container_host()
                                ->Clone());
diff --git a/content/browser/renderer_host/render_frame_host_owner.h b/content/browser/renderer_host/render_frame_host_owner.h
index b82942e..bf70744a 100644
--- a/content/browser/renderer_host/render_frame_host_owner.h
+++ b/content/browser/renderer_host/render_frame_host_owner.h
@@ -79,6 +79,8 @@
 
   virtual RenderFrameHostManager& GetRenderFrameHostManager() = 0;
 
+  virtual FrameTreeNode* GetOpener() const = 0;
+
   virtual void SetFocusedFrame(SiteInstanceGroup* source) = 0;
 
   // Called when the referrer policy changes.
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index ebe9c1e..5a6e206 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -2675,6 +2675,7 @@
 void RenderProcessHostImpl::IncrementKeepAliveRefCount(uint64_t handle_id) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(!are_ref_counts_disabled_);
+  CHECK(!deleting_soon_);
   ++keep_alive_ref_count_;
   DCHECK(!keep_alive_start_times_.contains(handle_id));
   keep_alive_start_times_[handle_id] = base::Time::Now();
@@ -2750,6 +2751,7 @@
 void RenderProcessHostImpl::IncrementWorkerRefCount() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(!are_ref_counts_disabled_);
+  CHECK(!deleting_soon_);
   ++worker_ref_count_;
 }
 
@@ -2845,6 +2847,7 @@
                                   ->set_render_process_host_listener_changed();
                 proto->set_routing_id(routing_id);
               });
+  CHECK(!deleting_soon_);
   CHECK(!listeners_.Lookup(routing_id))
       << "Found Routing ID Conflict: " << routing_id;
   listeners_.AddWithID(listener, routing_id);
diff --git a/content/browser/shared_storage/shared_storage_browsertest.cc b/content/browser/shared_storage/shared_storage_browsertest.cc
index 1a50097..ac9f840 100644
--- a/content/browser/shared_storage/shared_storage_browsertest.cc
+++ b/content/browser/shared_storage/shared_storage_browsertest.cc
@@ -4154,4 +4154,39 @@
   run_loop.Run();
 }
 
+IN_PROC_BROWSER_TEST_F(SharedStoragePrivateAggregationEnabledBrowserTest,
+                       PrivateAggregationPermissionsPolicyNone) {
+  GURL url = https_server()->GetURL(
+      "a.test",
+      "/shared_storage/private_aggregation_permissions_policy_none.html");
+
+  EXPECT_TRUE(NavigateToURL(shell(), url));
+
+  WebContentsConsoleObserver console_observer(shell()->web_contents());
+
+  EXPECT_CALL(browser_client(),
+              LogWebFeatureForCurrentPage(
+                  shell()->web_contents()->GetPrimaryMainFrame(),
+                  blink::mojom::WebFeature::kPrivateAggregationApiAll));
+  EXPECT_CALL(
+      browser_client(),
+      LogWebFeatureForCurrentPage(
+          shell()->web_contents()->GetPrimaryMainFrame(),
+          blink::mojom::WebFeature::kPrivateAggregationApiSharedStorage));
+  ON_CALL(browser_client(), IsPrivateAggregationAllowed)
+      .WillByDefault(testing::Return(true));
+
+  GURL out_script_url;
+  ExecuteScriptInWorklet(shell(), R"(
+      privateAggregation.sendHistogramReport({bucket: 1n, value: 2});
+    )",
+                         &out_script_url);
+
+  EXPECT_EQ(1u, console_observer.messages().size());
+  EXPECT_EQ(
+      "TypeError: The \"private-aggregation\" Permissions Policy denied the "
+      "method on privateAggregation",
+      base::UTF16ToUTF8(console_observer.messages()[0].message));
+}
+
 }  // namespace content
diff --git a/content/browser/shared_storage/shared_storage_worklet_host.cc b/content/browser/shared_storage/shared_storage_worklet_host.cc
index ecce4f40..2481738 100644
--- a/content/browser/shared_storage/shared_storage_worklet_host.cc
+++ b/content/browser/shared_storage/shared_storage_worklet_host.cc
@@ -826,12 +826,19 @@
 
 shared_storage_worklet::mojom::SharedStorageWorkletService*
 SharedStorageWorkletHost::GetAndConnectToSharedStorageWorkletService() {
+  DCHECK(document_service_);
+
   if (!shared_storage_worklet_service_) {
+    bool private_aggregation_permissions_policy_allowed =
+        document_service_->render_frame_host().IsFeatureEnabled(
+            blink::mojom::PermissionsPolicyFeature::kPrivateAggregation);
+
     driver_->StartWorkletService(
         shared_storage_worklet_service_.BindNewPipeAndPassReceiver());
 
     shared_storage_worklet_service_->Initialize(
         shared_storage_worklet_service_client_.BindNewEndpointAndPassRemote(),
+        private_aggregation_permissions_policy_allowed,
         MaybeBindPrivateAggregationHost());
   }
 
diff --git a/content/common/shared_storage_worklet_service.mojom b/content/common/shared_storage_worklet_service.mojom
index 69fd518c..e1b50313 100644
--- a/content/common/shared_storage_worklet_service.mojom
+++ b/content/common/shared_storage_worklet_service.mojom
@@ -77,10 +77,13 @@
 // in the worklet environment.
 // See https://github.com/pythagoraskitty/shared-storage/blob/main/README.md
 interface SharedStorageWorkletService {
-  // Binds `client` and, if not null, `pa_host`. Must be the first call on this
-  // interface.
+  // Binds `client` and, if not null, `pa_host`. Also initializes the
+  // "private-aggregation" permisisons policy's status to
+  // `private_aggregation_permissions_policy_allowed`. Must be the first call on
+  // this interface.
   Initialize(
     pending_associated_remote<SharedStorageWorkletServiceClient> client,
+    bool private_aggregation_permissions_policy_allowed,
     pending_remote<content.mojom.PrivateAggregationHost>? pa_host);
 
   // Handle sharedStorage.worklet.addModule(): download and load the script in
diff --git a/content/services/auction_worklet/private_aggregation_bindings.cc b/content/services/auction_worklet/private_aggregation_bindings.cc
index 7e3bb66..5dd19c2b 100644
--- a/content/services/auction_worklet/private_aggregation_bindings.cc
+++ b/content/services/auction_worklet/private_aggregation_bindings.cc
@@ -329,8 +329,11 @@
       static_cast<PrivateAggregationBindings*>(
           v8::External::Cast(*args.Data())->Value());
 
+  // TODO(crbug.com/1403364): pass the correct permissions policy state.
   content::mojom::AggregatableReportHistogramContributionPtr contribution =
-      worklet_utils::ParseSendHistogramReportArguments(gin::Arguments(args));
+      worklet_utils::ParseSendHistogramReportArguments(
+          gin::Arguments(args),
+          /*private_aggregation_permissions_policy_allowed=*/true);
   if (contribution.is_null()) {
     // Indicates an exception was thrown.
     return;
@@ -388,8 +391,11 @@
       static_cast<PrivateAggregationBindings*>(
           v8::External::Cast(*args.Data())->Value());
 
+  // TODO(crbug.com/1403364): pass the correct permissions policy state.
   worklet_utils::ParseAndApplyEnableDebugModeArguments(
-      gin::Arguments(args), bindings->debug_mode_details_);
+      gin::Arguments(args),
+      /*private_aggregation_permissions_policy_allowed=*/true,
+      bindings->debug_mode_details_);
 }
 
 std::vector<auction_worklet::mojom::PrivateAggregationForEventRequestPtr>
diff --git a/content/services/shared_storage_worklet/private_aggregation.cc b/content/services/shared_storage_worklet/private_aggregation.cc
index 26f3f637..43924e5 100644
--- a/content/services/shared_storage_worklet/private_aggregation.cc
+++ b/content/services/shared_storage_worklet/private_aggregation.cc
@@ -18,8 +18,12 @@
 
 PrivateAggregation::PrivateAggregation(
     mojom::SharedStorageWorkletServiceClient& client,
+    bool private_aggregation_permissions_policy_allowed,
     content::mojom::PrivateAggregationHost& private_aggregation_host)
-    : client_(client), private_aggregation_host_(private_aggregation_host) {}
+    : client_(client),
+      private_aggregation_permissions_policy_allowed_(
+          private_aggregation_permissions_policy_allowed),
+      private_aggregation_host_(private_aggregation_host) {}
 
 PrivateAggregation::~PrivateAggregation() = default;
 
@@ -41,7 +45,8 @@
   EnsureUseCountersAreRecorded();
 
   content::mojom::AggregatableReportHistogramContributionPtr contribution =
-      worklet_utils::ParseSendHistogramReportArguments(*args);
+      worklet_utils::ParseSendHistogramReportArguments(
+          *args, private_aggregation_permissions_policy_allowed_);
   if (contribution.is_null()) {
     // Indicates an exception was thrown.
     return;
@@ -61,8 +66,9 @@
 void PrivateAggregation::EnableDebugMode(gin::Arguments* args) {
   EnsureUseCountersAreRecorded();
 
-  worklet_utils::ParseAndApplyEnableDebugModeArguments(*args,
-                                                       debug_mode_details_);
+  worklet_utils::ParseAndApplyEnableDebugModeArguments(
+      *args, private_aggregation_permissions_policy_allowed_,
+      debug_mode_details_);
 }
 
 void PrivateAggregation::EnsureUseCountersAreRecorded() {
diff --git a/content/services/shared_storage_worklet/private_aggregation.h b/content/services/shared_storage_worklet/private_aggregation.h
index 5092c02..1c10afb 100644
--- a/content/services/shared_storage_worklet/private_aggregation.h
+++ b/content/services/shared_storage_worklet/private_aggregation.h
@@ -23,6 +23,7 @@
  public:
   PrivateAggregation(
       mojom::SharedStorageWorkletServiceClient& client,
+      bool private_aggregation_permissions_policy_allowed,
       content::mojom::PrivateAggregationHost& private_aggregation_host);
   ~PrivateAggregation() override;
 
@@ -40,6 +41,9 @@
   void EnsureUseCountersAreRecorded();
 
   raw_ref<mojom::SharedStorageWorkletServiceClient> client_;
+
+  bool private_aggregation_permissions_policy_allowed_;
+
   raw_ref<content::mojom::PrivateAggregationHost> private_aggregation_host_;
 
   bool has_recorded_use_counters_ = false;
diff --git a/content/services/shared_storage_worklet/shared_storage_worklet_global_scope.cc b/content/services/shared_storage_worklet/shared_storage_worklet_global_scope.cc
index 7b4d8fdd..dcb31cbd 100644
--- a/content/services/shared_storage_worklet/shared_storage_worklet_global_scope.cc
+++ b/content/services/shared_storage_worklet/shared_storage_worklet_global_scope.cc
@@ -43,7 +43,11 @@
 
 }  // namespace
 
-SharedStorageWorkletGlobalScope::SharedStorageWorkletGlobalScope() = default;
+SharedStorageWorkletGlobalScope::SharedStorageWorkletGlobalScope(
+    bool private_aggregation_permissions_policy_allowed)
+    : private_aggregation_permissions_policy_allowed_(
+          private_aggregation_permissions_policy_allowed) {}
+
 SharedStorageWorkletGlobalScope::~SharedStorageWorkletGlobalScope() = default;
 
 void SharedStorageWorkletGlobalScope::AddModule(
@@ -115,7 +119,8 @@
 
   if (private_aggregation_host) {
     private_aggregation_ = std::make_unique<PrivateAggregation>(
-        *client, *private_aggregation_host);
+        *client, private_aggregation_permissions_policy_allowed_,
+        *private_aggregation_host);
     global
         ->Set(context, gin::StringToSymbol(Isolate(), "privateAggregation"),
               private_aggregation_->GetWrapper(Isolate()).ToLocalChecked())
diff --git a/content/services/shared_storage_worklet/shared_storage_worklet_global_scope.h b/content/services/shared_storage_worklet/shared_storage_worklet_global_scope.h
index 66b2040..ed1a0a3 100644
--- a/content/services/shared_storage_worklet/shared_storage_worklet_global_scope.h
+++ b/content/services/shared_storage_worklet/shared_storage_worklet_global_scope.h
@@ -33,7 +33,8 @@
 // https://github.com/pythagoraskitty/shared-storage/blob/main/README.md
 class CONTENT_EXPORT SharedStorageWorkletGlobalScope {
  public:
-  SharedStorageWorkletGlobalScope();
+  explicit SharedStorageWorkletGlobalScope(
+      bool private_aggregation_permissions_policy_allowed);
   ~SharedStorageWorkletGlobalScope();
 
   void AddModule(
@@ -73,6 +74,8 @@
 
   v8::Local<v8::Context> LocalContext();
 
+  bool private_aggregation_permissions_policy_allowed_;
+
   std::unique_ptr<ModuleScriptDownloader> module_script_downloader_;
 
   std::unique_ptr<gin::IsolateHolder> isolate_holder_;
diff --git a/content/services/shared_storage_worklet/shared_storage_worklet_global_scope_unittest.cc b/content/services/shared_storage_worklet/shared_storage_worklet_global_scope_unittest.cc
index 464ad39..ad596cb7 100644
--- a/content/services/shared_storage_worklet/shared_storage_worklet_global_scope_unittest.cc
+++ b/content/services/shared_storage_worklet/shared_storage_worklet_global_scope_unittest.cc
@@ -276,7 +276,8 @@
         task_environment_.GetMainThreadTaskRunner());
     mock_private_aggregation_host_ =
         std::make_unique<MockMojomPrivateAggregationHost>();
-    global_scope_ = std::make_unique<SharedStorageWorkletGlobalScope>();
+    global_scope_ = std::make_unique<SharedStorageWorkletGlobalScope>(
+        /*private_aggregation_permissions_policy_allowed=*/true);
   }
 
   ~SharedStorageWorkletGlobalScopeTest() override = default;
@@ -289,6 +290,11 @@
     return global_scope_->LocalContext();
   }
 
+  void OverrideGlobalScope(
+      std::unique_ptr<SharedStorageWorkletGlobalScope> global_scope) {
+    global_scope_ = std::move(global_scope);
+  }
+
   v8::Local<v8::Value> EvalJs(const std::string& src) {
     std::string error_message;
     return WorkletV8Helper::CompileAndRunScript(LocalContext(), src,
@@ -1473,6 +1479,32 @@
 }
 
 TEST_F(SharedStorageRunOperationTest,
+       UnnamedOperationWithPrivateAggregationCall_PAPermissionsPolicyDisabled) {
+  OverrideGlobalScope(std::make_unique<SharedStorageWorkletGlobalScope>(
+      /*private_aggregation_permissions_policy_allowed=*/false));
+
+  SimulateAddModule(R"(
+      class TestClass {
+        async run() {
+          privateAggregation.sendHistogramReport({bucket: 1n, value: 2});
+        }
+      }
+
+      register("test-operation", TestClass);
+    )");
+
+  SimulateRunOperation("test-operation", /*serialized_data=*/{});
+
+  EXPECT_TRUE(unnamed_operation_finished());
+  EXPECT_FALSE(unnamed_operation_success());
+
+  EXPECT_EQ(unnamed_operation_error_message(),
+            "TypeError: The \"private-aggregation\" Permissions Policy denied "
+            "the method on privateAggregation");
+  EXPECT_TRUE(test_client()->observed_record_use_counter_call());
+}
+
+TEST_F(SharedStorageRunOperationTest,
        UnnamedOperationWithPrivateAggregationCall_PAHostNotDefined) {
   EXPECT_CALL(*mock_private_aggregation_host(), SendHistogramReport).Times(0);
 
diff --git a/content/services/shared_storage_worklet/shared_storage_worklet_service_impl.cc b/content/services/shared_storage_worklet/shared_storage_worklet_service_impl.cc
index 0017665..81d8bc4c3 100644
--- a/content/services/shared_storage_worklet/shared_storage_worklet_service_impl.cc
+++ b/content/services/shared_storage_worklet/shared_storage_worklet_service_impl.cc
@@ -25,10 +25,13 @@
 void SharedStorageWorkletServiceImpl::Initialize(
     mojo::PendingAssociatedRemote<mojom::SharedStorageWorkletServiceClient>
         client,
+    bool private_aggregation_permissions_policy_allowed,
     mojo::PendingRemote<content::mojom::PrivateAggregationHost>
         private_aggregation_host) {
   DCHECK(!global_scope_);
   client_.Bind(std::move(client));
+  private_aggregation_permissions_policy_allowed_ =
+      private_aggregation_permissions_policy_allowed;
   if (private_aggregation_host)
     private_aggregation_host_.Bind(std::move(private_aggregation_host));
 }
@@ -63,8 +66,10 @@
 
 SharedStorageWorkletGlobalScope*
 SharedStorageWorkletServiceImpl::GetGlobalScope() {
-  if (!global_scope_)
-    global_scope_ = std::make_unique<SharedStorageWorkletGlobalScope>();
+  if (!global_scope_) {
+    global_scope_ = std::make_unique<SharedStorageWorkletGlobalScope>(
+        private_aggregation_permissions_policy_allowed_);
+  }
 
   return global_scope_.get();
 }
diff --git a/content/services/shared_storage_worklet/shared_storage_worklet_service_impl.h b/content/services/shared_storage_worklet/shared_storage_worklet_service_impl.h
index 5e371d5..9ea14fe 100644
--- a/content/services/shared_storage_worklet/shared_storage_worklet_service_impl.h
+++ b/content/services/shared_storage_worklet/shared_storage_worklet_service_impl.h
@@ -32,6 +32,7 @@
   // mojom::SharedStorageWorkletService implementation:
   void Initialize(mojo::PendingAssociatedRemote<
                       mojom::SharedStorageWorkletServiceClient> client,
+                  bool private_aggregation_permissions_policy_allowed,
                   mojo::PendingRemote<content::mojom::PrivateAggregationHost>
                       private_aggregation_host) override;
   void AddModule(mojo::PendingRemote<network::mojom::URLLoaderFactory>
@@ -69,6 +70,10 @@
   // depend on / preserve the order with messages of other types.
   mojo::AssociatedRemote<mojom::SharedStorageWorkletServiceClient> client_;
 
+  // Whether the "private-aggregation" permissions policy is enabled in the
+  // worklet.
+  bool private_aggregation_permissions_policy_allowed_ = false;
+
   // No need to be associated as message ordering (relative to shared storage
   // operations) is unimportant.
   mojo::Remote<content::mojom::PrivateAggregationHost>
diff --git a/content/services/worklet_utils/private_aggregation_utils.cc b/content/services/worklet_utils/private_aggregation_utils.cc
index c6e600d..09cafa7 100644
--- a/content/services/worklet_utils/private_aggregation_utils.cc
+++ b/content/services/worklet_utils/private_aggregation_utils.cc
@@ -99,8 +99,19 @@
 }
 
 content::mojom::AggregatableReportHistogramContributionPtr
-ParseSendHistogramReportArguments(const gin::Arguments& args) {
+ParseSendHistogramReportArguments(
+    const gin::Arguments& args,
+    bool private_aggregation_permissions_policy_allowed) {
   v8::Isolate* isolate = args.isolate();
+
+  if (!private_aggregation_permissions_policy_allowed) {
+    isolate->ThrowException(v8::Exception::TypeError(CreateStringFromLiteral(
+        isolate,
+        "The \"private-aggregation\" Permissions Policy denied the method on "
+        "privateAggregation")));
+    return nullptr;
+  }
+
   std::vector<v8::Local<v8::Value>> argument_list = args.GetAll();
 
   // Any additional arguments are ignored.
@@ -183,10 +194,19 @@
 
 void ParseAndApplyEnableDebugModeArguments(
     const gin::Arguments& args,
+    bool private_aggregation_permissions_policy_allowed,
     content::mojom::DebugModeDetails& debug_mode_details) {
   v8::Isolate* isolate = args.isolate();
   v8::Local<v8::Context> context = isolate->GetCurrentContext();
 
+  if (!private_aggregation_permissions_policy_allowed) {
+    isolate->ThrowException(v8::Exception::TypeError(CreateStringFromLiteral(
+        isolate,
+        "The \"private-aggregation\" Permissions Policy denied the method on "
+        "privateAggregation")));
+    return;
+  }
+
   std::vector<v8::Local<v8::Value>> argument_list = args.GetAll();
 
   if (debug_mode_details.is_enabled) {
diff --git a/content/services/worklet_utils/private_aggregation_utils.h b/content/services/worklet_utils/private_aggregation_utils.h
index 1b6cafb..2f08dfbc 100644
--- a/content/services/worklet_utils/private_aggregation_utils.h
+++ b/content/services/worklet_utils/private_aggregation_utils.h
@@ -28,7 +28,9 @@
 // corresponding contribution. In case of an error, throws an exception and
 // returns `nullptr`.
 content::mojom::AggregatableReportHistogramContributionPtr
-ParseSendHistogramReportArguments(const gin::Arguments& args);
+ParseSendHistogramReportArguments(
+    const gin::Arguments& args,
+    bool private_aggregation_permissions_policy_allowed);
 
 // Parses arguments provided to `enableDebugMode()` and updates
 // `debug_mode_details` as appropriate. `debug_mode_details` must be passed a
@@ -36,6 +38,7 @@
 // throws an exception and does not update `debug_mode_details`.
 void ParseAndApplyEnableDebugModeArguments(
     const gin::Arguments& args,
+    bool private_aggregation_permissions_policy_allowed,
     content::mojom::DebugModeDetails& debug_mode_details);
 
 }  // namespace worklet_utils
diff --git a/content/test/data/shared_storage/private_aggregation_permissions_policy_none.html b/content/test/data/shared_storage/private_aggregation_permissions_policy_none.html
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/content/test/data/shared_storage/private_aggregation_permissions_policy_none.html
diff --git a/content/test/data/shared_storage/private_aggregation_permissions_policy_none.html.mock-http-headers b/content/test/data/shared_storage/private_aggregation_permissions_policy_none.html.mock-http-headers
new file mode 100644
index 0000000..75b6e2b
--- /dev/null
+++ b/content/test/data/shared_storage/private_aggregation_permissions_policy_none.html.mock-http-headers
@@ -0,0 +1,3 @@
+HTTP/1.1 200 OK
+Content-Type: text/html
+Permissions-Policy: private-aggregation=()
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
index 6b65503..28d25c8 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -316,8 +316,6 @@
 # New validation was not implemented on the validating command decoder.
 crbug.com/angleproject/6358 [ no-passthrough ] conformance/programs/program-test.html [ Failure ]
 
-crbug.com/1404705 conformance/context/context-release-upon-reload.html [ RetryOnFailure ]
-crbug.com/1404705 conformance/context/context-release-with-workers.html [ RetryOnFailure ]
 
 # Win / Intel / Vulkan / Passthrough command decoder
 # Technically flaky, but flake rate is too high for RetryOnFailure.
diff --git a/extensions/browser/api/app_window/app_window_api.cc b/extensions/browser/api/app_window/app_window_api.cc
index b3f4c84d..8fd5c01 100644
--- a/extensions/browser/api/app_window/app_window_api.cc
+++ b/extensions/browser/api/app_window/app_window_api.cc
@@ -204,20 +204,20 @@
               existing_window->Show(AppWindow::SHOW_ACTIVE);
           }
 
-          base::Value result(base::Value::Type::DICTIONARY);
-          result.SetIntKey("frameId", frame_id);
+          base::Value::Dict result;
+          result.Set("frameId", frame_id);
           existing_window->GetSerializedState(&result);
-          result.SetBoolKey("existingWindow", true);
+          result.Set("existingWindow", true);
           // We should not return the window until that window is properly
           // initialized. Hence, adding a callback for window first navigation
           // completion.
           if (existing_window->DidFinishFirstNavigation())
-            return RespondNow(OneArgument(std::move(result)));
+            return RespondNow(OneArgument(base::Value(std::move(result))));
 
-          existing_window->AddOnDidFinishFirstNavigationCallback(
-              base::BindOnce(&AppWindowCreateFunction::
-                                 OnAppWindowFinishedFirstNavigationOrClosed,
-                             this, OneArgument(std::move(result))));
+          existing_window->AddOnDidFinishFirstNavigationCallback(base::BindOnce(
+              &AppWindowCreateFunction::
+                  OnAppWindowFinishedFirstNavigationOrClosed,
+              this, OneArgument(base::Value(std::move(result)))));
           return RespondLater();
         }
       }
@@ -416,11 +416,11 @@
   if (create_params.creator_process_id == created_frame->GetProcess()->GetID())
     frame_id = created_frame->GetRoutingID();
 
-  base::Value result(base::Value::Type::DICTIONARY);
-  result.SetIntKey("frameId", frame_id);
-  result.SetStringKey("id", app_window->window_key());
+  base::Value::Dict result;
+  result.Set("frameId", frame_id);
+  result.Set("id", app_window->window_key());
   app_window->GetSerializedState(&result);
-  ResponseValue result_arg = OneArgument(std::move(result));
+  ResponseValue result_arg = OneArgument(base::Value(std::move(result)));
 
   if (AppWindowRegistry::Get(browser_context())
           ->HadDevToolsAttached(app_window->web_contents())) {
diff --git a/extensions/browser/api/declarative_net_request/filter_list_converter/converter.cc b/extensions/browser/api/declarative_net_request/filter_list_converter/converter.cc
index a7a14a19..56136ce 100644
--- a/extensions/browser/api/declarative_net_request/filter_list_converter/converter.cc
+++ b/extensions/browser/api/declarative_net_request/filter_list_converter/converter.cc
@@ -54,9 +54,7 @@
 
  private:
   ProtoToJSONRuleConverter(const proto::UrlRule& rule, int rule_id)
-      : input_rule_(rule),
-        rule_id_(rule_id),
-        json_rule_(base::Value::Type::DICTIONARY) {}
+      : input_rule_(rule), rule_id_(rule_id), json_rule_(base::Value::Dict()) {}
 
   base::Value Convert(std::string* error) {
     CHECK(error);
diff --git a/extensions/browser/api/device_permissions_manager.cc b/extensions/browser/api/device_permissions_manager.cc
index 182042c..3fe13f41 100644
--- a/extensions/browser/api/device_permissions_manager.cc
+++ b/extensions/browser/api/device_permissions_manager.cc
@@ -138,7 +138,7 @@
       continue;
     }
 
-    value = entry->ToValue();
+    value = base::Value(entry->ToValue());
     break;
   }
 }
@@ -300,27 +300,27 @@
   return !serial_number_.empty();
 }
 
-base::Value DevicePermissionEntry::ToValue() const {
+base::Value::Dict DevicePermissionEntry::ToValue() const {
   if (!IsPersistent()) {
-    return base::Value();
+    return base::Value::Dict();
   }
 
   DCHECK(!serial_number_.empty());
-  base::Value entry_dict(base::Value::Type::DICTIONARY);
-  entry_dict.SetStringKey(kDeviceType, TypeToString(type_));
-  entry_dict.SetIntKey(kDeviceVendorId, vendor_id_);
-  entry_dict.SetIntKey(kDeviceProductId, product_id_);
-  entry_dict.SetStringKey(kDeviceSerialNumber, serial_number_);
+  base::Value::Dict entry_dict;
+  entry_dict.Set(kDeviceType, TypeToString(type_));
+  entry_dict.Set(kDeviceVendorId, vendor_id_);
+  entry_dict.Set(kDeviceProductId, product_id_);
+  entry_dict.Set(kDeviceSerialNumber, serial_number_);
 
   if (!manufacturer_string_.empty()) {
-    entry_dict.SetStringKey(kDeviceManufacturerString, manufacturer_string_);
+    entry_dict.Set(kDeviceManufacturerString, manufacturer_string_);
   }
   if (!product_string_.empty()) {
-    entry_dict.SetStringKey(kDeviceProductString, product_string_);
+    entry_dict.Set(kDeviceProductString, product_string_);
   }
   if (!last_used_.is_null()) {
-    entry_dict.SetStringKey(kDeviceLastUsed,
-                            base::NumberToString(last_used_.ToInternalValue()));
+    entry_dict.Set(kDeviceLastUsed,
+                   base::NumberToString(last_used_.ToInternalValue()));
   }
 
   return entry_dict;
diff --git a/extensions/browser/api/device_permissions_manager.h b/extensions/browser/api/device_permissions_manager.h
index 7b06505..0135321c 100644
--- a/extensions/browser/api/device_permissions_manager.h
+++ b/extensions/browser/api/device_permissions_manager.h
@@ -18,6 +18,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/threading/thread_checker.h"
 #include "base/time/time.h"
+#include "base/values.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "services/device/public/mojom/hid.mojom.h"
@@ -26,7 +27,6 @@
 namespace base {
 template <typename T>
 struct DefaultSingletonTraits;
-class Value;
 }
 
 namespace content {
@@ -65,7 +65,7 @@
 
   // Convert the device to a serializable value, returns an is_none() value
   // if the entry is not persistent.
-  base::Value ToValue() const;
+  base::Value::Dict ToValue() const;
 
   std::u16string GetPermissionMessageString() const;
 
diff --git a/extensions/browser/api/messaging/messaging_api_message_filter.cc b/extensions/browser/api/messaging/messaging_api_message_filter.cc
index d13a449..fabdb8f 100644
--- a/extensions/browser/api/messaging/messaging_api_message_filter.cc
+++ b/extensions/browser/api/messaging/messaging_api_message_filter.cc
@@ -464,8 +464,16 @@
 void MessagingAPIMessageFilter::OnOpenMessagePort(const PortContext& source,
                                                   const PortId& port_id) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  if (!browser_context_)
+  auto* process = GetRenderProcessHost();
+  if (!process) {
     return;
+  }
+  TRACE_EVENT("extensions", "MessageFilter::OnOpenMessagePort",
+              ChromeTrackEvent::kRenderProcessHost, *process);
+
+  if (!IsValidSourceContext(*process, source)) {
+    return;
+  }
 
   MessageService::Get(browser_context_)
       ->OpenPort(port_id, render_process_id_, source);
@@ -476,10 +484,13 @@
     const PortId& port_id,
     bool force_close) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  if (!browser_context_)
+  auto* process = GetRenderProcessHost();
+  if (!process) {
     return;
+  }
+  TRACE_EVENT("extensions", "MessageFilter::OnCloseMessagePort",
+              ChromeTrackEvent::kRenderProcessHost, *process);
 
-  // Note, we need to add more stringent IPC validation here.
   if (!port_context.is_for_render_frame() &&
       !port_context.is_for_service_worker()) {
     bad_message::ReceivedBadMessage(render_process_id_,
@@ -487,6 +498,10 @@
     return;
   }
 
+  if (!IsValidSourceContext(*process, port_context)) {
+    return;
+  }
+
   MessageService::Get(browser_context_)
       ->ClosePort(port_id, render_process_id_, port_context, force_close);
 }
@@ -504,8 +519,16 @@
     const PortContext& port_context,
     const PortId& port_id) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  if (!browser_context_)
+  auto* process = GetRenderProcessHost();
+  if (!process) {
     return;
+  }
+  TRACE_EVENT("extensions", "MessageFilter::OnResponsePending",
+              ChromeTrackEvent::kRenderProcessHost, *process);
+
+  if (!IsValidSourceContext(*process, port_context)) {
+    return;
+  }
 
   MessageService::Get(browser_context_)
       ->NotifyResponsePending(port_id, render_process_id_, port_context);
diff --git a/extensions/browser/api/runtime/runtime_api.cc b/extensions/browser/api/runtime/runtime_api.cc
index 1ca2fe3..27d34ab 100644
--- a/extensions/browser/api/runtime/runtime_api.cc
+++ b/extensions/browser/api/runtime/runtime_api.cc
@@ -449,14 +449,14 @@
   }
 
   base::Value::List event_args;
-  base::Value info(base::Value::Type::DICTIONARY);
+  base::Value::Dict info;
   if (old_version.IsValid()) {
-    info.SetStringKey(kInstallReason, kInstallReasonUpdate);
-    info.SetStringKey(kInstallPreviousVersion, old_version.GetString());
+    info.Set(kInstallReason, kInstallReasonUpdate);
+    info.Set(kInstallPreviousVersion, old_version.GetString());
   } else if (chrome_updated) {
-    info.SetStringKey(kInstallReason, kInstallReasonChromeUpdate);
+    info.Set(kInstallReason, kInstallReasonChromeUpdate);
   } else {
-    info.SetStringKey(kInstallReason, kInstallReasonInstall);
+    info.Set(kInstallReason, kInstallReasonInstall);
   }
   event_args.Append(std::move(info));
   EventRouter* event_router = EventRouter::Get(context);
diff --git a/extensions/browser/api/socket/socket_api.cc b/extensions/browser/api/socket/socket_api.cc
index d358ce6..27de8195 100644
--- a/extensions/browser/api/socket/socket_api.cc
+++ b/extensions/browser/api/socket/socket_api.cc
@@ -291,9 +291,9 @@
 
   DCHECK(socket);
 
-  base::Value result(base::Value::Type::DICTIONARY);
-  result.SetKey(kSocketIdKey, base::Value(AddSocket(socket)));
-  return RespondNow(OneArgument(std::move(result)));
+  base::Value::Dict result;
+  result.Set(kSocketIdKey, AddSocket(socket));
+  return RespondNow(OneArgument(base::Value(std::move(result))));
 }
 
 ExtensionFunction::ResponseAction SocketDestroyFunction::Work() {
@@ -526,15 +526,15 @@
     const absl::optional<net::IPEndPoint>& remote_addr,
     mojo::ScopedDataPipeConsumerHandle receive_pipe_handle,
     mojo::ScopedDataPipeProducerHandle send_pipe_handle) {
-  base::Value result(base::Value::Type::DICTIONARY);
-  result.SetIntKey(kResultCodeKey, result_code);
+  base::Value::Dict result;
+  result.Set(kResultCodeKey, result_code);
   if (result_code == net::OK) {
     Socket* client_socket =
         new TCPSocket(std::move(socket), std::move(receive_pipe_handle),
                       std::move(send_pipe_handle), remote_addr, GetOriginId());
-    result.SetIntKey(kSocketIdKey, AddSocket(client_socket));
+    result.Set(kSocketIdKey, AddSocket(client_socket));
   }
-  Respond(OneArgument(std::move(result)));
+  Respond(OneArgument(base::Value(std::move(result))));
 }
 
 SocketReadFunction::SocketReadFunction() = default;
@@ -562,13 +562,13 @@
 void SocketReadFunction::OnCompleted(int bytes_read,
                                      scoped_refptr<net::IOBuffer> io_buffer,
                                      bool socket_destroying) {
-  base::Value result(base::Value::Type::DICTIONARY);
-  result.SetIntKey(kResultCodeKey, bytes_read);
+  base::Value::Dict result;
+  result.Set(kResultCodeKey, bytes_read);
   base::span<const uint8_t> data_span;
   if (bytes_read > 0)
     data_span = base::as_bytes(base::make_span(io_buffer->data(), bytes_read));
-  result.SetKey(kDataKey, base::Value(data_span));
-  Respond(OneArgument(std::move(result)));
+  result.Set(kDataKey, base::Value(data_span));
+  Respond(OneArgument(base::Value(std::move(result))));
 }
 
 SocketWriteFunction::SocketWriteFunction() = default;
@@ -603,9 +603,9 @@
 }
 
 void SocketWriteFunction::OnCompleted(int bytes_written) {
-  base::Value result(base::Value::Type::DICTIONARY);
-  result.SetIntKey(kBytesWrittenKey, bytes_written);
-  Respond(OneArgument(std::move(result)));
+  base::Value::Dict result;
+  result.Set(kBytesWrittenKey, bytes_written);
+  Respond(OneArgument(base::Value(std::move(result))));
 }
 
 SocketRecvFromFunction::SocketRecvFromFunction() = default;
@@ -636,15 +636,15 @@
                                          bool socket_destroying,
                                          const std::string& address,
                                          uint16_t port) {
-  base::Value result(base::Value::Type::DICTIONARY);
-  result.SetIntKey(kResultCodeKey, bytes_read);
+  base::Value::Dict result;
+  result.Set(kResultCodeKey, bytes_read);
   base::span<const uint8_t> data_span;
   if (bytes_read > 0)
     data_span = base::as_bytes(base::make_span(io_buffer->data(), bytes_read));
-  result.SetKey(kDataKey, base::Value(data_span));
-  result.SetStringKey(kAddressKey, address);
-  result.SetIntKey(kPortKey, port);
-  Respond(OneArgument(std::move(result)));
+  result.Set(kDataKey, base::Value(data_span));
+  result.Set(kAddressKey, address);
+  result.Set(kPortKey, port);
+  Respond(OneArgument(base::Value(std::move(result))));
 }
 
 SocketSendToFunction::SocketSendToFunction() = default;
diff --git a/extensions/browser/api/storage/session_storage_manager_unittest.cc b/extensions/browser/api/storage/session_storage_manager_unittest.cc
index 54e4dd2..cee4d74 100644
--- a/extensions/browser/api/storage/session_storage_manager_unittest.cc
+++ b/extensions/browser/api/storage/session_storage_manager_unittest.cc
@@ -42,12 +42,11 @@
   SessionStorageManagerUnittest()
       : value_int_(123),
         value_string_("value"),
-        value_list_(base::Value::Type::LIST),
-        value_dict_(base::Value::Type::DICTIONARY) {
+        value_list_(base::Value::Type::LIST) {
     value_list_.GetList().Append(1);
     value_list_.GetList().Append(2);
-    value_dict_.GetDict().Set("int", 123);
-    value_dict_.GetDict().Set("string", "abc");
+    value_dict_.Set("int", 123);
+    value_dict_.Set("string", "abc");
   }
 
  protected:
@@ -58,7 +57,7 @@
   base::Value value_int_;
   base::Value value_string_;
   base::Value value_list_;
-  base::Value value_dict_;
+  base::Value::Dict value_dict_;
 
   // Session storage manager being tested.
   raw_ptr<SessionStorageManager> manager_;
diff --git a/extensions/browser/api/web_request/upload_data_presenter_unittest.cc b/extensions/browser/api/web_request/upload_data_presenter_unittest.cc
index 411b1f0..73d0ef7 100644
--- a/extensions/browser/api/web_request/upload_data_presenter_unittest.cc
+++ b/extensions/browser/api/web_request/upload_data_presenter_unittest.cc
@@ -28,8 +28,8 @@
   // Expected output.
   base::Value values(base::Value::Type::LIST);
   values.Append("value");
-  base::Value expected_form(base::Value::Type::DICTIONARY);
-  expected_form.SetKey("key.with.dots", std::move(values));
+  base::Value::Dict expected_form;
+  expected_form.Set("key.with.dots", std::move(values));
 
   // Real output.
   std::unique_ptr<ParsedDataPresenter> parsed_data_presenter(
diff --git a/extensions/browser/app_window/app_window.cc b/extensions/browser/app_window/app_window.cc
index 58a791b..32298a2 100644
--- a/extensions/browser/app_window/app_window.cc
+++ b/extensions/browser/app_window/app_window.cc
@@ -80,33 +80,33 @@
 
 void SetConstraintProperty(const std::string& name,
                            int value,
-                           base::Value* bounds_properties) {
-  DCHECK(bounds_properties->is_dict());
+                           base::Value::Dict* bounds_properties) {
+  DCHECK(bounds_properties);
   if (value != SizeConstraints::kUnboundedSize)
-    bounds_properties->SetIntKey(name, value);
+    bounds_properties->Set(name, value);
   else
-    bounds_properties->SetKey(name, base::Value());
+    bounds_properties->Set(name, base::Value());
 }
 
 void SetBoundsProperties(const gfx::Rect& bounds,
                          const gfx::Size& min_size,
                          const gfx::Size& max_size,
                          const std::string& bounds_name,
-                         base::Value* window_properties) {
-  DCHECK(window_properties->is_dict());
-  base::Value bounds_properties(base::Value::Type::DICTIONARY);
+                         base::Value::Dict* window_properties) {
+  DCHECK(window_properties);
+  base::Value::Dict bounds_properties;
 
-  bounds_properties.SetIntKey("left", bounds.x());
-  bounds_properties.SetIntKey("top", bounds.y());
-  bounds_properties.SetIntKey("width", bounds.width());
-  bounds_properties.SetIntKey("height", bounds.height());
+  bounds_properties.Set("left", bounds.x());
+  bounds_properties.Set("top", bounds.y());
+  bounds_properties.Set("width", bounds.width());
+  bounds_properties.Set("height", bounds.height());
 
   SetConstraintProperty("minWidth", min_size.width(), &bounds_properties);
   SetConstraintProperty("minHeight", min_size.height(), &bounds_properties);
   SetConstraintProperty("maxWidth", max_size.width(), &bounds_properties);
   SetConstraintProperty("maxHeight", max_size.height(), &bounds_properties);
 
-  window_properties->SetKey(bounds_name, std::move(bounds_properties));
+  window_properties->Set(bounds_name, std::move(bounds_properties));
 }
 
 // Combines the constraints of the content and window, and returns constraints
@@ -747,17 +747,15 @@
     UpdateNativeAlwaysOnTop();
 }
 
-void AppWindow::GetSerializedState(base::Value* properties) const {
+void AppWindow::GetSerializedState(base::Value::Dict* properties) const {
   DCHECK(properties);
-  DCHECK(properties->is_dict());
 
-  properties->SetBoolKey("fullscreen",
-                         native_app_window_->IsFullscreenOrPending());
-  properties->SetBoolKey("minimized", native_app_window_->IsMinimized());
-  properties->SetBoolKey("maximized", native_app_window_->IsMaximized());
-  properties->SetBoolKey("alwaysOnTop", IsAlwaysOnTop());
-  properties->SetBoolKey("hasFrameColor", native_app_window_->HasFrameColor());
-  properties->SetBoolKey(
+  properties->Set("fullscreen", native_app_window_->IsFullscreenOrPending());
+  properties->Set("minimized", native_app_window_->IsMinimized());
+  properties->Set("maximized", native_app_window_->IsMaximized());
+  properties->Set("alwaysOnTop", IsAlwaysOnTop());
+  properties->Set("hasFrameColor", native_app_window_->HasFrameColor());
+  properties->Set(
       "alphaEnabled",
       requested_alpha_enabled_ && native_app_window_->CanHaveAlphaEnabled());
 
@@ -765,12 +763,12 @@
   // removed to
   // make the values easier to check.
   SkColor transparent_white = ~SK_ColorBLACK;
-  properties->SetIntKey(
-      "activeFrameColor",
-      native_app_window_->ActiveFrameColor() & transparent_white);
-  properties->SetIntKey(
-      "inactiveFrameColor",
-      native_app_window_->InactiveFrameColor() & transparent_white);
+  properties->Set("activeFrameColor",
+                  static_cast<int>(native_app_window_->ActiveFrameColor() &
+                                   transparent_white));
+  properties->Set("inactiveFrameColor",
+                  static_cast<int>(native_app_window_->InactiveFrameColor() &
+                                   transparent_white));
 
   gfx::Rect content_bounds = GetClientBounds();
   gfx::Size content_min_size = native_app_window_->GetContentMinimumSize();
diff --git a/extensions/browser/app_window/app_window.h b/extensions/browser/app_window/app_window.h
index a9130a5d..dc5c4e0 100644
--- a/extensions/browser/app_window/app_window.h
+++ b/extensions/browser/app_window/app_window.h
@@ -363,7 +363,7 @@
 
   // Retrieve the current state of the app window as a dictionary, to pass to
   // the renderer.
-  void GetSerializedState(base::Value* properties) const;
+  void GetSerializedState(base::Value::Dict* properties) const;
 
   // Whether the app window wants to be alpha enabled.
   bool requested_alpha_enabled() const { return requested_alpha_enabled_; }
diff --git a/extensions/browser/app_window/app_window_contents.cc b/extensions/browser/app_window/app_window_contents.cc
index a1e35cc..c6986e8 100644
--- a/extensions/browser/app_window/app_window_contents.cc
+++ b/extensions/browser/app_window/app_window_contents.cc
@@ -61,7 +61,7 @@
 
 void AppWindowContentsImpl::NativeWindowChanged(
     NativeAppWindow* native_app_window) {
-  base::Value dictionary(base::Value::Type::DICTIONARY);
+  base::Value::Dict dictionary;
   host_->GetSerializedState(&dictionary);
   base::Value::List args;
   args.Append(std::move(dictionary));
diff --git a/extensions/browser/computed_hashes.cc b/extensions/browser/computed_hashes.cc
index 63df27ed..315d41f 100644
--- a/extensions/browser/computed_hashes.cc
+++ b/extensions/browser/computed_hashes.cc
@@ -241,7 +241,7 @@
   if (!base::CreateDirectoryAndGetError(path.DirName(), nullptr))
     return false;
 
-  base::Value file_list(base::Value::Type::LIST);
+  base::Value::List file_list;
   for (const auto& resource_info : data_.items()) {
     const Data::HashInfo& hash_info = resource_info.second;
     int block_size = hash_info.block_size;
@@ -255,21 +255,19 @@
       block_hashes.Append(std::move(encoded));
     }
 
-    base::Value dict(base::Value::Type::DICTIONARY);
-    dict.SetStringKey(computed_hashes::kPathKey,
-                      hash_info.relative_unix_path.AsUTF8Unsafe());
-    dict.SetIntKey(computed_hashes::kBlockSizeKey, block_size);
-    dict.SetKey(computed_hashes::kBlockHashesKey,
-                base::Value(std::move(block_hashes)));
+    base::Value::Dict dict;
+    dict.Set(computed_hashes::kPathKey,
+             hash_info.relative_unix_path.AsUTF8Unsafe());
+    dict.Set(computed_hashes::kBlockSizeKey, block_size);
+    dict.Set(computed_hashes::kBlockHashesKey, std::move(block_hashes));
 
     file_list.Append(std::move(dict));
   }
 
   std::string json;
-  base::Value top_dictionary(base::Value::Type::DICTIONARY);
-  top_dictionary.SetIntKey(computed_hashes::kVersionKey,
-                           computed_hashes::kVersion);
-  top_dictionary.SetKey(computed_hashes::kFileHashesKey, std::move(file_list));
+  base::Value::Dict top_dictionary;
+  top_dictionary.Set(computed_hashes::kVersionKey, computed_hashes::kVersion);
+  top_dictionary.Set(computed_hashes::kFileHashesKey, std::move(file_list));
 
   if (!base::JSONWriter::Write(top_dictionary, &json))
     return false;
diff --git a/extensions/browser/updater/update_service.cc b/extensions/browser/updater/update_service.cc
index 4b1948f3..487b4b3 100644
--- a/extensions/browser/updater/update_service.cc
+++ b/extensions/browser/updater/update_service.cc
@@ -126,11 +126,12 @@
   }
 
   if (should_perform_action_on_omaha_attributes) {
-    base::Value attributes = GetExtensionOmahaAttributes(extension_id);
+    base::Value::Dict attributes = GetExtensionOmahaAttributes(extension_id);
     // Note that it's important to perform actions even if |attributes| is
     // empty, missing values may default to false and have associated logic.
     ExtensionSystem::Get(browser_context_)
-        ->PerformActionBasedOnOmahaAttributes(extension_id, attributes);
+        ->PerformActionBasedOnOmahaAttributes(
+            extension_id, base::Value(std::move(attributes)));
   }
 }
 
@@ -263,10 +264,10 @@
       content::Details<UpdateDetails>(&update_info));
 }
 
-base::Value UpdateService::GetExtensionOmahaAttributes(
+base::Value::Dict UpdateService::GetExtensionOmahaAttributes(
     const std::string& extension_id) {
   update_client::CrxUpdateItem update_item;
-  base::Value attributes(base::Value::Type::DICTIONARY);
+  base::Value::Dict attributes;
   if (!update_client_->GetCrxUpdateState(extension_id, &update_item))
     return attributes;
 
@@ -277,7 +278,7 @@
     // Only create the attribute if it's defined in the custom update check
     // data. We want to distinguish true, false and undefined values.
     if (iter != update_item.custom_updatecheck_data.end())
-      attributes.SetKey(key, base::Value(iter->second == "true"));
+      attributes.Set(key, iter->second == "true");
   }
   return attributes;
 }
diff --git a/extensions/browser/updater/update_service.h b/extensions/browser/updater/update_service.h
index f689390..d434fdfd 100644
--- a/extensions/browser/updater/update_service.h
+++ b/extensions/browser/updater/update_service.h
@@ -105,7 +105,8 @@
   void HandleComponentUpdateFoundEvent(const std::string& extension_id) const;
 
   // Get the extension Omaha attributes sent from update config.
-  base::Value GetExtensionOmahaAttributes(const std::string& extension_id);
+  base::Value::Dict GetExtensionOmahaAttributes(
+      const std::string& extension_id);
 
  private:
   raw_ptr<content::BrowserContext> browser_context_;
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg
index 8bfde17..45d5b323 100644
--- a/infra/config/generated/luci/cr-buildbucket.cfg
+++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -25287,7 +25287,7 @@
       }
       experiments {
         key: "luci.buildbucket.omit_python2"
-        value: 0
+        value: 100
       }
       experiments {
         key: "luci.recipes.use_python3"
diff --git a/infra/config/subprojects/chromium/ci/chromium.android.star b/infra/config/subprojects/chromium/ci/chromium.android.star
index 369ff0d..835be90e 100644
--- a/infra/config/subprojects/chromium/ci/chromium.android.star
+++ b/infra/config/subprojects/chromium/ci/chromium.android.star
@@ -1377,4 +1377,7 @@
         short_name = "12",
     ),
     execution_timeout = 4 * time.hour,
+
+    # TODO(crbug.com/1366956): remove this after confirm py3 works on this builder.
+    omit_python2 = True,
 )
diff --git a/ios/chrome/browser/commerce/push_notification/BUILD.gn b/ios/chrome/browser/commerce/push_notification/BUILD.gn
index 7b7fd91..601ac5f 100644
--- a/ios/chrome/browser/commerce/push_notification/BUILD.gn
+++ b/ios/chrome/browser/commerce/push_notification/BUILD.gn
@@ -12,11 +12,15 @@
 
   deps = [
     "//base",
+    "//components/bookmarks/browser:browser",
     "//components/commerce/core:feature_list",
     "//components/commerce/core:proto",
+    "//components/commerce/core:shopping_service",
     "//components/optimization_guide/proto:optimization_guide_proto",
     "//ios/chrome/browser/application_context:application_context",
+    "//ios/chrome/browser/bookmarks:bookmarks",
     "//ios/chrome/browser/browser_state:browser_state",
+    "//ios/chrome/browser/commerce:shopping_service",
     "//ios/chrome/browser/main:public",
     "//ios/chrome/browser/optimization_guide",
     "//ios/chrome/browser/push_notification:push_notification_client",
@@ -37,14 +41,22 @@
     ":push_notification",
     "//base",
     "//base/test:test_support",
+    "//components/commerce/core:commerce_subscription_db_content_proto",
     "//components/commerce/core:proto",
+    "//components/commerce/core:shopping_service",
+    "//components/commerce/core:shopping_service_test_support",
     "//components/optimization_guide/proto:optimization_guide_proto",
+    "//components/session_proto_db:session_proto_db",
+    "//ios/chrome/browser/bookmarks:bookmarks",
     "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/browser_state:test_support",
+    "//ios/chrome/browser/commerce:session_proto_db",
+    "//ios/chrome/browser/commerce:shopping_service",
     "//ios/chrome/browser/main:public",
     "//ios/chrome/browser/main:test_support",
     "//ios/chrome/browser/url_loading:test_support",
     "//ios/chrome/browser/url_loading:url_loading",
+    "//ios/chrome/test:test_support",
     "//ios/web/public/test",
     "//ios/web/public/test/fakes",
     "//testing/gtest",
diff --git a/ios/chrome/browser/commerce/push_notification/commerce_push_notification_client.h b/ios/chrome/browser/commerce/push_notification/commerce_push_notification_client.h
index 46e4b17..ba39f49 100644
--- a/ios/chrome/browser/commerce/push_notification/commerce_push_notification_client.h
+++ b/ios/chrome/browser/commerce/push_notification/commerce_push_notification_client.h
@@ -5,6 +5,9 @@
 #ifndef IOS_CHROME_BROWSER_COMMERCE_PUSH_NOTIFICATION_COMMERCE_PUSH_NOTIFICATION_CLIENT_H_
 #define IOS_CHROME_BROWSER_COMMERCE_PUSH_NOTIFICATION_COMMERCE_PUSH_NOTIFICATION_CLIENT_H_
 
+#import "ios/chrome/browser/bookmarks/bookmark_model_factory.h"
+#import "ios/chrome/browser/browser_state/chrome_browser_state.h"
+#import "ios/chrome/browser/commerce/shopping_service_factory.h"
 #import "ios/chrome/browser/optimization_guide/optimization_guide_push_notification_client.h"
 #import "ios/chrome/browser/push_notification/push_notification_client.h"
 
@@ -13,6 +16,18 @@
 
 class CommercePushNotificationClientTest;
 
+namespace base {
+class RunLoop;
+}  // namespace base
+
+namespace bookmarks {
+class BookmarkModel;
+}  // namespace bookmarks
+
+namespace commerce {
+class ShoppingService;
+}  // namespace commerce
+
 class CommercePushNotificationClient
     : public OptimizationGuidePushNotificationClient {
  public:
@@ -29,9 +44,14 @@
  private:
   friend class ::CommercePushNotificationClientTest;
 
+  commerce::ShoppingService* GetShoppingService();
+  bookmarks::BookmarkModel* GetBookmarkModel();
+
   // Handle the interaction from the user be it tapping the notification or
   // long pressing and then presing 'Visit Site' or 'Untrack Price'.
-  void HandleNotificationInteraction(NSString* action_identifier,
-                                     NSDictionary* user_info);
+  void HandleNotificationInteraction(
+      NSString* action_identifier,
+      NSDictionary* user_info,
+      base::RunLoop* on_complete_for_testing = nil);
 };
 #endif  // IOS_CHROME_BROWSER_COMMERCE_PUSH_NOTIFICATION_COMMERCE_PUSH_NOTIFICATION_CLIENT_H_
diff --git a/ios/chrome/browser/commerce/push_notification/commerce_push_notification_client.mm b/ios/chrome/browser/commerce/push_notification/commerce_push_notification_client.mm
index bc542d6..e749f00 100644
--- a/ios/chrome/browser/commerce/push_notification/commerce_push_notification_client.mm
+++ b/ios/chrome/browser/commerce/push_notification/commerce_push_notification_client.mm
@@ -4,6 +4,10 @@
 
 #import "ios/chrome/browser/commerce/push_notification/commerce_push_notification_client.h"
 
+#import "base/run_loop.h"
+#import "components/bookmarks/browser/bookmark_model.h"
+#import "components/bookmarks/browser/bookmark_node.h"
+#import "components/commerce/core/price_tracking_utils.h"
 #import "components/commerce/core/proto/price_tracking.pb.h"
 #import "components/optimization_guide/proto/push_notification.pb.h"
 #import "ios/chrome/browser/application_context/application_context.h"
@@ -33,7 +37,12 @@
 // notification.
 NSString* kVisitSiteActionIdentifier = @"visit_site";
 // Text for option for long press.
-NSString* kVisitSiteTitle = @"Visit Site";
+NSString* kVisitSiteTitle = @"Visit site";
+// Identifier for user pressing 'Untrack price' after long pressing
+// notification.
+NSString* kUntrackPriceIdentifier = @"untrack_price";
+// Text for option 'Untrack price' when long pressing notification.
+NSString* kUntrackPriceTitle = @"Untrack price";
 
 }  // namespace
 
@@ -64,16 +73,48 @@
       actionWithIdentifier:kVisitSiteActionIdentifier
                      title:kVisitSiteTitle
                    options:UNNotificationActionOptionForeground];
+  UNNotificationAction* kUntrackPriceAction = [UNNotificationAction
+      actionWithIdentifier:kUntrackPriceIdentifier
+                     title:kUntrackPriceTitle
+                   options:UNNotificationActionOptionForeground];
+
   return @[ [UNNotificationCategory
       categoryWithIdentifier:kCommerceCategoryIdentifier
-                     actions:@[ kVisitSiteAction ]
+                     actions:@[ kVisitSiteAction, kUntrackPriceAction ]
            intentIdentifiers:@[]
                      options:UNNotificationCategoryOptionNone] ];
 }
 
+commerce::ShoppingService*
+CommercePushNotificationClient::GetShoppingService() {
+  return commerce::ShoppingServiceFactory::GetForBrowserState(
+      GetLastUsedBrowserState());
+}
+
+bookmarks::BookmarkModel* CommercePushNotificationClient::GetBookmarkModel() {
+  return ios::BookmarkModelFactory::GetForBrowserState(
+      GetLastUsedBrowserState());
+}
+
 void CommercePushNotificationClient::HandleNotificationInteraction(
     NSString* action_identifier,
-    NSDictionary* user_info) {
+    NSDictionary* user_info,
+    base::RunLoop* on_complete_for_testing) {
+  std::unique_ptr<optimization_guide::proto::HintNotificationPayload>
+      hint_notification_payload =
+          OptimizationGuidePushNotificationClient::ParseHintNotificationPayload(
+              [user_info objectForKey:kSerializedPayloadKey]);
+  if (!hint_notification_payload) {
+    return;
+  }
+
+  commerce::PriceDropNotificationPayload price_drop_notification;
+  if (!hint_notification_payload->has_payload() ||
+      !price_drop_notification.ParseFromString(
+          hint_notification_payload->payload().value())) {
+    return;
+  }
+
   // TODO(crbug.com/1362342) handle the user tapping 'untrack price'.
   // User taps notification or long presses notification and presses 'Visit
   // Site'.
@@ -82,21 +123,6 @@
     // TODO(crbug.com/1403190) implement alternate Open URL handler which
     // attempts to find if a Tab with the URL already exists and switch
     // to that Tab.
-    std::unique_ptr<optimization_guide::proto::HintNotificationPayload>
-        hint_notification_payload = OptimizationGuidePushNotificationClient::
-            ParseHintNotificationPayload(
-                [user_info objectForKey:kSerializedPayloadKey]);
-    if (!hint_notification_payload) {
-      return;
-    }
-
-    commerce::PriceDropNotificationPayload price_drop_notification;
-    if (!hint_notification_payload->has_payload() ||
-        !price_drop_notification.ParseFromString(
-            hint_notification_payload->payload().value())) {
-      return;
-    }
-
     BrowserList* browser_list =
         BrowserListFactory::GetForBrowserState(GetLastUsedBrowserState());
     if (!browser_list->AllRegularBrowsers().size()) {
@@ -108,5 +134,16 @@
     UrlLoadParams params = UrlLoadParams::InNewTab(
         GURL(price_drop_notification.destination_url()));
     UrlLoadingBrowserAgent::FromBrowser(browser)->Load(params);
+  } else if ([action_identifier isEqualToString:kUntrackPriceIdentifier]) {
+    const bookmarks::BookmarkNode* bookmark =
+        GetBookmarkModel()->GetMostRecentlyAddedUserNodeForURL(
+            GURL(price_drop_notification.destination_url()));
+    commerce::SetPriceTrackingStateForBookmark(
+        GetShoppingService(), GetBookmarkModel(), bookmark, false,
+        base::BindOnce(^(bool success) {
+          if (on_complete_for_testing) {
+            on_complete_for_testing->Quit();
+          }
+        }));
   }
 }
diff --git a/ios/chrome/browser/commerce/push_notification/commerce_push_notification_client_unittest.mm b/ios/chrome/browser/commerce/push_notification/commerce_push_notification_client_unittest.mm
index 60f06a1..3709ede 100644
--- a/ios/chrome/browser/commerce/push_notification/commerce_push_notification_client_unittest.mm
+++ b/ios/chrome/browser/commerce/push_notification/commerce_push_notification_client_unittest.mm
@@ -5,16 +5,29 @@
 #import "ios/chrome/browser/commerce/push_notification/commerce_push_notification_client.h"
 
 #import "base/base64.h"
+#import "base/run_loop.h"
 #import "base/strings/sys_string_conversions.h"
-#import "base/test/task_environment.h"
+#import "base/strings/utf_string_conversions.h"
+#import "components/bookmarks/browser/bookmark_model.h"
+#import "components/bookmarks/test/bookmark_test_helpers.h"
+#import "components/bookmarks/test/test_bookmark_client.h"
+#import "components/commerce/core/mock_shopping_service.h"
+#import "components/commerce/core/price_tracking_utils.h"
+#import "components/commerce/core/proto/commerce_subscription_db_content.pb.h"
 #import "components/commerce/core/proto/price_tracking.pb.h"
+#import "components/commerce/core/test_utils.h"
 #import "components/optimization_guide/proto/push_notification.pb.h"
+#import "components/session_proto_db/session_proto_db.h"
+#import "ios/chrome/browser/bookmarks/bookmark_model_factory.h"
 #import "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
+#import "ios/chrome/browser/commerce/session_proto_db_factory.h"
+#import "ios/chrome/browser/commerce/shopping_service_factory.h"
 #import "ios/chrome/browser/main/browser_list.h"
 #import "ios/chrome/browser/main/browser_list_factory.h"
 #import "ios/chrome/browser/main/test_browser.h"
 #import "ios/chrome/browser/url_loading/fake_url_loading_browser_agent.h"
 #import "ios/chrome/browser/url_loading/url_loading_notifier_browser_agent.h"
+#import "ios/web/public/test/web_task_environment.h"
 #import "testing/gmock/include/gmock/gmock.h"
 #import "testing/gtest/include/gtest/gtest.h"
 #import "testing/platform_test.h"
@@ -26,52 +39,15 @@
 namespace {
 
 constexpr char kHintKey[] = "https://www.merchant.com/price_drop_product";
+std::string kBookmarkTitle = "My product title";
+uint64_t kClusterId = 12345L;
 NSString* kSerializedPayloadKey = @"op";
 NSString* kVisitSiteActionId = @"visit_site";
-NSString* kVisitSiteTitle = @"Visit Site";
+NSString* kVisitSiteTitle = @"Visit site";
+NSString* kUntrackPriceActionId = @"untrack_price";
+NSString* kUntrackPriceTitle = @"Untrack price";
 
-}  // namespace
-
-class CommercePushNotificationClientTest : public PlatformTest {
- public:
-  CommercePushNotificationClientTest() {}
-  ~CommercePushNotificationClientTest() override = default;
-
-  void SetUp() override {
-    PlatformTest::SetUp();
-    TestChromeBrowserState::Builder test_browser_state_builder;
-    chrome_browser_state_ = test_browser_state_builder.Build();
-    browser_list_ =
-        BrowserListFactory::GetForBrowserState(chrome_browser_state_.get());
-    browser_ = std::make_unique<TestBrowser>(chrome_browser_state_.get());
-    browser_list_->AddBrowser(browser_.get());
-    UrlLoadingNotifierBrowserAgent::CreateForBrowser(browser_.get());
-    FakeUrlLoadingBrowserAgent::InjectForBrowser(browser_.get());
-    commerce_push_notification_client_.SetLastUsedChromeBrowserStateForTesting(
-        chrome_browser_state_.get());
-  }
-
-  CommercePushNotificationClient* GetCommercePushNotificationClient() {
-    return &commerce_push_notification_client_;
-  }
-
-  Browser* GetBrowser() { return browser_.get(); }
-
-  void HandleNotificationInteraction(NSString* action_identifier,
-                                     NSDictionary* user_info) {
-    commerce_push_notification_client_.HandleNotificationInteraction(
-        action_identifier, user_info);
-  }
-
- protected:
-  base::test::TaskEnvironment task_environment_;
-  CommercePushNotificationClient commerce_push_notification_client_;
-  std::unique_ptr<Browser> browser_;
-  std::unique_ptr<TestChromeBrowserState> chrome_browser_state_;
-  BrowserList* browser_list_;
-};
-
-TEST_F(CommercePushNotificationClientTest, TestNotificationInteraction) {
+NSDictionary* SerializeOptGuideCommercePayload() {
   // Serialized PriceDropNotificationPayload
   commerce::PriceDropNotificationPayload price_drop_notification;
   price_drop_notification.set_destination_url(kHintKey);
@@ -108,6 +84,92 @@
   NSDictionary* user_info = @{
     kSerializedPayloadKey : base::SysUTF8ToNSString(serialized_any_escaped)
   };
+  return user_info;
+}
+
+void TrackBookmark(commerce::ShoppingService* shopping_service,
+                   bookmarks::BookmarkModel* bookmark_model,
+                   const bookmarks::BookmarkNode* product) {
+  base::RunLoop run_loop;
+  SetPriceTrackingStateForBookmark(
+      shopping_service, bookmark_model, product, true,
+      base::BindOnce(
+          [](base::RunLoop* run_loop, bool success) {
+            EXPECT_TRUE(success);
+            run_loop->Quit();
+          },
+          &run_loop));
+  run_loop.Run();
+}
+
+}  // namespace
+
+class CommercePushNotificationClientTest : public PlatformTest {
+ public:
+  CommercePushNotificationClientTest() {}
+  ~CommercePushNotificationClientTest() override = default;
+
+  void SetUp() override {
+    PlatformTest::SetUp();
+    TestChromeBrowserState::Builder builder;
+    builder.AddTestingFactory(ios::BookmarkModelFactory::GetInstance(),
+                              ios::BookmarkModelFactory::GetDefaultFactory());
+    builder.AddTestingFactory(
+        commerce::ShoppingServiceFactory::GetInstance(),
+        base::BindRepeating(
+            [](web::BrowserState*) -> std::unique_ptr<KeyedService> {
+              return std::make_unique<commerce::MockShoppingService>();
+            }));
+    builder.AddTestingFactory(
+        SessionProtoDBFactory<
+            commerce_subscription_db::CommerceSubscriptionContentProto>::
+            GetInstance(),
+        SessionProtoDBFactory<
+            commerce_subscription_db::CommerceSubscriptionContentProto>::
+            GetDefaultFactory());
+    chrome_browser_state_ = builder.Build();
+    browser_list_ =
+        BrowserListFactory::GetForBrowserState(chrome_browser_state_.get());
+    browser_ = std::make_unique<TestBrowser>(chrome_browser_state_.get());
+    browser_list_->AddBrowser(browser_.get());
+    UrlLoadingNotifierBrowserAgent::CreateForBrowser(browser_.get());
+    FakeUrlLoadingBrowserAgent::InjectForBrowser(browser_.get());
+    commerce_push_notification_client_.SetLastUsedChromeBrowserStateForTesting(
+        chrome_browser_state_.get());
+    bookmark_model_ = ios::BookmarkModelFactory::GetForBrowserState(
+        chrome_browser_state_.get());
+    bookmarks::test::WaitForBookmarkModelToLoad(bookmark_model_);
+    shopping_service_ = static_cast<commerce::MockShoppingService*>(
+        commerce::ShoppingServiceFactory::GetForBrowserState(
+            chrome_browser_state_.get()));
+  }
+
+  CommercePushNotificationClient* GetCommercePushNotificationClient() {
+    return &commerce_push_notification_client_;
+  }
+
+  Browser* GetBrowser() { return browser_.get(); }
+
+  void HandleNotificationInteraction(
+      NSString* action_identifier,
+      NSDictionary* user_info,
+      base::RunLoop* on_complete_for_testing = nil) {
+    commerce_push_notification_client_.HandleNotificationInteraction(
+        action_identifier, user_info, on_complete_for_testing);
+  }
+
+ protected:
+  web::WebTaskEnvironment task_environment_;
+  CommercePushNotificationClient commerce_push_notification_client_;
+  std::unique_ptr<Browser> browser_;
+  std::unique_ptr<TestChromeBrowserState> chrome_browser_state_;
+  BrowserList* browser_list_;
+  bookmarks::BookmarkModel* bookmark_model_;
+  commerce::MockShoppingService* shopping_service_;
+};
+
+TEST_F(CommercePushNotificationClientTest, TestNotificationInteraction) {
+  NSDictionary* user_info = SerializeOptGuideCommercePayload();
 
   // Simulate user clicking 'visit site'.
   HandleNotificationInteraction(kVisitSiteActionId, user_info);
@@ -116,8 +178,7 @@
   FakeUrlLoadingBrowserAgent* url_loader =
       FakeUrlLoadingBrowserAgent::FromUrlLoadingBrowserAgent(
           UrlLoadingBrowserAgent::FromBrowser(GetBrowser()));
-  EXPECT_EQ(price_drop_notification.destination_url(),
-            url_loader->last_params.web_params.url);
+  EXPECT_EQ(kHintKey, url_loader->last_params.web_params.url);
 }
 
 TEST_F(CommercePushNotificationClientTest, TestActionableNotifications) {
@@ -125,8 +186,36 @@
       GetCommercePushNotificationClient()->RegisterActionableNotifications();
   EXPECT_EQ(1u, [actionable_notifications count]);
   UNNotificationCategory* notification_category = actionable_notifications[0];
+  EXPECT_EQ(2u, [notification_category.actions count]);
   EXPECT_TRUE([notification_category.actions[0].identifier
       isEqualToString:kVisitSiteActionId]);
   EXPECT_TRUE(
       [notification_category.actions[0].title isEqualToString:kVisitSiteTitle]);
+  EXPECT_TRUE([notification_category.actions[1].identifier
+      isEqualToString:kUntrackPriceActionId]);
+  EXPECT_TRUE([notification_category.actions[1].title
+      isEqualToString:kUntrackPriceTitle]);
+}
+
+TEST_F(CommercePushNotificationClientTest, TestUntrackPrice) {
+  const bookmarks::BookmarkNode* product = commerce::AddProductBookmark(
+      bookmark_model_, base::UTF8ToUTF16(kBookmarkTitle), GURL(kHintKey),
+      kClusterId, true);
+  shopping_service_->SetSubscribeCallbackValue(true);
+  shopping_service_->SetUnsubscribeCallbackValue(true);
+  TrackBookmark(shopping_service_, bookmark_model_, product);
+
+  commerce::ProductInfo product_info;
+  product_info.title = kBookmarkTitle;
+  absl::optional<commerce::ProductInfo> optional_product_info;
+  optional_product_info.emplace(product_info);
+  shopping_service_->SetResponseForGetProductInfoForUrl(optional_product_info);
+  EXPECT_TRUE(commerce::IsBookmarkPriceTracked(bookmark_model_, product));
+
+  NSDictionary* user_info = SerializeOptGuideCommercePayload();
+  base::RunLoop run_loop;
+  // Simulate user clicking 'visit site'.
+  HandleNotificationInteraction(kUntrackPriceActionId, user_info, &run_loop);
+  run_loop.Run();
+  EXPECT_FALSE(commerce::IsBookmarkPriceTracked(bookmark_model_, product));
 }
diff --git a/ios/chrome/browser/commerce/session_proto_db_factory.h b/ios/chrome/browser/commerce/session_proto_db_factory.h
index e8a599a..b267c7e5 100644
--- a/ios/chrome/browser/commerce/session_proto_db_factory.h
+++ b/ios/chrome/browser/commerce/session_proto_db_factory.h
@@ -19,6 +19,28 @@
 
 namespace {
 const char kCommerceSubscriptionDBFolder[] = "commerce_subscription_db";
+
+template <typename T>
+std::unique_ptr<KeyedService> BuildSessionProtoDB(web::BrowserState* state) {
+  DCHECK(!state->IsOffTheRecord());
+
+  if (std::is_base_of<
+          commerce_subscription_db::CommerceSubscriptionContentProto,
+          T>::value) {
+    return std::make_unique<SessionProtoDB<T>>(
+        state->GetProtoDatabaseProvider(),
+        state->GetStatePath().AppendASCII(kCommerceSubscriptionDBFolder),
+        leveldb_proto::ProtoDbType::COMMERCE_SUBSCRIPTION_DATABASE,
+        web::GetUIThreadTaskRunner({}));
+  } else {
+    // Must add in leveldb_proto::ProtoDbType and database directory folder
+    // new protos.
+    DCHECK(false) << "Provided template is not supported. To support add "
+                     "unique folder in the above proto -> folder name mapping. "
+                     "This check could also fail because the template is not "
+                     "supported on current platform.";
+  }
+}
 }  // namespace
 
 SessionProtoDBFactory<
@@ -34,6 +56,8 @@
   static SessionProtoDBFactory<T>* GetInstance();
   static SessionProtoDB<T>* GetForBrowserState(web::BrowserState* state);
 
+  static TestingFactory GetDefaultFactory();
+
  private:
   friend class base::NoDestructor<SessionProtoDBFactory<T>>;
 
@@ -57,6 +81,12 @@
 }
 
 template <typename T>
+BrowserStateKeyedServiceFactory::TestingFactory
+SessionProtoDBFactory<T>::GetDefaultFactory() {
+  return base::BindRepeating(&BuildSessionProtoDB<T>);
+}
+
+template <typename T>
 SessionProtoDBFactory<T>::SessionProtoDBFactory()
     : BrowserStateKeyedServiceFactory(
           "SessionProtoDB",
@@ -65,24 +95,7 @@
 template <typename T>
 std::unique_ptr<KeyedService> SessionProtoDBFactory<T>::BuildServiceInstanceFor(
     web::BrowserState* state) const {
-  DCHECK(!state->IsOffTheRecord());
-
-  if (std::is_base_of<
-          commerce_subscription_db::CommerceSubscriptionContentProto,
-          T>::value) {
-    return std::make_unique<SessionProtoDB<T>>(
-        state->GetProtoDatabaseProvider(),
-        state->GetStatePath().AppendASCII(kCommerceSubscriptionDBFolder),
-        leveldb_proto::ProtoDbType::COMMERCE_SUBSCRIPTION_DATABASE,
-        web::GetUIThreadTaskRunner({}));
-  } else {
-    // Must add in leveldb_proto::ProtoDbType and database directory folder
-    // new protos.
-    DCHECK(false) << "Provided template is not supported. To support add "
-                     "unique folder in the above proto -> folder name mapping. "
-                     "This check could also fail because the template is not "
-                     "supported on current platform.";
-  }
+  return BuildSessionProtoDB<T>(state);
 }
 
 #endif  // IOS_CHROME_BROWSER_COMMERCE_SESSION_PROTO_DB_FACTORY_H_
diff --git a/ipc/ipc_sync_channel_unittest.cc b/ipc/ipc_sync_channel_unittest.cc
index ea06ac57..6f200f3 100644
--- a/ipc/ipc_sync_channel_unittest.cc
+++ b/ipc/ipc_sync_channel_unittest.cc
@@ -53,7 +53,8 @@
                               base::WaitableEvent::InitialState::NOT_SIGNALED)),
         channel_handle_(std::move(channel_handle)),
         mode_(mode),
-        ipc_thread_((thread_name + "_ipc").c_str()),
+        ipc_thread_(
+            std::make_unique<base::Thread>((thread_name + "_ipc").c_str())),
         listener_thread_((thread_name + "_listener").c_str()),
         overrided_thread_(nullptr),
         shutdown_event_(base::WaitableEvent::ResetPolicy::MANUAL,
@@ -70,7 +71,7 @@
                               base::WaitableEvent::InitialState::NOT_SIGNALED)),
         channel_handle_(std::move(channel_handle)),
         mode_(mode),
-        ipc_thread_("ipc thread"),
+        ipc_thread_(std::make_unique<base::Thread>("ipc thread")),
         listener_thread_("listener thread"),
         overrided_thread_(nullptr),
         shutdown_event_(base::WaitableEvent::ResetPolicy::MANUAL,
@@ -101,16 +102,11 @@
     // may result in a race conditions. See http://crbug.com/25841.
     WaitableEvent listener_done(
         base::WaitableEvent::ResetPolicy::AUTOMATIC,
-        base::WaitableEvent::InitialState::NOT_SIGNALED),
-        ipc_done(base::WaitableEvent::ResetPolicy::AUTOMATIC,
-                 base::WaitableEvent::InitialState::NOT_SIGNALED);
+        base::WaitableEvent::InitialState::NOT_SIGNALED);
     ListenerThread()->task_runner()->PostTask(
-        FROM_HERE,
-        base::BindOnce(&Worker::OnListenerThreadShutdown1,
-                       base::Unretained(this), &listener_done, &ipc_done));
+        FROM_HERE, base::BindOnce(&Worker::OnListenerThreadShutdown1,
+                                  base::Unretained(this), &listener_done));
     listener_done.Wait();
-    ipc_done.Wait();
-    ipc_thread_.Stop();
     listener_thread_.Stop();
     is_shutdown_ = true;
   }
@@ -176,7 +172,7 @@
 
   virtual SyncChannel* CreateChannel() {
     std::unique_ptr<SyncChannel> channel = SyncChannel::Create(
-        TakeChannelHandle(), mode_, this, ipc_thread_.task_runner(),
+        TakeChannelHandle(), mode_, this, ipc_thread_->task_runner(),
         base::SingleThreadTaskRunner::GetCurrentDefault(), true,
         &shutdown_event_);
     return channel.release();
@@ -186,29 +182,33 @@
     return overrided_thread_ ? overrided_thread_.get() : &listener_thread_;
   }
 
-  const base::Thread& ipc_thread() const { return ipc_thread_; }
+  const base::Thread& ipc_thread() const { return *ipc_thread_.get(); }
 
  private:
   // Called on the listener thread to create the sync channel.
   void OnStart() {
     // Link ipc_thread_, listener_thread_ and channel_ altogether.
-    StartThread(&ipc_thread_, base::MessagePumpType::IO);
+    StartThread(ipc_thread_.get(), base::MessagePumpType::IO);
     channel_.reset(CreateChannel());
     channel_created_->Signal();
     Run();
   }
 
-  void OnListenerThreadShutdown1(WaitableEvent* listener_event,
-                                 WaitableEvent* ipc_event) {
+  void OnListenerThreadShutdown1(WaitableEvent* listener_event) {
+    WaitableEvent ipc_event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+                            base::WaitableEvent::InitialState::NOT_SIGNALED);
     // SyncChannel needs to be destructed on the thread that it was created on.
     channel_.reset();
 
     base::RunLoop().RunUntilIdle();
 
-    ipc_thread_.task_runner()->PostTask(
+    ipc_thread_->task_runner()->PostTask(
         FROM_HERE,
         base::BindOnce(&Worker::OnIPCThreadShutdown, base::Unretained(this),
-                       listener_event, ipc_event));
+                       listener_event, &ipc_event));
+    ipc_event.Wait();
+    // This destructs `ipc_thread_` on the listener thread.
+    ipc_thread_.reset();
   }
 
   void OnIPCThreadShutdown(WaitableEvent* listener_event,
@@ -248,7 +248,10 @@
   mojo::ScopedMessagePipeHandle channel_handle_;
   Channel::Mode mode_;
   std::unique_ptr<SyncChannel> channel_;
-  base::Thread ipc_thread_;
+  // This thread is constructed on the main thread, Start() on
+  // `listener_thread_`, and therefore destructed/Stop()'d on the
+  // `listener_thread_` too.
+  std::unique_ptr<base::Thread> ipc_thread_;
   base::Thread listener_thread_;
   raw_ptr<base::Thread> overrided_thread_;
 
diff --git a/net/base/file_stream_unittest.cc b/net/base/file_stream_unittest.cc
index fc57783..8c9dac3e 100644
--- a/net/base/file_stream_unittest.cc
+++ b/net/base/file_stream_unittest.cc
@@ -616,18 +616,21 @@
   int total_bytes_written = 0;
   int total_bytes_read = 0;
   std::string data_read;
-  TestWriteReadCompletionCallback callback(stream.get(), &total_bytes_written,
-                                           &total_bytes_read, &data_read);
+  {
+    // `callback` can't outlive `stream`.
+    TestWriteReadCompletionCallback callback(stream.get(), &total_bytes_written,
+                                             &total_bytes_read, &data_read);
 
-  scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
-  rv = stream->Write(buf.get(), buf->size(), callback.callback());
-  if (rv == ERR_IO_PENDING)
-    rv = callback.WaitForResult();
-  EXPECT_LT(0, rv);
-  EXPECT_EQ(kTestDataSize, total_bytes_written);
+    scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
+    rv = stream->Write(buf.get(), buf->size(), callback.callback());
+    if (rv == ERR_IO_PENDING) {
+      rv = callback.WaitForResult();
+    }
+    EXPECT_LT(0, rv);
+    EXPECT_EQ(kTestDataSize, total_bytes_written);
 
-  callback.ValidateWrittenData();
-
+    callback.ValidateWrittenData();
+  }
   stream.reset();
 
   EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
@@ -720,15 +723,18 @@
   EXPECT_EQ(file_size, callback64.WaitForResult());
 
   int total_bytes_written = 0;
-  TestWriteCloseCompletionCallback callback(stream.get(), &total_bytes_written);
-
-  scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
-  rv = stream->Write(buf.get(), buf->size(), callback.callback());
-  if (rv == ERR_IO_PENDING)
-    total_bytes_written = callback.WaitForResult();
-  EXPECT_LT(0, total_bytes_written);
-  EXPECT_EQ(kTestDataSize, total_bytes_written);
-
+  {
+    // `callback` can't outlive `stream`.
+    TestWriteCloseCompletionCallback callback(stream.get(),
+                                              &total_bytes_written);
+    scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer();
+    rv = stream->Write(buf.get(), buf->size(), callback.callback());
+    if (rv == ERR_IO_PENDING) {
+      total_bytes_written = callback.WaitForResult();
+    }
+    EXPECT_LT(0, total_bytes_written);
+    EXPECT_EQ(kTestDataSize, total_bytes_written);
+  }
   stream.reset();
 
   EXPECT_TRUE(base::GetFileSize(temp_file_path(), &file_size));
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json
index 1f6be1d8f..ad074f9 100644
--- a/testing/buildbot/chrome.json
+++ b/testing/buildbot/chrome.json
@@ -78,7 +78,8 @@
       {
         "args": [
           "--magic-vm-cache=magic_cros_vm_cache",
-          "--strip-chrome"
+          "--strip-chrome",
+          "--tast-retries=1"
         ],
         "merge": {
           "args": [],
@@ -1416,6 +1417,9 @@
         }
       },
       {
+        "args": [
+          "--tast-retries=1"
+        ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index 23164d48..d797279d 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -5817,9 +5817,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5517.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5518.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 111.0.5517.0",
+        "description": "Run with ash-chrome version 111.0.5518.0",
         "isolate_profile_data": true,
         "merge": {
           "args": [],
@@ -5831,8 +5831,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v111.0.5517.0",
-              "revision": "version:111.0.5517.0"
+              "location": "lacros_version_skew_tests_v111.0.5518.0",
+              "revision": "version:111.0.5518.0"
             }
           ],
           "dimension_sets": [
@@ -5988,9 +5988,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5517.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5518.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 111.0.5517.0",
+        "description": "Run with ash-chrome version 111.0.5518.0",
         "isolate_profile_data": true,
         "merge": {
           "args": [],
@@ -6002,8 +6002,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v111.0.5517.0",
-              "revision": "version:111.0.5517.0"
+              "location": "lacros_version_skew_tests_v111.0.5518.0",
+              "revision": "version:111.0.5518.0"
             }
           ],
           "dimension_sets": [
@@ -6140,9 +6140,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5517.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5518.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 111.0.5517.0",
+        "description": "Run with ash-chrome version 111.0.5518.0",
         "isolate_profile_data": true,
         "merge": {
           "args": [],
@@ -6154,8 +6154,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v111.0.5517.0",
-              "revision": "version:111.0.5517.0"
+              "location": "lacros_version_skew_tests_v111.0.5518.0",
+              "revision": "version:111.0.5518.0"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 1bdbb8c..b98fb18 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -85435,9 +85435,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5517.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5518.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 111.0.5517.0",
+        "description": "Run with ash-chrome version 111.0.5518.0",
         "isolate_profile_data": true,
         "merge": {
           "args": [],
@@ -85449,8 +85449,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v111.0.5517.0",
-              "revision": "version:111.0.5517.0"
+              "location": "lacros_version_skew_tests_v111.0.5518.0",
+              "revision": "version:111.0.5518.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -85576,9 +85576,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5517.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5518.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 111.0.5517.0",
+        "description": "Run with ash-chrome version 111.0.5518.0",
         "isolate_profile_data": true,
         "merge": {
           "args": [],
@@ -85590,8 +85590,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v111.0.5517.0",
-              "revision": "version:111.0.5517.0"
+              "location": "lacros_version_skew_tests_v111.0.5518.0",
+              "revision": "version:111.0.5518.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -85703,9 +85703,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5517.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5518.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 111.0.5517.0",
+        "description": "Run with ash-chrome version 111.0.5518.0",
         "isolate_profile_data": true,
         "merge": {
           "args": [],
@@ -85717,8 +85717,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v111.0.5517.0",
-              "revision": "version:111.0.5517.0"
+              "location": "lacros_version_skew_tests_v111.0.5518.0",
+              "revision": "version:111.0.5518.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -87051,9 +87051,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5517.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5518.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 111.0.5517.0",
+        "description": "Run with ash-chrome version 111.0.5518.0",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -87064,8 +87064,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v111.0.5517.0",
-              "revision": "version:111.0.5517.0"
+              "location": "lacros_version_skew_tests_v111.0.5518.0",
+              "revision": "version:111.0.5518.0"
             }
           ],
           "dimension_sets": [
@@ -87222,9 +87222,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5517.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5518.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 111.0.5517.0",
+        "description": "Run with ash-chrome version 111.0.5518.0",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -87235,8 +87235,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v111.0.5517.0",
-              "revision": "version:111.0.5517.0"
+              "location": "lacros_version_skew_tests_v111.0.5518.0",
+              "revision": "version:111.0.5518.0"
             }
           ],
           "dimension_sets": [
@@ -87374,9 +87374,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5517.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5518.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 111.0.5517.0",
+        "description": "Run with ash-chrome version 111.0.5518.0",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -87387,8 +87387,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v111.0.5517.0",
-              "revision": "version:111.0.5517.0"
+              "location": "lacros_version_skew_tests_v111.0.5518.0",
+              "revision": "version:111.0.5518.0"
             }
           ],
           "dimension_sets": [
@@ -88912,9 +88912,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5517.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5518.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 111.0.5517.0",
+        "description": "Run with ash-chrome version 111.0.5518.0",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -88925,8 +88925,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v111.0.5517.0",
-              "revision": "version:111.0.5517.0"
+              "location": "lacros_version_skew_tests_v111.0.5518.0",
+              "revision": "version:111.0.5518.0"
             }
           ],
           "dimension_sets": [
@@ -89083,9 +89083,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5517.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5518.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 111.0.5517.0",
+        "description": "Run with ash-chrome version 111.0.5518.0",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -89096,8 +89096,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v111.0.5517.0",
-              "revision": "version:111.0.5517.0"
+              "location": "lacros_version_skew_tests_v111.0.5518.0",
+              "revision": "version:111.0.5518.0"
             }
           ],
           "dimension_sets": [
@@ -89235,9 +89235,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5517.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5518.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 111.0.5517.0",
+        "description": "Run with ash-chrome version 111.0.5518.0",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -89248,8 +89248,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v111.0.5517.0",
-              "revision": "version:111.0.5517.0"
+              "location": "lacros_version_skew_tests_v111.0.5518.0",
+              "revision": "version:111.0.5518.0"
             }
           ],
           "dimension_sets": [
@@ -90021,9 +90021,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5517.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5518.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 111.0.5517.0",
+        "description": "Run with ash-chrome version 111.0.5518.0",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -90034,8 +90034,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v111.0.5517.0",
-              "revision": "version:111.0.5517.0"
+              "location": "lacros_version_skew_tests_v111.0.5518.0",
+              "revision": "version:111.0.5518.0"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index 5251dbf..fbc1767de 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -18653,12 +18653,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5517.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5518.0/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 111.0.5517.0",
+        "description": "Run with ash-chrome version 111.0.5518.0",
         "isolate_profile_data": true,
         "merge": {
           "args": [],
@@ -18670,8 +18670,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v111.0.5517.0",
-              "revision": "version:111.0.5517.0"
+              "location": "lacros_version_skew_tests_v111.0.5518.0",
+              "revision": "version:111.0.5518.0"
             }
           ],
           "dimension_sets": [
@@ -18844,12 +18844,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5517.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5518.0/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 111.0.5517.0",
+        "description": "Run with ash-chrome version 111.0.5518.0",
         "isolate_profile_data": true,
         "merge": {
           "args": [],
@@ -18861,8 +18861,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v111.0.5517.0",
-              "revision": "version:111.0.5517.0"
+              "location": "lacros_version_skew_tests_v111.0.5518.0",
+              "revision": "version:111.0.5518.0"
             }
           ],
           "dimension_sets": [
@@ -19011,12 +19011,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5517.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5518.0/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 111.0.5517.0",
+        "description": "Run with ash-chrome version 111.0.5518.0",
         "isolate_profile_data": true,
         "merge": {
           "args": [],
@@ -19028,8 +19028,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v111.0.5517.0",
-              "revision": "version:111.0.5517.0"
+              "location": "lacros_version_skew_tests_v111.0.5518.0",
+              "revision": "version:111.0.5518.0"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index 07a21de..d86da3f 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -1211,6 +1211,7 @@
         'args': [
           # This bot sets symbol_level=2, which doesn't fit inside a normal VM.
           '--strip-chrome',
+          '--tast-retries=1',
         ],
       },
       'chromeos-betty-pi-arc-chrome': {
@@ -1219,6 +1220,9 @@
         },
       },
       'chromeos-eve-chrome': {
+        'args':[
+          '--tast-retries=1',
+        ],
         'swarming': {
           # Increased timeout to 2 hours due to shard timeout.
           'hard_timeout': 7200,
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index 959e147..f090735cd 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_v111.0.5517.0/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v111.0.5518.0/test_ash_chrome',
     ],
-    'description': 'Run with ash-chrome version 111.0.5517.0',
+    'description': 'Run with ash-chrome version 111.0.5518.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_v111.0.5517.0',
-          'revision': 'version:111.0.5517.0',
+          'location': 'lacros_version_skew_tests_v111.0.5518.0',
+          'revision': 'version:111.0.5518.0',
         },
       ],
     },
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index e131608..12add93a 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -2627,17 +2627,17 @@
             ],
             "experiments": [
                 {
-                    "name": "EnabledGroupA_20221003",
+                    "name": "EnabledGroupC_20230103",
                     "params": {
-                        "CrOSZramWritebackWritebackBackoffTimeSec": "900",
-                        "ZramWritebackHuge": "true",
+                        "CrOSZramWritebackWritebackBackoffTimeSec": "1800",
+                        "ZramWritebackHuge": "false",
                         "ZramWritebackHugeIdle": "true",
-                        "ZramWritebackIdle": "false",
-                        "ZramWritebackIdleMaxTimeSec": "10800",
-                        "ZramWritebackIdleMinTimeSec": "1800",
-                        "ZramWritebackMaxPages": "25600",
-                        "ZramWritebackMinPages": "2560",
-                        "ZramWritebackPeriodicTimeSec": "180"
+                        "ZramWritebackIdle": "true",
+                        "ZramWritebackIdleMaxTimeSec": "86400",
+                        "ZramWritebackIdleMinTimeSec": "43200",
+                        "ZramWritebackMaxPages": "51200",
+                        "ZramWritebackMinPages": "1280",
+                        "ZramWritebackPeriodicTimeSec": "600"
                     },
                     "enable_features": [
                         "ChromeOSZramWriteback"
diff --git a/third_party/blink/public/common/frame/fenced_frame_permissions_policies.h b/third_party/blink/public/common/frame/fenced_frame_permissions_policies.h
index 95e98b1..ad511c68 100644
--- a/third_party/blink/public/common/frame/fenced_frame_permissions_policies.h
+++ b/third_party/blink/public/common/frame/fenced_frame_permissions_policies.h
@@ -17,7 +17,9 @@
 constexpr blink::mojom::PermissionsPolicyFeature
     kFencedFrameOpaqueAdsDefaultAllowedFeatures[] = {
         blink::mojom::PermissionsPolicyFeature::kAttributionReporting,
-        blink::mojom::PermissionsPolicyFeature::kSharedStorage};
+        blink::mojom::PermissionsPolicyFeature::kSharedStorage,
+        blink::mojom::PermissionsPolicyFeature::kSharedStorageSelectUrl,
+        blink::mojom::PermissionsPolicyFeature::kPrivateAggregation};
 
 }  // namespace blink
 
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
index 758f2173..8892fde 100644
--- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl
+++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -7218,12 +7218,14 @@
       otp-credentials
       payment
       picture-in-picture
+      private-aggregation
       publickey-credentials-get
       run-ad-auction
       screen-wake-lock
       serial
       shared-autofill
       shared-storage
+      shared-storage-select-url
       smart-card
       storage-access
       sync-xhr
diff --git a/third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom b/third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom
index 6dac562..ae2ee8a 100644
--- a/third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom
+++ b/third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom
@@ -227,7 +227,15 @@
   kComputePressure = 106,
 
   // Web Smart Card API
-  kSmartCard = 107
+  kSmartCard = 107,
+
+  // "shared-storage-select-url" permissions policy that controls the use of
+  // sharedStorage.selectURL().
+  kSharedStorageSelectUrl = 108,
+
+  // "private-aggregation" permissions policy that controls the use of
+  // privateAggregation within the shared storage worklet.
+  kPrivateAggregation = 109
 
   // Don't change assigned numbers of any item, and don't reuse removed slots.
   // Add new features at the end of the enum.
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h
index 48c40a3..590cc49 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h
@@ -305,12 +305,6 @@
   PhysicalRect ScrollableOverflow(TextHeightType height_type) const;
   PhysicalRect ScrollableOverflowFromChildren(TextHeightType height_type) const;
 
-  OverflowClipAxes GetOverflowClipAxes() const {
-    if (const auto* layout_object = GetLayoutObject())
-      return layout_object->GetOverflowClipAxes();
-    return kNoOverflowClip;
-  }
-
   // TODO(layout-dev): These three methods delegate to legacy layout for now,
   // update them to use LayoutNG based overflow information from the fragment
   // and change them to use NG geometry types once LayoutNG supports overflow.
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
index 707050b..9722a122 100644
--- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
+++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -2887,7 +2887,7 @@
       // descendants need special treatment inside block fragmentation.
       context_.current.is_in_block_fragmentation =
           pre_paint_info_->fragmentainer_is_oof_containing_block &&
-          box->GetNGPaginationBreakability() != LayoutBox::kForbidBreaks;
+          !pre_paint_info_->box_fragment.IsMonolithic();
     } else {
       // TODO(pdr): Several calls in this function walk back up the tree to
       // calculate containers (e.g., physicalLocation,
diff --git a/third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5 b/third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5
index e677d78..bc6019f3 100644
--- a/third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5
+++ b/third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5
@@ -323,6 +323,14 @@
       feature_default: "EnableForAll",
     },
     {
+      name: "PrivateAggregation",
+      permissions_policy_name: "private-aggregation",
+      feature_default: "EnableForAll",
+      // TODO(yaoxia): add "Fledge" to the `depends_on` list and implement their
+      // permission checks.
+      depends_on: ["SharedStorageAPI"],
+    },
+    {
       name: "PublicKeyCredentialsGet",
       permissions_policy_name: "publickey-credentials-get",
     },
@@ -357,6 +365,12 @@
       depends_on: ["SharedStorageAPI"],
     },
     {
+      name: "SharedStorageSelectUrl",
+      permissions_policy_name: "shared-storage-select-url",
+      feature_default: "EnableForAll",
+      depends_on: ["SharedStorageAPI"],
+    },
+    {
       name: "SmartCard",
       permissions_policy_name: "smart-card",
       depends_on: ["SmartCard"],
diff --git a/third_party/blink/renderer/modules/shared_storage/shared_storage.cc b/third_party/blink/renderer/modules/shared_storage/shared_storage.cc
index 9feefa8..1ad8193d 100644
--- a/third_party/blink/renderer/modules/shared_storage/shared_storage.cc
+++ b/third_party/blink/renderer/modules/shared_storage/shared_storage.cc
@@ -382,6 +382,19 @@
     return promise;
   }
 
+  if (!execution_context->IsFeatureEnabled(
+          mojom::blink::PermissionsPolicyFeature::kSharedStorageSelectUrl)) {
+    resolver->Reject(V8ThrowDOMException::CreateOrEmpty(
+        script_state->GetIsolate(), DOMExceptionCode::kInvalidAccessError,
+        "The \"shared-storage-select-url\" Permissions Policy denied the usage "
+        "of window.sharedStorage.selectURL()."));
+
+    LogSharedStorageWorkletError(
+        SharedStorageWorkletErrorType::kSelectURLWebVisible);
+
+    return promise;
+  }
+
   if (!IsValidSharedStorageURLsArrayLength(urls.size())) {
     resolver->Reject(V8ThrowDOMException::CreateOrEmpty(
         script_state->GetIsolate(), DOMExceptionCode::kDataError,
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc
index 11af55b..e588fc7c 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc
@@ -851,11 +851,11 @@
   }
 }
 
-PaintRecord PaintChunksToCcLayer::Convert(const PaintChunkSubset& chunks,
-                                          const PropertyTreeState& layer_state,
-                                          const gfx::Vector2dF& layer_offset) {
+PaintRecord PaintChunksToCcLayer::Convert(
+    const PaintChunkSubset& chunks,
+    const PropertyTreeState& layer_state) {
   PaintOpBufferExt buffer;
-  ConversionContext(layer_state, layer_offset, buffer).Convert(chunks);
+  ConversionContext(layer_state, gfx::Vector2dF(), buffer).Convert(chunks);
   return buffer.ReleaseAsRecord();
 }
 
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.h b/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.h
index e7653c0..58ced9a 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.h
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.h
@@ -63,8 +63,7 @@
 
   // Similar to ConvertInto(), but returns a PaintRecord.
   static PaintRecord Convert(const PaintChunkSubset&,
-                             const PropertyTreeState& layer_state,
-                             const gfx::Vector2dF& layer_offset);
+                             const PropertyTreeState& layer_state);
 
   // Returns true if any selection was painted in the provided PaintChunkSubset.
   static bool UpdateLayerSelection(cc::Layer& layer,
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc
index ad23c92..0d4895a0 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc
@@ -233,8 +233,8 @@
   chunks.AddChunk(t0(), c0(), *e1, gfx::Rect(0, 0, 50, 50));
   chunks.AddChunk(t0(), c0(), *e1, gfx::Rect(20, 20, 70, 70));
 
-  PaintRecord output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF());
+  PaintRecord output =
+      PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
   EXPECT_THAT(
       output,
       PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha,  // <e1>
@@ -253,8 +253,8 @@
   chunks.AddChunk(t0(), c0(), *e2);
   chunks.AddChunk(t0(), c0(), *e3, gfx::Rect(111, 222, 333, 444));
 
-  PaintRecord output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF());
+  PaintRecord output =
+      PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
   EXPECT_THAT(
       output,
       PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha,  // <e1>
@@ -283,8 +283,8 @@
   chunks.AddChunk(*t2, c0(), *e1, gfx::Rect(0, 0, 50, 50));
   chunks.AddChunk(*t1, c0(), *e2, gfx::Rect(20, 20, 70, 70));
 
-  PaintRecord output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF());
+  PaintRecord output =
+      PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
   EXPECT_THAT(
       output,
       PaintRecordMatcher::Make(
@@ -327,8 +327,8 @@
   chunks.AddChunk(t0(), *c3, *e1, gfx::Rect(20, 20, 70, 70));
   chunks.AddChunk(t0(), *c4, e0());
 
-  PaintRecord output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF());
+  PaintRecord output =
+      PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
   EXPECT_THAT(output, PaintRecordMatcher::Make(
                           {cc::PaintOpType::Save,
                            cc::PaintOpType::ClipRect,    // <c1+c2>
@@ -369,8 +369,8 @@
   TestChunks chunks;
   chunks.AddChunk(t0(), *c1, e0());
 
-  PaintRecord output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF());
+  PaintRecord output =
+      PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
   EXPECT_THAT(output,
               PaintRecordMatcher::Make(
                   {cc::PaintOpType::Save, cc::PaintOpType::Concat,  // <t1
@@ -395,8 +395,8 @@
   chunks.AddChunk(t0(), c0(), *e1);
   chunks.AddChunk(*t1, c0(), *e1);
 
-  PaintRecord output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF());
+  PaintRecord output =
+      PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
   EXPECT_THAT(output,
               PaintRecordMatcher::Make(
                   {cc::PaintOpType::Save, cc::PaintOpType::Concat,  // <t1>
@@ -427,8 +427,8 @@
   TestChunks chunks;
   chunks.AddChunk(t0(), c0(), *e1);
 
-  auto output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF());
+  auto output =
+      PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
   EXPECT_THAT(output,
               PaintRecordMatcher::Make(
                   {cc::PaintOpType::Save, cc::PaintOpType::Concat,  // <t1>
@@ -453,7 +453,7 @@
   chunks.AddChunk(*t1, *c1, *e1);
 
   PaintRecord output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState(*t1, *c1, *e1), gfx::Vector2dF());
+      chunks.Build(), PropertyTreeState(*t1, *c1, *e1));
   EXPECT_THAT(output, PaintRecordMatcher::Make({cc::PaintOpType::DrawRecord}));
 }
 
@@ -467,7 +467,7 @@
   chunks.AddChunk(t0(), *c1, *e1);
 
   PaintRecord output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState(*t1, *c1, *e1), gfx::Vector2dF());
+      chunks.Build(), PropertyTreeState(*t1, *c1, *e1));
   EXPECT_THAT(output,
               PaintRecordMatcher::Make(
                   {cc::PaintOpType::Save, cc::PaintOpType::Concat,  // <t1^-1>
@@ -485,7 +485,7 @@
   chunks.AddChunk(t0(), *c2, *e1);
 
   PaintRecord output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState(t0(), *c1, e0()), gfx::Vector2dF());
+      chunks.Build(), PropertyTreeState(t0(), *c1, e0()));
   EXPECT_THAT(
       output,
       PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha,  // <e1>
@@ -506,8 +506,8 @@
   TestChunks chunks;
   chunks.AddChunk(t0(), *c1, *e2);
 
-  PaintRecord output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF());
+  PaintRecord output =
+      PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
   EXPECT_THAT(
       output,
       PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha,  // <e1>
@@ -532,7 +532,7 @@
   chunks.AddChunk(t0(), *c1, *e2);
 
   PaintRecord output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState(t0(), c0(), *e1), gfx::Vector2dF());
+      chunks.Build(), PropertyTreeState(t0(), c0(), *e1));
   EXPECT_THAT(
       output,
       PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha,  // <e2>
@@ -554,7 +554,7 @@
   chunks.AddChunk(t0(), *c1, *e2);
 
   PaintRecord output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState(t0(), *c1, *e1), gfx::Vector2dF());
+      chunks.Build(), PropertyTreeState(t0(), *c1, *e1));
   EXPECT_THAT(
       output,
       PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha,  // <e2>
@@ -592,8 +592,8 @@
   TestChunks chunks;
   chunks.AddChunk(t0(), *c1, e0());
 
-  auto output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF());
+  auto output =
+      PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
   EXPECT_THAT(
       output,
@@ -618,8 +618,8 @@
   // D1
   chunks.AddChunk(t0(), *c2, e0());
 
-  PaintRecord output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF());
+  PaintRecord output =
+      PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
   // Note that c1 and c1c2 are elided.
   EXPECT_THAT(output, PaintRecordMatcher::Make({
@@ -645,8 +645,8 @@
   // D2
   chunks.AddChunk(t0(), *c2, e0());
 
-  PaintRecord output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF());
+  PaintRecord output =
+      PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
   EXPECT_THAT(output,
               PaintRecordMatcher::Make({
@@ -666,8 +666,8 @@
   chunks.AddChunk(PaintRecord(), t0(), c0(), e0());
   chunks.AddChunk(PaintRecord(), t0(), c0(), *e1);
 
-  PaintRecord output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF());
+  PaintRecord output =
+      PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
   EXPECT_THAT(output, PaintRecordMatcher::Make({
                           cc::PaintOpType::SaveLayerAlpha,  // <e1>
@@ -690,8 +690,8 @@
   chunks.AddChunk(*t1, *c6, e0());
   chunks.AddChunk(*t1, *c3, e0());
 
-  PaintRecord output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF());
+  PaintRecord output =
+      PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
   EXPECT_THAT(
       output,
@@ -724,8 +724,8 @@
   TestChunks chunks;
   chunks.AddChunk(*non_invertible, *c4, e0());
 
-  PaintRecord output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF());
+  PaintRecord output =
+      PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
   // We combine c1/c2 across |identity|, but not c2/c3 across |non_identity|
   // and c3/c4 across |non_invertible|.
@@ -765,8 +765,8 @@
   TestChunks chunks;
   chunks.AddChunk(t0(), *c7, e0());
 
-  PaintRecord output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF());
+  PaintRecord output =
+      PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
   EXPECT_THAT(
       output,
@@ -804,8 +804,8 @@
   chunks.AddChunk(*t2, *c1, e0());
   chunks.AddChunk(*t2, *c1, e0());
 
-  PaintRecord output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF());
+  PaintRecord output =
+      PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
   EXPECT_THAT(output,
               PaintRecordMatcher::Make(
@@ -840,8 +840,8 @@
   chunks.AddChunk(*t1, c0(), e0());
   chunks.AddChunk(*t1, *c2, e0());
 
-  auto output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF());
+  auto output =
+      PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
   EXPECT_THAT(output,
               PaintRecordMatcher::Make(
@@ -866,8 +866,8 @@
   chunks.AddChunk(*t1, c0(), *e1);
   chunks.AddChunk(*t1, c0(), *e2);
 
-  auto output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF());
+  auto output =
+      PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
   EXPECT_THAT(output,
               PaintRecordMatcher::Make(
@@ -892,8 +892,8 @@
   chunks.AddChunk(*t1, c0(), *e1);
   chunks.AddChunk(*t1, c0(), *e2);
 
-  auto output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF());
+  auto output =
+      PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
   EXPECT_THAT(output,
               PaintRecordMatcher::Make(
@@ -924,8 +924,8 @@
   chunks.AddChunk(*noop_t5, c0(), e0());
   chunks.AddChunk(*t4, c0(), e0());
 
-  auto output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF());
+  auto output =
+      PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
   EXPECT_THAT(output,
               PaintRecordMatcher::Make({
@@ -953,8 +953,8 @@
   chunks.AddChunk(*noop_t1, c0(), e0());
   chunks.AddChunk(*noop_t2, c0(), e0());
 
-  auto output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF());
+  auto output =
+      PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
   EXPECT_THAT(output, PaintRecordMatcher::Make({cc::PaintOpType::DrawRecord,
                                                 cc::PaintOpType::DrawRecord,
@@ -970,8 +970,8 @@
   chunks.AddChunk(*noop_t2, c0(), e0());
   chunks.AddChunk(*t1, c0(), e0());
 
-  auto output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF());
+  auto output =
+      PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
   EXPECT_THAT(output, PaintRecordMatcher::Make({
                           cc::PaintOpType::DrawRecord,  // t0
@@ -994,8 +994,8 @@
   // The clip's local transform is t1, which is the parent of noop_t2.
   chunks.AddChunk(*noop_t2, *c1, e0());
 
-  auto output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF());
+  auto output =
+      PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
   EXPECT_THAT(output, PaintRecordMatcher::Make({
                           cc::PaintOpType::DrawRecord,  // t0
@@ -1020,8 +1020,8 @@
   // The effects's local transform is t1, which is the parent of noop_t2.
   chunks.AddChunk(*noop_t2, c0(), *e1);
 
-  auto output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF());
+  auto output =
+      PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
   EXPECT_THAT(output, PaintRecordMatcher::Make({
                           cc::PaintOpType::DrawRecord,  // t0
@@ -1051,8 +1051,8 @@
   chunks.AddChunk(t0(), *noop_c2, e0());
   chunks.AddChunk(t0(), *c1, e0());
 
-  auto output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF());
+  auto output =
+      PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
   EXPECT_THAT(output,
               PaintRecordMatcher::Make({
@@ -1080,8 +1080,8 @@
   chunks.AddChunk(t0(), *noop_c2, e0());
   chunks.AddChunk(t0(), *noop_c2, *e1);
 
-  auto output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF());
+  auto output =
+      PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
   EXPECT_THAT(output,
               PaintRecordMatcher::Make({
@@ -1109,8 +1109,8 @@
   chunks.AddChunk(t0(), c0(), *noop_e2);
   chunks.AddChunk(t0(), c0(), *e1);
 
-  auto output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF());
+  auto output =
+      PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
 
   EXPECT_THAT(output,
               PaintRecordMatcher::Make({
@@ -1135,8 +1135,8 @@
   TestChunks chunks;
   chunks.AddChunk(PaintRecord(), t0(), c0(), *e1, {0, 0, 0, 0});
 
-  auto output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF());
+  auto output =
+      PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
   EXPECT_THAT(output,
               PaintRecordMatcher::Make({cc::PaintOpType::SaveLayer,   // <e1>
                                         cc::PaintOpType::Restore}));  // </e1>
@@ -1230,8 +1230,8 @@
   chunks.AddChunk(t0(), *clip_expander, *e1, gfx::Rect(5, 10, 200, 300),
                   gfx::Rect(10, 15, 20, 30));
 
-  auto output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF());
+  auto output =
+      PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
   ASSERT_EQ(7u, output.total_op_count());
   EXPECT_THAT(output,
               PaintRecordMatcher::Make(
@@ -1361,8 +1361,8 @@
   TestChunks chunks;
   chunks.AddChunk(t0(), c0(), *e1, gfx::Rect(0, 0, 50, 50));
 
-  PaintRecord output = PaintChunksToCcLayer::Convert(
-      chunks.Build(), PropertyTreeState::Root(), gfx::Vector2dF());
+  PaintRecord output =
+      PaintChunksToCcLayer::Convert(chunks.Build(), PropertyTreeState::Root());
   // TODO(crbug.com/1334293): For now non-composited backdrop filters are
   // ignored.
   EXPECT_THAT(output, PaintRecordMatcher::Make({cc::PaintOpType::SaveLayerAlpha,
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc b/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc
index e35290c..4f334e2 100644
--- a/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc
@@ -22,8 +22,7 @@
 
 PaintRecord PaintArtifact::GetPaintRecord(
     const PropertyTreeState& replay_state) const {
-  return PaintChunksToCcLayer::Convert(PaintChunkSubset(this), replay_state,
-                                       gfx::Vector2dF());
+  return PaintChunksToCcLayer::Convert(PaintChunkSubset(this), replay_state);
 }
 
 void PaintArtifact::RecordDebugInfo(DisplayItemClientId client_id,
diff --git a/third_party/blink/renderer/platform/wtf/hash_map.h b/third_party/blink/renderer/platform/wtf/hash_map.h
index 47b5d51c..19d673cc 100644
--- a/third_party/blink/renderer/platform/wtf/hash_map.h
+++ b/third_party/blink/renderer/platform/wtf/hash_map.h
@@ -185,10 +185,10 @@
   MappedType Take(KeyPeekInType);  // efficient combination of get with remove
 
   // An alternate version of find() that finds the object by hashing and
-  // comparing with some other type, to avoid the cost of type
-  // conversion. HashTranslator must have the following function members:
-  //   static unsigned hash(const T&);
-  //   static bool equal(const ValueType&, const T&);
+  // comparing with some other type, to avoid the cost of type conversion.
+  // HashTranslator must have the following function members:
+  //   static unsigned GetHash(const T&);
+  //   static bool Equal(const ValueType&, const T&);
   template <typename HashTranslator, typename T>
   iterator Find(const T&);
   template <typename HashTranslator, typename T>
@@ -320,7 +320,7 @@
   }
 };
 
-template <typename ValueTraits, typename HashFunctions, typename Allocator>
+template <typename ValueTraits, typename HashFunctions>
 struct HashMapTranslator {
   STATIC_ONLY(HashMapTranslator);
   template <typename T>
@@ -349,11 +349,6 @@
   static bool Equal(const T& a, const U& b) {
     return Translator::Equal(a, b);
   }
-  template <typename T, typename U, typename V>
-  static void Translate(T& location, U&& key, V&& mapped, unsigned hash_code) {
-    Translator::Translate(location.key, std::forward<U>(key), hash_code);
-    ValueTraits::ValueTraits::store(std::forward<V>(mapped), location.value);
-  }
 };
 
 template <typename T,
@@ -540,8 +535,7 @@
 typename HashMap<T, U, V, W, X, Allocator>::AddResult
 HashMap<T, U, V, W, X, Allocator>::InlineAdd(IncomingKeyType&& key,
                                              IncomingMappedType&& mapped) {
-  return impl_.template insert<
-      HashMapTranslator<ValueTraits, HashFunctions, Allocator>>(
+  return impl_.template insert<HashMapTranslator<ValueTraits, HashFunctions>>(
       std::forward<IncomingKeyType>(key),
       std::forward<IncomingMappedType>(mapped));
 }
@@ -559,7 +553,7 @@
   AddResult result = InlineAdd(std::forward<IncomingKeyType>(key),
                                std::forward<IncomingMappedType>(mapped));
   if (!result.is_new_entry) {
-    // The inlineAdd call above found an existing hash table entry; we need
+    // The InlineAdd call above found an existing hash table entry; we need
     // to set the mapped value.
     //
     // It's safe to call std::forward again, because |mapped| isn't moved if
diff --git a/third_party/blink/renderer/platform/wtf/hash_set.h b/third_party/blink/renderer/platform/wtf/hash_set.h
index e15288b..7e78284 100644
--- a/third_party/blink/renderer/platform/wtf/hash_set.h
+++ b/third_party/blink/renderer/platform/wtf/hash_set.h
@@ -103,8 +103,8 @@
   // An alternate version of find() that finds the object by hashing and
   // comparing with some other type, to avoid the cost of type
   // conversion. HashTranslator must have the following function members:
-  //   static unsigned hash(const T&);
-  //   static bool equal(const ValueType&, const T&);
+  //   static unsigned GetHash(const T&);
+  //   static bool Equal(const ValueType&, const T&);
   template <typename HashTranslator, typename T>
   iterator Find(const T&) const;
   template <typename HashTranslator, typename T>
@@ -115,13 +115,13 @@
   template <typename IncomingValueType>
   AddResult insert(IncomingValueType&&);
 
-  // An alternate version of add() that finds the object by hashing and
+  // An alternate version of insert() that finds the object by hashing and
   // comparing with some other type, to avoid the cost of type conversion if
   // the object is already in the table. HashTranslator must have the
   // following function members:
-  //   static unsigned hash(const T&);
-  //   static bool equal(const ValueType&, const T&);
-  //   static translate(ValueType&, T&&, unsigned hashCode);
+  //   static unsigned GetHash(const T&);
+  //   static bool Equal(const ValueType&, const T&);
+  //   static Translate(ValueType&, T&&, unsigned hash_code);
   template <typename HashTranslator, typename T>
   AddResult AddWithTranslator(T&&);
 
diff --git a/third_party/blink/renderer/platform/wtf/hash_table.h b/third_party/blink/renderer/platform/wtf/hash_table.h
index b24a713..e5d135c9 100644
--- a/third_party/blink/renderer/platform/wtf/hash_table.h
+++ b/third_party/blink/renderer/platform/wtf/hash_table.h
@@ -586,7 +586,7 @@
   }
 };
 
-template <typename HashFunctions, typename Traits, typename Allocator>
+template <typename HashFunctions>
 class IdentityHashTranslator {
   STATIC_ONLY(IdentityHashTranslator);
 
@@ -741,8 +741,7 @@
   typedef Value ValueType;
   typedef Extractor ExtractorType;
   typedef KeyTraits KeyTraitsType;
-  typedef IdentityHashTranslator<HashFunctions, Traits, Allocator>
-      IdentityTranslatorType;
+  typedef IdentityHashTranslator<HashFunctions> IdentityTranslatorType;
   typedef HashTableAddResult<HashTable, ValueType> AddResult;
 
   HashTable();
@@ -801,8 +800,16 @@
   // A special version of insert() that finds the object by hashing and
   // comparing with some other type, to avoid the cost of type conversion if the
   // object is already in the table.
+  // HashTranslator must have the following function members:
+  //   static unsigned GetHash(const T&);
+  //   static bool Equal(const ValueType&, const T&);
+  //   static void Translate(T& location, KeyType&&, ValueType&&);
   template <typename HashTranslator, typename T, typename Extra>
   AddResult insert(T&& key, Extra&&);
+  // Similar to the above, but passes additional `unsigned hash_code`, which
+  // is computed from `HashTranslator::GetHash(key)`, to HashTranslator method
+  //   static Translate(T&, KeyType&&, ValueType&&, unsigned hash_code);
+  // to avoid recomputation of the hash code when needed in the method.
   template <typename HashTranslator, typename T, typename Extra>
   AddResult InsertPassingHashCode(T&& key, Extra&&);
 
@@ -814,6 +821,11 @@
     return Contains<IdentityTranslatorType>(key);
   }
 
+  // A special version of find() that finds the object by hashing and
+  // comparing with some other type, to avoid the cost of type conversion.
+  // HashTranslator must have the following function members:
+  //   static unsigned GetHash(const T&);
+  //   static bool Equal(const ValueType&, const T&);
   template <typename HashTranslator, typename T>
   iterator Find(const T&);
   template <typename HashTranslator, typename T>
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 bfbe26b2..1e942c98 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
@@ -89727,6 +89727,32 @@
        {}
       ]
      ],
+     "out-of-flow-in-multicolumn-112.html": [
+      "5c9be2f3947e1ee4fd41debfae690eac432f1fc7",
+      [
+       null,
+       [
+        [
+         "/css/reference/ref-filled-green-100px-square.xht",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "out-of-flow-in-multicolumn-113.html": [
+      "9495933b3d3f4ce404931fb8dcd53969a8088c22",
+      [
+       null,
+       [
+        [
+         "/css/reference/ref-filled-green-100px-square.xht",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
      "overflow-clip-000.html": [
       "72b10f5cdd3092a042f1f90bff04e9428d61608e",
       [
@@ -261061,11 +261087,11 @@
   "support": {
    ".cache": {
     "gitignore2.json": [
-     "a9a50c606d91db61eac8164126993fa1d3b3f9ec",
+     "c32fa02f6a92cff39a1bce0fb487369cdcfe714f",
      []
     ],
     "mtime.json": [
-     "e749d08df272726f0abfe4f62d6de2bcd6733914",
+     "35eb6f24f2f7a21622f4b601d0a545d693fcc776",
      []
     ]
    },
@@ -261288,7 +261314,7 @@
       []
      ],
      "url-lifetime.html.ini": [
-      "6f3b4e89f9951aceac7138fbf7d985fb09071382",
+      "4b04d98270767189c7bda1cbe894eeddc7dcb017",
       []
      ],
      "url-reload.window-expected.txt": [
@@ -261343,11 +261369,11 @@
      []
     ],
     "idbindex-rename-abort.html.ini": [
-     "35b36a10a7b2aa1324f3a9699c44e1108f1b3ed1",
+     "e0d6f453ab53cd9653380fd3d34b8f704603fd9b",
      []
     ],
     "idbobjectstore_batchGetAll_largeValue.tentative.any.js.ini": [
-     "30d63af0175e4d825e3a3233b74b0fca1e976a6e",
+     "5d511eff9d381582a787724cb7b1d78afbb9b362",
      []
     ],
     "resources": {
@@ -261405,7 +261431,7 @@
      []
     ],
     "structured-clone.any.js.ini": [
-     "e58382d32f9f4db4fc23570cb34e814d37f41f76",
+     "2fe6bf87780461c988447d5c8271ee5190176b8e",
      []
     ],
     "transaction-abort-generator-revert.html.ini": [
@@ -262212,7 +262238,7 @@
       []
      ],
      "test.html.ini": [
-      "c8912513d1acc0793255ac02ac33f112376bf92c",
+      "c1cf79e445e567b873816f3bda1edfefc4cd06c3",
       []
      ],
      "xhtml.1": [
@@ -266262,7 +266288,7 @@
         []
        ],
        "sharedworker-import.http.html.ini": [
-        "831cd4f99fcef58d3d4c9d0d64e6727e0fa0cfe4",
+        "862676a5970cb7b160e139b4ea072a7888b81913",
         []
        ],
        "sharedworker-import.https-expected.txt": [
@@ -266525,6 +266551,10 @@
       "7eb847a0268bd10502726ba130c396651e1e88c2",
       []
      ],
+     "history-iframe.sub.html.ini": [
+      "3d47c07320d23e9f61a5faf20eee5119d20d0b8a",
+      []
+     ],
      "iframe-all-local-schemes.sub.html.ini": [
       "759ae54e5d7bdae75a5974acef0ff19a3d11f4df",
       []
@@ -266820,7 +266850,7 @@
       []
      ],
      "prefetch-header-allowed.html.ini": [
-      "1aa1e894994ce74a612daa45fa27aaf85c8efcdf",
+      "05edd2d5dbf006abbab8e3f902505b39883c4b4f",
       []
      ],
      "prefetch-header-blocked-by-default.html.headers": [
@@ -267757,7 +267787,7 @@
      []
     ],
     "cookieListItem_attributes.https.any.js.ini": [
-     "035485e0a713bb745dac8ae3ce4d7e30211bf6f9",
+     "0f2e60c7d78496d92ac1a4aa6cd13992eafb58d7",
      []
     ],
     "cookieStore_get_set_across_origins.sub.https.html.ini": [
@@ -267765,11 +267795,11 @@
      []
     ],
     "cookieStore_set_arguments.https.any.js.ini": [
-     "3cb3ddfa95af6a392d4c525e5603b9fb663b8a32",
+     "991863ef9c10a74754b27370402d8a38d4762149",
      []
     ],
     "cookieStore_subscribe_arguments.https.any.js.ini": [
-     "03cbe5413680d85643fc9110f1757ca00a9fbe21",
+     "ced6aca6a7c11717408c84bc79b1ab6b41e3dcd6",
      []
     ],
     "resources": {
@@ -271131,7 +271161,7 @@
        []
       ],
       "float-nowrap-4.html.ini": [
-       "118137923cf41d279118a91dc1e6d3caca8e1ef7",
+       "5b5e8dbb4ca2103520f29ee0352a8a413b00b51c",
        []
       ],
       "float-nowrap-5-ref.html": [
@@ -276953,6 +276983,10 @@
       "ff88b1e74a951b77458340de03b91d177302543e",
       []
      ],
+     "anchor-name-inline-001.html.ini": [
+      "35bea808d82e0e7fa2aabbdd5d3c79b90a3556dc",
+      []
+     ],
      "anchor-position-inline-001.html.ini": [
       "3d4c03ba4c36adfecd604a86d2246417a376e6b7",
       []
@@ -283135,7 +283169,7 @@
        []
       ],
       "nested-query-containers.html.ini": [
-       "e92a5bb1a4fa7e9a60bb42f506d455adf8c71d9a",
+       "076a237cb6ed39fb8a51cd6b9ce67f6cbdab5f88",
        []
       ],
       "percentage-padding-orthogonal-expected.txt": [
@@ -287814,7 +287848,7 @@
       []
      ],
      "image-as-flexitem-size-007v.html.ini": [
-      "29ec443eb46590639eacd77cf6f942b54e16ac37",
+      "c33d2d7ad799c9224fbb027618cf9bdc0dcd88d8",
       []
      ],
      "interactive": {
@@ -299117,7 +299151,7 @@
        []
       ],
       "subgrid-baseline-002.html.ini": [
-       "4300e380326adc7f4c7a700306fde72b33e7eb1b",
+       "c8f5d5e48be8ad5beb292de4b0b9e096c087a92d",
        []
       ],
       "subgrid-baseline-003-ref.html": [
@@ -301215,7 +301249,7 @@
        []
       ],
       "initial-letter-drop-initial-vlr.html.ini": [
-       "1e3e90322b20750c45315a4553d727d330e621e8",
+       "984123ce1ba95aaa082597019805d29f51c77e3b",
        []
       ],
       "initial-letter-drop-initial-vrl-ref.html": [
@@ -301247,7 +301281,7 @@
        []
       ],
       "initial-letter-float-001-vlr.html.ini": [
-       "bd18bc07afa5ee270669f57cba44bb0655e9b384",
+       "72b9d1f623146292108a7bcad02e61f0d85da5b0",
        []
       ],
       "initial-letter-float-001-vrl-ref.html": [
@@ -301255,11 +301289,11 @@
        []
       ],
       "initial-letter-float-001-vrl.html.ini": [
-       "a18c5464f5026e45a21f831363c83c8eca388b34",
+       "ff51dd5cdcff0bccc5d40823c59f455f9227ecb4",
        []
       ],
       "initial-letter-float-001.html.ini": [
-       "ae13c19797a134284cfe0ffd2c225b9e7bbc0b3e",
+       "4b45bbf55e041276119bcbd59878946c3a181b5b",
        []
       ],
       "initial-letter-float-002-ref.html": [
@@ -301283,7 +301317,7 @@
        []
       ],
       "initial-letter-float-004.html.ini": [
-       "4030844f14a45ef2407ccd1e385f5476eacfb7b7",
+       "d614985677939eaa1215fce3dade526bbaf911fd",
        []
       ],
       "initial-letter-float-005-ref.html": [
@@ -301307,7 +301341,7 @@
        []
       ],
       "initial-letter-indentation.html.ini": [
-       "fbc24c225c34e2f35829cc904f469bff56350f9a",
+       "b5046078b3627326c5ffdfe3c77ce849d4445dbe",
        []
       ],
       "initial-letter-layout-text-decoration-underline-ref.html": [
@@ -301315,7 +301349,7 @@
        []
       ],
       "initial-letter-layout-text-decoration-underline.html.ini": [
-       "6679ea68f5c7d1fd3727277a901eecbbc1bed2e5",
+       "7b6eb186ade47b702b61254c2e72aeab888433e7",
        []
       ],
       "initial-letter-raise-initial-ref.html": [
@@ -301343,7 +301377,7 @@
        []
       ],
       "initial-letter-raise-initial-vrl.html.ini": [
-       "1bf7046aff7b0cfc821b8d11522c00f723cf31f6",
+       "4f49317efbbf4f4031cde2ce5db278d585983354",
        []
       ],
       "initial-letter-raise-initial.html.ini": [
@@ -301355,7 +301389,7 @@
        []
       ],
       "initial-letter-raised-sunken-caps-raise.html.ini": [
-       "56b3ed619093439c9fb4fcb32570ff49c56afd09",
+       "20d257d084d1c674f557b5675678b67b2cef6e2e",
        []
       ],
       "initial-letter-raised-sunken-caps-sunken-ref.html": [
@@ -301399,7 +301433,7 @@
        []
       ],
       "initial-letter-sunk-initial-vlr.html.ini": [
-       "82403e6cdd18b0ebec9a7c35b1b47fc6b75784e1",
+       "63edb9daefeaa31d03daeaadcb51df9c06d934a9",
        []
       ],
       "initial-letter-sunk-initial-vrl-ref.html": [
@@ -301411,7 +301445,7 @@
        []
       ],
       "initial-letter-sunk-initial.html.ini": [
-       "2a59287b17e01ed8269d07ba13bb1676f9161c73",
+       "25b43d78291c9950b3fee422a58c99c8c51d1a99",
        []
       ],
       "initial-letter-valid.html.ini": [
@@ -301423,7 +301457,7 @@
        []
       ],
       "initial-letter-with-first-line.html.ini": [
-       "7f69acbb5b8b735f2cc960f4832090c3f085738a",
+       "56e94a8670efbccb3863be467419c218b0835400",
        []
       ],
       "initial-letter-with-tab-ref.html": [
@@ -301647,7 +301681,7 @@
      },
      "fallback-layout": {
       "constructor-error.https.html.ini": [
-       "ec85dd01b511a3edf5a7c7531259a15aabb2a158",
+       "3ab53016c15110c81b40cdd928fc8f072afb021c",
        []
       ],
       "fallback-layout-fallback-ref.html": [
@@ -304025,10 +304059,6 @@
       "78f81bd358fc69d813a81cd385f5dd52f34cd545",
       []
      ],
-     "getclientrects-001.html.ini": [
-      "1d32d9521dcde0c9ac9163f7b37cbfd9a5985063",
-      []
-     ],
      "hit-test-transformed-child.html.ini": [
       "5e4ac36dbba9dd7ff4b0e5db9a4b2b930500c17f",
       []
@@ -305916,7 +305946,7 @@
       []
      ],
      "scrollable-overflow-input-001.html.ini": [
-      "6351a3d300d23195dab2184d6186ddabe934b9f4",
+      "0fd1d59cb6c19d9b4b5345ed50e850ffaa5eafd8",
       []
      ],
      "scrollable-overflow-input-002-ref.html": [
@@ -306496,7 +306526,7 @@
       []
      ],
      "parse-input-arguments-022.https.html.ini": [
-      "6ba66bd89150dab549a623dfa1415f74d2cd3466",
+      "a607705d4acd2bf282c9c4c0590d039e2a0c62a0",
       []
      ],
      "parse-input-arguments-ref.html": [
@@ -309255,8 +309285,8 @@
       "db4f23c886c44282afc27fd09475ade0c189e6f8",
       []
      ],
-     "ruby-text-combine-upright-001a.html.ini": [
-      "0df837fbb07d756aa4f778765d6ce08a5f296275",
+     "ruby-text-combine-upright-001b.html.ini": [
+      "654ce463d1c2e4eac1fc8aad024ad0e5ce2313f9",
       []
      ],
      "ruby-text-combine-upright-002-ref.html": [
@@ -309264,7 +309294,7 @@
       []
      ],
      "ruby-text-combine-upright-002a.html.ini": [
-      "3ba2bb3b78b4c4947fab7bc4c2923c1ba9f7873f",
+      "894ea23afe9741293f87e2b20eecbc56dacc8921",
       []
      ],
      "ruby-text-combine-upright-002b.html.ini": [
@@ -316552,20 +316582,16 @@
        "38e66a2dc4a6c69a3dd79df3f84abe55bd072294",
        []
       ],
-      "text-transform-capitalize-005.html.ini": [
-       "c06d2b0fcf72d84e5512352f5f74279544c73498",
-       []
-      ],
       "text-transform-capitalize-007.html.ini": [
        "4dd4f078df482979aef56a6f67251ad514fe3ad0",
        []
       ],
       "text-transform-capitalize-010.html.ini": [
-       "892a514c8de51b620ba30af9b89244aaa370327e",
+       "a501ea396ccd5515d5f84196aeec7f268c5cb022",
        []
       ],
-      "text-transform-capitalize-014.html.ini": [
-       "f0b7504e565abdf6d671ad61ed287bc662140cf7",
+      "text-transform-capitalize-016.html.ini": [
+       "869d3178e27f1539e32ecd49339a5d6b2db5956f",
        []
       ],
       "text-transform-capitalize-018.html.ini": [
@@ -330578,7 +330604,7 @@
       []
      ],
      "scroll-behavior-main-frame-root.html.ini": [
-      "89c7c0b751e2aef0c2ae4638ae0055290c4c2630",
+      "d5fe958db40f7f781b73cd31f82757a981f171da",
       []
      ],
      "scroll-behavior-main-frame-window.html.ini": [
@@ -335930,7 +335956,7 @@
       []
      ],
      "join-pre-and-other-block.html.ini": [
-      "0c485cc345d183a603b92109971fd4c0b68ef821",
+      "fad6ad2385d23b505b199ee8be44f06574a3842f",
       []
      ],
      "join-pre-and-other-block_method=backspace_block=blockquote-expected.txt": [
@@ -336072,7 +336098,7 @@
       []
      ],
      "bold.html.ini": [
-      "dd18f2db7ce90dcff953a03d0f6c43e472f05026",
+      "41bb690a9338d498880921d7475505af945c50af",
       []
      ],
      "bold_3001-last-expected.txt": [
@@ -336192,7 +336218,7 @@
       []
      ],
      "formatblock.html.ini": [
-      "8247fe6b6b711d75c510c855a63b8d0fd0023edc",
+      "cf2a6f46cc2706010a1b8f94a9ce7e9176ca2784",
       []
      ],
      "formatblock_1-1000-expected.txt": [
@@ -336785,7 +336811,7 @@
        []
       ],
       "eucjp-encode-href-errors-han.html.ini": [
-       "5aa7112eecb4672185416a08f41ddafc68804125",
+       "de94c744ab12e2787d0b62bcbf6a18543bb8f663",
        []
       ],
       "eucjp-encode-href-errors-hangul.html.headers": [
@@ -337097,7 +337123,7 @@
     "legacy-mb-korean": {
      "euc-kr": {
       "euckr-decode-iso-ir-149.html.ini": [
-       "50f8f02df430975536ed137acfde4224c3041ec1",
+       "4434e25957d7b1bd604904021a8fcd2d418fe3a2",
        []
       ],
       "euckr-decode-ksc5601.html.ini": [
@@ -339400,6 +339426,10 @@
        "dad8083eda643cfbf24e7fca2fcd0d947029cc96",
        []
       ],
+      "keepalive.html.ini": [
+       "357820eb50ca8d5c3bf98edbfbcc5cc2ca60176e",
+       []
+      ],
       "response-null-body.any-expected.txt": [
        "fa818f443d303b3903069f46bc8824dd2bf8bb27",
        []
@@ -340907,7 +340937,7 @@
        []
       ],
       "element-meta-refresh.https.optional.sub.html.ini": [
-       "6594b0afb0fc79fe0486642e79aff15a044f1cb8",
+       "86cd06a416677654309e18c9d84b393130469edf",
        []
       ],
       "element-meta-refresh.optional.sub.html.ini": [
@@ -340963,7 +340993,7 @@
        []
       ],
       "window-history.https.sub.html.ini": [
-       "f5c7bcb5085f594f1955aa5b81e83cec35910fbc",
+       "3905902d31f4bfe73904da41048c2327f779fc61",
        []
       ],
       "worker-dedicated-constructor.sub.html.ini": [
@@ -341520,7 +341550,7 @@
       ]
      },
      "service-worker-background-fetch.https.window.js.ini": [
-      "82a91238fffb51c04fc7d527fd9b210869c812b1",
+      "71a608241880e804f7c295bffda04cb61b569849",
       []
      ],
      "service-worker-fetch.https.window.js.ini": [
@@ -341694,7 +341724,7 @@
       ]
      },
      "stale-css.html.ini": [
-      "957be3365304544817a837c81874bc215905d705",
+      "d08487a8592050805645c50910ec150390025386",
       []
      ],
      "stale-image.html.ini": [
@@ -341861,7 +341891,7 @@
      []
     ],
     "focus-already-focused-iframe-same-site.html.ini": [
-     "cd78228dd3869ed7ac233ad82d076832dd8df95e",
+     "c8cb0f97f7b02f70990a80ee9fe25f1d9b8db7a2",
      []
     ],
     "focus-event-after-focusing-iframes-expected.txt": [
@@ -341945,7 +341975,7 @@
      []
     ],
     "iframe-focus-with-different-site-intermediate-frame.html.ini": [
-     "3dbc2c45845203ba4bbcc1a31bb3bcb9455c35b9",
+     "a4e9ffefd3d4c43282dea6fd72191db23d6006cb",
      []
     ],
     "iframe-focus-with-same-as-top-intermediate-frame-expected.txt": [
@@ -343389,7 +343419,7 @@
      []
     ],
     "FileSystemFileHandle-create-sync-access-handle.https.tentative.window.js.ini": [
-     "b46450f6b8dc52edc97516f432e8f5a3faccbedc",
+     "2d96c8eae5cc46b3d3602a0ad255c0c3de110c81",
      []
     ],
     "META.yml": [
@@ -344296,7 +344326,7 @@
       []
      ],
      "embedding.tentative.https.window.js.ini": [
-      "5600c7c866ccea02746cb4508223d7bb9fe9d773",
+      "c0c94b22d95a3cf100decad911c9f051ec7bd360",
       []
      ],
      "fenced-frame-bypass.tentative.https.window-expected.txt": [
@@ -344351,7 +344381,7 @@
          []
         ],
         "broadcast-channel.html.ini": [
-         "d597d3dca08ba439a179b600fb869d2dc2f36a9c",
+         "7d0aa08442264ad61566942919c71c0e2a4c7fed",
          []
         ],
         "dedicated-worker.html.ini": [
@@ -344565,7 +344595,7 @@
          []
         ],
         "before-load-hash.html.ini": [
-         "66dd895b772600041eb0423eb4611f136e14e3e2",
+         "07db753679f024ede5d7459689eb2e35e7edd6a6",
          []
         ]
        },
@@ -345182,7 +345212,7 @@
         []
        ],
        "same-document-traversal-cross-document-traversal.html.ini": [
-        "b5b7f69154f31ee966590e28e64c55cdd437ed0d",
+        "71dab1dde8f9cd56e469d48031b7028e256f5e9e",
         []
        ],
        "same-document-traversal-same-document-traversal-hashchange.html.ini": [
@@ -345616,7 +345646,7 @@
         []
        ],
        "combination_history_006.html.ini": [
-        "a339e37fb2dee62a70403a338ee10df1a684f356",
+        "9a7593eab709f3940ee46d0deb382620b4e5e8d4",
         []
        ],
        "history-state-after-bfcache.window.js.ini": [
@@ -345631,10 +345661,6 @@
         "78547019f3a43b3a318618a9221dd23283cd78a8",
         []
        ],
-       "history_back_cross_realm_method.html.ini": [
-        "036c330b855092baef190ae6a91312dbc7163c86",
-        []
-       ],
        "history_entry.html": [
         "e5929ddbe84389641a083f29057a3ea7b9f5076b",
         []
@@ -345762,7 +345788,7 @@
         []
        ],
        "traverse_the_history_4.html.ini": [
-        "8df09c0557a43b3018d6e1a25d451a9462e20e07",
+        "a3d5fd95566fda1ae64791efc5ee191c9467c86e",
         []
        ],
        "traverse_the_history_5-1.html": [
@@ -345864,7 +345890,7 @@
         []
        ],
        "location-protocol-setter-non-broken.html.ini": [
-        "fc6898e67c553fd302e260e6aac5d6ad9181a338",
+        "31f51cf42107748d72536cf32c60b4ec7f2c38c2",
         []
        ],
        "location-prototype-setting-cross-origin-domain.sub-expected.txt": [
@@ -346153,7 +346179,7 @@
          []
         ],
         "parent-yes-child-no-port.sub.https.html.ini": [
-         "5504eb18d1640f0d5f622b3cfa215e1f0848689b",
+         "f5c7844313e14001e89f1cf40759104ab6a9f43d",
          []
         ],
         "parent-yes-child-no-same.sub.https.html.headers": [
@@ -346161,7 +346187,7 @@
          []
         ],
         "parent-yes-child-no-same.sub.https.html.ini": [
-         "2066f0aa9ca91dd53bc2d525ebcf3a6e723370e7",
+         "c5662b40305800686cf263cc61750628ee4e991c",
          []
         ],
         "parent-yes-child-no-subdomain.sub.https.html.headers": [
@@ -346169,7 +346195,7 @@
          []
         ],
         "parent-yes-child-no-subdomain.sub.https.html.ini": [
-         "61e0306ed4771662e0ee52578eb4fd2e6021fae3",
+         "88fd82f5ed244ea415ff50b2d0d5dcdee19abb06",
          []
         ],
         "parent-yes-child-yes-port.sub.https.html.headers": [
@@ -346177,7 +346203,7 @@
          []
         ],
         "parent-yes-child-yes-port.sub.https.html.ini": [
-         "5f428d85c58be189cc011c3e8b44b6892f5b6083",
+         "2c3782b364adde0e5fecca73eec09a86c377271f",
          []
         ],
         "parent-yes-child-yes-same.sub.https.html.headers": [
@@ -346193,7 +346219,7 @@
          []
         ],
         "parent-yes-child-yes-subdomain.sub.https.html.ini": [
-         "bd62a143286b869ec8411cf4778a1b1020f5a364",
+         "7d1f8d71a7f1c246989e97c433364988505a9850",
          []
         ]
        },
@@ -346207,15 +346233,15 @@
          []
         ],
         "parent-no-child1-no-subdomain1-child2-yes-subdomain2.sub.https.html.ini": [
-         "ff06302c1d7e9e24e4913d2105fff02c1c570c2b",
+         "8d6437a2bc36ae118e40acab1deaf8005272e01d",
          []
         ],
         "parent-no-child1-yes-subdomain-child2-no-port.sub.https.html.ini": [
-         "677d865317d5c5fc2983c5cf9594e906ee60c6b9",
+         "8b8493d7d3127bf61316869c8a13a64d1c154d48",
          []
         ],
         "parent-no-child1-yes-subdomain-child2-no-subdomain.sub.https.html.ini": [
-         "2a0462ef0b1606a5eff1448b2695394a50f998f0",
+         "2ae4867c1c4fc9e6b1049177e5f6c0476956640b",
          []
         ],
         "parent-yes-child1-no-subdomain-child2-no-subdomain.sub.https.html.headers": [
@@ -346223,7 +346249,7 @@
          []
         ],
         "parent-yes-child1-no-subdomain-child2-no-subdomain.sub.https.html.ini": [
-         "19af2dda97d3d09bf3927912421bffa60602f806",
+         "a6a8b30b86e1738b531feef0c99b2b70862577ce",
          []
         ],
         "parent-yes-child1-no-subdomain-child2-no-subdomain2.sub.https.html.headers": [
@@ -346231,7 +346257,7 @@
          []
         ],
         "parent-yes-child1-no-subdomain-child2-no-subdomain2.sub.https.html.ini": [
-         "8f4b5ee80c62f798763ee51030e5b739bbfcc1ad",
+         "5671887b26e265cf9ca1574df4eca12c8c4369bc",
          []
         ],
         "parent-yes-child1-no-subdomain-child2-yes-subdomain.sub.https.html.headers": [
@@ -346251,7 +346277,7 @@
          []
         ],
         "parent-yes-child1-no-subdomain-child2-yes-subdomainport.sub.https.html.ini": [
-         "7ba4e734b61e2c82f12f4dbf60462f5c2ae1ad9d",
+         "ce259823becd55217b53ed2a8347f27771d28166",
          []
         ],
         "parent-yes-child1-yes-subdomain-child2-no-port.sub.https.html.headers": [
@@ -346259,7 +346285,7 @@
          []
         ],
         "parent-yes-child1-yes-subdomain-child2-no-port.sub.https.html.ini": [
-         "c9174382298bba9bb710f6c18f25b8599ad1eb6c",
+         "d9ff6bde0a80622e37e7a08e8f5e16b2257c85d7",
          []
         ],
         "parent-yes-child1-yes-subdomain-child2-no-subdomain.sub.https.html.headers": [
@@ -346267,7 +346293,7 @@
          []
         ],
         "parent-yes-child1-yes-subdomain-child2-no-subdomain.sub.https.html.ini": [
-         "bb8a3cbbad45f294edb5ba2e60bdee1f32acd5ea",
+         "ce7dbbfda2430ac74efd6e77aa0f8c0315fd281f",
          []
         ],
         "parent-yes-child1-yes-subdomain-child2-yes-subdomain.sub.https.html.headers": [
@@ -346283,7 +346309,7 @@
          []
         ],
         "parent-yes-child1-yes-subdomain-child2-yes-subdomain2.sub.https.html.ini": [
-         "1702c5018d7456ac590c1e3fc32b4a6720f9987a",
+         "cdeff1ef2022fb11645ab1c31225f8212a56b034",
          []
         ],
         "parent-yes-child1-yes-subdomain-child2-yes-subdomainport.sub.https.html.headers": [
@@ -346291,7 +346317,7 @@
          []
         ],
         "parent-yes-child1-yes-subdomain-child2-yes-subdomainport.sub.https.html.ini": [
-         "e3b0508f4657609580638d04ce6d4902d3c18ee9",
+         "05729211a40f89914e08a4462d315d98c013b735",
          []
         ]
        },
@@ -346357,7 +346383,7 @@
          []
         ],
         "javascript-url-yes.https.html.ini": [
-         "189de0412095c179a135e6aa017e6c204b9e0446",
+         "300ae43ef4c3e8800127b329607ad79591d30700",
          []
         ],
         "removed-iframe.sub.https.html.headers": [
@@ -346407,7 +346433,7 @@
          []
         ],
         "sandboxed-same-origin-iframe-yes.https.html.ini": [
-         "e6f5815e73121d3e298955c5849616fd2807cf2f",
+         "71f8030d85162e0bad5c0d7e41f58165d9a7d53d",
          []
         ]
        },
@@ -346421,27 +346447,27 @@
        ],
        "iframe-navigation": {
         "parent-no-1-no-same-2-yes-port.sub.https.html.ini": [
-         "c8482cb814f6a2f548bfb6be8b9f8a9736349a54",
+         "7dd4eacf802bd2655ff6178afd87ddaf8610d61f",
          []
         ],
         "parent-no-1-no-same-2-yes-subdomain.sub.https.html.ini": [
-         "7d0cf3bd9aa6e3f2ca8f4c4d36ec15807c4fddda",
+         "1600e6fc8a11413f7500b8d534b47dc9e6600a90",
          []
         ],
         "parent-no-1-no-subdomain-2-yes-subdomain.sub.https.html.ini": [
-         "f45685b9f42e31e502d536ea2516c14033ba21f6",
+         "eae6fc7f81a169a7a8497434d7938dca79b495af",
          []
         ],
         "parent-no-1-no-subdomain-2-yes-subdomain2.sub.https.html.ini": [
-         "346f1ceb1f6cf17f741dae7a6682881ce1d3bd55",
+         "16816d416ecf363e793607903f34eb779ddddeaf",
          []
         ],
         "parent-no-1-subdomain-yes-2-subdomain2-no.sub.https.html.ini": [
-         "419e0eddeabce0c5d49adc26ddcc7b14293393e3",
+         "fdcb26e785d34c9b00059041c0d124c2d1a61ff6",
          []
         ],
         "parent-no-1-yes-subdomain-2-no-subdomain.sub.https.html.ini": [
-         "65c36743e8de832e045bf49a2c602805a3e6e7cc",
+         "aa701dfece5d837c59b9ccf1c00407252557bd5f",
          []
         ],
         "parent-yes-1-no-same-2-no-port.sub.https.html.headers": [
@@ -346449,7 +346475,7 @@
          []
         ],
         "parent-yes-1-no-same-2-no-port.sub.https.html.ini": [
-         "62a430f54f8948086dfcc8d68322812ce128f8a8",
+         "bf08842a95539dd79c8aede5cf7c6612230bd010",
          []
         ],
         "parent-yes-1-no-same-2-no-subdomain.sub.https.html.headers": [
@@ -346457,7 +346483,7 @@
          []
         ],
         "parent-yes-1-no-same-2-no-subdomain.sub.https.html.ini": [
-         "0727d38b6c0cf094cba741faf6ffbac1ba956a1c",
+         "844f2b1bea35a7c67e7a329bf4d1e749752cfef9",
          []
         ]
        },
@@ -346470,12 +346496,8 @@
         []
        ],
        "popups": {
-        "opener-no-openee-yes-same.sub.https.html.ini": [
-         "6f746fe60f8a4e5874fbc0da2fb4e8de6a99c2e2",
-         []
-        ],
         "opener-no-openee-yes-subdomain.sub.https.html.ini": [
-         "a13be28eba7ad1e202fbb7bda21fadb0e7ccb201",
+         "afa51c3e414cbea6919adb9cfb65b5e625fd6f50",
          []
         ],
         "opener-yes-openee-no-port.sub.https.html.headers": [
@@ -346483,7 +346505,7 @@
          []
         ],
         "opener-yes-openee-no-port.sub.https.html.ini": [
-         "ee2567b52e0a5a31a1419d6b327ecb06794fee8d",
+         "1ddca58b67d024c0f556dcb991043ae1a4182e8c",
          []
         ],
         "opener-yes-openee-no-same.sub.https.html.headers": [
@@ -346499,7 +346521,7 @@
          []
         ],
         "opener-yes-openee-no-subdomain.sub.https.html.ini": [
-         "8dfaf02191cb09aed18fd750eb879fc054bc74a1",
+         "83fcc1fe1ce693d1b36c9ca3daef9ab38cb52aa6",
          []
         ],
         "opener-yes-openee-yes-port.sub.https.html.headers": [
@@ -346515,7 +346537,7 @@
          []
         ],
         "opener-yes-openee-yes-same.sub.https.html.ini": [
-         "b6a98657923c945fa98d6cb43ce69180ac9beee1",
+         "851a368312622c507f15313d07d8639a593a7979",
          []
         ],
         "opener-yes-openee-yes-subdomain.sub.https.html.headers": [
@@ -346523,7 +346545,7 @@
          []
         ],
         "opener-yes-openee-yes-subdomain.sub.https.html.ini": [
-         "d6b4f05a7f2746db2ba2ebff19ebd970081ed85a",
+         "42f89ad89f2319febbf177f3fcf115b5f678c7af",
          []
         ]
        },
@@ -346536,7 +346558,7 @@
         []
        ],
        "removing-iframes.sub.https.html.ini": [
-        "cb6578700d10c64dc4bdd5cb6526d5ed28b5b4a4",
+        "d943b31962c0c3aa451b6472158658179ddbfcc3",
         []
        ],
        "resources": {
@@ -346881,6 +346903,10 @@
          []
         ]
        },
+       "open-features-is-popup-condition.html.ini": [
+        "05409bab024e90c5473631368a46e867d505aeed",
+        []
+       ],
        "open-features-negative-innerwidth-innerheight.html.ini": [
         "ad6ace0710760cedf3840baf02a126775e92c870",
         []
@@ -346961,10 +346987,6 @@
         "e05e8a3bcbab57f52352fb305219cb1af318369a",
         []
        ],
-       "open-features-tokenization-width-height.html.ini": [
-        "25200b9fcdb4c04d9579be0768e9efcbb236abbc",
-        []
-       ],
        "resources": {
         "close-self.html": [
          "0c0cf9fc4911de2404a6b9247c862297c22038f1",
@@ -348561,7 +348583,7 @@
          []
         ],
         "canvas-display-p3-drawImage-ImageBitmap-video.html.ini": [
-         "d709e57559eb8549497e83925fbc741271860c6a",
+         "4900e47dc25bca8b98835c8fccab40a3914f150d",
          []
         ],
         "canvas-display-p3-drawImage-expected.txt": [
@@ -349122,12 +349144,6 @@
        "d0524194c9186da948d150da7b36f0f1144a61f9",
        []
       ],
-      "drawing-images-to-the-canvas": {
-       "2d.drawImage.animated.poster.html.ini": [
-        "55cf49a5996f364b25c55a553a419b2ee026a4e9",
-        []
-       ]
-      },
       "fill-and-stroke-styles": {
        "2d.pattern.paint.repeat.basic.html.ini": [
         "59c6d7d3f9c14d3dd9470bb82563a12804617949",
@@ -349155,7 +349171,7 @@
          []
         ],
         "offscreencanvas.resize.html.ini": [
-         "04ad5a0b9d01c3b4320dcc24934e97ac3dfe10b2",
+         "fd91f0f4b0bc089e5c7f10ec0ed1c66be5262794",
          []
         ],
         "offscreencanvas.transferrable-expected.txt": [
@@ -349691,7 +349707,7 @@
        []
       ],
       "dedicated-worker.https.window.js.ini": [
-       "47f8c959ac00cd3f7e328e80ea3c89904cc34f53",
+       "e304d0e0960858efc7d195958082dceb869c61b5",
        []
       ],
       "fetch.https.window.js.ini": [
@@ -349711,7 +349727,7 @@
        []
       ],
       "reporting-subresource-corp.https.window.js.ini": [
-       "6b202862d8f8070e74803bff00f78b8fe0d7aae1",
+       "dc3970db5c07e161ad737624d2f0d38e501a3438",
        []
       ],
       "resources": {
@@ -350216,11 +350232,11 @@
       []
      ],
      "coop-sandbox.https.html.ini": [
-      "63b8eb62b2311c7e034dec970a76ae3f167b3e9c",
+      "e003d2bb2946910aa31942370e4f6dc7eec55d70",
       []
      ],
      "header-parsing-failures.https.html.ini": [
-      "4b66b2a6530aa1f0736b0bebe36d97ede8c52103",
+      "1272acc4db378a41c9accfe25f9b65d3ea69b0d5",
       []
      ],
      "header-parsing-non-ascii.https.html.headers": [
@@ -350257,7 +350273,7 @@
        []
       ],
       "popup-same-site-unsafe-allow-outgoing-with-cross-origin.https.html.ini": [
-       "e5f17f9505c6f62917ea16c5fc78add6a4d97015",
+       "1879499d14a5dacfc8e07ed2dd15df7e1924f968",
        []
       ],
       "popup-same-site-unsafe-allow-outgoing-with-same-origin.https.html.headers": [
@@ -350272,10 +350288,6 @@
        "ab7b28948150ff64101ef080b0d9c7cc9a6a34d2",
        []
       ],
-      "popup-same-site-unsafe-allow-outgoing-with-same-site.https.html.ini": [
-       "596920f4928fd12de33820295d77abde57b89138",
-       []
-      ],
       "popup-same-site-with-cross-origin.https.html.headers": [
        "34bd099a302f893f92586241ea38aac812bf28d0",
        []
@@ -350288,6 +350300,10 @@
        "34bd099a302f893f92586241ea38aac812bf28d0",
        []
       ],
+      "popup-same-site-with-same-origin.https.html.ini": [
+       "71fe175cf71dcb57025122ae5251bb2abfbcfbaa",
+       []
+      ],
       "popup-same-site-with-same-site.https.html.headers": [
        "34bd099a302f893f92586241ea38aac812bf28d0",
        []
@@ -350310,7 +350326,7 @@
       []
      ],
      "iframe-popup-same-origin-allow-popups-to-same-origin.https.html.ini": [
-      "fbb8b7ea360ac444a02016d6e916050745585372",
+      "852cb8e7d076d066975c7fe2b59baabf2a5ee2e0",
       []
      ],
      "iframe-popup-same-origin-allow-popups-to-unsafe-none.https.html.headers": [
@@ -350326,7 +350342,7 @@
       []
      ],
      "iframe-popup-same-origin-to-same-origin.https.html.ini": [
-      "d38d7d20f99a3462274f47810d43c778c52e77b1",
+      "223c26b5d730d933a5f58b18a1597c67a0aac633",
       []
      ],
      "iframe-popup-same-origin-to-unsafe-none.https.html.headers": [
@@ -350354,11 +350370,11 @@
       []
      ],
      "javascript-url.https.html.ini": [
-      "afd683904d33298de1e57868e182df500156194e",
+      "043f54e21263e0b98143fb900231e4ea89ccb498",
       []
      ],
      "navigate-top-to-aboutblank.https.html.ini": [
-      "d5c6b7629520bbf8969208c96e72707a0ef0454e",
+      "1aeca853cfa3c55b386ca9cb36493b699d321c2b",
       []
      ],
      "no-https.html.headers": [
@@ -350374,7 +350390,11 @@
       []
      ],
      "popup-redirect-cache.https.html.ini": [
-      "9c8fdd8eaea28070402a7e7d7d330a03eae331dd",
+      "a2126157625cd8daee02358582ad29f8d7adebda",
+      []
+     ],
+     "popup-redirect-same-origin-allow-popups.https.html.ini": [
+      "4cc8d43391fcd469555c9dcc045d76c782bf09eb",
       []
      ],
      "popup-same-origin-allow-popups-with-cross-origin.https.html.headers": [
@@ -350401,6 +350421,10 @@
       "46ad58d83bf6e98913ca4c564b7acb8f19fa0093",
       []
      ],
+     "popup-same-origin-non-initial-about-blank.https.html.ini": [
+      "ef4c70f6f150f5815fd6f6651131c89741e07cde",
+      []
+     ],
      "popup-same-origin-with-cross-origin.https.html.headers": [
       "46ad58d83bf6e98913ca4c564b7acb8f19fa0093",
       []
@@ -350413,10 +350437,6 @@
       "46ad58d83bf6e98913ca4c564b7acb8f19fa0093",
       []
      ],
-     "popup-same-origin-with-same-site.https.html.ini": [
-      "efa88bcf39bc8e49c23bad6caadd6ff1d05d2297",
-      []
-     ],
      "popup-unsafe-none-with-cross-origin.https.html.headers": [
       "073ce7adfbd81cb7c0b2f91f96c8349b6677f26c",
       []
@@ -350429,10 +350449,18 @@
       "073ce7adfbd81cb7c0b2f91f96c8349b6677f26c",
       []
      ],
+     "popup-unsafe-none-with-same-site.https.html.ini": [
+      "604de218d0bb79bd663522c70ec31d106a271e02",
+      []
+     ],
      "popup-unspecified-with-cross-origin.https.html.ini": [
       "6f1e872520590723fb96d2c67837a02d78f18977",
       []
      ],
+     "popup-unspecified-with-same-origin.https.html.ini": [
+      "cc0aa6279c4c6300209e802cc37a9fd36f33de32",
+      []
+     ],
      "popup-with-structured-header.https.html.headers": [
       "46ad58d83bf6e98913ca4c564b7acb8f19fa0093",
       []
@@ -350444,7 +350472,7 @@
       ],
       "access-reporting": {
        "access-from-coop-page-to-openee_coop-ro.https.html.ini": [
-        "59258e97f4655d24edc749db900a792e73a39960",
+        "ef6ec988d5ce37413283b835433725af38794e01",
         []
        ],
        "access-from-coop-page-to-openee_coop-ro_cross-origin.https.html.ini": [
@@ -350468,7 +350496,7 @@
         []
        ],
        "access-to-coop-page-from-openee_coop-ro.https.html.ini": [
-        "45761bcac8beb541cddf6110a9432b612089da0b",
+        "bf827e7921d353b76aa69e62ef999129f23aa7d3",
         []
        ],
        "access-to-coop-page-from-openee_coop-ro_cross-origin.https.html.ini": [
@@ -350476,15 +350504,15 @@
         []
        ],
        "access-to-coop-page-from-opener_coop-ro.https.html.ini": [
-        "126bb781deb49f040d95036268ae95af60d600de",
+        "235fd40a5cfe8e609d8dfb144ed164bbe57ab3fb",
         []
        ],
        "access-to-coop-page-from-opener_coop-ro_cross-origin.https.html.ini": [
-        "9e0d21c428dd877d354da9a9f4064a357e3f95dc",
+        "851d459dc9f5bcc7bba4964b07a4e73ae99fccbe",
         []
        ],
        "access-to-coop-page-from-other_coop-ro.https.html.ini": [
-        "22693c3d4521115956429a962468b7b769327914",
+        "12463d2a477294446d1b508952f81fdfcfd6296e",
         []
        ],
        "access-to-coop-page-from-other_coop-ro_cross-origin.https.html.ini": [
@@ -350504,11 +350532,11 @@
         []
        ],
        "property-focus.https.html.ini": [
-        "82c8de373481ed99ed4539e9781a19f6001a19d0",
+        "2db32f1edef3c5c1def240fb6fa5fbf980b5e42b",
         []
        ],
        "property-frames.https.html.ini": [
-        "f6d2d333bad5ce93e388b23469807f3f04336d18",
+        "01f4fcd2960d85861b72c469942031529268ec2f",
         []
        ],
        "property-indexed-getter.https.html.headers": [
@@ -350528,7 +350556,7 @@
         []
        ],
        "property-location-set.https.html.ini": [
-        "175abd50466fb400cd12a2037fe8c45562610689",
+        "e016cf9c67e1853eefcc7da328877d3d0866029c",
         []
        ],
        "property-named-getter.https.html.headers": [
@@ -350536,19 +350564,15 @@
         []
        ],
        "property-named-getter.https.html.ini": [
-        "d654a715676c6c157522e5b0621143e8faa66bc4",
+        "a713a5f1fd7eea7cfad4e994ae94b6f4efea9a42",
         []
        ],
        "property-opener-get.https.html.ini": [
         "e053a92320caf24980ff5f4d623361e7485303db",
         []
        ],
-       "property-opener-set.https.html.ini": [
-        "5111ef2d847cd0803ce419b5c105a4cc5201287d",
-        []
-       ],
        "property-postmessage-1.https.html.ini": [
-        "943353e4f9e25b62aaec539cff959e753180bc02",
+        "ab4e882800645f49b748ce816f1108237bde01a8",
         []
        ],
        "property-postmessage-2.https.html.ini": [
@@ -350568,7 +350592,7 @@
         []
        ],
        "report-to-both_coop-ro.https.html.ini": [
-        "d4653ba3bc4737029f06e32eecac15936e97218f",
+        "46d3e2453d8b141994297fa9ca23abea51bbb623",
         []
        ],
        "reporting-observer.html.ini": [
@@ -350796,7 +350820,7 @@
         []
        ],
        "iframe-popup-to-soap.https.html.ini": [
-        "9311679589c79eb9c3b7a6756121044bee700977",
+        "f8661d582e1632d4967a02fc2a63c594f5c87a44",
         []
        ],
        "iframe-popup-to-un.https.html.headers": [
@@ -350804,7 +350828,7 @@
         []
        ],
        "iframe-popup-to-un.https.html.ini": [
-        "9afd7b3f9b0ba4181c16b1de799a272170e49feb",
+        "275706e4b4b566e979c0822359ded85f476fde89",
         []
        ],
        "iframe-popup-to-un.https_1-2-expected.txt": [
@@ -350832,7 +350856,7 @@
         []
        ],
        "iframe-popup.https.html.ini": [
-        "f3681f22e7aaacd0c447883a6d4c2e4b530cfde0",
+        "4f6dc509504b25a91462730fcac2315ccc823f69",
         []
        ],
        "iframe-popup.https_1-2-expected.txt": [
@@ -350888,7 +350912,7 @@
         []
        ],
        "popup-u.https.html.ini": [
-        "d559eb64d610b064449741c83a2d92c703e4b238",
+        "e594813511b6d8b463f199e677c6a2cc6c849b30",
         []
        ],
        "popup-un.https-expected.txt": [
@@ -350912,7 +350936,7 @@
         []
        ],
        "popup-with-cross-origin.https.html.ini": [
-        "fca3b7c3e8f677f571d091f75a427352539790f5",
+        "f97561bf0fff98b15162863581a99dfd0dc6bbc5",
         []
        ],
        "popup-with-same-origin.https-expected.txt": [
@@ -351004,7 +351028,7 @@
         []
        ],
        "document-cookie.html.ini": [
-        "87ed3754a09930097225b085f7f8528dd5256968",
+        "fc63f6d0f5c4c265aefdac70e3e4bfadb1f17af6",
         []
        ],
        "document-lastModified.html.headers": [
@@ -351496,12 +351520,8 @@
       []
      ],
      "render-blocking": {
-      "remove-attr-script-keeps-blocking.tentative.html.ini": [
-       "f223edf8a78a537692d286edd8e27d7138683331",
-       []
-      ],
       "script-inserted-script.html.ini": [
-       "7e15d963c5f2b665894fc557655c9d5d6234c31a",
+       "e11044cfb6253752396bd957d05295fc1d8c2c07",
        []
       ],
       "script-inserted-stylesheet-link.tentative.html.ini": [
@@ -357197,7 +357217,7 @@
          []
         ],
         "resource-selection-invoke-audio-constructor.html.ini": [
-         "832554d322a83d49960e5586a1b22eb166cf8708",
+         "0fb6a8301e84fda502c54a63dd632e2fed3fe47a",
          []
         ],
         "resource-selection-invoke-in-sync-event-expected.txt": [
@@ -357225,11 +357245,11 @@
          []
         ],
         "resource-selection-invoke-insert-source-not-in-document.html.ini": [
-         "9a1d7917db87ed1449e48064598982c8a80b1721",
+         "0d35b24d35d3d91e2c9a565df4d85199db7fab3b",
          []
         ],
         "resource-selection-invoke-insert-source.html.ini": [
-         "5e49a00b82fc89743dcc0069127766610ae786fa",
+         "90bfb401de4601bdb01e22caa517ec61f3a10f98",
          []
         ],
         "resource-selection-invoke-load.html.ini": [
@@ -357237,7 +357257,7 @@
          []
         ],
         "resource-selection-invoke-pause-networkState.html.ini": [
-         "08db93d9bdea4dfb142bd0f315c9cffaa8f7faf8",
+         "fb095150a0d522562806caf4e43af4887f5bdb80",
          []
         ],
         "resource-selection-invoke-pause.html.ini": [
@@ -357252,16 +357272,12 @@
          "940dd055965fc8216fc7b76adf46fce4ea80c73c",
          []
         ],
-        "resource-selection-invoke-remove-src.html.ini": [
-         "7b5bb152205763528c58273ca15c428fbdbf2aee",
-         []
-        ],
         "resource-selection-invoke-set-src-not-in-document.html.ini": [
          "7fe38a1b008003d6f1e3f989dfbec12f6ade05fc",
          []
         ],
         "resource-selection-invoke-set-src.html.ini": [
-         "c0581652ef344bf42e125cffdd9d6761b9b91d4b",
+         "1d86d05b30bbae23f96c56f3b0cc2bcb4da62c47",
          []
         ],
         "resource-selection-pointer-control-expected.txt": [
@@ -357752,7 +357768,7 @@
           []
          ],
          "track-cue-rendering-after-controls-removed.html.ini": [
-          "e839e1a5276987b282d7fc781f63bee58c28387e",
+          "cd1b74eeb79be9307b34f5ed97d40da43b33b932",
           []
          ],
          "track-cue-rendering-line-doesnt-fit-ref.html": [
@@ -358222,19 +358238,19 @@
         []
        ],
        "sandbox-top-navigation-child-special-cases.tentative.sub.window.js.ini": [
-        "bdfd528b939bf75dcd6a844f7f7acc1f8869bc6c",
+        "7774528cba503b088738104d94c86dde95a92e8b",
         []
        ],
        "sandbox-top-navigation-child.tentative.sub.window.js.ini": [
-        "4d916ea98cfcaa51a6b60d1bddcd140e3d53fb5e",
+        "9e36063fb286f655dd09c1a3c8321469a15d89fe",
         []
        ],
        "sandbox-top-navigation-escalate-privileges.tentative.sub.window.js.ini": [
-        "ae3370f78198955144375363786e6be34e977508",
+        "5a471c5d14bef67abb14524830cb1dee4d5a5683",
         []
        ],
        "sandbox-top-navigation-grandchild.tentative.sub.window.js.ini": [
-        "a28e10d1b54c3ae2e4e7420525752d6be185c9ce",
+        "f6d097fe095955bb078b69bde166b123ba27c40a",
         []
        ],
        "stash.py": [
@@ -358530,7 +358546,7 @@
         []
        ],
        "image-loading-lazy-data-url-to-https.html.ini": [
-        "d6926983e202daf0105db5fccac9dafa113bd96d",
+        "668679d346a232ccd1a51db6cf1cab1beb05bbaf",
         []
        ],
        "image-loading-lazy-expected.txt": [
@@ -358959,10 +358975,6 @@
          []
         ]
        },
-       "text-plain.window.js.ini": [
-        "e236680b1d85d430a4a0446633e11149e744e1f0",
-        []
-       ],
        "urlencoded2.window.js.ini": [
         "c14d03067bea6c73844940da6d6c6f69188902a6",
         []
@@ -359318,7 +359330,7 @@
         []
        ],
        "selectmenu-form-state-restore.tentative.html.ini": [
-        "2dbfcd2a827090ec23178c8e097b29712ffd5de1",
+        "12a4ba6bdc34b75a8bbc2857619930c03a08a76b",
         []
        ],
        "selectmenu-keyboard.tentative.html.ini": [
@@ -359726,7 +359738,7 @@
         []
        ],
        "activation-behavior.window.js.ini": [
-        "0bebe05b1708bf4dd9803a70029723546a43f0eb",
+        "b02e6bff1e09e278ce309cbba67bc9726e807f9d",
         []
        ]
       },
@@ -359888,10 +359900,6 @@
        "4da507b5fa6f83ea20ce950e365d0c26546cc3aa",
        []
       ],
-      "popover-focus.tentative.html.ini": [
-       "3e5f99f4b5080babd7fa728c1216e463676b9f29",
-       []
-      ],
       "popover-hidden-display-ref.tentative.html": [
        "2dc0d558b634279a09703798e9a531748215a563",
        []
@@ -363637,6 +363645,12 @@
        ]
       }
      },
+     "microtask-queuing": {
+      "queue-microtask-exceptions.any.js.ini": [
+       "6029268ecaf4d335446cd6eee6940d1de48f20eb",
+       []
+      ]
+     },
      "scripting": {
       "event-loops": {
        "fully_active_document.window-expected.txt": [
@@ -364429,7 +364443,7 @@
      ]
     },
     "bare-specifiers.sub.html.ini": [
-     "e8a067e1fa43aefe0d9fc6e481a280ef30296a6d",
+     "5e759f2363634ee769c267bb03c3ee4910ad956c",
      []
     ],
     "csp": {
@@ -365164,7 +365178,7 @@
       []
      ],
      "webtransport-h3.https.sub.any.js.ini": [
-      "daba249a449508333c9d23e6fe1969044383d0e3",
+      "667aadcf01418289fbe5842a37335b9cdddd9b56",
       []
      ],
      "wpt-server-wpt-flags.sub.html.ini": [
@@ -365289,7 +365303,7 @@
      []
     ],
     "idlharness.window.js.ini": [
-     "e505678b1bcc029f63e807c82bddd0ffd3fcecc5",
+     "c9abaca051b20c2325cba7baa3aa93bf116f3b3c",
      []
     ]
    },
@@ -366559,7 +366573,7 @@
      []
     ],
     "cross-origin-iframe.sub.html.ini": [
-     "72e6f6508aafa556ca854a05cf9b9be8128423bd",
+     "a93fa19475c19c312c7d05d2263f5c7ba8ac52b9",
      []
     ],
     "idlharness.window-expected.txt": [
@@ -366570,10 +366584,6 @@
      "a943671178997c89e4fb0751439a1efd490d7b9c",
      []
     ],
-    "iframe-no-root-with-wrapping-scroller.html.ini": [
-     "7d550a59d508efba1893a023669aedc01c765863",
-     []
-    ],
     "nested-cross-origin-iframe.sub.html.ini": [
      "eb080a976f546ede7d1c83d667442ed093024923",
      []
@@ -366863,7 +366873,7 @@
      ]
     },
     "first-paint-equals-lcp-text.html.ini": [
-     "2ce953e63e4ecc84959417db0c022c732e03b5eb",
+     "2e33519c46d6f33c42e399a635264256aceff165",
      []
     ],
     "image-upscaling-expected.txt": [
@@ -366999,7 +367009,7 @@
      []
     ],
     "freeze.html.ini": [
-     "cbfe5c129a6d886ed12ab00a3b864f2d904043a8",
+     "38d7adaceef563a79aea605eff043db12b081828",
      []
     ],
     "resources": {
@@ -367116,7 +367126,7 @@
       []
      ],
      "preload-finished-before-final-response.h2.window.js.ini": [
-      "be2aa9a26325f514d5059de9f1f3ecad29564d71",
+      "27b93e4049a5624f18f3acf5102c08590cdcfa83",
       []
      ],
      "preload-finished-while-receiving-final-response-body.h2.window.js.ini": [
@@ -367172,7 +367182,7 @@
       []
      ],
      "referrer-policy-origin.h2.window.js.ini": [
-      "afb4eab4a896559b5757bcec8080bb1451aebb4b",
+      "ea7126e8319f8d8b60b4986c241905fc14cdfb7b",
       []
      ],
      "referrer-policy-same-origin.h2.window.js.ini": [
@@ -367180,7 +367190,7 @@
       []
      ],
      "referrer-policy-unsafe-url.h2.window.js.ini": [
-      "a03c3f90011268cf4006c84988d85a9b99f86765",
+      "a432caa2324441ba258a7c9a2bbbf2386baf373f",
       []
      ],
      "resources": {
@@ -367410,10 +367420,6 @@
      "91c07f9fd3f3097367f2ad87a2ebb0d98b11d4e2",
      []
     ],
-    "long-microtask.window.js.ini": [
-     "5db0634a8964b47eb02430ef5ee536bbfdb124a9",
-     []
-    ],
     "longtask-in-childiframe-crossorigin.html.ini": [
      "00fee073c6cea6d8e41a5306d10e64c188681b8e",
      []
@@ -367423,7 +367429,7 @@
      []
     ],
     "longtask-in-sibling-iframe-crossorigin.html.ini": [
-     "11c1f412c110ffe5d4bdeea53f2f3683ac14adde",
+     "1a806b495fe18933dcd2e9a3763b9f6c27baa645",
      []
     ],
     "longtask-sync-xhr.html.ini": [
@@ -367916,6 +367922,10 @@
        "f72fdc8403719b0d07a283ad725975ce72dfe056",
        []
       ],
+      "operator-dictionary-arabic-002.html.ini": [
+       "f0fa72f41bfa4a4f79b8af912e2e1b3857c5b907",
+       []
+      ],
       "operator-dictionary-empty-and-three-chars-ref.html": [
        "2cbed129401e721fccfeb12874d6b7223bff8def",
        []
@@ -368143,7 +368153,7 @@
        ]
       },
       "ignored-properties-001.html.ini": [
-       "f779190fb74e4065db3ee9deee4b617b02213af3",
+       "5b2c3d516e3a1d4db12e797e087230664156fc7d",
        []
       ],
       "legacy-scriptminsize-attribute-ref.html": [
@@ -369203,11 +369213,11 @@
      []
     ],
     "mediasource-appendbuffer-quota-exceeded.html.ini": [
-     "627cac7406b16bd173b468381a1c6267077da484",
+     "0dd051012546496ff21aea166d30e2dc914d55e8",
      []
     ],
     "mediasource-avtracks.html.ini": [
-     "cac368b95bdf0e953eebea853c76b61b65c815cd",
+     "a211a60e109ac6a1beb629e1372d9203e285c35f",
      []
     ],
     "mediasource-buffered-expected.txt": [
@@ -369279,7 +369289,7 @@
      []
     ],
     "mediasource-duration.html.ini": [
-     "0197c08c13123adadc0bbd2270eb8479afab18da",
+     "d73c3f22958564d711eddcdd6dd5837fa1fa367a",
      []
     ],
     "mediasource-endofstream-expected.txt": [
@@ -369616,6 +369626,10 @@
      "e7a1b7e607d9228a6876f4a49598d28a9a23fad4",
      []
     ],
+    "MediaStreamTrackGenerator-video.https.html.ini": [
+     "656234549e6da9420b2adabe7cc1bcf2b7a489c1",
+     []
+    ],
     "MediaStreamTrackProcessor-backpressure.https.html.ini": [
      "26d30cf01b3dc98a4d2d89808d348a94c78036a9",
      []
@@ -370582,10 +370596,6 @@
       []
      ]
     },
-    "detach_iframe_during_open.https.window.js.ini": [
-     "b3facba90a7069cd7eb018bff6456149a3a90719",
-     []
-    ],
     "resources": {
      "opaque-origin-sandbox.html": [
       "b3490c3341a892052ccab603722059cf8bca0cd5",
@@ -370928,10 +370938,6 @@
        "580dc21c19e71cbc51833c5d458ee34bc5e66717",
        []
       ],
-      "navigate-initial-about-blank.html.ini": [
-       "7680dc945c75d67196719a543d9ae9bb5c7674fc",
-       []
-      ],
       "navigate-intercept-interrupted.html.ini": [
        "5df966b3082d4dd15b10bad9ef94202e51794b84",
        []
@@ -371205,11 +371211,7 @@
       "afe09530d75866dbfd84ad4c346b0d8d6f27e5d3",
       []
      ]
-    },
-    "test-performance-attributes.sub.html.ini": [
-     "6cea40d48ad94d099d704cfeae69100bbf5db807",
-     []
-    ]
+    }
    },
    "netinfo": {
     "DIR_METADATA": [
@@ -371979,7 +371981,7 @@
      []
     ],
     "pending_beacon-sendondiscard.tentative.https.window.js.ini": [
-     "45cc94984865b6ec52fd60c5a0ace8ae170e04d8",
+     "34e4879e89cb58fda5df658c6422efe29ceeb454",
      []
     ],
     "pending_beacon-sendonhidden.tentative.https.window.js.ini": [
@@ -372076,7 +372078,7 @@
       []
      ],
      "performance-navigation-timing-same-origin-bfcache.tentative.window.js.ini": [
-      "967f7f1accdfbd46ebf2870d0466fb46942f65fd",
+      "b84c0c60cfc69eb767dd686943a8a4ee6ac7c205",
       []
      ],
      "performance-navigation-timing-same-origin-replace.tentative.window.js.ini": [
@@ -375831,7 +375833,7 @@
      []
     ],
     "deadline-max-rAF-dynamic.html.ini": [
-     "f827d6250bf610959f743f72b5d29b4f9522627d",
+     "04b0e95e76cf5bce0496de6e6f24ffdaf1ef66c0",
      []
     ],
     "deadline-max-rAF.html.ini": [
@@ -375839,7 +375841,7 @@
      []
     ],
     "deadline-max-timeout-dynamic.html.ini": [
-     "36bd303bf0ef4285d724732aab4f62d0608997be",
+     "e86c52100ce2d0c59e5bedf252a41dbc3abe116d",
      []
     ],
     "deadline-max.html.ini": [
@@ -375943,7 +375945,7 @@
      []
     ],
     "content-type-parsing.html.ini": [
-     "f628e90a03205e5f6f16ca4b78220001f5d988b1",
+     "17aa7dbcc6d221125e412094bc476262d0147cd9",
      []
     ],
     "frameset-timing.html": [
@@ -375982,6 +375984,10 @@
      "33006cf002b9b9c3f4fb4c4757916052ae12fe92",
      []
     ],
+    "nested-context-navigations-iframe.html.ini": [
+     "58d4c1014736b3b59f15fd1d5f7fb57a923ac48b",
+     []
+    ],
     "nextHopProtocol-is-tao-protected.https.html.ini": [
      "1073d65b02642b0bdac93f3b3d33f0111e369515",
      []
@@ -375991,7 +375997,7 @@
      []
     ],
     "no-entries-for-cross-origin-css-fetched-memory-cache.sub.html.ini": [
-     "6f1569d44c5476e21ab11940d2b608ca4f2f6a2e",
+     "be64ae2e80ab56dfa6b68027a551ad69be3d667e",
      []
     ],
     "ping-rt-entries-expected.txt": [
@@ -376389,7 +376395,7 @@
      ]
     },
     "response-status-code.html.ini": [
-     "8e34cbd838f07950d924e4f55bfaf810dfc1bae8",
+     "1b6605f1b1955d587fbb4c31453a4bd34ce3de9f",
      []
     ],
     "sleep.py": [
@@ -377119,7 +377125,7 @@
      []
     ],
     "redirects.html.ini": [
-     "2a4f0143486a0bf774c6c70eeb35e1ed2f536612",
+     "bca11087b9a5bba4235057adba38257bbf1becda",
      []
     ],
     "resources": {
@@ -378352,7 +378358,7 @@
       []
      ],
      "cache-add.https.any.js.ini": [
-      "93c7a0a4d8bc0d19353cc3798f317c66b2f9574c",
+      "a4f459911f261afbbd0e3fb21b0dcc034af2a914",
       []
      ],
      "cache-add.https.any.serviceworker-expected.txt": [
@@ -378610,11 +378616,11 @@
       []
      ],
      "about-blank-replacement.https.html.ini": [
-      "44673f0a5f7c3367517b39b82019fb80db5262b9",
+      "b2a61d9c24fb4e80b97cb4747249e50855d8dddb",
       []
      ],
      "client-navigate.https.html.ini": [
-      "ed96e18bfc432651cc62c5b31786bd7fbde3f820",
+      "a8461b4ee03ceec4debc39d832812c38d41052c6",
       []
      ],
      "client-url-of-blob-url-worker.https-expected.txt": [
@@ -378738,7 +378744,7 @@
       []
      ],
      "getregistrations.https.html.ini": [
-      "5651cd24eb56cded68298b7c425de7b92cf688c7",
+      "a1193b5da43c34a908d956e37a4bb6abf2829e48",
       []
      ],
      "idlharness-sw.https-expected.txt": [
@@ -380510,7 +380516,7 @@
       []
      ],
      "unregister-immediately-during-extendable-events.https.html.ini": [
-      "acf3dea87b93fb7e85940d9a0b96f098f0efc1ab",
+      "48187be6cf659c80f88dd2bbf4828e0763dd24f2",
       []
      ],
      "unregister-then-register-new-script.https-expected.txt": [
@@ -381436,7 +381442,7 @@
       []
      ],
      "csp-script-src-self.html.ini": [
-      "812723f4d5d2ad51231550433e49f8e8e24b0e05",
+      "03af32c4ad3c3f7c1c775cc0a17a90438d279b2f",
       []
      ],
      "csp-script-src-unsafe-inline.html.ini": [
@@ -381468,7 +381474,7 @@
       []
      ],
      "media-autoplay.html.ini": [
-      "dcad0990b062253b60381f1c830be6cd905126e5",
+      "dbcd03784b4242abb9f2fa661b1bbe0a8d8a9b24",
       []
      ],
      "navigation-intercepted-by-service-worker.https.html.ini": [
@@ -381476,7 +381482,7 @@
       []
      ],
      "navigator-plugins.tentative.html.ini": [
-      "7e5ff8fc7e8625c119169b949de3f1931ba14fbf",
+      "6d40224b5f63c0761e26dcc880f5c97c2302d641",
       []
      ],
      "navigator-subapp.https.tentative.html.ini": [
@@ -381492,7 +381498,7 @@
       []
      ],
      "referrer-policy-no-referrer.html.ini": [
-      "9c2d1085fbbd59397e4aa1bd782ed2d8edf8d454",
+      "0a70c55e029e0ec01b921fcaafc4aa3b4752c4ae",
       []
      ],
      "referrer-policy-origin.html.ini": [
@@ -381922,11 +381928,11 @@
       ]
      },
      "response-code-non-successful.html.ini": [
-      "f7732f90e6f3db967beb0190fbc9c2b643155a76",
+      "ba0befaada95db283d4615c26d289ad9e390b92b",
       []
      ],
      "response-code-successful.html.ini": [
-      "b10e24ccaf4d436d51f7a32932afe7b587218128",
+      "b60b1de7e9ebd129b4416f06f9dbac828028a127",
       []
      ],
      "restriction-audio-setSinkId-with-invalid-sinkId.https.tentative.html.ini": [
@@ -382002,7 +382008,7 @@
       []
      ],
      "restriction-message-boxes.html.ini": [
-      "aeb2a55b80067815a8f7a29f90ebe9516a3f2544",
+      "8bd97880f870a2162a3f55e3fd75921935149f95",
       []
      ],
      "restriction-midi-sysex.https.html.ini": [
@@ -382034,7 +382040,7 @@
       []
      ],
      "restriction-request-picture-in-picture.html.ini": [
-      "745c20dc1c7da6527d59ddd93af071fed58d22c6",
+      "9bfa95ff89d6b4a022ac7a56aa4a2714c610007a",
       []
      ],
      "restriction-screen-capture.https.html.ini": [
@@ -382074,7 +382080,7 @@
       []
      ],
      "restriction-speech-synthesis.html.ini": [
-      "ad1ad4c2b02022f3bdfe9a9b47eb552ff4a2e77f",
+      "6984300e6cd9030dfa2b49775fba95f141b0a14c",
       []
      ],
      "restriction-storage-persist.https.html.ini": [
@@ -382106,7 +382112,7 @@
       []
      ],
      "restriction-web-usb.https.html.ini": [
-      "2930410061ae675e7ec7d80d8ecae7a7b00cdbfb",
+      "2fb4aa2fd1451f6cbb2990b624bc6485654f10ea",
       []
      ],
      "restriction-web-xr-immersive-vr-session.https.html.ini": [
@@ -382114,11 +382120,11 @@
       []
      ],
      "restriction-web-xr-inline-session.https.html.ini": [
-      "de3f51bc683e82fce24e6f41365797507fce9256",
+      "ea71fd807083994b5c7a44a3b3ff9f69514da4f2",
       []
      ],
      "restriction-window-move.html.ini": [
-      "1f07b4c2d4998f2362163af38a7b4ab95c7befaa",
+      "241db3c6ae3ceca2e0028c3a96405802838fa6ab",
       []
      ],
      "restriction-window-open.html.ini": [
@@ -382126,7 +382132,7 @@
       []
      ],
      "restriction-window-resize.html.ini": [
-      "625e373b23f8bdbbe135dc5d79cef6af15b7682f",
+      "f7758699c05f12148afe5b2709a284ef58a39369",
       []
      ],
      "restrictions.html.ini": [
@@ -382194,11 +382200,11 @@
       []
      ],
      "windowclient-navigate.https.html.ini": [
-      "f209d85eb5b81c6ed51464cd365c37a5a5377f02",
+      "cdaf1ae05915a3cce5aabcc7884288ef2ad6cbf0",
       []
      ],
      "workers.html.ini": [
-      "827d09da648c60a4f7a18d153e3588e45420c8cf",
+      "bea4222f27851dccbb90476168b980946342743c",
       []
      ]
     }
@@ -382308,10 +382314,6 @@
      "8a7d54555472bc0b62505c770b780be2302c79cd",
      []
     ],
-    "partitioned-estimate-usage-details-caches.tentative.https.sub.html.ini": [
-     "b9d6883afc971201618441fccaf3f8e4b4a1d9ec",
-     []
-    ],
     "resources": {
      "partitioned-estimate-usage-details-caches-helper-frame.html": [
       "13786d7ceafca799bd44c20482085278283303ca",
@@ -386011,7 +386013,7 @@
      []
     ],
     "a-element-xhtml.xhtml.ini": [
-     "3dc8d455537c89b242feafef3751138a73246fa7",
+     "a90e16b8c38a1dc542c8402c820788ef098d5c31",
      []
     ],
     "a-element-xhtml_include=javascript-expected.txt": [
@@ -386023,7 +386025,7 @@
      []
     ],
     "a-element.html.ini": [
-     "82a234752d4f5432cfec9797946059081cc8381b",
+     "85ce55478a5ea8f11db3c6a2f7a0c3192552d5b6",
      []
     ],
     "a-element_include=javascript-expected.txt": [
@@ -386035,7 +386037,7 @@
      []
     ],
     "failure.html.ini": [
-     "5f3314da573f67b736b3308e0d9a782c3778fde1",
+     "4364c892cde3d29b38bf7cace0017c9e9c5da053",
      []
     ],
     "idlharness-shadowrealm.window-expected.txt": [
@@ -386047,7 +386049,7 @@
      []
     ],
     "percent-encoding.window.js.ini": [
-     "1091bffa2c6ebfc3c45547eb4ba0f53edaab55cc",
+     "36d57023fae6a0fbf2d834ab075a368470e527de",
      []
     ],
     "resources": {
@@ -386113,7 +386115,7 @@
      []
     ],
     "url-setters-a-area.window.js.ini": [
-     "763ab28306a3f016564ff0fa18b614a61e81b39b",
+     "a11a7016bd64c7c004fa11c7bb6f6c8a6cf04b5f",
      []
     ],
     "url-setters-a-area.window_include=javascript-expected.txt": [
@@ -386129,7 +386131,7 @@
      []
     ],
     "url-setters-stripping.any.js.ini": [
-     "ad2f860fc3677f34b0f5d29d7f7248d15cd4099b",
+     "5c23a98a6205bc1eeba0e0623b80063b03a8d6f1",
      []
     ],
     "url-setters-stripping.any.worker-expected.txt": [
@@ -386161,7 +386163,7 @@
      []
     ],
     "urlsearchparams-delete.any.js.ini": [
-     "9f22a447d7a66f9514b01ba4102d38c7aff7d171",
+     "e35316b04d7b07af1c492394667bdc0a1388039d",
      []
     ],
     "urlsearchparams-delete.any.worker-expected.txt": [
@@ -386169,7 +386171,11 @@
      []
     ],
     "urlsearchparams-get.any.js.ini": [
-     "e0afce635f0b70de1d746af7d99c52f03a2f4aab",
+     "9c74fd4fd8d68e549eeced0730dbb78e09125ef9",
+     []
+    ],
+    "urlsearchparams-stringifier.any.js.ini": [
+     "e3259c3a89c26e14f9cb23a2047b939b33fdaeb8",
      []
     ]
    },
@@ -387399,7 +387405,7 @@
        []
       ],
       "sibling-iframe-timeline.html.ini": [
-       "db1fc3d9642f489fe0f0be7dfa37dade2cf39898",
+       "60172dd34fead1471dd91e42bf1e0039a9ae2ed3",
        []
       ],
       "timelines.html.ini": [
@@ -387883,7 +387889,7 @@
      []
     ],
     "query-ordering.tentative.https.html.ini": [
-     "b63d722ab7dd33bb4eac37228311c006f2ed749b",
+     "236f81ad0bebb737c8cf24c41b4b375df775be5a",
      []
     ],
     "query.tentative.https.any.js.ini": [
@@ -388185,7 +388191,7 @@
      },
      "the-analysernode-interface": {
       "test-analyser-output.html.ini": [
-       "448db8fda7ac24ef480e0b1c3f1078e2bac8ba2b",
+       "b2da746bbef1182d895f8dc4c22ef9fcbfaf3599",
        []
       ]
      },
@@ -388286,10 +388292,6 @@
        "5574a563d6f48095e521ecc4aaf7060541d3c725",
        []
       ],
-      "audioworkletnode-output-channel-count.https.html.ini": [
-       "97f1aa6933157db4fc4564d7095f4c274919d1ec",
-       []
-      ],
       "audioworkletprocessor-promises.https-expected.txt": [
        "ecc24fe05e8a87fcd79a9de92e21f7e38207ca0f",
        []
@@ -388469,19 +388471,13 @@
      },
      "the-mediaelementaudiosourcenode-interface": {
       "mediaElementAudioSourceToScriptProcessorTest.html.ini": [
-       "88f3f0f560a735cacf8c8c58972ea1ee75f099de",
+       "efe3d87894b34d3d1f24dd770c227575c348c1ff",
        []
       ],
       "no-cors.https.html.ini": [
        "af268033c7d6d8d28ea340ce3a1dfe37ad488677",
        []
       ]
-     },
-     "the-pannernode-interface": {
-      "test-pannernode-automation.html.ini": [
-       "a0c0660a92aa922fcd5abc7c4ebc6b417cc3b4ee",
-       []
-      ]
      }
     }
    },
@@ -389630,7 +389626,7 @@
       ]
      },
      "workers.html.ini": [
-      "49c27878b8e2dd76c9318c237adb8158c68ad935",
+      "fd51247a007880b73ef8775e6641bb619b299ba4",
       []
      ]
     },
@@ -389688,7 +389684,7 @@
       []
      ],
      "broadcastchannel-incumbent.sub.html.ini": [
-      "b15baab7faf137cd6228e0ad84e836adfd76dd0e",
+      "b7ed439511b5a8337fc4d9c8cf7de759e0ea3891",
       []
      ],
      "support": {
@@ -389779,10 +389775,6 @@
       "225bd7a41e38280bdb0891ecbf8cd4c39a4c3029",
       []
      ],
-     "020.html.ini": [
-      "265c7a6def4cc8db611bbcb8f304bdfab086a23c",
-      []
-     ],
      "021.html.ini": [
       "fd4aad14082878fb8cd021b5a6791e1d0e4ec620",
       []
@@ -389940,10 +389932,6 @@
      "85e18d8ebe952d851bb4a3e2a820a9fdd1726de2",
      []
     ],
-    "RTCIceConnectionState-candidate-pair.https.html.ini": [
-     "4e15800ca79b87a69bf94df4067e7ac8e96d6d16",
-     []
-    ],
     "RTCIceTransport-expected.txt": [
      "ea2802c5199b90734a8d0264fe2b9935c58fd98e",
      []
@@ -394867,7 +394855,7 @@
      []
     ],
     "events_referenceSpace_reset_inline.https.html.ini": [
-     "fddaa5b930051715ecfd3f17869ba0b776c39b55",
+     "c348a52f35b2c0cc051257b0ade447bfa00a6a14",
      []
     ],
     "events_session_select.https.html.ini": [
@@ -394952,16 +394940,16 @@
       []
      ],
      "xrRay_matrix.https.html.ini": [
-      "43d34bacaeb185a3fb69d635848a055c5cd8b672",
+      "b22a17ae0df0d9690ab4db9d0ae3e6369b45327e",
       []
      ]
     },
     "idlharness.https.window-expected.txt": [
-     "5c8507260f586b1b63e99b7a1c0338e77dfa84fe",
+     "4ddf4e7f11e85042d1bbe047aad420206166417e",
      []
     ],
     "idlharness.https.window.js.ini": [
-     "ef2fbdfa6541060d97986f43e2413e6ddc1e39fd",
+     "ae0831a7c7bac09f6050a7a33b56d5e0e0db4870",
      []
     ],
     "layers": {
@@ -395034,7 +395022,7 @@
       []
      ],
      "webxr_test_constants.js": [
-      "cabc4b4a965d5db8d9993a5c4591355dd01a1d21",
+      "1a0d7bddad558f8064195d034c8b58775669eadc",
       []
      ],
      "webxr_test_constants_fake_depth.js": [
@@ -395198,6 +395186,10 @@
      "42da7ae73ddce2517438573f27bddb175ec3b3ae",
      []
     ],
+    "xrSession_enabledFeatures.https.html.ini": [
+     "e77d7e77c4fb37ec3168eff309261fa0ff19f8a7",
+     []
+    ],
     "xrSession_end.https.html.ini": [
      "05ed1b16d815e27288d8cea2f7baa9d889ea600c",
      []
@@ -395223,7 +395215,7 @@
      []
     ],
     "xrSession_requestAnimationFrame_getViewerPose.https.html.ini": [
-     "fd22b34a0c12a853179814f71a3c2bcc1eca2838",
+     "13ee403018cff6c6a876a924f21469c64bebaf7a",
      []
     ],
     "xrSession_requestAnimationFrame_timestamp.https.html.ini": [
@@ -395235,7 +395227,7 @@
      []
     ],
     "xrSession_requestReferenceSpace_features.https.html.ini": [
-     "9d84a7b2938521b7170bd842d879ec38880e73d3",
+     "819352f75170ff7890e8f4299266d5e4e7158570",
      []
     ],
     "xrSession_requestSessionDuringEnd.https.html.ini": [
@@ -395259,7 +395251,7 @@
      []
     ],
     "xrStationaryReferenceSpace_floorlevel_updates.https.html.ini": [
-     "66f1822acf687c891474dcea9dd63a3f4c5537c5",
+     "288ec60eb75a5be9bbdd3a2ba22517f9f278e7de",
      []
     ],
     "xrView_eyes.https.html.ini": [
@@ -395518,10 +395510,6 @@
        "2cf26a723e8efd9865628cb6a0d6c899ffa0fb14",
        []
       ],
-      "dummy-name.html.ini": [
-       "2ff8507016af72224b8cbd32c5a9593050b7efdf",
-       []
-      ],
       "dummy-shared-worker.js": [
        "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391",
        []
@@ -395730,7 +395718,7 @@
         []
        ],
        "setting.html.ini": [
-        "2244b2520510040380164b5f6493cd398b797de9",
+        "45a75a52353f752684031bb350133099df724c99",
         []
        ],
        "setting.js": [
@@ -395791,6 +395779,10 @@
         "1c6515f8e201ef9439a48434033acafaecd68517",
         []
        ],
+       "redirect.html.ini": [
+        "fd33d33be2f9c0d25ef8afed8d0a024b96686d2f",
+        []
+       ],
        "redirect.js": [
         "2db48544a2d7d7f55201043e73297283cd99c263",
         []
@@ -396002,7 +395994,7 @@
       []
      ],
      "dedicated-worker-import-meta.html.ini": [
-      "f19304df704b1d471ff207e02c732b496ca0efee",
+      "f8185f10976eba9cc50ff6423ba9337629f38735",
       []
      ],
      "dedicated-worker-options-credentials.html.headers": [
@@ -396784,10 +396776,6 @@
      "b06ea33cd926fd99d890b0dd7544213170a15e8e",
      []
     ],
-    "animation-worklet-import.https.html.ini": [
-     "0b7048512beac8867185ac44dda506974829672a",
-     []
-    ],
     "animation-worklet-referrer.https.html.ini": [
      "5eb7251bd364e2b5d715b4a700d3a84654962eb4",
      []
@@ -544409,7 +544397,7 @@
        ]
       ],
       "popover-focus.tentative.html": [
-       "82b8a5e62f648be99cccc596ef3e0ca9923b8665",
+       "b1e59a13971c7be224663ef3d1161ee83c0527ed",
        [
         null,
         {
@@ -552883,6 +552871,13 @@
          {}
         ]
        ],
+       "compile-event-handler-lexical-scopes-form-owner.html": [
+        "e31bd2496a1fee19e356650f502a66e804899713",
+        [
+         null,
+         {}
+        ]
+       ],
        "compile-event-handler-lexical-scopes.html": [
         "ed6c006651162aeaac41a4ad7a8e81ad0bbd457e",
         [
@@ -643251,6 +643246,13 @@
       {}
      ]
     ],
+    "xrSession_enabledFeatures.https.html": [
+     "ba9045597c2d507c2b909f10a96248fc0c4345f1",
+     [
+      null,
+      {}
+     ]
+    ],
     "xrSession_end.https.html": [
      "dccc550be58b2e8c99ca7220f0c33e0ea9e4f3b5",
      [
diff --git a/third_party/blink/web_tests/external/wpt/FileAPI/url/url-lifetime.html.ini b/third_party/blink/web_tests/external/wpt/FileAPI/url/url-lifetime.html.ini
index 6f3b4e8..4b04d98 100644
--- a/third_party/blink/web_tests/external/wpt/FileAPI/url/url-lifetime.html.ini
+++ b/third_party/blink/web_tests/external/wpt/FileAPI/url/url-lifetime.html.ini
@@ -1,4 +1,4 @@
 [url-lifetime.html]
   [Terminating worker revokes its URLs]
     expected:
-      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+      if (flag_specific == "") and (product == "chrome"): [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/IndexedDB/idbindex-rename-abort.html.ini b/third_party/blink/web_tests/external/wpt/IndexedDB/idbindex-rename-abort.html.ini
index 35b36a1..e0d6f453 100644
--- a/third_party/blink/web_tests/external/wpt/IndexedDB/idbindex-rename-abort.html.ini
+++ b/third_party/blink/web_tests/external/wpt/IndexedDB/idbindex-rename-abort.html.ini
@@ -1,4 +1,4 @@
 [idbindex-rename-abort.html]
   [IndexedDB index creation and rename in an aborted transaction]
     expected:
-      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
+      if os == "win": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/IndexedDB/idbobjectstore_batchGetAll_largeValue.tentative.any.js.ini b/third_party/blink/web_tests/external/wpt/IndexedDB/idbobjectstore_batchGetAll_largeValue.tentative.any.js.ini
index 30d63af..5d511ef 100644
--- a/third_party/blink/web_tests/external/wpt/IndexedDB/idbobjectstore_batchGetAll_largeValue.tentative.any.js.ini
+++ b/third_party/blink/web_tests/external/wpt/IndexedDB/idbobjectstore_batchGetAll_largeValue.tentative.any.js.ini
@@ -1,7 +1,6 @@
 [idbobjectstore_batchGetAll_largeValue.tentative.any.html]
   expected:
-    if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [OK, TIMEOUT]
-    if product == "chrome": OK
+    if (flag_specific == "") and (product == "chrome"): OK
     TIMEOUT
   [Get upper/lower excluded]
     expected: [PASS, TIMEOUT]
@@ -14,7 +13,9 @@
 
 
 [idbobjectstore_batchGetAll_largeValue.tentative.any.worker.html]
-  expected: TIMEOUT
+  expected:
+    if flag_specific == "disable-site-isolation-trials": OK
+    TIMEOUT
   [Get bound range with maxCount]
     expected: [PASS, TIMEOUT]
 
@@ -22,4 +23,5 @@
     expected: [PASS, TIMEOUT]
 
   [Get upper/lower excluded]
-    expected: TIMEOUT
+    expected:
+      if product == "chrome": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/IndexedDB/structured-clone.any.js.ini b/third_party/blink/web_tests/external/wpt/IndexedDB/structured-clone.any.js.ini
index e58382d3..2fe6bf87 100644
--- a/third_party/blink/web_tests/external/wpt/IndexedDB/structured-clone.any.js.ini
+++ b/third_party/blink/web_tests/external/wpt/IndexedDB/structured-clone.any.js.ini
@@ -4,7 +4,35 @@
 
 [structured-clone.any.worker.html?101-last]
   expected:
-    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [OK, TIMEOUT]
+    if product == "chrome": [OK, TIMEOUT]
+  [Blob: [object Blob\]]
+    expected:
+      if product == "chrome": [PASS, TIMEOUT]
+
+  [Not serializable: Event: [object Event\]]
+    expected:
+      if product == "chrome": [PASS, NOTRUN]
+
+  [Not serializable: DedicatedWorkerGlobalScope: [object DedicatedWorkerGlobalScope\]]
+    expected:
+      if product == "chrome": [PASS, NOTRUN]
+
+  [Not serializable: function: function() {}]
+    expected:
+      if product == "chrome": [PASS, NOTRUN]
+
+  [Not serializable: symbol: Symbol(desc)]
+    expected:
+      if product == "chrome": [PASS, NOTRUN]
+
+  [File: [object File\]]
+    expected:
+      if product == "chrome": [PASS, NOTRUN]
+
+  [Not serializable: MessageChannel: [object MessageChannel\]]
+    expected:
+      if product == "chrome": [PASS, NOTRUN]
+
 
 [structured-clone.any.worker.html?41-60]
 
diff --git a/third_party/blink/web_tests/external/wpt/acid/acid3/test.html.ini b/third_party/blink/web_tests/external/wpt/acid/acid3/test.html.ini
index c891251..c1cf79e 100644
--- a/third_party/blink/web_tests/external/wpt/acid/acid3/test.html.ini
+++ b/third_party/blink/web_tests/external/wpt/acid/acid3/test.html.ini
@@ -1,4 +1,4 @@
 [test.html]
   expected:
-    if (flag_specific == "") and (os == "win"): [FAIL, TIMEOUT]
+    if (os == "linux") and (flag_specific == "disable-layout-ng"): [FAIL, TIMEOUT]
     FAIL
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/gen/top.meta/script-src-self/sharedworker-import.http.html.ini b/third_party/blink/web_tests/external/wpt/content-security-policy/gen/top.meta/script-src-self/sharedworker-import.http.html.ini
index 831cd4f..862676a 100644
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/gen/top.meta/script-src-self/sharedworker-import.http.html.ini
+++ b/third_party/blink/web_tests/external/wpt/content-security-policy/gen/top.meta/script-src-self/sharedworker-import.http.html.ini
@@ -1,4 +1,6 @@
 [sharedworker-import.http.html]
+  expected:
+    if flag_specific == "disable-layout-ng": [OK, TIMEOUT]
   [Content Security Policy: Expects blocked for sharedworker-import to cross-http origin and keep-origin redirection from http context.: securitypolicyviolation]
     expected: FAIL
 
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/history-iframe.sub.html.ini b/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/history-iframe.sub.html.ini
new file mode 100644
index 0000000..3d47c07
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/history-iframe.sub.html.ini
@@ -0,0 +1,3 @@
+[history-iframe.sub.html]
+  expected:
+    if os == "win": [OK, TIMEOUT]
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/prefetch-src/prefetch-header-allowed.html.ini b/third_party/blink/web_tests/external/wpt/content-security-policy/prefetch-src/prefetch-header-allowed.html.ini
index 1aa1e89..05edd2d5 100644
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/prefetch-src/prefetch-header-allowed.html.ini
+++ b/third_party/blink/web_tests/external/wpt/content-security-policy/prefetch-src/prefetch-header-allowed.html.ini
@@ -1,3 +1,4 @@
 [prefetch-header-allowed.html]
   expected:
-    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [OK, TIMEOUT]
+    if flag_specific == "disable-layout-ng": [OK, TIMEOUT]
+    if flag_specific == "disable-site-isolation-trials": [OK, TIMEOUT]
diff --git a/third_party/blink/web_tests/external/wpt/cookie-store/cookieListItem_attributes.https.any.js.ini b/third_party/blink/web_tests/external/wpt/cookie-store/cookieListItem_attributes.https.any.js.ini
index 035485e0..0f2e60c 100644
--- a/third_party/blink/web_tests/external/wpt/cookie-store/cookieListItem_attributes.https.any.js.ini
+++ b/third_party/blink/web_tests/external/wpt/cookie-store/cookieListItem_attributes.https.any.js.ini
@@ -1,11 +1,18 @@
 [cookieListItem_attributes.https.any.serviceworker.html]
   [CookieListItem - cookieStore.set with expires set to a timestamp 10 years in the future]
     expected:
+      if os == "win": FAIL
+
+  [CookieListItem - cookieStore.set with expires set to a Date 10 years in the future]
+    expected:
+      if os == "win": FAIL
+
+
+[cookieListItem_attributes.https.any.html]
+  [CookieListItem - cookieStore.set with expires set to a timestamp 10 years in the future]
+    expected:
       if os == "win": [PASS, FAIL]
 
   [CookieListItem - cookieStore.set with expires set to a Date 10 years in the future]
     expected:
       if os == "win": [PASS, FAIL]
-
-
-[cookieListItem_attributes.https.any.html]
diff --git a/third_party/blink/web_tests/external/wpt/cookie-store/cookieStore_set_arguments.https.any.js.ini b/third_party/blink/web_tests/external/wpt/cookie-store/cookieStore_set_arguments.https.any.js.ini
index 3cb3ddf..991863e 100644
--- a/third_party/blink/web_tests/external/wpt/cookie-store/cookieStore_set_arguments.https.any.js.ini
+++ b/third_party/blink/web_tests/external/wpt/cookie-store/cookieStore_set_arguments.https.any.js.ini
@@ -1,18 +1,14 @@
 [cookieStore_set_arguments.https.any.serviceworker.html]
   [cookieStore.set with expires set to a future Date]
     expected:
-      if os == "win": [PASS, FAIL]
+      if os == "win": FAIL
 
   [cookieStore.set with expires set to a future timestamp]
     expected:
-      if os == "win": [PASS, FAIL]
+      if os == "win": FAIL
 
 
 [cookieStore_set_arguments.https.any.html]
   [cookieStore.set with expires set to a future Date]
     expected:
       if os == "win": FAIL
-
-  [cookieStore.set with expires set to a future timestamp]
-    expected:
-      if os == "win": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/cookie-store/cookieStore_subscribe_arguments.https.any.js.ini b/third_party/blink/web_tests/external/wpt/cookie-store/cookieStore_subscribe_arguments.https.any.js.ini
index 03cbe54..ced6aca 100644
--- a/third_party/blink/web_tests/external/wpt/cookie-store/cookieStore_subscribe_arguments.https.any.js.ini
+++ b/third_party/blink/web_tests/external/wpt/cookie-store/cookieStore_subscribe_arguments.https.any.js.ini
@@ -1,17 +1,9 @@
 [cookieStore_subscribe_arguments.https.any.html]
   expected:
-    if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [OK, ERROR]
-  [cookieStore.subscribe with invalid url path in option]
-    expected:
-      if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [PASS, NOTRUN]
-
-  [cookieStore.subscribe is idempotent]
-    expected:
-      if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [PASS, NOTRUN]
-
+    if (flag_specific == "") and (os == "win"): [OK, ERROR]
   [CookieStore.unsubscribe is idempotent]
     expected:
-      if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [PASS, NOTRUN]
+      if (flag_specific == "") and (os == "win"): [PASS, NOTRUN]
 
 
 [cookieStore_subscribe_arguments.https.any.serviceworker.html]
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/floats/float-nowrap-4.html.ini b/third_party/blink/web_tests/external/wpt/css/CSS2/floats/float-nowrap-4.html.ini
index 1181379..5b5e8dbb 100644
--- a/third_party/blink/web_tests/external/wpt/css/CSS2/floats/float-nowrap-4.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/CSS2/floats/float-nowrap-4.html.ini
@@ -1,4 +1,5 @@
 [float-nowrap-4.html]
   expected:
-    if (os == "linux") and (flag_specific == "disable-layout-ng"): PASS
+    if (flag_specific == "") and (os == "win"): [TIMEOUT, CRASH]
+    if flag_specific == "disable-layout-ng": PASS
     CRASH
diff --git a/third_party/blink/web_tests/external/wpt/css/css-anchor-position/anchor-name-inline-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-anchor-position/anchor-name-inline-001.html.ini
new file mode 100644
index 0000000..35bea808
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-anchor-position/anchor-name-inline-001.html.ini
@@ -0,0 +1,12 @@
+[anchor-name-inline-001.html]
+  [.target 1]
+    expected:
+      if product == "chrome": [PASS, FAIL]
+
+  [.target 2]
+    expected:
+      if product == "chrome": [PASS, FAIL]
+
+  [.target 3]
+    expected:
+      if product == "chrome": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-112.html b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-112.html
new file mode 100644
index 0000000..5c9be2f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-112.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1404718">
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div style="columns:2; gap:0; column-fill:auto; width:100px; height:100px; background:red;">
+  <div style="height:150px; background:green;"></div>
+  <div style="position:relative; overflow:clip; height:50px;">
+    <div style="position:absolute; width:100%; height:20px; background:green;">
+      <div style="position:absolute; top:20px; width:100%; height:30px; background:green;"></div>
+    </div>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-113.html b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-113.html
new file mode 100644
index 0000000..9495933b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-113.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1404718">
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div style="columns:2; gap:0; column-fill:auto; width:100px; height:100px; background:red;">
+  <div style="height:40px; background:green;"></div>
+  <div style="position:relative; overflow:clip; height:60px;">
+    <div style="position:absolute; width:100%; height:60px; background:green;"></div>
+    <div style="height:100px;"></div>
+  </div>
+  <div style="height:40px; background:green;"></div>
+  <div style="position:relative; overflow:clip; height:60px;">
+    <div style="position:absolute; width:100%; height:60px; background:green;"></div>
+    <div style="height:100px;"></div>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/nested-query-containers.html.ini b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/nested-query-containers.html.ini
index e92a5bb1..076a237 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/nested-query-containers.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/nested-query-containers.html.ini
@@ -1,4 +1,2 @@
 [nested-query-containers.html]
-  expected:
-    if os == "win": [TIMEOUT, CRASH]
-    CRASH
+  expected: CRASH
diff --git a/third_party/blink/web_tests/external/wpt/css/css-flexbox/image-as-flexitem-size-007v.html.ini b/third_party/blink/web_tests/external/wpt/css/css-flexbox/image-as-flexitem-size-007v.html.ini
index 29ec443e..c33d2d7 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-flexbox/image-as-flexitem-size-007v.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/image-as-flexitem-size-007v.html.ini
@@ -6,3 +6,35 @@
   [.flexbox > img 4]
     expected:
       if flag_specific == "disable-layout-ng": FAIL
+
+  [.flexbox > img 11]
+    expected:
+      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+
+  [.flexbox > img 6]
+    expected:
+      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+
+  [.flexbox > img 12]
+    expected:
+      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+
+  [.flexbox > img 9]
+    expected:
+      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+
+  [.flexbox > img 7]
+    expected:
+      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+
+  [.flexbox > img 14]
+    expected:
+      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+
+  [.flexbox > img 10]
+    expected:
+      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+
+  [.flexbox > img 1]
+    expected:
+      if flag_specific == "disable-layout-ng": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/subgrid-baseline-002.html.ini b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/subgrid-baseline-002.html.ini
index 4300e380..c8f5d5e 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/subgrid-baseline-002.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/subgrid-baseline-002.html.ini
@@ -1,4 +1,2 @@
 [subgrid-baseline-002.html]
-  expected:
-    if os == "win": [TIMEOUT, CRASH]
-    CRASH
+  expected: CRASH
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial-vlr.html.ini b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial-vlr.html.ini
index 1e3e903..984123ce 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial-vlr.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial-vlr.html.ini
@@ -1,4 +1,3 @@
 [initial-letter-drop-initial-vlr.html]
   expected:
-    if (os == "linux") and (product == "content_shell") and (flag_specific == "disable-layout-ng"): FAIL
-    if (os == "linux") and (product == "chrome"): FAIL
+    if flag_specific == "disable-layout-ng": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-float-001-vlr.html.ini b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-float-001-vlr.html.ini
index bd18bc0..72b9d1f 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-float-001-vlr.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-float-001-vlr.html.ini
@@ -1,4 +1,3 @@
 [initial-letter-float-001-vlr.html]
   expected:
-    if (os == "linux") and (product == "content_shell") and (flag_specific == "disable-layout-ng"): FAIL
-    if (os == "linux") and (product == "chrome"): FAIL
+    if flag_specific == "disable-layout-ng": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-float-001-vrl.html.ini b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-float-001-vrl.html.ini
index a18c546..ff51dd5 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-float-001-vrl.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-float-001-vrl.html.ini
@@ -1,3 +1,4 @@
 [initial-letter-float-001-vrl.html]
   expected:
-    if flag_specific == "disable-layout-ng": FAIL
+    if (os == "linux") and (product == "content_shell") and (flag_specific == "disable-layout-ng"): FAIL
+    if (os == "linux") and (product == "chrome"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-float-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-float-001.html.ini
index ae13c19..4b45bbf 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-float-001.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-float-001.html.ini
@@ -1,4 +1,3 @@
 [initial-letter-float-001.html]
   expected:
-    if (os == "linux") and (product == "content_shell") and (flag_specific == "disable-layout-ng"): FAIL
-    if (os == "linux") and (product == "chrome"): FAIL
+    if flag_specific == "disable-layout-ng": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-float-004.html.ini b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-float-004.html.ini
index 4030844f..d614985 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-float-004.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-float-004.html.ini
@@ -1,3 +1,4 @@
 [initial-letter-float-004.html]
   expected:
-    if flag_specific == "disable-layout-ng": FAIL
+    if (os == "linux") and (product == "content_shell") and (flag_specific == "disable-layout-ng"): FAIL
+    if (os == "linux") and (product == "chrome"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-indentation.html.ini b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-indentation.html.ini
index fbc24c2..b504607 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-indentation.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-indentation.html.ini
@@ -1,4 +1,3 @@
 [initial-letter-indentation.html]
   expected:
-    if (product == "content_shell") and (flag_specific == "disable-layout-ng"): FAIL
-    if product == "chrome": FAIL
+    if flag_specific == "disable-layout-ng": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-layout-text-decoration-underline.html.ini b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-layout-text-decoration-underline.html.ini
index 6679ea68..7b6eb18 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-layout-text-decoration-underline.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-layout-text-decoration-underline.html.ini
@@ -1,4 +1,3 @@
 [initial-letter-layout-text-decoration-underline.html]
   expected:
-    if (os == "linux") and (product == "content_shell") and (flag_specific == "disable-layout-ng"): FAIL
-    if (os == "linux") and (product == "chrome"): FAIL
+    if flag_specific == "disable-layout-ng": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-vrl.html.ini b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-vrl.html.ini
index 1bf7046..4f49317 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-vrl.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-vrl.html.ini
@@ -1,3 +1,4 @@
 [initial-letter-raise-initial-vrl.html]
   expected:
-    if flag_specific == "disable-layout-ng": FAIL
+    if (os == "linux") and (product == "content_shell") and (flag_specific == "disable-layout-ng"): FAIL
+    if (os == "linux") and (product == "chrome"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raised-sunken-caps-raise.html.ini b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raised-sunken-caps-raise.html.ini
index 56b3ed6..20d257d 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raised-sunken-caps-raise.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raised-sunken-caps-raise.html.ini
@@ -1,3 +1,4 @@
 [initial-letter-raised-sunken-caps-raise.html]
   expected:
-    if flag_specific == "disable-layout-ng": FAIL
+    if (os == "linux") and (product == "content_shell") and (flag_specific == "disable-layout-ng"): FAIL
+    if (os == "linux") and (product == "chrome"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial-vlr.html.ini b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial-vlr.html.ini
index 82403e6..63edb9d 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial-vlr.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial-vlr.html.ini
@@ -1,4 +1,3 @@
 [initial-letter-sunk-initial-vlr.html]
   expected:
-    if (os == "linux") and (product == "content_shell") and (flag_specific == "disable-layout-ng"): FAIL
-    if (os == "linux") and (product == "chrome"): FAIL
+    if flag_specific == "disable-layout-ng": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial.html.ini b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial.html.ini
index 2a59287..25b43d78 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial.html.ini
@@ -1,3 +1,4 @@
 [initial-letter-sunk-initial.html]
   expected:
-    if flag_specific == "disable-layout-ng": FAIL
+    if (os == "linux") and (product == "content_shell") and (flag_specific == "disable-layout-ng"): FAIL
+    if (os == "linux") and (product == "chrome"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-with-first-line.html.ini b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-with-first-line.html.ini
index 7f69acb..56e94a867 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-with-first-line.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-with-first-line.html.ini
@@ -1,3 +1,4 @@
 [initial-letter-with-first-line.html]
   expected:
-    if flag_specific == "disable-layout-ng": FAIL
+    if (os == "linux") and (product == "content_shell") and (flag_specific == "disable-layout-ng"): FAIL
+    if (os == "linux") and (product == "chrome"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-layout-api/fallback-layout/constructor-error.https.html.ini b/third_party/blink/web_tests/external/wpt/css/css-layout-api/fallback-layout/constructor-error.https.html.ini
index ec85dd0..3ab53016 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-layout-api/fallback-layout/constructor-error.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-layout-api/fallback-layout/constructor-error.https.html.ini
@@ -1,3 +1,3 @@
 [constructor-error.https.html]
   expected:
-    if product == "chrome": [PASS, ERROR]
+    if product == "chrome": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/css/css-multicol/getclientrects-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-multicol/getclientrects-001.html.ini
deleted file mode 100644
index 1d32d95..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-multicol/getclientrects-001.html.ini
+++ /dev/null
@@ -1,24 +0,0 @@
-[getclientrects-001.html]
-  [horizontal-tb ltr]
-    expected:
-      if product == "chrome": FAIL
-
-  [vertical-lr ltr]
-    expected:
-      if product == "chrome": FAIL
-
-  [vertical-rl ltr]
-    expected:
-      if product == "chrome": FAIL
-
-  [horizontal-tb rtl]
-    expected:
-      if product == "chrome": FAIL
-
-  [vertical-lr rtl]
-    expected:
-      if product == "chrome": FAIL
-
-  [vertical-rl rtl]
-    expected:
-      if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollable-overflow-input-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollable-overflow-input-001.html.ini
index 6351a3d..0fd1d59 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollable-overflow-input-001.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollable-overflow-input-001.html.ini
@@ -1,3 +1,4 @@
 [scrollable-overflow-input-001.html]
   expected:
-    if flag_specific == "disable-layout-ng": FAIL
+    if (os == "linux") and (product == "content_shell") and (flag_specific == "disable-layout-ng"): FAIL
+    if (os == "linux") and (product == "chrome"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-paint-api/parse-input-arguments-022.https.html.ini b/third_party/blink/web_tests/external/wpt/css/css-paint-api/parse-input-arguments-022.https.html.ini
index 6ba66bd..a607705 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-paint-api/parse-input-arguments-022.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-paint-api/parse-input-arguments-022.https.html.ini
@@ -1,3 +1,3 @@
 [parse-input-arguments-022.https.html]
   expected:
-    if os == "win": [PASS, TIMEOUT]
+    if os == "win": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-text-combine-upright-001a.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-text-combine-upright-001a.html.ini
deleted file mode 100644
index 0df837fb..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-text-combine-upright-001a.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[ruby-text-combine-upright-001a.html]
-  expected:
-    if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-text-combine-upright-001b.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-text-combine-upright-001b.html.ini
new file mode 100644
index 0000000..654ce46
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-text-combine-upright-001b.html.ini
@@ -0,0 +1,3 @@
+[ruby-text-combine-upright-001b.html]
+  expected:
+    if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-text-combine-upright-002a.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-text-combine-upright-002a.html.ini
index 3ba2bb3b7..894ea23 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-text-combine-upright-002a.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-ruby/ruby-text-combine-upright-002a.html.ini
@@ -1,3 +1,3 @@
 [ruby-text-combine-upright-002a.html]
   expected:
-    if product == "chrome": [PASS, FAIL]
+    if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-005.html.ini b/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-005.html.ini
deleted file mode 100644
index c06d2b0..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-005.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[text-transform-capitalize-005.html]
-  expected:
-    if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-010.html.ini b/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-010.html.ini
index 892a514c..a501ea3 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-010.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-010.html.ini
@@ -1,3 +1,3 @@
 [text-transform-capitalize-010.html]
   expected:
-    if product == "chrome": FAIL
+    if (os == "linux") and (flag_specific == ""): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-014.html.ini b/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-014.html.ini
deleted file mode 100644
index f0b7504..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-014.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[text-transform-capitalize-014.html]
-  expected:
-    if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-016.html.ini b/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-016.html.ini
new file mode 100644
index 0000000..869d317
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-016.html.ini
@@ -0,0 +1,3 @@
+[text-transform-capitalize-016.html]
+  expected:
+    if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom-view/scroll-behavior-main-frame-root.html.ini b/third_party/blink/web_tests/external/wpt/css/cssom-view/scroll-behavior-main-frame-root.html.ini
index 89c7c0b..d5fe958 100644
--- a/third_party/blink/web_tests/external/wpt/css/cssom-view/scroll-behavior-main-frame-root.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/cssom-view/scroll-behavior-main-frame-root.html.ini
@@ -1,75 +1,3 @@
 [scroll-behavior-main-frame-root.html]
   [Main frame with smooth scroll-behavior ; scrollIntoView() with instant behavior]
     expected: FAIL
-
-  [Main frame with smooth scroll-behavior ; scrollTo() with smooth behavior]
-    expected:
-      if flag_specific == "disable-layout-ng": [PASS, FAIL]
-
-  [Main frame with smooth scroll-behavior ; scrollBy() with default behavior]
-    expected:
-      if flag_specific == "disable-layout-ng": [FAIL, PASS]
-
-  [Main frame with auto scroll-behavior ; scrollIntoView() with smooth behavior]
-    expected:
-      if flag_specific == "disable-layout-ng": [FAIL, PASS]
-
-  [Main frame with smooth scroll-behavior ; scroll() with smooth behavior]
-    expected:
-      if flag_specific == "disable-layout-ng": [FAIL, PASS]
-
-  [Main frame with smooth scroll-behavior ; scrollTo() with auto behavior]
-    expected:
-      if flag_specific == "disable-layout-ng": [FAIL, PASS]
-
-  [Main frame with auto scroll-behavior ; scrollBy() with smooth behavior]
-    expected:
-      if flag_specific == "disable-layout-ng": [FAIL, PASS]
-
-  [Main frame with smooth scroll-behavior ; scrollBy() with auto behavior]
-    expected:
-      if flag_specific == "disable-layout-ng": [FAIL, PASS]
-
-  [Main frame with auto scroll-behavior ; scroll() with smooth behavior]
-    expected:
-      if flag_specific == "disable-layout-ng": [FAIL, PASS]
-
-  [Main frame with smooth scroll-behavior ; scrollTo() with default behavior]
-    expected:
-      if flag_specific == "disable-layout-ng": [FAIL, PASS]
-
-  [Main frame with auto scroll-behavior ; scrollTo() with smooth behavior]
-    expected:
-      if flag_specific == "disable-layout-ng": [FAIL, PASS]
-
-  [Main frame with smooth scroll-behavior ; scroll() with default behavior]
-    expected:
-      if flag_specific == "disable-layout-ng": [FAIL, PASS]
-
-  [Main frame with smooth scroll-behavior ; scroll() with auto behavior]
-    expected:
-      if flag_specific == "disable-layout-ng": [FAIL, PASS]
-
-  [Set scrollLeft to frame with smooth scroll-behavior]
-    expected:
-      if flag_specific == "disable-layout-ng": [FAIL, PASS]
-
-  [Main frame with smooth scroll-behavior ; scrollIntoView() with auto behavior]
-    expected:
-      if flag_specific == "disable-layout-ng": [FAIL, PASS]
-
-  [Set scrollTop to frame with smooth scroll-behavior]
-    expected:
-      if flag_specific == "disable-layout-ng": [FAIL, PASS]
-
-  [Main frame with smooth scroll-behavior ; scrollBy() with smooth behavior]
-    expected:
-      if flag_specific == "disable-layout-ng": [FAIL, PASS]
-
-  [Main frame with smooth scroll-behavior ; scrollIntoView() with smooth behavior]
-    expected:
-      if flag_specific == "disable-layout-ng": FAIL
-
-  [Main frame with smooth scroll-behavior ; scrollIntoView() with default behavior]
-    expected:
-      if flag_specific == "disable-layout-ng": [FAIL, PASS]
diff --git a/third_party/blink/web_tests/external/wpt/editing/other/join-pre-and-other-block.html.ini b/third_party/blink/web_tests/external/wpt/editing/other/join-pre-and-other-block.html.ini
index 0c485cc..fad6ad23 100644
--- a/third_party/blink/web_tests/external/wpt/editing/other/join-pre-and-other-block.html.ini
+++ b/third_party/blink/web_tests/external/wpt/editing/other/join-pre-and-other-block.html.ini
@@ -38,6 +38,9 @@
 [join-pre-and-other-block.html?method=select-boundary&block=blockquote]
   expected: [OK, TIMEOUT]
   [delete at <blockquote>abc[</blockquote>\\n<pre><b>\]def<br></b>ghi</pre> (with <style>pre { white-space: pre; }</style>)]
+    expected: [PASS, NOTRUN]
+
+  [delete at <blockquote>abc[</blockquote><pre><b>\]def<br></b>ghi</pre> (with <style>pre { white-space: pre; }</style>)]
     expected: [PASS, TIMEOUT]
 
 
@@ -62,7 +65,7 @@
     expected: [PASS, NOTRUN]
 
   [forwarddelete at <blockquote>abc[\]</blockquote>\\n<pre><b>def<br></b>ghi</pre> (with <style>pre { white-space: pre; }</style>)]
-    expected: [PASS, NOTRUN]
+    expected: [PASS, TIMEOUT]
 
   [forwarddelete at <blockquote>abc[\]</blockquote><pre>\\ndef\\nghi</pre> (with <style>pre { white-space: pre; }</style>)]
     expected: [PASS, NOTRUN]
@@ -86,7 +89,7 @@
     expected: [PASS, NOTRUN]
 
   [forwarddelete at <div>abc[\]</div>\\n<pre>\\ndef\\nghi</pre> (with <style>pre { white-space: pre; }</style>)]
-    expected: [PASS, TIMEOUT]
+    expected: [PASS, NOTRUN]
 
   [forwarddelete at <div>abc[\]</div>\\n<pre><b>def\\n</b>ghi</pre> (with <style>pre { white-space: pre; }</style>)]
     expected: [PASS, NOTRUN]
@@ -98,7 +101,7 @@
     expected: [PASS, NOTRUN]
 
   [forwarddelete at <div>abc[\]</div><pre>\\ndef\\nghi</pre> (with <style>pre { white-space: pre; }</style>)]
-    expected: [PASS, NOTRUN]
+    expected: [PASS, TIMEOUT]
 
   [forwarddelete at <div>abc[\]</div>\\n<pre><b>def</b><br>ghi</pre> (with <style>pre { white-space: pre; }</style>)]
     expected: [PASS, NOTRUN]
diff --git a/third_party/blink/web_tests/external/wpt/editing/run/bold.html.ini b/third_party/blink/web_tests/external/wpt/editing/run/bold.html.ini
index dd18f2db..41bb690a 100644
--- a/third_party/blink/web_tests/external/wpt/editing/run/bold.html.ini
+++ b/third_party/blink/web_tests/external/wpt/editing/run/bold.html.ini
@@ -1463,6 +1463,8 @@
 
 
 [bold.html?3001-last]
+  expected:
+    if flag_specific == "disable-site-isolation-trials": [OK, CRASH]
   [[["stylewithcss","false"\],["bold",""\]\] "<span style=font-weight:100>fo[o</span><span style=font-weight:200>b\]ar</span>" queryCommandState("stylewithcss") after]
     expected: FAIL
 
diff --git a/third_party/blink/web_tests/external/wpt/editing/run/formatblock.html.ini b/third_party/blink/web_tests/external/wpt/editing/run/formatblock.html.ini
index 8247fe6b..cf2a6f46 100644
--- a/third_party/blink/web_tests/external/wpt/editing/run/formatblock.html.ini
+++ b/third_party/blink/web_tests/external/wpt/editing/run/formatblock.html.ini
@@ -97,6 +97,8 @@
 
 
 [formatblock.html?1001-2000]
+  expected:
+    if os == "win": [OK, CRASH]
   [[["defaultparagraphseparator","p"\],["formatblock","<div>"\]\] "<del>[foobar\]</del>" queryCommandValue("formatblock") after]
     expected: FAIL
 
@@ -685,8 +687,6 @@
 
 
 [formatblock.html?3001-4000]
-  expected:
-    if os == "win": [OK, CRASH]
   [[["defaultparagraphseparator","div"\],["formatblock","<h5>"\]\] "<p>[foobar\]</p>" queryCommandValue("formatblock") after]
     expected: FAIL
 
diff --git a/third_party/blink/web_tests/external/wpt/encoding/legacy-mb-japanese/euc-jp/eucjp-encode-href-errors-han.html.ini b/third_party/blink/web_tests/external/wpt/encoding/legacy-mb-japanese/euc-jp/eucjp-encode-href-errors-han.html.ini
index 5aa7112..de94c74 100644
--- a/third_party/blink/web_tests/external/wpt/encoding/legacy-mb-japanese/euc-jp/eucjp-encode-href-errors-han.html.ini
+++ b/third_party/blink/web_tests/external/wpt/encoding/legacy-mb-japanese/euc-jp/eucjp-encode-href-errors-han.html.ini
@@ -25,8 +25,6 @@
 [eucjp-encode-href-errors-han.html?18001-19000]
 
 [eucjp-encode-href-errors-han.html?16001-17000]
-  expected:
-    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [OK, CRASH]
 
 [eucjp-encode-href-errors-han.html?19001-20000]
 
@@ -43,3 +41,5 @@
 [eucjp-encode-href-errors-han.html?2001-3000]
 
 [eucjp-encode-href-errors-han.html?4001-5000]
+  expected:
+    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [OK, CRASH]
diff --git a/third_party/blink/web_tests/external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-decode-iso-ir-149.html.ini b/third_party/blink/web_tests/external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-decode-iso-ir-149.html.ini
index 50f8f02..4434e25 100644
--- a/third_party/blink/web_tests/external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-decode-iso-ir-149.html.ini
+++ b/third_party/blink/web_tests/external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-decode-iso-ir-149.html.ini
@@ -11,6 +11,8 @@
 [euckr-decode-iso-ir-149.html?1-1000]
 
 [euckr-decode-iso-ir-149.html?15001-16000]
+  expected:
+    if flag_specific == "disable-layout-ng": [OK, CRASH]
 
 [euckr-decode-iso-ir-149.html?1001-2000]
 
@@ -31,7 +33,5 @@
 [euckr-decode-iso-ir-149.html?11001-12000]
 
 [euckr-decode-iso-ir-149.html?7001-8000]
-  expected:
-    if flag_specific == "disable-layout-ng": [OK, CRASH]
 
 [euckr-decode-iso-ir-149.html?3001-4000]
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/basic/keepalive.html.ini b/third_party/blink/web_tests/external/wpt/fetch/api/basic/keepalive.html.ini
new file mode 100644
index 0000000..357820e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/fetch/api/basic/keepalive.html.ini
@@ -0,0 +1,4 @@
+[keepalive.html]
+  [keepalive in onunload in nested frame in another window]
+    expected:
+      if os == "win": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/fetch/metadata/generated/element-meta-refresh.https.optional.sub.html.ini b/third_party/blink/web_tests/external/wpt/fetch/metadata/generated/element-meta-refresh.https.optional.sub.html.ini
index 6594b0a..86cd06a 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/metadata/generated/element-meta-refresh.https.optional.sub.html.ini
+++ b/third_party/blink/web_tests/external/wpt/fetch/metadata/generated/element-meta-refresh.https.optional.sub.html.ini
@@ -1,3 +1,3 @@
 [element-meta-refresh.https.optional.sub.html]
   expected:
-    if os == "win": [OK, TIMEOUT]
+    if os == "win": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/fetch/metadata/generated/window-history.https.sub.html.ini b/third_party/blink/web_tests/external/wpt/fetch/metadata/generated/window-history.https.sub.html.ini
index f5c7bcb5..3905902 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/metadata/generated/window-history.https.sub.html.ini
+++ b/third_party/blink/web_tests/external/wpt/fetch/metadata/generated/window-history.https.sub.html.ini
@@ -1,3 +1,3 @@
 [window-history.https.sub.html]
   expected:
-    if (flag_specific == "") and (os == "win"): [OK, TIMEOUT]
+    if os == "win": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/service-worker-background-fetch.https.window.js.ini b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/service-worker-background-fetch.https.window.js.ini
index 82a91238..71a6082 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/service-worker-background-fetch.https.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/service-worker-background-fetch.https.window.js.ini
@@ -1,12 +1,12 @@
 [service-worker-background-fetch.https.window.html]
   [local to local: success.]
     expected:
-      if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
-      if product == "chrome": FAIL
+      if (flag_specific == "") and (os == "linux") and (product == "chrome"): FAIL
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
+      if flag_specific == "disable-site-isolation-trials": FAIL
 
   [private to local: success.]
     expected:
-      if (product == "content_shell") and (flag_specific == "") and (os == "linux"): FAIL
       if product == "chrome": FAIL
 
   [private to private: success.]
@@ -15,6 +15,8 @@
 
   [public to local: success.]
     expected:
+      if (product == "content_shell") and (flag_specific == "") and (os == "linux"): [PASS, FAIL]
+      if (product == "content_shell") and (flag_specific == "disable-layout-ng"): [PASS, FAIL]
       if product == "chrome": FAIL
 
   [public to private: success.]
diff --git a/third_party/blink/web_tests/external/wpt/fetch/stale-while-revalidate/stale-css.html.ini b/third_party/blink/web_tests/external/wpt/fetch/stale-while-revalidate/stale-css.html.ini
index 957be33..d08487a8 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/stale-while-revalidate/stale-css.html.ini
+++ b/third_party/blink/web_tests/external/wpt/fetch/stale-while-revalidate/stale-css.html.ini
@@ -1,5 +1,4 @@
 [stale-css.html]
   [Cache returns stale resource]
     expected:
-      if (flag_specific == "") and (product == "chrome"): FAIL
-      if flag_specific == "disable-layout-ng": FAIL
+      if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/focus/focus-already-focused-iframe-same-site.html.ini b/third_party/blink/web_tests/external/wpt/focus/focus-already-focused-iframe-same-site.html.ini
index cd78228..c8cb0f97 100644
--- a/third_party/blink/web_tests/external/wpt/focus/focus-already-focused-iframe-same-site.html.ini
+++ b/third_party/blink/web_tests/external/wpt/focus/focus-already-focused-iframe-same-site.html.ini
@@ -1,4 +1,4 @@
 [focus-already-focused-iframe-same-site.html]
   expected:
-    if flag_specific == "disable-site-isolation-trials": [TIMEOUT, CRASH]
+    if flag_specific == "disable-site-isolation-trials": CRASH
     TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/focus/iframe-focus-with-different-site-intermediate-frame.html.ini b/third_party/blink/web_tests/external/wpt/focus/iframe-focus-with-different-site-intermediate-frame.html.ini
index 3dbc2c45..a4e9ffe 100644
--- a/third_party/blink/web_tests/external/wpt/focus/iframe-focus-with-different-site-intermediate-frame.html.ini
+++ b/third_party/blink/web_tests/external/wpt/focus/iframe-focus-with-different-site-intermediate-frame.html.ini
@@ -1,5 +1,3 @@
 [iframe-focus-with-different-site-intermediate-frame.html]
-  expected:
-    if flag_specific == "disable-site-isolation-trials": CRASH
   [Check result]
     expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/fs/FileSystemFileHandle-create-sync-access-handle.https.tentative.window.js.ini b/third_party/blink/web_tests/external/wpt/fs/FileSystemFileHandle-create-sync-access-handle.https.tentative.window.js.ini
index b46450f..2d96c8ea 100644
--- a/third_party/blink/web_tests/external/wpt/fs/FileSystemFileHandle-create-sync-access-handle.https.tentative.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/fs/FileSystemFileHandle-create-sync-access-handle.https.tentative.window.js.ini
@@ -1,4 +1,4 @@
 [FileSystemFileHandle-create-sync-access-handle.https.tentative.window.html]
   [Attempt to create a sync access handle.]
     expected:
-      if (os == "linux") and (product == "chrome"): [PASS, FAIL]
+      if (product == "content_shell") and (flag_specific == "") and (os == "linux"): [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/html/anonymous-iframe/embedding.tentative.https.window.js.ini b/third_party/blink/web_tests/external/wpt/html/anonymous-iframe/embedding.tentative.https.window.js.ini
index 5600c7c8..c0c94b2 100644
--- a/third_party/blink/web_tests/external/wpt/html/anonymous-iframe/embedding.tentative.https.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/html/anonymous-iframe/embedding.tentative.https.window.js.ini
@@ -17,6 +17,8 @@
     if product == "chrome": ERROR
 
 [embedding.tentative.https.window.html?11-11]
+  expected:
+    if product == "chrome": [OK, ERROR]
 
 [embedding.tentative.https.window.html?5-5]
 
@@ -27,8 +29,6 @@
 [embedding.tentative.https.window.html?7-7]
 
 [embedding.tentative.https.window.html?10-10]
-  expected:
-    if product == "chrome": [OK, ERROR]
 
 [embedding.tentative.https.window.html?2-2]
 
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/eligibility/broadcast-channel.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/eligibility/broadcast-channel.html.ini
index d597d3d..7d0aa084 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/eligibility/broadcast-channel.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/eligibility/broadcast-channel.html.ini
@@ -4,5 +4,4 @@
 
   [Eligibility (BroadcastChannel closed in the pagehide event)]
     expected:
-      if (os == "linux") and (product == "chrome"): PRECONDITION_FAILED
-      if os == "win": PRECONDITION_FAILED
+      if product == "chrome": PRECONDITION_FAILED
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/event-order/before-load-hash.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/event-order/before-load-hash.html.ini
index 66dd895..07db753 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/event-order/before-load-hash.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/event-order/before-load-hash.html.ini
@@ -1,4 +1,5 @@
 [before-load-hash.html]
   [when changing hash, before load]
     expected:
-      if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [FAIL, PASS]
+      if (flag_specific == "") and (os == "linux") and (product == "chrome"): [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/overlapping-navigations-and-traversals/same-document-traversal-cross-document-traversal.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/overlapping-navigations-and-traversals/same-document-traversal-cross-document-traversal.html.ini
index b5b7f69..71dab1d 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/overlapping-navigations-and-traversals/same-document-traversal-cross-document-traversal.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/overlapping-navigations-and-traversals/same-document-traversal-cross-document-traversal.html.ini
@@ -1,7 +1,6 @@
 [same-document-traversal-cross-document-traversal.html]
   expected:
-    if (flag_specific == "") and (os == "win"): [OK, TIMEOUT]
-    if flag_specific == "disable-layout-ng": TIMEOUT
+    if (os == "linux") and (flag_specific == "") and (product == "content_shell"): [OK, TIMEOUT]
   [traversals in the same (back) direction: queued up]
     expected: [PASS, TIMEOUT]
 
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/history/the-history-interface/combination_history_006.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/history/the-history-interface/combination_history_006.html.ini
index a339e37..9a7593e 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/history/the-history-interface/combination_history_006.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/history/the-history-interface/combination_history_006.html.ini
@@ -1,3 +1,3 @@
 [combination_history_006.html]
   expected:
-    if os == "win": [OK, TIMEOUT]
+    if os == "win": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/history/the-history-interface/history_back_cross_realm_method.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/history/the-history-interface/history_back_cross_realm_method.html.ini
deleted file mode 100644
index 036c330b..0000000
--- a/third_party/blink/web_tests/external/wpt/html/browsers/history/the-history-interface/history_back_cross_realm_method.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[history_back_cross_realm_method.html]
-  expected:
-    if flag_specific == "disable-layout-ng": CRASH
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/history/the-history-interface/traverse_the_history_4.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/history/the-history-interface/traverse_the_history_4.html.ini
index 8df09c0..a3d5fd9 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/history/the-history-interface/traverse_the_history_4.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/history/the-history-interface/traverse_the_history_4.html.ini
@@ -1,4 +1,4 @@
 [traverse_the_history_4.html]
   [Multiple history traversals, last would be aborted]
     expected:
-      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+      if (flag_specific == "") and (os == "win"): [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken.html.ini
index fc6898e6..31f51cf4 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/history/the-location-interface/location-protocol-setter-non-broken.html.ini
@@ -4,5 +4,5 @@
 
   [Set data URL frame location.protocol to data]
     expected:
-      if (flag_specific == "") and (product == "content_shell"): PASS
+      if flag_specific == "disable-layout-ng": PASS
       FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/1-iframe/parent-yes-child-no-port.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/1-iframe/parent-yes-child-no-port.sub.https.html.ini
index 5504eb1..f5c78443 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/1-iframe/parent-yes-child-no-port.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/1-iframe/parent-yes-child-no-port.sub.https.html.ini
@@ -1,8 +1,10 @@
 [parent-yes-child-no-port.sub.https.html]
   [setting document.domain must not give sync access]
     expected:
+      if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
       if product == "chrome": FAIL
 
   [parent: originAgentCluster must equal true]
     expected:
+      if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
       if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/1-iframe/parent-yes-child-no-same.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/1-iframe/parent-yes-child-no-same.sub.https.html.ini
index 2066f0aa..c5662b4 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/1-iframe/parent-yes-child-no-same.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/1-iframe/parent-yes-child-no-same.sub.https.html.ini
@@ -1,8 +1,10 @@
 [parent-yes-child-no-same.sub.https.html]
   [parent: originAgentCluster must equal true]
     expected:
+      if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
       if product == "chrome": FAIL
 
   [child: originAgentCluster must equal true]
     expected:
+      if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
       if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/1-iframe/parent-yes-child-no-subdomain.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/1-iframe/parent-yes-child-no-subdomain.sub.https.html.ini
index 61e0306..88fd82f 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/1-iframe/parent-yes-child-no-subdomain.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/1-iframe/parent-yes-child-no-subdomain.sub.https.html.ini
@@ -1,11 +1,11 @@
 [parent-yes-child-no-subdomain.sub.https.html]
   [setting document.domain must not give sync access]
     expected:
-      if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
-      if product == "chrome": FAIL
+      if (flag_specific == "") and (product == "chrome"): FAIL
+      if flag_specific == "disable-site-isolation-trials": FAIL
 
   [parent: originAgentCluster must equal true]
     expected:
       if (flag_specific == "") and (product == "chrome"): FAIL
-      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+      if flag_specific == "disable-site-isolation-trials": FAIL
       if flag_specific == "disable-layout-ng": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/1-iframe/parent-yes-child-yes-port.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/1-iframe/parent-yes-child-yes-port.sub.https.html.ini
index 5f428d85c..2c3782b 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/1-iframe/parent-yes-child-yes-port.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/1-iframe/parent-yes-child-yes-port.sub.https.html.ini
@@ -1,5 +1,5 @@
 [parent-yes-child-yes-port.sub.https.html]
   [parent: originAgentCluster must equal true]
     expected:
-      if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
-      if product == "chrome": FAIL
+      if (flag_specific == "") and (product == "chrome"): FAIL
+      if flag_specific == "disable-site-isolation-trials": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/1-iframe/parent-yes-child-yes-subdomain.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/1-iframe/parent-yes-child-yes-subdomain.sub.https.html.ini
index bd62a14..7d1f8d71 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/1-iframe/parent-yes-child-yes-subdomain.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/1-iframe/parent-yes-child-yes-subdomain.sub.https.html.ini
@@ -1,6 +1,13 @@
 [parent-yes-child-yes-subdomain.sub.https.html]
-  expected:
-    if flag_specific == "disable-site-isolation-trials": [OK, CRASH]
   [parent: originAgentCluster must equal true]
     expected:
+      if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
       if product == "chrome": FAIL
+
+  [child: originAgentCluster must equal true]
+    expected:
+      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+
+  [setting document.domain must not give sync access]
+    expected:
+      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-no-child1-no-subdomain1-child2-yes-subdomain2.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-no-child1-no-subdomain1-child2-yes-subdomain2.sub.https.html.ini
index ff06302c..8d6437a 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-no-child1-no-subdomain1-child2-yes-subdomain2.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-no-child1-no-subdomain1-child2-yes-subdomain2.sub.https.html.ini
@@ -2,8 +2,5 @@
   [Parent to child1: setting document.domain must give sync access]
     expected:
       if (flag_specific == "") and (product == "chrome"): PASS
+      if flag_specific == "disable-site-isolation-trials": PASS
       FAIL
-
-  [parent: originAgentCluster must equal false]
-    expected:
-      if flag_specific == "disable-site-isolation-trials": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-no-child1-yes-subdomain-child2-no-port.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-no-child1-yes-subdomain-child2-no-port.sub.https.html.ini
index 677d865..8b8493d 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-no-child1-yes-subdomain-child2-no-port.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-no-child1-yes-subdomain-child2-no-port.sub.https.html.ini
@@ -1,22 +1,4 @@
 [parent-no-child1-yes-subdomain-child2-no-port.sub.https.html]
   [child1: originAgentCluster must equal true]
     expected:
-      if (flag_specific == "") and (product == "chrome"): PASS
-      if flag_specific == "disable-layout-ng": PASS
-      FAIL
-
-  [child2 to child1: setting document.domain must not give sync access]
-    expected:
-      if flag_specific == "disable-site-isolation-trials": FAIL
-
-  [child1 to child2: setting document.domain must not give sync access]
-    expected:
-      if flag_specific == "disable-site-isolation-trials": FAIL
-
-  [parent: originAgentCluster must equal false]
-    expected:
-      if flag_specific == "disable-site-isolation-trials": FAIL
-
-  [Parent to child2: setting document.domain must give sync access]
-    expected:
-      if flag_specific == "disable-site-isolation-trials": FAIL
+      if (flag_specific == "") and (product == "content_shell"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-no-child1-yes-subdomain-child2-no-subdomain.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-no-child1-yes-subdomain-child2-no-subdomain.sub.https.html.ini
index 2a0462e..2ae4867 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-no-child1-yes-subdomain-child2-no-subdomain.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-no-child1-yes-subdomain-child2-no-subdomain.sub.https.html.ini
@@ -1,16 +1,16 @@
 [parent-no-child1-yes-subdomain-child2-no-subdomain.sub.https.html]
   [Parent to child1: setting document.domain must not give sync access]
     expected:
-      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+      if flag_specific == "disable-site-isolation-trials": FAIL
 
   [Parent to child2: setting document.domain must not give sync access]
     expected:
-      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+      if flag_specific == "disable-site-isolation-trials": FAIL
 
   [child1: originAgentCluster must equal true]
     expected:
-      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+      if flag_specific == "disable-site-isolation-trials": FAIL
 
   [child2: originAgentCluster must equal true]
     expected:
-      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+      if flag_specific == "disable-site-isolation-trials": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-yes-child1-no-subdomain-child2-no-subdomain.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-yes-child1-no-subdomain-child2-no-subdomain.sub.https.html.ini
index 19af2dda..a6a8b30 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-yes-child1-no-subdomain-child2-no-subdomain.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-yes-child1-no-subdomain-child2-no-subdomain.sub.https.html.ini
@@ -1,23 +1,15 @@
 [parent-yes-child1-no-subdomain-child2-no-subdomain.sub.https.html]
   [Parent to child1: setting document.domain must not give sync access]
     expected:
-      if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
-      if product == "chrome": FAIL
+      if (flag_specific == "") and (product == "chrome"): FAIL
+      if flag_specific == "disable-site-isolation-trials": FAIL
 
   [Parent to child2: setting document.domain must not give sync access]
     expected:
-      if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
-      if product == "chrome": FAIL
+      if (flag_specific == "") and (product == "chrome"): FAIL
+      if flag_specific == "disable-site-isolation-trials": FAIL
 
   [parent: originAgentCluster must equal true]
     expected:
-      if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
-      if product == "chrome": FAIL
-
-  [child2: originAgentCluster must equal false]
-    expected:
-      if flag_specific == "disable-layout-ng": FAIL
-
-  [child1: originAgentCluster must equal false]
-    expected:
-      if flag_specific == "disable-layout-ng": FAIL
+      if (flag_specific == "") and (product == "chrome"): FAIL
+      if flag_specific == "disable-site-isolation-trials": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-yes-child1-no-subdomain-child2-no-subdomain2.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-yes-child1-no-subdomain-child2-no-subdomain2.sub.https.html.ini
index 8f4b5ee..5671887b 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-yes-child1-no-subdomain-child2-no-subdomain2.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-yes-child1-no-subdomain-child2-no-subdomain2.sub.https.html.ini
@@ -13,12 +13,15 @@
 
   [parent: originAgentCluster must equal true]
     expected:
+      if (flag_specific == "") and (product == "chrome"): FAIL
       if flag_specific == "disable-site-isolation-trials": FAIL
 
   [Parent to child1: setting document.domain must not give sync access]
     expected:
+      if (flag_specific == "") and (product == "chrome"): FAIL
       if flag_specific == "disable-site-isolation-trials": FAIL
 
   [Parent to child2: setting document.domain must not give sync access]
     expected:
+      if (flag_specific == "") and (product == "chrome"): FAIL
       if flag_specific == "disable-site-isolation-trials": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-yes-child1-no-subdomain-child2-yes-subdomainport.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-yes-child1-no-subdomain-child2-yes-subdomainport.sub.https.html.ini
index 7ba4e73..ce25982 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-yes-child1-no-subdomain-child2-yes-subdomainport.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-yes-child1-no-subdomain-child2-yes-subdomainport.sub.https.html.ini
@@ -6,7 +6,3 @@
   [parent: originAgentCluster must equal true]
     expected:
       if product == "chrome": FAIL
-
-  [child1: originAgentCluster must equal false]
-    expected:
-      if flag_specific == "disable-site-isolation-trials": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-yes-child1-yes-subdomain-child2-no-port.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-yes-child1-yes-subdomain-child2-no-port.sub.https.html.ini
index c9174382..d9ff6bd 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-yes-child1-yes-subdomain-child2-no-port.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-yes-child1-yes-subdomain-child2-no-port.sub.https.html.ini
@@ -1,26 +1,26 @@
 [parent-yes-child1-yes-subdomain-child2-no-port.sub.https.html]
   [Parent to child2: setting document.domain must not give sync access]
     expected:
-      if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
-      if product == "chrome": FAIL
+      if (flag_specific == "") and (product == "chrome"): FAIL
+      if flag_specific == "disable-site-isolation-trials": FAIL
 
   [parent: originAgentCluster must equal true]
     expected:
-      if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
-      if product == "chrome": FAIL
+      if (flag_specific == "") and (product == "chrome"): FAIL
+      if flag_specific == "disable-site-isolation-trials": FAIL
 
   [Parent to child1: setting document.domain must not give sync access]
     expected:
-      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+      if flag_specific == "disable-site-isolation-trials": FAIL
 
   [child1: originAgentCluster must equal true]
     expected:
-      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+      if flag_specific == "disable-site-isolation-trials": FAIL
 
   [child2 to child1: setting document.domain must not give sync access]
     expected:
-      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+      if flag_specific == "disable-site-isolation-trials": FAIL
 
   [child1 to child2: setting document.domain must not give sync access]
     expected:
-      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+      if flag_specific == "disable-site-isolation-trials": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-yes-child1-yes-subdomain-child2-no-subdomain.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-yes-child1-yes-subdomain-child2-no-subdomain.sub.https.html.ini
index bb8a3cbb..ce7dbbf 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-yes-child1-yes-subdomain-child2-no-subdomain.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-yes-child1-yes-subdomain-child2-no-subdomain.sub.https.html.ini
@@ -1,12 +1,23 @@
 [parent-yes-child1-yes-subdomain-child2-no-subdomain.sub.https.html]
   [parent: originAgentCluster must equal true]
     expected:
+      if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
       if product == "chrome": FAIL
 
   [child1: originAgentCluster must equal true]
     expected:
+      if (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
       if os == "win": FAIL
 
   [child2: originAgentCluster must equal true]
     expected:
+      if (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
       if os == "win": FAIL
+
+  [Parent to child2: setting document.domain must not give sync access]
+    expected:
+      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+
+  [Parent to child1: setting document.domain must not give sync access]
+    expected:
+      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-yes-child1-yes-subdomain-child2-yes-subdomain2.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-yes-child1-yes-subdomain-child2-yes-subdomain2.sub.https.html.ini
index 1702c50..cdeff1ef 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-yes-child1-yes-subdomain-child2-yes-subdomain2.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-yes-child1-yes-subdomain-child2-yes-subdomain2.sub.https.html.ini
@@ -14,3 +14,15 @@
   [child2: originAgentCluster must equal true]
     expected:
       if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+
+  [Parent to child2: setting document.domain must not give sync access]
+    expected:
+      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+
+  [Parent to child1: setting document.domain must not give sync access]
+    expected:
+      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+
+  [parent: originAgentCluster must equal true]
+    expected:
+      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-yes-child1-yes-subdomain-child2-yes-subdomainport.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-yes-child1-yes-subdomain-child2-yes-subdomainport.sub.https.html.ini
index e3b0508..0572921 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-yes-child1-yes-subdomain-child2-yes-subdomainport.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-yes-child1-yes-subdomain-child2-yes-subdomainport.sub.https.html.ini
@@ -1,6 +1,7 @@
 [parent-yes-child1-yes-subdomain-child2-yes-subdomainport.sub.https.html]
   [parent: originAgentCluster must equal true]
     expected:
+      if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
       if product == "chrome": FAIL
 
   [child1: originAgentCluster must equal true]
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/getter-special-cases/javascript-url-yes.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/getter-special-cases/javascript-url-yes.https.html.ini
index 189de04..300ae43 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/getter-special-cases/javascript-url-yes.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/getter-special-cases/javascript-url-yes.https.html.ini
@@ -1,3 +1,3 @@
 [javascript-url-yes.https.html]
   expected:
-    if flag_specific == "disable-site-isolation-trials": [OK, CRASH]
+    if flag_specific == "disable-site-isolation-trials": CRASH
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/getter-special-cases/sandboxed-same-origin-iframe-yes.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/getter-special-cases/sandboxed-same-origin-iframe-yes.https.html.ini
index e6f5815..71f8030 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/getter-special-cases/sandboxed-same-origin-iframe-yes.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/getter-special-cases/sandboxed-same-origin-iframe-yes.https.html.ini
@@ -1,5 +1,5 @@
 [sandboxed-same-origin-iframe-yes.https.html]
   [originAgentCluster must equal true]
     expected:
-      if (flag_specific == "") and (product == "chrome"): FAIL
-      if flag_specific == "disable-site-isolation-trials": FAIL
+      if (product == "content_shell") and (flag_specific == "") and (os == "linux"): [PASS, FAIL]
+      if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-no-1-no-same-2-yes-port.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-no-1-no-same-2-yes-port.sub.https.html.ini
index c8482cb..7dd4eac 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-no-1-no-same-2-yes-port.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-no-1-no-same-2-yes-port.sub.https.html.ini
@@ -1,12 +1,12 @@
 [parent-no-1-no-same-2-yes-port.sub.https.html]
   [before parent: originAgentCluster must equal false]
     expected:
-      if os == "win": FAIL
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
 
   [before child: originAgentCluster must equal false]
     expected:
-      if os == "win": FAIL
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
 
   [after parent: originAgentCluster must equal false]
     expected:
-      if os == "win": FAIL
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-no-1-no-same-2-yes-subdomain.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-no-1-no-same-2-yes-subdomain.sub.https.html.ini
index 7d0cf3b..1600e6f 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-no-1-no-same-2-yes-subdomain.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-no-1-no-same-2-yes-subdomain.sub.https.html.ini
@@ -1,24 +1,18 @@
 [parent-no-1-no-same-2-yes-subdomain.sub.https.html]
   [before parent: originAgentCluster must equal false]
     expected:
-      if (os == "linux") and (flag_specific == "disable-layout-ng"): [PASS, FAIL]
-      if os == "win": FAIL
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
+      if (flag_specific == "") and (os == "win"): FAIL
+      if flag_specific == "disable-layout-ng": FAIL
 
   [before child: originAgentCluster must equal false]
     expected:
-      if (os == "linux") and (flag_specific == "disable-layout-ng"): [PASS, FAIL]
-      if os == "win": FAIL
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
+      if (flag_specific == "") and (os == "win"): FAIL
+      if flag_specific == "disable-layout-ng": FAIL
 
   [after parent: originAgentCluster must equal false]
     expected:
-      if (os == "linux") and (flag_specific == "disable-layout-ng"): [PASS, FAIL]
-      if os == "win": FAIL
-
-  [after child: originAgentCluster must equal true]
-    expected:
-      if flag_specific == "disable-layout-ng": [PASS, FAIL]
-      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
-
-  [After: parent to child: setting document.domain must not give sync access]
-    expected:
-      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
+      if (flag_specific == "") and (os == "win"): FAIL
+      if flag_specific == "disable-layout-ng": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-no-1-no-subdomain-2-yes-subdomain.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-no-1-no-subdomain-2-yes-subdomain.sub.https.html.ini
index f45685b..eae6fc7f 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-no-1-no-subdomain-2-yes-subdomain.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-no-1-no-subdomain-2-yes-subdomain.sub.https.html.ini
@@ -1,24 +1,24 @@
 [parent-no-1-no-subdomain-2-yes-subdomain.sub.https.html]
   [Before: parent to child: setting document.domain must give sync access]
     expected:
-      if (flag_specific == "") and (product == "chrome"): PASS
-      if flag_specific == "disable-site-isolation-trials": PASS
+      if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
+      if product == "chrome": PASS
       FAIL
 
   [After: parent to child: setting document.domain must give sync access]
     expected:
-      if (flag_specific == "") and (product == "chrome"): PASS
-      if flag_specific == "disable-site-isolation-trials": PASS
+      if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
+      if product == "chrome": PASS
       FAIL
 
   [before parent: originAgentCluster must equal false]
     expected:
-      if (os == "linux") and (flag_specific == "") and (product == "content_shell"): [PASS, FAIL]
-      if (os == "linux") and (flag_specific == "disable-layout-ng"): [PASS, FAIL]
-      if os == "win": FAIL
+      if (flag_specific == "") and (os == "linux") and (product == "chrome"): PASS
+      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+      FAIL
 
   [after parent: originAgentCluster must equal false]
     expected:
-      if (os == "linux") and (flag_specific == "") and (product == "content_shell"): [PASS, FAIL]
-      if (os == "linux") and (flag_specific == "disable-layout-ng"): [PASS, FAIL]
-      if os == "win": FAIL
+      if (flag_specific == "") and (os == "linux") and (product == "chrome"): PASS
+      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+      FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-no-1-no-subdomain-2-yes-subdomain2.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-no-1-no-subdomain-2-yes-subdomain2.sub.https.html.ini
index 346f1ce..16816d4 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-no-1-no-subdomain-2-yes-subdomain2.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-no-1-no-subdomain-2-yes-subdomain2.sub.https.html.ini
@@ -1,8 +1,8 @@
 [parent-no-1-no-subdomain-2-yes-subdomain2.sub.https.html]
   [Before: parent to child: setting document.domain must give sync access]
     expected:
-      if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
-      if product == "chrome": PASS
+      if (flag_specific == "") and (product == "chrome"): PASS
+      if flag_specific == "disable-site-isolation-trials": PASS
       FAIL
 
   [before child: originAgentCluster must equal false]
@@ -11,10 +11,16 @@
 
   [before parent: originAgentCluster must equal false]
     expected:
-      if (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
-      if os == "win": FAIL
+      if (flag_specific == "") and (os == "win"): FAIL
 
   [after parent: originAgentCluster must equal false]
     expected:
-      if (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
-      if os == "win": FAIL
+      if (flag_specific == "") and (os == "win"): FAIL
+
+  [After: parent to child: setting document.domain must not give sync access]
+    expected:
+      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+
+  [after child: originAgentCluster must equal true]
+    expected:
+      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-no-1-subdomain-yes-2-subdomain2-no.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-no-1-subdomain-yes-2-subdomain2-no.sub.https.html.ini
index 419e0edd..fdcb26e 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-no-1-subdomain-yes-2-subdomain2-no.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-no-1-subdomain-yes-2-subdomain2-no.sub.https.html.ini
@@ -2,12 +2,13 @@
   [After: parent to child: setting document.domain must give sync access]
     expected:
       if (flag_specific == "") and (product == "chrome"): PASS
+      if flag_specific == "disable-site-isolation-trials": PASS
       FAIL
 
   [before parent: originAgentCluster must equal false]
     expected:
-      if flag_specific == "disable-site-isolation-trials": FAIL
+      if flag_specific == "disable-layout-ng": [PASS, FAIL]
 
   [after parent: originAgentCluster must equal false]
     expected:
-      if flag_specific == "disable-site-isolation-trials": FAIL
+      if flag_specific == "disable-layout-ng": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-no-1-yes-subdomain-2-no-subdomain.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-no-1-yes-subdomain-2-no-subdomain.sub.https.html.ini
index 65c3674..aa701df 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-no-1-yes-subdomain-2-no-subdomain.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-no-1-yes-subdomain-2-no-subdomain.sub.https.html.ini
@@ -1,20 +1,18 @@
 [parent-no-1-yes-subdomain-2-no-subdomain.sub.https.html]
   [before parent: originAgentCluster must equal false]
     expected:
-      if (os == "linux") and (flag_specific == "") and (product == "content_shell"): [PASS, FAIL]
-      if (os == "linux") and (flag_specific == "disable-layout-ng"): FAIL
+      if (os == "linux") and (flag_specific == "") and (product == "content_shell"): FAIL
+      if os == "win": [PASS, FAIL]
 
   [before child: originAgentCluster must equal true]
     expected:
-      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
-      if flag_specific == "disable-layout-ng": FAIL
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): FAIL
 
   [after parent: originAgentCluster must equal false]
     expected:
-      if (os == "linux") and (flag_specific == "") and (product == "content_shell"): [PASS, FAIL]
-      if (os == "linux") and (flag_specific == "disable-layout-ng"): FAIL
+      if (os == "linux") and (flag_specific == "") and (product == "content_shell"): FAIL
+      if os == "win": [PASS, FAIL]
 
   [after child: originAgentCluster must equal true]
     expected:
-      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
-      if flag_specific == "disable-layout-ng": FAIL
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-yes-1-no-same-2-no-port.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-yes-1-no-same-2-no-port.sub.https.html.ini
index 62a430f5..bf08842 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-yes-1-no-same-2-no-port.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-yes-1-no-same-2-no-port.sub.https.html.ini
@@ -1,13 +1,13 @@
 [parent-yes-1-no-same-2-no-port.sub.https.html]
   [before parent: originAgentCluster must equal true]
     expected:
-      if (flag_specific == "") and (product == "chrome"): FAIL
-      if flag_specific == "disable-layout-ng": FAIL
+      if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
+      if product == "chrome": FAIL
 
   [before child: originAgentCluster must equal true]
     expected:
-      if (flag_specific == "") and (product == "chrome"): FAIL
-      if flag_specific == "disable-layout-ng": FAIL
+      if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
+      if product == "chrome": FAIL
 
   [After: parent to child: setting document.domain must not give sync access]
     expected:
@@ -15,9 +15,9 @@
 
   [after parent: originAgentCluster must equal true]
     expected:
-      if (flag_specific == "") and (product == "chrome"): FAIL
-      if flag_specific == "disable-layout-ng": FAIL
+      if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
+      if product == "chrome": FAIL
 
   [after child: originAgentCluster must equal false]
     expected:
-      if flag_specific == "disable-layout-ng": FAIL
+      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-yes-1-no-same-2-no-subdomain.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-yes-1-no-same-2-no-subdomain.sub.https.html.ini
index 0727d38..844f2b1b 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-yes-1-no-same-2-no-subdomain.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/iframe-navigation/parent-yes-1-no-same-2-no-subdomain.sub.https.html.ini
@@ -1,17 +1,19 @@
 [parent-yes-1-no-same-2-no-subdomain.sub.https.html]
   [before parent: originAgentCluster must equal true]
     expected:
-      if os == "win": FAIL
+      if (flag_specific == "") and (os == "linux") and (product == "chrome"): FAIL
+      if (flag_specific == "") and (os == "win"): FAIL
 
   [after parent: originAgentCluster must equal true]
     expected:
-      if os == "win": FAIL
+      if (flag_specific == "") and (os == "linux") and (product == "chrome"): FAIL
+      if (flag_specific == "") and (os == "win"): FAIL
 
   [before child: originAgentCluster must equal true]
     expected:
-      if os == "win": FAIL
+      if (flag_specific == "") and (os == "linux") and (product == "chrome"): FAIL
+      if (flag_specific == "") and (os == "win"): FAIL
 
-  [after child: originAgentCluster must equal false]
+  [After: parent to child: setting document.domain must not give sync access]
     expected:
-      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): FAIL
-      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+      if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-no-openee-yes-same.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-no-openee-yes-same.sub.https.html.ini
deleted file mode 100644
index 6f746fe6..0000000
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-no-openee-yes-same.sub.https.html.ini
+++ /dev/null
@@ -1,10 +0,0 @@
-[opener-no-openee-yes-same.sub.https.html]
-  [opener: originAgentCluster must equal false]
-    expected:
-      if flag_specific == "disable-layout-ng": FAIL
-      if flag_specific == "disable-site-isolation-trials": FAIL
-
-  [openee: originAgentCluster must equal false]
-    expected:
-      if flag_specific == "disable-site-isolation-trials": FAIL
-      if flag_specific == "disable-layout-ng": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-no-openee-yes-subdomain.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-no-openee-yes-subdomain.sub.https.html.ini
index a13be28..afa51c3 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-no-openee-yes-subdomain.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-no-openee-yes-subdomain.sub.https.html.ini
@@ -1,10 +1,4 @@
 [opener-no-openee-yes-subdomain.sub.https.html]
   [opener: originAgentCluster must equal false]
     expected:
-      if (flag_specific == "") and (os == "win"): FAIL
       if flag_specific == "disable-layout-ng": FAIL
-      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
-
-  [openee: originAgentCluster must equal true]
-    expected:
-      if os == "win": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-yes-openee-no-port.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-yes-openee-no-port.sub.https.html.ini
index ee2567b..1ddca58 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-yes-openee-no-port.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-yes-openee-no-port.sub.https.html.ini
@@ -1,8 +1,8 @@
 [opener-yes-openee-no-port.sub.https.html]
   [setting document.domain must not give sync access]
     expected:
-      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
 
   [opener: originAgentCluster must equal true]
     expected:
-      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-yes-openee-no-subdomain.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-yes-openee-no-subdomain.sub.https.html.ini
index 8dfaf021..83fcc1f 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-yes-openee-no-subdomain.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-yes-openee-no-subdomain.sub.https.html.ini
@@ -9,4 +9,4 @@
 
   [openee: originAgentCluster must equal false]
     expected:
-      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
+      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-yes-openee-yes-same.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-yes-openee-yes-same.sub.https.html.ini
index b6a9865..851a368 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-yes-openee-yes-same.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-yes-openee-yes-same.sub.https.html.ini
@@ -1,10 +1,10 @@
 [opener-yes-openee-yes-same.sub.https.html]
   [opener: originAgentCluster must equal true]
     expected:
-      if (product == "content_shell") and (flag_specific == "") and (os == "linux"): [PASS, FAIL]
+      if (product == "content_shell") and (flag_specific == "") and (os == "linux"): FAIL
       if product == "chrome": FAIL
 
   [openee: originAgentCluster must equal true]
     expected:
-      if (product == "content_shell") and (flag_specific == "") and (os == "linux"): [PASS, FAIL]
+      if (product == "content_shell") and (flag_specific == "") and (os == "linux"): FAIL
       if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-yes-openee-yes-subdomain.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-yes-openee-yes-subdomain.sub.https.html.ini
index d6b4f05..42f89ad 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-yes-openee-yes-subdomain.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-yes-openee-yes-subdomain.sub.https.html.ini
@@ -5,4 +5,4 @@
 
   [opener: originAgentCluster must equal true]
     expected:
-      if product == "chrome": FAIL
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/removing-iframes.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/removing-iframes.sub.https.html.ini
index cb65787..d943b31 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/removing-iframes.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/removing-iframes.sub.https.html.ini
@@ -13,20 +13,16 @@
 
   [Before: setting document.domain must not give sync access]
     expected:
-      if (flag_specific == "") and (product == "chrome"): FAIL
       if flag_specific == "disable-site-isolation-trials": FAIL
 
   [parent: originAgentCluster must equal true]
     expected:
-      if (flag_specific == "") and (product == "chrome"): FAIL
       if flag_specific == "disable-site-isolation-trials": FAIL
 
   [Parent to child2: setting document.domain must not give sync access]
     expected:
-      if (flag_specific == "") and (product == "chrome"): FAIL
       if flag_specific == "disable-site-isolation-trials": FAIL
 
   [Parent to child3: setting document.domain must not give sync access]
     expected:
-      if (flag_specific == "") and (product == "chrome"): FAIL
       if flag_specific == "disable-site-isolation-trials": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/open-close/open-features-is-popup-condition.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/open-close/open-features-is-popup-condition.html.ini
new file mode 100644
index 0000000..05409ba
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/open-close/open-features-is-popup-condition.html.ini
@@ -0,0 +1,9 @@
+[open-features-is-popup-condition.html?single-2]
+
+[open-features-is-popup-condition.html?position]
+
+[open-features-is-popup-condition.html?single-1]
+  expected:
+    if product == "chrome": [TIMEOUT, ERROR]
+
+[open-features-is-popup-condition.html?combination]
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/open-close/open-features-tokenization-width-height.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/open-close/open-features-tokenization-width-height.html.ini
deleted file mode 100644
index 25200b9..0000000
--- a/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/open-close/open-features-tokenization-width-height.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[open-features-tokenization-width-height.html]
-  expected:
-    if product == "chrome": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-video.html.ini b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-video.html.ini
index d709e575..4900e47 100644
--- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-video.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-ImageBitmap-video.html.ini
@@ -65,6 +65,6 @@
   [Rec2020-222000000, Context display-p3, ImageData display-p3, cropSource=true]
     expected: FAIL
 
-  [sRGB-FF0100, Context srgb, ImageData display-p3, cropSource=true]
+  [sRGB-BB0000, Context srgb, ImageData display-p3, cropSource=false]
     expected:
-      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+      if flag_specific == "disable-layout-ng": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.animated.poster.html.ini b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.animated.poster.html.ini
deleted file mode 100644
index 55cf49a5..0000000
--- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.animated.poster.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[2d.drawImage.animated.poster.html]
-  expected:
-    if product == "chrome": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.resize.html.ini b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.resize.html.ini
index 04ad5a0..fd91f0f 100644
--- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.resize.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.resize.html.ini
@@ -1,15 +1,15 @@
 [offscreencanvas.resize.html]
   [Verify that resizing an OffscreenCanvas with a webgl context propagates the new size to its placeholder canvas asynchronously.]
     expected:
-      if (flag_specific == "") and (product == "content_shell") and (os == "linux"): [FAIL, PASS]
-      if (flag_specific == "") and (product == "content_shell") and (os == "win"): [PASS, FAIL]
-      if (flag_specific == "") and (product == "chrome"): FAIL
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): FAIL
+      if (flag_specific == "") and (os == "linux") and (product == "chrome"): FAIL
+      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
 
   [Verify that drawImage uses the size of the frame as the intinsic size of a placeholder canvas.]
     expected:
-      if (flag_specific == "") and (os == "linux"): FAIL
-      if flag_specific == "disable-site-isolation-trials": PASS
-      [FAIL, PASS]
+      if (flag_specific == "") and (os == "win"): PASS
+      if flag_specific == "disable-site-isolation-trials": [FAIL, PASS]
+      FAIL
 
   [Verify that resizing an OffscreenCanvas with a 2d context propagates the new size to its placeholder canvas asynchronously.]
     expected:
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/credentialless/dedicated-worker.https.window.js.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/credentialless/dedicated-worker.https.window.js.ini
index 47f8c95..e304d0e0 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/credentialless/dedicated-worker.https.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/credentialless/dedicated-worker.https.window.js.ini
@@ -1,5 +1,3 @@
 [dedicated-worker.https.window.html]
-  expected:
-    if product == "chrome": ERROR
   [fetch cross-origin + credentialless worker]
     expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/credentialless/reporting-subresource-corp.https.window.js.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/credentialless/reporting-subresource-corp.https.window.js.ini
index 6b20286..dc3970d 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/credentialless/reporting-subresource-corp.https.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/credentialless/reporting-subresource-corp.https.window.js.ini
@@ -1,3 +1,3 @@
 [reporting-subresource-corp.https.window.html]
   expected:
-    if flag_specific == "disable-layout-ng": [OK, TIMEOUT]
+    if flag_specific == "disable-layout-ng": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/coop-sandbox.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/coop-sandbox.https.html.ini
index 63b8eb62..e003d2bb 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/coop-sandbox.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/coop-sandbox.https.html.ini
@@ -1,3 +1,3 @@
 [coop-sandbox.https.html]
   expected:
-    if os == "win": [OK, TIMEOUT]
+    if os == "win": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/header-parsing-failures.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/header-parsing-failures.https.html.ini
index 4b66b2a..1272acc 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/header-parsing-failures.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/header-parsing-failures.https.html.ini
@@ -3,7 +3,7 @@
 [header-parsing-failures.https.html?12-last]
 
 [header-parsing-failures.https.html?9-12]
+  expected:
+    if product == "chrome": [OK, ERROR]
 
 [header-parsing-failures.https.html?5-8]
-  expected:
-    if product == "chrome": [ERROR, OK]
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/historical/popup-same-site-unsafe-allow-outgoing-with-cross-origin.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/historical/popup-same-site-unsafe-allow-outgoing-with-cross-origin.https.html.ini
index e5f17f95..1879499d 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/historical/popup-same-site-unsafe-allow-outgoing-with-cross-origin.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/historical/popup-same-site-unsafe-allow-outgoing-with-cross-origin.https.html.ini
@@ -1,3 +1,3 @@
 [popup-same-site-unsafe-allow-outgoing-with-cross-origin.https.html]
   expected:
-    if product == "chrome": [OK, ERROR]
+    if product == "chrome": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/historical/popup-same-site-unsafe-allow-outgoing-with-same-site.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/historical/popup-same-site-unsafe-allow-outgoing-with-same-site.https.html.ini
deleted file mode 100644
index 596920f..0000000
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/historical/popup-same-site-unsafe-allow-outgoing-with-same-site.https.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[popup-same-site-unsafe-allow-outgoing-with-same-site.https.html]
-  expected:
-    if product == "chrome": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/historical/popup-same-site-with-same-origin.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/historical/popup-same-site-with-same-origin.https.html.ini
new file mode 100644
index 0000000..71fe175
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/historical/popup-same-site-with-same-origin.https.html.ini
@@ -0,0 +1,3 @@
+[popup-same-site-with-same-origin.https.html]
+  expected:
+    if product == "chrome": [OK, ERROR]
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-same-origin.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-same-origin.https.html.ini
index fbb8b7e..852cb8e 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-same-origin.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-same-origin.https.html.ini
@@ -15,5 +15,3 @@
     if product == "chrome": ERROR
 
 [iframe-popup-same-origin-allow-popups-to-same-origin.https.html?7-8]
-  expected:
-    if product == "chrome": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/iframe-popup-same-origin-to-same-origin.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/iframe-popup-same-origin-to-same-origin.https.html.ini
index d38d7d2..223c26b 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/iframe-popup-same-origin-to-same-origin.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/iframe-popup-same-origin-to-same-origin.https.html.ini
@@ -1,4 +1,6 @@
 [iframe-popup-same-origin-to-same-origin.https.html?1-2]
+  expected:
+    if product == "chrome": ERROR
 
 [iframe-popup-same-origin-to-same-origin.https.html?5-6]
   expected:
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/javascript-url.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/javascript-url.https.html.ini
index afd6839..043f54e 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/javascript-url.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/javascript-url.https.html.ini
@@ -7,10 +7,10 @@
     if product == "chrome": ERROR
 
 [javascript-url.https.html?11-12]
-  expected:
-    if product == "chrome": ERROR
 
 [javascript-url.https.html?13-14]
+  expected:
+    if product == "chrome": [OK, ERROR]
 
 [javascript-url.https.html?15-16]
 
@@ -20,10 +20,12 @@
 
 [javascript-url.https.html?5-6]
   expected:
-    if product == "chrome": [OK, ERROR]
+    if product == "chrome": ERROR
 
 [javascript-url.https.html?7-8]
   expected:
     if product == "chrome": ERROR
 
 [javascript-url.https.html?9-10]
+  expected:
+    if product == "chrome": [OK, ERROR]
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/navigate-top-to-aboutblank.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/navigate-top-to-aboutblank.https.html.ini
index d5c6b762..1aeca85 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/navigate-top-to-aboutblank.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/navigate-top-to-aboutblank.https.html.ini
@@ -1,12 +1,8 @@
 [navigate-top-to-aboutblank.https.html]
   expected:
-    if product == "chrome": [OK, ERROR]
+    if product == "chrome": ERROR
   [Navigate top to about:blank from iframe with opener COOP: |header(Cross-Origin-Opener-Policy,same-origin), iframe origin: https://www1.web-platform.test:8444]
     expected: FAIL
 
   [Navigate top to about:blank from iframe with opener COOP: |header(Cross-Origin-Opener-Policy,same-origin-allow-popups), iframe origin: https://www1.web-platform.test:8444]
     expected: FAIL
-
-  [Navigate top to about:blank from iframe with opener COOP: |header(Cross-Origin-Opener-Policy,same-origin), iframe origin: https://web-platform.test:8444]
-    expected:
-      if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-redirect-cache.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-redirect-cache.https.html.ini
index 9c8fdd8..a2126157 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-redirect-cache.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-redirect-cache.https.html.ini
@@ -3,9 +3,11 @@
 [popup-redirect-cache.https.html?0-1]
 
 [popup-redirect-cache.https.html?6-7]
-  expected:
-    if product == "chrome": [ERROR, OK]
 
 [popup-redirect-cache.https.html?4-5]
+  expected:
+    if product == "chrome": [OK, ERROR]
 
 [popup-redirect-cache.https.html?8-last]
+  expected:
+    if product == "chrome": [OK, ERROR]
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-redirect-same-origin-allow-popups.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-redirect-same-origin-allow-popups.https.html.ini
new file mode 100644
index 0000000..4cc8d43
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-redirect-same-origin-allow-popups.https.html.ini
@@ -0,0 +1,3 @@
+[popup-redirect-same-origin-allow-popups.https.html]
+  expected:
+    if product == "chrome": [OK, ERROR]
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-same-origin-non-initial-about-blank.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-same-origin-non-initial-about-blank.https.html.ini
new file mode 100644
index 0000000..ef4c70f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-same-origin-non-initial-about-blank.https.html.ini
@@ -0,0 +1,3 @@
+[popup-same-origin-non-initial-about-blank.https.html]
+  expected:
+    if product == "chrome": [OK, ERROR]
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-same-origin-with-same-site.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-same-origin-with-same-site.https.html.ini
deleted file mode 100644
index efa88bc..0000000
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-same-origin-with-same-site.https.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[popup-same-origin-with-same-site.https.html]
-  expected:
-    if product == "chrome": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-unsafe-none-with-same-site.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-unsafe-none-with-same-site.https.html.ini
new file mode 100644
index 0000000..604de218
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-unsafe-none-with-same-site.https.html.ini
@@ -0,0 +1,3 @@
+[popup-unsafe-none-with-same-site.https.html]
+  expected:
+    if product == "chrome": [OK, ERROR]
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-unspecified-with-same-origin.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-unspecified-with-same-origin.https.html.ini
new file mode 100644
index 0000000..cc0aa62
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-unspecified-with-same-origin.https.html.ini
@@ -0,0 +1,3 @@
+[popup-unspecified-with-same-origin.https.html]
+  expected:
+    if product == "chrome": [OK, ERROR]
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-openee_coop-ro.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-openee_coop-ro.https.html.ini
index 59258e97..ef6ec98 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-openee_coop-ro.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-from-coop-page-to-openee_coop-ro.https.html.ini
@@ -1,3 +1,8 @@
 [access-from-coop-page-to-openee_coop-ro.https.html]
-  expected:
-    if product == "chrome": ERROR
+  [access-from-coop-page-to-openee, same-origin]
+    expected:
+      if product == "chrome": FAIL
+
+  [access-from-coop-page-to-openee, same-origin + redirect]
+    expected:
+      if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-openee_coop-ro.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-openee_coop-ro.https.html.ini
index 45761bca..bf827e7 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-openee_coop-ro.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-openee_coop-ro.https.html.ini
@@ -1,3 +1,10 @@
 [access-to-coop-page-from-openee_coop-ro.https.html]
   expected:
-    if product == "chrome": ERROR
+    if product == "chrome": [OK, ERROR]
+  [access-to-coop-page-from-openee, same-origin + redirect]
+    expected:
+      if product == "chrome": FAIL
+
+  [access-to-coop-page-from-openee, same-origin]
+    expected:
+      if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-opener_coop-ro.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-opener_coop-ro.https.html.ini
index 126bb78..235fd40 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-opener_coop-ro.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-opener_coop-ro.https.html.ini
@@ -1,3 +1,8 @@
 [access-to-coop-page-from-opener_coop-ro.https.html]
-  expected:
-    if product == "chrome": ERROR
+  [access-to-coop-page-from-opener, same-origin]
+    expected:
+      if product == "chrome": FAIL
+
+  [access-to-coop-page-from-opener, same-origin + redirect]
+    expected:
+      if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-opener_coop-ro_cross-origin.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-opener_coop-ro_cross-origin.https.html.ini
index 9e0d21c..851d459 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-opener_coop-ro_cross-origin.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-opener_coop-ro_cross-origin.https.html.ini
@@ -1,3 +1,8 @@
 [access-to-coop-page-from-opener_coop-ro_cross-origin.https.html]
-  expected:
-    if product == "chrome": ERROR
+  [access-to-coop-page-from-opener, cross-origin + redirect]
+    expected:
+      if product == "chrome": FAIL
+
+  [access-to-coop-page-from-opener, cross-origin]
+    expected:
+      if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-other_coop-ro.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-other_coop-ro.https.html.ini
index 22693c3..12463d2 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-other_coop-ro.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/access-to-coop-page-from-other_coop-ro.https.html.ini
@@ -1,6 +1,3 @@
 [access-to-coop-page-from-other_coop-ro.https.html]
   expected:
-    if product == "chrome": [OK, ERROR]
-  [access-to-coop-page-from-other (COOP-RO)]
-    expected:
-      if product == "chrome": FAIL
+    if product == "chrome": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-focus.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-focus.https.html.ini
index 82c8de3..2db32f1e 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-focus.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-focus.https.html.ini
@@ -1,10 +1,3 @@
 [property-focus.https.html]
   expected:
-    if product == "chrome": [OK, ERROR]
-  [same-origin > w => w.focus()]
-    expected:
-      if product == "chrome": FAIL
-
-  [cross-origin > w => w.focus()]
-    expected:
-      if product == "chrome": FAIL
+    if product == "chrome": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-frames.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-frames.https.html.ini
index f6d2d33..01f4fcd 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-frames.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-frames.https.html.ini
@@ -1,10 +1,3 @@
 [property-frames.https.html]
   expected:
-    if product == "chrome": [OK, ERROR]
-  [cross-origin > w => w.frames]
-    expected:
-      if product == "chrome": FAIL
-
-  [same-origin > w => w.frames]
-    expected:
-      if product == "chrome": FAIL
+    if product == "chrome": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-location-set.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-location-set.https.html.ini
index 175abd5..e016cf9 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-location-set.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-location-set.https.html.ini
@@ -1,10 +1,3 @@
 [property-location-set.https.html]
   expected:
-    if product == "chrome": [OK, ERROR]
-  [cross-origin > w => w.location = "#"]
-    expected:
-      if product == "chrome": FAIL
-
-  [same-origin > w => w.location = "#"]
-    expected:
-      if product == "chrome": FAIL
+    if product == "chrome": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-named-getter.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-named-getter.https.html.ini
index d654a715..a713a5f 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-named-getter.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-named-getter.https.html.ini
@@ -1,3 +1,3 @@
 [property-named-getter.https.html]
   expected:
-    if product == "chrome": [OK, ERROR]
+    if product == "chrome": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-opener-set.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-opener-set.https.html.ini
deleted file mode 100644
index 5111ef2..0000000
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-opener-set.https.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[property-opener-set.https.html]
-  expected:
-    if product == "chrome": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-postmessage-1.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-postmessage-1.https.html.ini
index 943353e..ab4e882 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-postmessage-1.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-postmessage-1.https.html.ini
@@ -1,4 +1,6 @@
 [property-postmessage-1.https.html]
+  expected:
+    if product == "chrome": [ERROR, OK]
   [same-origin > w => w.postMessage("", "")]
     expected:
       if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/report-to-both_coop-ro.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/report-to-both_coop-ro.https.html.ini
index d4653ba..46d3e245 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/report-to-both_coop-ro.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/report-to-both_coop-ro.https.html.ini
@@ -1,10 +1,3 @@
 [report-to-both_coop-ro.https.html]
   expected:
-    if product == "chrome": [OK, ERROR]
-  [Access from openee]
-    expected:
-      if product == "chrome": FAIL
-
-  [Access from opener]
-    expected:
-      if product == "chrome": FAIL
+    if product == "chrome": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup-to-soap.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup-to-soap.https.html.ini
index 9311679..f8661d5 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup-to-soap.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup-to-soap.https.html.ini
@@ -15,5 +15,3 @@
     if product == "chrome": ERROR
 
 [iframe-popup-to-soap.https.html?9-last]
-  expected:
-    if product == "chrome": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup-to-un.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup-to-un.https.html.ini
index 9afd7b3f..275706e 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup-to-un.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup-to-un.https.html.ini
@@ -19,8 +19,6 @@
 
 
 [iframe-popup-to-un.https.html?9-last]
-  expected:
-    if product == "chrome": [ERROR, OK]
   [COOP: restrict-properties to popup COOP: unsafe-none via an iframe, with cross origin iframe, cross origin popup with window_open]
     expected: FAIL
 
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup.https.html.ini
index f3681f2..4f6dc5095 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup.https.html.ini
@@ -9,8 +9,6 @@
 
 
 [iframe-popup.https.html?9-last]
-  expected:
-    if product == "chrome": ERROR
   [COOP: restrict-properties to popup COOP: restrict-properties via an iframe, with cross origin iframe, cross origin popup with window_open]
     expected: FAIL
 
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/popup-u.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/popup-u.https.html.ini
index d559eb64..e594813 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/popup-u.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/popup-u.https.html.ini
@@ -1,6 +1,4 @@
 [popup-u.https.html]
-  expected:
-    if product == "chrome": ERROR
   [SAME_ORIGIN popup with coop restrict-properties]
     expected: FAIL
 
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-cross-origin.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-cross-origin.https.html.ini
index fca3b7c..f97561b 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-cross-origin.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-cross-origin.https.html.ini
@@ -1,4 +1,6 @@
 [popup-with-cross-origin.https.html]
+  expected:
+    if product == "chrome": [OK, ERROR]
   [Cross-origin popup with empty coop]
     expected: FAIL
 
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/documents/resource-metadata-management/document-cookie.html.ini b/third_party/blink/web_tests/external/wpt/html/dom/documents/resource-metadata-management/document-cookie.html.ini
index 87ed375..fc63f6d 100644
--- a/third_party/blink/web_tests/external/wpt/html/dom/documents/resource-metadata-management/document-cookie.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/dom/documents/resource-metadata-management/document-cookie.html.ini
@@ -1,3 +1,15 @@
 [document-cookie.html]
   [document.cookie 2]
     expected: FAIL
+
+  [document has no cookie]
+    expected:
+      if product == "chrome": [PASS, FAIL]
+
+  [document.cookie]
+    expected:
+      if product == "chrome": [PASS, FAIL]
+
+  [document.cookie 1]
+    expected:
+      if product == "chrome": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/remove-attr-script-keeps-blocking.tentative.html.ini b/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/remove-attr-script-keeps-blocking.tentative.html.ini
deleted file mode 100644
index f223edf..0000000
--- a/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/remove-attr-script-keeps-blocking.tentative.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[remove-attr-script-keeps-blocking.tentative.html]
-  [Rendering is blocked before render-blocking resources are loaded]
-    expected:
-      if os == "win": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/script-inserted-script.html.ini b/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/script-inserted-script.html.ini
index 7e15d96..e11044c 100644
--- a/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/script-inserted-script.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/script-inserted-script.html.ini
@@ -1,4 +1,4 @@
 [script-inserted-script.html]
   [Rendering is blocked before render-blocking resources are loaded]
     expected:
-      if (flag_specific == "") and (product == "content_shell"): FAIL
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-audio-constructor.html.ini b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-audio-constructor.html.ini
index 832554d..0fb6a830 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-audio-constructor.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-audio-constructor.html.ini
@@ -1,3 +1,5 @@
 [resource-selection-invoke-audio-constructor.html]
   [invoking resource selection with new Audio(src)]
-    expected: FAIL
+    expected:
+      if flag_specific == "disable-site-isolation-trials": PASS
+      FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-not-in-document.html.ini b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-not-in-document.html.ini
index 9a1d791..0d35b24d 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-not-in-document.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-not-in-document.html.ini
@@ -1,5 +1,3 @@
 [resource-selection-invoke-insert-source-not-in-document.html]
   [invoking resource selection by inserting <source> in video not in a document]
-    expected:
-      if flag_specific == "disable-layout-ng": FAIL
-      if flag_specific == "disable-site-isolation-trials": FAIL
+    expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source.html.ini b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source.html.ini
index 5e49a00..90bfb40 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source.html.ini
@@ -1,3 +1,5 @@
 [resource-selection-invoke-insert-source.html]
   [invoking resource selection by inserting <source>]
-    expected: FAIL
+    expected:
+      if flag_specific == "disable-layout-ng": PASS
+      FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-pause-networkState.html.ini b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-pause-networkState.html.ini
index 08db93d..fb095150 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-pause-networkState.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-pause-networkState.html.ini
@@ -1,6 +1,6 @@
 [resource-selection-invoke-pause-networkState.html]
   [NOT invoking resource selection with pause() when networkState is not NETWORK_EMPTY]
     expected:
-      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): PASS
+      if (flag_specific == "") and (os == "win"): PASS
       if flag_specific == "disable-site-isolation-trials": PASS
       FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-src.html.ini b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-src.html.ini
deleted file mode 100644
index 7b5bb15..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-src.html.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[resource-selection-invoke-remove-src.html]
-  [NOT invoking media load or resource selection when removing the src attribute]
-    expected:
-      if (flag_specific == "") and (product == "chrome"): [PASS, FAIL]
-      if flag_specific == "disable-site-isolation-trials": [FAIL, PASS]
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src.html.ini b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src.html.ini
index c0581652..1d86d05 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src.html.ini
@@ -1,3 +1,6 @@
 [resource-selection-invoke-set-src.html]
   [invoking load by setting src]
-    expected: FAIL
+    expected:
+      if (flag_specific == "") and (os == "linux") and (product == "chrome"): PASS
+      if (flag_specific == "") and (os == "win"): PASS
+      FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-after-controls-removed.html.ini b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-after-controls-removed.html.ini
index e839e1a5..cd1b74e 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-after-controls-removed.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-after-controls-removed.html.ini
@@ -1,4 +1,4 @@
 [track-cue-rendering-after-controls-removed.html]
   expected:
-    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): FAIL
-    if flag_specific == "disable-site-isolation-trials": FAIL
+    if (flag_specific == "") and (os == "win"): FAIL
+    if flag_specific == "disable-layout-ng": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-special-cases.tentative.sub.window.js.ini b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-special-cases.tentative.sub.window.js.ini
index bdfd528..7774528 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-special-cases.tentative.sub.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child-special-cases.tentative.sub.window.js.ini
@@ -1,5 +1,4 @@
 [sandbox-top-navigation-child-special-cases.tentative.sub.window.html]
   expected:
-    if (product == "content_shell") and (flag_specific == "") and (os == "win"): [OK, TIMEOUT]
-    if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): TIMEOUT
-    if product == "chrome": ERROR
+    if (os == "linux") and (product == "chrome"): ERROR
+    if os == "win": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child.tentative.sub.window.js.ini b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child.tentative.sub.window.js.ini
index 4d916ea..9e36063f 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child.tentative.sub.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-child.tentative.sub.window.js.ini
@@ -1,4 +1,3 @@
 [sandbox-top-navigation-child.tentative.sub.window.html]
   expected:
-    if (flag_specific == "") and (product == "chrome"): ERROR
-    if flag_specific == "disable-site-isolation-trials": TIMEOUT
+    if product == "chrome": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-escalate-privileges.tentative.sub.window.js.ini b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-escalate-privileges.tentative.sub.window.js.ini
index ae3370f..5a471c5d 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-escalate-privileges.tentative.sub.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-escalate-privileges.tentative.sub.window.js.ini
@@ -1,4 +1,5 @@
 [sandbox-top-navigation-escalate-privileges.tentative.sub.window.html]
   expected:
-    if (flag_specific == "") and (product == "chrome"): ERROR
-    if flag_specific == "disable-site-isolation-trials": TIMEOUT
+    if (product == "content_shell") and (flag_specific == "") and (os == "linux"): [OK, TIMEOUT]
+    if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): TIMEOUT
+    if product == "chrome": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild.tentative.sub.window.js.ini b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild.tentative.sub.window.js.ini
index a28e10d..f6d097fe 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild.tentative.sub.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox-top-navigation-grandchild.tentative.sub.window.js.ini
@@ -1,4 +1,4 @@
 [sandbox-top-navigation-grandchild.tentative.sub.window.html]
   expected:
-    if (flag_specific == "") and (os == "linux") and (product == "chrome"): ERROR
-    if flag_specific == "disable-site-isolation-trials": [OK, TIMEOUT]
+    if (flag_specific == "") and (product == "chrome"): ERROR
+    if flag_specific == "disable-site-isolation-trials": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-img-element/image-loading-lazy-data-url-to-https.html.ini b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-img-element/image-loading-lazy-data-url-to-https.html.ini
index d692698..668679d34 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-img-element/image-loading-lazy-data-url-to-https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-img-element/image-loading-lazy-data-url-to-https.html.ini
@@ -1,3 +1,3 @@
 [image-loading-lazy-data-url-to-https.html]
   expected:
-    if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+    if (flag_specific == "") and (os == "win"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-0/text-plain.window.js.ini b/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-0/text-plain.window.js.ini
deleted file mode 100644
index e236680..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-0/text-plain.window.js.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[text-plain.window.html]
-  expected:
-    if flag_specific == "disable-layout-ng": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-selectmenu-element/selectmenu-form-state-restore.tentative.html.ini b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-selectmenu-element/selectmenu-form-state-restore.tentative.html.ini
index 2dbfcd2..12a4ba6 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-selectmenu-element/selectmenu-form-state-restore.tentative.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-selectmenu-element/selectmenu-form-state-restore.tentative.html.ini
@@ -1,4 +1,4 @@
 [selectmenu-form-state-restore.tentative.html]
   expected:
-    if flag_specific == "disable-site-isolation-trials": OK
-    ERROR
+    if (flag_specific == "") and (os == "linux") and (product == "chrome"): ERROR
+    if (flag_specific == "") and (os == "win"): ERROR
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/links/following-hyperlinks/activation-behavior.window.js.ini b/third_party/blink/web_tests/external/wpt/html/semantics/links/following-hyperlinks/activation-behavior.window.js.ini
index 0bebe05b..b02e6bff1 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/links/following-hyperlinks/activation-behavior.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/links/following-hyperlinks/activation-behavior.window.js.ini
@@ -1,10 +1,7 @@
 [activation-behavior.window.html]
   [<area> that is not connected should not be followed]
-    expected:
-      if flag_specific == "disable-layout-ng": PASS
-      FAIL
+    expected: FAIL
 
   [<a> that is not connected should be followed]
     expected:
-      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
-      if flag_specific == "disable-layout-ng": FAIL
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-focus.tentative.html.ini b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-focus.tentative.html.ini
deleted file mode 100644
index 3e5f99f..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-focus.tentative.html.ini
+++ /dev/null
@@ -1,6 +0,0 @@
-[popover-focus.tentative.html]
-  [Popover focus test: default behavior - popover is not focused]
-    expected: FAIL
-
-  [Popover button click focus test: default behavior - popover is not focused]
-    expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/webappapis/microtask-queuing/queue-microtask-exceptions.any.js.ini b/third_party/blink/web_tests/external/wpt/html/webappapis/microtask-queuing/queue-microtask-exceptions.any.js.ini
new file mode 100644
index 0000000..6029268e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/webappapis/microtask-queuing/queue-microtask-exceptions.any.js.ini
@@ -0,0 +1,9 @@
+[queue-microtask-exceptions.any.sharedworker.html]
+
+[queue-microtask-exceptions.any.serviceworker.html]
+
+[queue-microtask-exceptions.any.worker.html]
+  expected:
+    if product == "chrome": ERROR
+
+[queue-microtask-exceptions.any.html]
diff --git a/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/compile-event-handler-lexical-scopes-form-owner.html b/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/compile-event-handler-lexical-scopes-form-owner.html
new file mode 100644
index 0000000..e31bd249
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/compile-event-handler-lexical-scopes-form-owner.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Form's lexical scope is established only for form-associated elements</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/forms.html#form-associated-element">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/webappapis.html#getting-the-current-value-of-the-event-handler">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<form id="form">
+  <input onclick="window.inputOnClickElements = elements;">
+  <img onclick="window.imgOnClickElements = elements;" alt="img">
+  <div onclick="window.divOnClickElements = elements;">div</div>
+  <x-foo onclick="window.xFooOnClickElements = elements;">x-foo</x-foo>
+</form>
+
+<script>
+"use strict";
+
+window.elements = "global_elements";
+
+test(() => {
+  const input = form.querySelector("input");
+  input.click();
+  assert_equals(window.inputOnClickElements, form.elements);
+}, "<input> has a form owner");
+
+test(() => {
+  const img = form.querySelector("img");
+  img.click();
+  assert_equals(window.imgOnClickElements, form.elements);
+}, "<img> has a form owner");
+
+test(() => {
+  const div = form.querySelector("div");
+  div.click();
+  assert_equals(window.divOnClickElements, window.elements);
+}, "<div> doesn't have a form owner");
+
+test(() => {
+  customElements.define("x-foo", class extends HTMLElement {
+    static formAssociated = true;
+  });
+
+  const xFoo = form.querySelector("x-foo");
+  xFoo.click();
+  assert_equals(window.xFooOnClickElements, form.elements);
+}, "form-associated <x-foo> has a form owner");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/import-maps/bare-specifiers.sub.html.ini b/third_party/blink/web_tests/external/wpt/import-maps/bare-specifiers.sub.html.ini
index e8a067e..5e759f23 100644
--- a/third_party/blink/web_tests/external/wpt/import-maps/bare-specifiers.sub.html.ini
+++ b/third_party/blink/web_tests/external/wpt/import-maps/bare-specifiers.sub.html.ini
@@ -1,3 +1,3 @@
 [bare-specifiers.sub.html]
   expected:
-    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [OK, CRASH]
+    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): CRASH
diff --git a/third_party/blink/web_tests/external/wpt/infrastructure/server/webtransport-h3.https.sub.any.js.ini b/third_party/blink/web_tests/external/wpt/infrastructure/server/webtransport-h3.https.sub.any.js.ini
index daba249..667aadcf 100644
--- a/third_party/blink/web_tests/external/wpt/infrastructure/server/webtransport-h3.https.sub.any.js.ini
+++ b/third_party/blink/web_tests/external/wpt/infrastructure/server/webtransport-h3.https.sub.any.js.ini
@@ -5,10 +5,15 @@
 
 
 [webtransport-h3.https.sub.any.serviceworker.html]
-
-[webtransport-h3.https.sub.any.sharedworker.html]
-
-[webtransport-h3.https.sub.any.html]
   [WebTransport server should be running and should handle a bidirectional stream]
     expected:
       if os == "win": FAIL
+
+
+[webtransport-h3.https.sub.any.sharedworker.html]
+  [WebTransport server should be running and should handle a bidirectional stream]
+    expected:
+      if os == "win": FAIL
+
+
+[webtransport-h3.https.sub.any.html]
diff --git a/third_party/blink/web_tests/external/wpt/input-device-capabilities/idlharness.window.js.ini b/third_party/blink/web_tests/external/wpt/input-device-capabilities/idlharness.window.js.ini
index e505678b..c9abaca 100644
--- a/third_party/blink/web_tests/external/wpt/input-device-capabilities/idlharness.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/input-device-capabilities/idlharness.window.js.ini
@@ -1,4 +1,6 @@
 [idlharness.window.html]
+  expected:
+    if flag_specific == "disable-site-isolation-trials": [OK, CRASH]
   [InputDeviceCapabilities interface: attribute pointerMovementScrolls]
     expected: FAIL
 
diff --git a/third_party/blink/web_tests/external/wpt/intersection-observer/cross-origin-iframe.sub.html.ini b/third_party/blink/web_tests/external/wpt/intersection-observer/cross-origin-iframe.sub.html.ini
index 72e6f65..a93fa19 100644
--- a/third_party/blink/web_tests/external/wpt/intersection-observer/cross-origin-iframe.sub.html.ini
+++ b/third_party/blink/web_tests/external/wpt/intersection-observer/cross-origin-iframe.sub.html.ini
@@ -1,15 +1,12 @@
 [cross-origin-iframe.sub.html]
   [topDocument.scrollingElement.scrollTop = 200]
     expected:
-      if (flag_specific == "") and (product == "content_shell") and (os == "win"): [PASS, FAIL]
-      if (flag_specific == "") and (product == "chrome"): FAIL
-      if flag_specific == "disable-site-isolation-trials": FAIL
-
-  [topDocument.scrollingElement.scrollTop = 100]
-    expected:
-      if (flag_specific == "") and (os == "win"): [PASS, FAIL]
-      if flag_specific == "disable-layout-ng": FAIL
+      if (os == "linux") and (flag_specific == "") and (product == "content_shell"): [PASS, FAIL]
+      if (os == "linux") and (flag_specific == "disable-layout-ng"): [PASS, FAIL]
+      FAIL
 
   [iframeDocument.scrollingElement.scrollTop = 250]
     expected:
-      if os == "win": [PASS, FAIL]
+      if (os == "linux") and (flag_specific == "") and (product == "content_shell"): [PASS, FAIL]
+      if (os == "linux") and (flag_specific == "disable-layout-ng"): [PASS, FAIL]
+      if os == "win": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/intersection-observer/iframe-no-root-with-wrapping-scroller.html.ini b/third_party/blink/web_tests/external/wpt/intersection-observer/iframe-no-root-with-wrapping-scroller.html.ini
deleted file mode 100644
index 7d550a5..0000000
--- a/third_party/blink/web_tests/external/wpt/intersection-observer/iframe-no-root-with-wrapping-scroller.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[iframe-no-root-with-wrapping-scroller.html]
-  expected:
-    if flag_specific == "disable-site-isolation-trials": CRASH
diff --git a/third_party/blink/web_tests/external/wpt/largest-contentful-paint/first-paint-equals-lcp-text.html.ini b/third_party/blink/web_tests/external/wpt/largest-contentful-paint/first-paint-equals-lcp-text.html.ini
index 2ce953e..2e33519 100644
--- a/third_party/blink/web_tests/external/wpt/largest-contentful-paint/first-paint-equals-lcp-text.html.ini
+++ b/third_party/blink/web_tests/external/wpt/largest-contentful-paint/first-paint-equals-lcp-text.html.ini
@@ -1,6 +1,5 @@
 [first-paint-equals-lcp-text.html]
   [FCP and LCP are the same when there is a single text element in the page.]
     expected:
-      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): PASS
-      if flag_specific == "disable-layout-ng": PASS
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
       FAIL
diff --git a/third_party/blink/web_tests/external/wpt/lifecycle/freeze.html.ini b/third_party/blink/web_tests/external/wpt/lifecycle/freeze.html.ini
index cbfe5c1..38d7ada 100644
--- a/third_party/blink/web_tests/external/wpt/lifecycle/freeze.html.ini
+++ b/third_party/blink/web_tests/external/wpt/lifecycle/freeze.html.ini
@@ -1,5 +1,5 @@
 [freeze.html]
   [Test freeze callback.]
     expected:
-      if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
-      if product == "chrome": FAIL
+      if (flag_specific == "") and (os == "linux") and (product == "chrome"): FAIL
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/loading/early-hints/preload-finished-before-final-response.h2.window.js.ini b/third_party/blink/web_tests/external/wpt/loading/early-hints/preload-finished-before-final-response.h2.window.js.ini
index be2aa9a..27b93e40 100644
--- a/third_party/blink/web_tests/external/wpt/loading/early-hints/preload-finished-before-final-response.h2.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/loading/early-hints/preload-finished-before-final-response.h2.window.js.ini
@@ -1,4 +1,2 @@
 [preload-finished-before-final-response.h2.window.html]
-  expected:
-    if product == "chrome": [OK, ERROR]
-    ERROR
+  expected: ERROR
diff --git a/third_party/blink/web_tests/external/wpt/loading/early-hints/referrer-policy-origin.h2.window.js.ini b/third_party/blink/web_tests/external/wpt/loading/early-hints/referrer-policy-origin.h2.window.js.ini
index afb4eab4..ea7126e 100644
--- a/third_party/blink/web_tests/external/wpt/loading/early-hints/referrer-policy-origin.h2.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/loading/early-hints/referrer-policy-origin.h2.window.js.ini
@@ -1,4 +1,4 @@
 [referrer-policy-origin.h2.window.html]
   expected:
-    if product == "chrome": OK
+    if product == "chrome": [OK, ERROR]
     ERROR
diff --git a/third_party/blink/web_tests/external/wpt/loading/early-hints/referrer-policy-unsafe-url.h2.window.js.ini b/third_party/blink/web_tests/external/wpt/loading/early-hints/referrer-policy-unsafe-url.h2.window.js.ini
index a03c3f90..a432caa 100644
--- a/third_party/blink/web_tests/external/wpt/loading/early-hints/referrer-policy-unsafe-url.h2.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/loading/early-hints/referrer-policy-unsafe-url.h2.window.js.ini
@@ -1,4 +1,2 @@
 [referrer-policy-unsafe-url.h2.window.html]
-  expected:
-    if product == "chrome": [OK, ERROR]
-    ERROR
+  expected: ERROR
diff --git a/third_party/blink/web_tests/external/wpt/longtask-timing/long-microtask.window.js.ini b/third_party/blink/web_tests/external/wpt/longtask-timing/long-microtask.window.js.ini
deleted file mode 100644
index 5db0634..0000000
--- a/third_party/blink/web_tests/external/wpt/longtask-timing/long-microtask.window.js.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[long-microtask.window.html]
-  [A short task followed by a long microtask is observable.]
-    expected:
-      if flag_specific == "disable-site-isolation-trials": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/longtask-timing/longtask-in-sibling-iframe-crossorigin.html.ini b/third_party/blink/web_tests/external/wpt/longtask-timing/longtask-in-sibling-iframe-crossorigin.html.ini
index 11c1f41..1a806b4 100644
--- a/third_party/blink/web_tests/external/wpt/longtask-timing/longtask-in-sibling-iframe-crossorigin.html.ini
+++ b/third_party/blink/web_tests/external/wpt/longtask-timing/longtask-in-sibling-iframe-crossorigin.html.ini
@@ -1,5 +1,4 @@
 [longtask-in-sibling-iframe-crossorigin.html]
   [Performance longtask entries from cross-origin iframe are observable in its sibling.]
     expected:
-      if (flag_specific == "") and (product == "content_shell") and (os == "win"): [PASS, FAIL]
-      if (flag_specific == "") and (product == "content_shell") and (os == "linux"): [PASS, FAIL]
+      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/operators/operator-dictionary-arabic-002.html.ini b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/operators/operator-dictionary-arabic-002.html.ini
new file mode 100644
index 0000000..f0fa72f4
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/operators/operator-dictionary-arabic-002.html.ini
@@ -0,0 +1,3 @@
+[operator-dictionary-arabic-002.html]
+  expected:
+    if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/ignored-properties-001.html.ini b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/ignored-properties-001.html.ini
index f779190..5b2c3d5 100644
--- a/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/ignored-properties-001.html.ini
+++ b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/ignored-properties-001.html.ini
@@ -1,6 +1,7 @@
 [ignored-properties-001.html]
   expected:
-    if flag_specific == "disable-site-isolation-trials": [OK, TIMEOUT]
+    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [OK, TIMEOUT]
+    if flag_specific == "disable-site-isolation-trials": TIMEOUT
   [maction layout is not affected by width: 100px !important; height: 200px !important;]
     expected: FAIL
 
diff --git a/third_party/blink/web_tests/external/wpt/media-source/mediasource-appendbuffer-quota-exceeded.html.ini b/third_party/blink/web_tests/external/wpt/media-source/mediasource-appendbuffer-quota-exceeded.html.ini
index 627cac7..0dd0510 100644
--- a/third_party/blink/web_tests/external/wpt/media-source/mediasource-appendbuffer-quota-exceeded.html.ini
+++ b/third_party/blink/web_tests/external/wpt/media-source/mediasource-appendbuffer-quota-exceeded.html.ini
@@ -1,3 +1,4 @@
 [mediasource-appendbuffer-quota-exceeded.html]
   expected:
-    if flag_specific == "disable-site-isolation-trials": [OK, TIMEOUT]
+    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [OK, TIMEOUT]
+    if flag_specific == "disable-site-isolation-trials": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/media-source/mediasource-avtracks.html.ini b/third_party/blink/web_tests/external/wpt/media-source/mediasource-avtracks.html.ini
index cac368b9..a211a60e 100644
--- a/third_party/blink/web_tests/external/wpt/media-source/mediasource-avtracks.html.ini
+++ b/third_party/blink/web_tests/external/wpt/media-source/mediasource-avtracks.html.ini
@@ -4,6 +4,6 @@
 
   [Media tracks must be removed when the SourceBuffer is removed from the MediaSource]
     expected:
-      if (product == "content_shell") and (flag_specific == "") and (os == "linux"): PASS
-      if (product == "content_shell") and (flag_specific == "disable-layout-ng"): [PASS, FAIL]
+      if (flag_specific == "") and (product == "chrome"): PASS
+      if flag_specific == "disable-layout-ng": PASS
       FAIL
diff --git a/third_party/blink/web_tests/external/wpt/media-source/mediasource-duration.html.ini b/third_party/blink/web_tests/external/wpt/media-source/mediasource-duration.html.ini
index 0197c08c..d73c3f2 100644
--- a/third_party/blink/web_tests/external/wpt/media-source/mediasource-duration.html.ini
+++ b/third_party/blink/web_tests/external/wpt/media-source/mediasource-duration.html.ini
@@ -1,12 +1,8 @@
 [mediasource-duration.html]
   expected:
-    if (flag_specific == "") and (os == "linux") and (product == "chrome"): OK
-    if (flag_specific == "") and (os == "win"): OK
-    ERROR
-  [Test appendBuffer completes previous seek to truncated duration]
-    expected:
-      if flag_specific == "disable-layout-ng": [PASS, FAIL]
-
+    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): ERROR
+    if flag_specific == "disable-site-isolation-trials": ERROR
   [Test endOfStream completes previous seek to truncated duration]
     expected:
-      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+      if (flag_specific == "") and (product == "chrome"): [PASS, FAIL]
+      if flag_specific == "disable-layout-ng": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/mediacapture-insertable-streams/MediaStreamTrackGenerator-video.https.html.ini b/third_party/blink/web_tests/external/wpt/mediacapture-insertable-streams/MediaStreamTrackGenerator-video.https.html.ini
new file mode 100644
index 0000000..65623454
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/mediacapture-insertable-streams/MediaStreamTrackGenerator-video.https.html.ini
@@ -0,0 +1,4 @@
+[MediaStreamTrackGenerator-video.https.html]
+  [Tests that frames are sent correctly with RTCRtpEncodingParameters.scaleResolutionDownBy.]
+    expected:
+      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/native-io/detach_iframe_during_open.https.window.js.ini b/third_party/blink/web_tests/external/wpt/native-io/detach_iframe_during_open.https.window.js.ini
deleted file mode 100644
index b3facba..0000000
--- a/third_party/blink/web_tests/external/wpt/native-io/detach_iframe_during_open.https.window.js.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[detach_iframe_during_open.https.window.html]
-  expected:
-    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [OK, CRASH]
-    if (flag_specific == "") and (os == "win"): [OK, TIMEOUT]
-    if flag_specific == "disable-layout-ng": CRASH
diff --git a/third_party/blink/web_tests/external/wpt/navigation-api/navigation-methods/return-value/navigate-initial-about-blank.html.ini b/third_party/blink/web_tests/external/wpt/navigation-api/navigation-methods/return-value/navigate-initial-about-blank.html.ini
deleted file mode 100644
index 7680dc94..0000000
--- a/third_party/blink/web_tests/external/wpt/navigation-api/navigation-methods/return-value/navigate-initial-about-blank.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[navigate-initial-about-blank.html]
-  expected:
-    if flag_specific == "disable-layout-ng": ERROR
-    if flag_specific == "disable-site-isolation-trials": [OK, ERROR]
diff --git a/third_party/blink/web_tests/external/wpt/navigation-timing/test-performance-attributes.sub.html.ini b/third_party/blink/web_tests/external/wpt/navigation-timing/test-performance-attributes.sub.html.ini
deleted file mode 100644
index 6cea40d..0000000
--- a/third_party/blink/web_tests/external/wpt/navigation-timing/test-performance-attributes.sub.html.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[test-performance-attributes.sub.html]
-  [Check that performance.timing has reasonable values for secureConnectionStart and other attributes]
-    expected:
-      if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
-      if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/pending-beacon/pending_beacon-sendondiscard.tentative.https.window.js.ini b/third_party/blink/web_tests/external/wpt/pending-beacon/pending_beacon-sendondiscard.tentative.https.window.js.ini
index 45cc949..34e4879 100644
--- a/third_party/blink/web_tests/external/wpt/pending-beacon/pending_beacon-sendondiscard.tentative.https.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/pending-beacon/pending_beacon-sendondiscard.tentative.https.window.js.ini
@@ -3,15 +3,8 @@
     if product == "chrome": ERROR
   [A discarded document does not send an already sent beacon.]
     expected:
-      if flag_specific == "disable-layout-ng": [FAIL, PASS]
-      if flag_specific == "disable-site-isolation-trials": [FAIL, PASS]
+      if (flag_specific == "") and (os == "win"): FAIL
 
   [A discarded document sends all its beacons of which backgroundTimeouts are\n    not default.]
     expected:
-      if flag_specific == "disable-layout-ng": [PASS, FAIL]
-      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
-
-  [A discarded document sends all its beacons of which timeouts are not\n    default.]
-    expected:
-      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
-      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+      if (flag_specific == "") and (os == "win"): [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-same-origin-bfcache.tentative.window.js.ini b/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-same-origin-bfcache.tentative.window.js.ini
index 967f7f1..b84c0c6 100644
--- a/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-same-origin-bfcache.tentative.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-same-origin-bfcache.tentative.window.js.ini
@@ -1,6 +1,5 @@
 [performance-navigation-timing-same-origin-bfcache.tentative.window.html]
   [RemoteContextHelper navigation using BFCache]
     expected:
-      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): PASS
-      if flag_specific == "disable-site-isolation-trials": [FAIL, PASS]
-      FAIL
+      if (flag_specific == "") and (os == "linux") and (product == "chrome"): FAIL
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [FAIL, PASS]
diff --git a/third_party/blink/web_tests/external/wpt/requestidlecallback/deadline-max-rAF-dynamic.html.ini b/third_party/blink/web_tests/external/wpt/requestidlecallback/deadline-max-rAF-dynamic.html.ini
index f827d62..04b0e95 100644
--- a/third_party/blink/web_tests/external/wpt/requestidlecallback/deadline-max-rAF-dynamic.html.ini
+++ b/third_party/blink/web_tests/external/wpt/requestidlecallback/deadline-max-rAF-dynamic.html.ini
@@ -1,3 +1,3 @@
 [deadline-max-rAF-dynamic.html]
   expected:
-    if (flag_specific == "") and (os == "win"): [OK, TIMEOUT]
+    if (os == "linux") and (flag_specific == "disable-layout-ng"): [OK, TIMEOUT]
diff --git a/third_party/blink/web_tests/external/wpt/requestidlecallback/deadline-max-timeout-dynamic.html.ini b/third_party/blink/web_tests/external/wpt/requestidlecallback/deadline-max-timeout-dynamic.html.ini
index 36bd303..e86c521 100644
--- a/third_party/blink/web_tests/external/wpt/requestidlecallback/deadline-max-timeout-dynamic.html.ini
+++ b/third_party/blink/web_tests/external/wpt/requestidlecallback/deadline-max-timeout-dynamic.html.ini
@@ -1,6 +1,5 @@
 [deadline-max-timeout-dynamic.html]
   expected:
-    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): TIMEOUT
-    if flag_specific == "disable-site-isolation-trials": [OK, TIMEOUT]
+    if flag_specific == "disable-site-isolation-trials": TIMEOUT
   [Check that the deadline is changed if there is a new timeout from within requestIdleCallback.]
     expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/content-type-parsing.html.ini b/third_party/blink/web_tests/external/wpt/resource-timing/content-type-parsing.html.ini
index f628e90..17aa7db 100644
--- a/third_party/blink/web_tests/external/wpt/resource-timing/content-type-parsing.html.ini
+++ b/third_party/blink/web_tests/external/wpt/resource-timing/content-type-parsing.html.ini
@@ -37,12 +37,14 @@
 
   [content-type 13 : text/plain,*/*;charset=gbk]
     expected:
-      if os == "win": PASS
+      if (flag_specific == "") and (os == "win"): PASS
+      if flag_specific == "disable-site-isolation-trials": PASS
       FAIL
 
   [content-type 14 : text/html,*/*;charset=gbk]
     expected:
-      if os == "win": PASS
+      if (flag_specific == "") and (os == "win"): PASS
+      if flag_specific == "disable-site-isolation-trials": PASS
       FAIL
 
   [content-type 15 : text/html;x=",text/plain]
@@ -162,11 +164,3 @@
   [content-type 12 : */*,text/html]
     expected:
       if os == "win": FAIL
-
-  [content-type 3 : text/plain;charset=gbk,text/html]
-    expected:
-      if os == "win": FAIL
-
-  [content-type 2 : text/html,text/plain]
-    expected:
-      if os == "win": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/nested-context-navigations-iframe.html.ini b/third_party/blink/web_tests/external/wpt/resource-timing/nested-context-navigations-iframe.html.ini
new file mode 100644
index 0000000..58d4c10
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/resource-timing/nested-context-navigations-iframe.html.ini
@@ -0,0 +1,4 @@
+[nested-context-navigations-iframe.html]
+  [Test that crossorigin iframe navigations are not observable by the parent, even after history navigations by the parent]
+    expected:
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/no-entries-for-cross-origin-css-fetched-memory-cache.sub.html.ini b/third_party/blink/web_tests/external/wpt/resource-timing/no-entries-for-cross-origin-css-fetched-memory-cache.sub.html.ini
index 6f1569d4..be64ae2 100644
--- a/third_party/blink/web_tests/external/wpt/resource-timing/no-entries-for-cross-origin-css-fetched-memory-cache.sub.html.ini
+++ b/third_party/blink/web_tests/external/wpt/resource-timing/no-entries-for-cross-origin-css-fetched-memory-cache.sub.html.ini
@@ -1,6 +1,5 @@
 [no-entries-for-cross-origin-css-fetched-memory-cache.sub.html]
   [Make sure that resources fetched by cross origin CSS are not in the timeline.]
     expected:
-      if (flag_specific == "") and (os == "win"): [FAIL, PASS]
-      if flag_specific == "disable-layout-ng": PASS
+      if (os == "linux") and (flag_specific == "") and (product == "content_shell"): PASS
       FAIL
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/response-status-code.html.ini b/third_party/blink/web_tests/external/wpt/resource-timing/response-status-code.html.ini
index 8e34cbd..1b6605f1 100644
--- a/third_party/blink/web_tests/external/wpt/resource-timing/response-status-code.html.ini
+++ b/third_party/blink/web_tests/external/wpt/resource-timing/response-status-code.html.ini
@@ -1,10 +1,7 @@
 [response-status-code.html]
-  [This test validates the response status of resources. 276]
-    expected:
-      if flag_specific == "disable-site-isolation-trials": FAIL
-
   [This test validates the response status of resources. 273]
-    expected: [PASS, NOTRUN]
+    expected:
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
 
   [This test validates the response status of resources. 271]
     expected: [PASS, NOTRUN]
@@ -15,15 +12,6 @@
   [This test validates the response status of resources. 267]
     expected: [NOTRUN, PASS]
 
-  [This test validates the response status of resources. 272]
-    expected:
-      if (flag_specific == "") and (product == "chrome"): [PASS, FAIL]
-      if flag_specific == "disable-layout-ng": FAIL
-
-  [This test validates the response status of resources. 274]
-    expected:
-      if product == "chrome": [PASS, FAIL]
-
   [This test validates the response status of resources. 270]
     expected: [PASS, NOTRUN]
 
@@ -447,11 +435,6 @@
   [This test validates the response status of resources. 89]
     expected: [PASS, TIMEOUT]
 
-  [This test validates the response status of resources. 259]
-    expected:
-      if (flag_specific == "") and (product == "chrome"): [PASS, FAIL]
-      if flag_specific == "disable-layout-ng": FAIL
-
   [This test validates the response status of resources. 237]
     expected: [PASS, NOTRUN]
 
@@ -557,10 +540,6 @@
   [This test validates the response status of resources. 229]
     expected: [PASS, NOTRUN]
 
-  [This test validates the response status of resources. 84]
-    expected:
-      if product == "chrome": [PASS, FAIL]
-
   [This test validates the response status of resources. 218]
     expected: [PASS, NOTRUN]
 
@@ -581,3 +560,11 @@
 
   [This test validates the response status of resources. 191]
     expected: [PASS, NOTRUN]
+
+  [This test validates the response status of resources. 277]
+    expected:
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
+
+  [This test validates the response status of resources. 278]
+    expected:
+      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/scroll-to-text-fragment/redirects.html.ini b/third_party/blink/web_tests/external/wpt/scroll-to-text-fragment/redirects.html.ini
index 2a4f014..bca11087 100644
--- a/third_party/blink/web_tests/external/wpt/scroll-to-text-fragment/redirects.html.ini
+++ b/third_party/blink/web_tests/external/wpt/scroll-to-text-fragment/redirects.html.ini
@@ -1,5 +1,5 @@
 [redirects.html]
-  expected: [OK, ERROR]
+  expected: [OK, TIMEOUT]
   [Text fragment propagated through HTTP 303 redirect.]
     expected: [PASS, TIMEOUT]
 
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/cache-add.https.any.js.ini b/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/cache-add.https.any.js.ini
index 93c7a0a..a4f4599 100644
--- a/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/cache-add.https.any.js.ini
+++ b/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/cache-add.https.any.js.ini
@@ -12,6 +12,10 @@
   [Cache.addAll called with the same Request object specified twice]
     expected: FAIL
 
+  [Cache.addAll should succeed when entries differ by vary header]
+    expected:
+      if product == "chrome": [PASS, FAIL]
+
 
 [cache-add.https.any.html]
   [Cache.addAll called with the same Request object specified twice]
@@ -19,4 +23,4 @@
 
   [Cache.addAll should succeed when entries differ by vary header]
     expected:
-      if product == "chrome": [PASS, FAIL]
+      if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/about-blank-replacement.https.html.ini b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/about-blank-replacement.https.html.ini
index 44673f0a..b2a61d9c 100644
--- a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/about-blank-replacement.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/about-blank-replacement.https.html.ini
@@ -1,4 +1,6 @@
 [about-blank-replacement.https.html]
+  expected:
+    if product == "chrome": [OK, ERROR]
   [Initial about:blank is controlled, exposed to clients.matchAll(), and matches final Client.]
     expected: FAIL
 
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/client-navigate.https.html.ini b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/client-navigate.https.html.ini
index ed96e18b..a8461b4 100644
--- a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/client-navigate.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/client-navigate.https.html.ini
@@ -1,4 +1,4 @@
 [client-navigate.https.html]
-  [Frame location should not be accessible after redirect]
+  [Frame location should not be accessible after cross-origin navigation]
     expected:
-      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
+      if flag_specific == "disable-layout-ng": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/getregistrations.https.html.ini b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/getregistrations.https.html.ini
index 5651cd2..a1193b5 100644
--- a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/getregistrations.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/getregistrations.https.html.ini
@@ -1,12 +1,15 @@
 [getregistrations.https.html]
   [Register then Unregister then getRegistrations]
     expected:
-      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): FAIL
+      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
 
   [Register then Unregister with controlled frame then getRegistrations]
     expected:
-      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): FAIL
+      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
 
   [getRegistrations promise resolves only with same origin registrations.]
     expected:
-      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): FAIL
+      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+      if flag_specific == "disable-layout-ng": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/unregister-immediately-during-extendable-events.https.html.ini b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/unregister-immediately-during-extendable-events.https.html.ini
index acf3dea8..48187be 100644
--- a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/unregister-immediately-during-extendable-events.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/unregister-immediately-during-extendable-events.https.html.ini
@@ -1,7 +1,6 @@
 [unregister-immediately-during-extendable-events.https.html]
   expected:
-    if flag_specific == "disable-layout-ng": [TIMEOUT, OK]
-    if flag_specific == "disable-site-isolation-trials": OK
+    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): OK
     TIMEOUT
   [Clear-Site-Data must fail pending subresource fetch events.]
     expected:
diff --git a/third_party/blink/web_tests/external/wpt/shared-storage/resources/select-url-permissions-policy-helper.html b/third_party/blink/web_tests/external/wpt/shared-storage/resources/select-url-permissions-policy-helper.html
new file mode 100644
index 0000000..b70d763
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/shared-storage/resources/select-url-permissions-policy-helper.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<body>
+  <script src="/resources/testharness.js"></script>
+  <script src="/resources/testharnessreport.js"></script>
+  <script src="/shared-storage/resources/util.js"></script>
+  <script>
+  'use strict';
+
+  window.onload = async function() {
+    if (await IsSharedStorageSelectUrlAllowedByPermissionsPolicy()) {
+      parent.postMessage({ type: 'availability-result', enabled: true }, '*');
+      return;
+    }
+
+    parent.postMessage({ type: 'availability-result', enabled: false }, '*');
+  }
+  </script>
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/shared-storage/resources/permissions-policy-helper.html b/third_party/blink/web_tests/external/wpt/shared-storage/resources/shared-storage-permissions-policy-helper.html
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/shared-storage/resources/permissions-policy-helper.html
rename to third_party/blink/web_tests/external/wpt/shared-storage/resources/shared-storage-permissions-policy-helper.html
diff --git a/third_party/blink/web_tests/external/wpt/shared-storage/resources/util.js b/third_party/blink/web_tests/external/wpt/shared-storage/resources/util.js
index 4dea983..838885a 100644
--- a/third_party/blink/web_tests/external/wpt/shared-storage/resources/util.js
+++ b/third_party/blink/web_tests/external/wpt/shared-storage/resources/util.js
@@ -1,5 +1,23 @@
 'use strict';
 
+async function IsSharedStorageSelectUrlAllowedByPermissionsPolicy() {
+  const errorMessage = 'The \"shared-storage-select-url\" Permissions Policy denied the usage of window.sharedStorage.selectURL().';
+  let allowedByPermissionsPolicy = true;
+  try {
+    // Run selectURL() with without addModule() and this should always fail.
+    // Check the error message to distinguish between the permissions policy
+    // error and the missing addModule() error.
+    await sharedStorage.selectURL("operation", [{url: "1.html"}]);
+    assert_unreached("did not fail");
+  } catch (e) {
+    if (e.message === errorMessage) {
+      allowedByPermissionsPolicy = false;
+    }
+  }
+
+  return allowedByPermissionsPolicy;
+}
+
 // Execute all shared storage methods and capture their errors. Return true if
 // the permissions policy allows all of them; return false if the permissions
 // policy disallows all of them. Precondition: only these two outcomes are
diff --git a/third_party/blink/web_tests/external/wpt/shared-storage/select-url-permissions-policy-default.tentative.https.sub.html b/third_party/blink/web_tests/external/wpt/shared-storage/select-url-permissions-policy-default.tentative.https.sub.html
new file mode 100644
index 0000000..67911388
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/shared-storage/select-url-permissions-policy-default.tentative.https.sub.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<body>
+  <script src=/resources/testharness.js></script>
+  <script src=/resources/testharnessreport.js></script>
+  <script src=/permissions-policy/resources/permissions-policy.js></script>
+  <script src="/shared-storage/resources/util.js"></script>
+  <script>
+    'use strict';
+    const same_origin_src = '/shared-storage/resources/select-url-permissions-policy-helper.html';
+    const cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
+      same_origin_src;
+    const header = 'Default permissions policy';
+
+    promise_test(async t => {
+      const allowed = await IsSharedStorageSelectUrlAllowedByPermissionsPolicy();
+      assert_true(allowed);
+    }, header + ' allows sharedStorage.selectURL() in the current page.');
+
+    async_test(t => {
+      test_feature_availability('shared-storage-select-url', t, same_origin_src,
+          expect_feature_available_default);
+    }, header + ' allows sharedStorage.selectURL() in same-origin iframes.');
+
+    async_test(t => {
+      test_feature_availability('shared-storage-select-url', t, cross_origin_src,
+          expect_feature_available_default);
+    }, header + ' allows sharedStorage.selectURL() in cross-origin iframes.');
+  </script>
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/shared-storage/select-url-permissions-policy-none.tentative.https.sub.html b/third_party/blink/web_tests/external/wpt/shared-storage/select-url-permissions-policy-none.tentative.https.sub.html
new file mode 100644
index 0000000..6820edb
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/shared-storage/select-url-permissions-policy-none.tentative.https.sub.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<body>
+  <script src=/resources/testharness.js></script>
+  <script src=/resources/testharnessreport.js></script>
+  <script src=/permissions-policy/resources/permissions-policy.js></script>
+  <script src="/shared-storage/resources/util.js"></script>
+  <script>
+    'use strict';
+    const same_origin_src = '/shared-storage/resources/select-url-permissions-policy-helper.html';
+    const cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
+      same_origin_src;
+    const header = 'permissions policy header shared-storage-select-url=()';
+
+    promise_test(async t => {
+      const allowed = await IsSharedStorageSelectUrlAllowedByPermissionsPolicy();
+      assert_false(allowed);
+    }, header + ' disallows sharedStorage.selectURL() in the current page.');
+
+    async_test(t => {
+      test_feature_availability('shared-storage-select-url', t, same_origin_src,
+          expect_feature_unavailable_default);
+    }, header + ' disallows sharedStorage.selectURL() in same-origin iframes.');
+
+    async_test(t => {
+      test_feature_availability('shared-storage-select-url', t, cross_origin_src,
+          expect_feature_unavailable_default);
+    }, header + ' disallows sharedStorage.selectURL() in cross-origin iframes.');
+  </script>
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/shared-storage/select-url-permissions-policy-none.tentative.https.sub.html.headers b/third_party/blink/web_tests/external/wpt/shared-storage/select-url-permissions-policy-none.tentative.https.sub.html.headers
new file mode 100644
index 0000000..fdd2e378
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/shared-storage/select-url-permissions-policy-none.tentative.https.sub.html.headers
@@ -0,0 +1 @@
+Permissions-Policy: shared-storage-select-url=()
diff --git a/third_party/blink/web_tests/external/wpt/shared-storage/select-url-permissions-policy-self.tentative.https.sub.html b/third_party/blink/web_tests/external/wpt/shared-storage/select-url-permissions-policy-self.tentative.https.sub.html
new file mode 100644
index 0000000..b79bc06
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/shared-storage/select-url-permissions-policy-self.tentative.https.sub.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<body>
+  <script src=/resources/testharness.js></script>
+  <script src=/resources/testharnessreport.js></script>
+  <script src=/permissions-policy/resources/permissions-policy.js></script>
+  <script src="/shared-storage/resources/util.js"></script>
+  <script>
+    'use strict';
+    const same_origin_src = '/shared-storage/resources/select-url-permissions-policy-helper.html';
+    const cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
+      same_origin_src;
+    const header = 'permissions policy header shared-storage-select-url=(self)';
+
+    promise_test(async t => {
+      const allowed = await IsSharedStorageSelectUrlAllowedByPermissionsPolicy();
+      assert_true(allowed);
+    }, header + ' allows sharedStorage.selectURL() in the current page.');
+
+    async_test(t => {
+      test_feature_availability('shared-storage-select-url', t, same_origin_src,
+          expect_feature_available_default);
+    }, header + ' allows sharedStorage.selectURL() in same-origin iframes.');
+
+    async_test(t => {
+      test_feature_availability('shared-storage-select-url', t, cross_origin_src,
+          expect_feature_unavailable_default);
+    }, header + ' disallows sharedStorage.selectURL() in cross-origin iframes.');
+  </script>
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/shared-storage/select-url-permissions-policy-self.tentative.https.sub.html.headers b/third_party/blink/web_tests/external/wpt/shared-storage/select-url-permissions-policy-self.tentative.https.sub.html.headers
new file mode 100644
index 0000000..20d5451
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/shared-storage/select-url-permissions-policy-self.tentative.https.sub.html.headers
@@ -0,0 +1 @@
+Permissions-Policy: shared-storage-select-url=(self)
diff --git a/third_party/blink/web_tests/external/wpt/shared-storage/permissions-policy-default.tentative.https.sub.html b/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-permissions-policy-default.tentative.https.sub.html
similarity index 91%
rename from third_party/blink/web_tests/external/wpt/shared-storage/permissions-policy-default.tentative.https.sub.html
rename to third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-permissions-policy-default.tentative.https.sub.html
index f055ae0..5439df2 100644
--- a/third_party/blink/web_tests/external/wpt/shared-storage/permissions-policy-default.tentative.https.sub.html
+++ b/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-permissions-policy-default.tentative.https.sub.html
@@ -6,7 +6,7 @@
   <script src="/shared-storage/resources/util.js"></script>
   <script>
     'use strict';
-    const same_origin_src = '/shared-storage/resources/permissions-policy-helper.html';
+    const same_origin_src = '/shared-storage/resources/shared-storage-permissions-policy-helper.html';
     const cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
       same_origin_src;
     const header = 'Default permissions policy';
diff --git a/third_party/blink/web_tests/external/wpt/shared-storage/permissions-policy-default.tentative.https.sub.html.ini b/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-permissions-policy-default.tentative.https.sub.html.ini
similarity index 83%
rename from third_party/blink/web_tests/external/wpt/shared-storage/permissions-policy-default.tentative.https.sub.html.ini
rename to third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-permissions-policy-default.tentative.https.sub.html.ini
index 9deb6782..660ded2 100644
--- a/third_party/blink/web_tests/external/wpt/shared-storage/permissions-policy-default.tentative.https.sub.html.ini
+++ b/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-permissions-policy-default.tentative.https.sub.html.ini
@@ -1,4 +1,4 @@
-[permissions-policy-default.tentative.https.sub.html]
+[shared-storage-permissions-policy-default.tentative.https.sub.html]
   expected:
     if product == "content_shell": ERROR
     TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/shared-storage/permissions-policy-none.tentative.https.sub.html b/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-permissions-policy-none.tentative.https.sub.html
similarity index 91%
rename from third_party/blink/web_tests/external/wpt/shared-storage/permissions-policy-none.tentative.https.sub.html
rename to third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-permissions-policy-none.tentative.https.sub.html
index 7154061..17a4bf1 100644
--- a/third_party/blink/web_tests/external/wpt/shared-storage/permissions-policy-none.tentative.https.sub.html
+++ b/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-permissions-policy-none.tentative.https.sub.html
@@ -6,7 +6,7 @@
   <script src="/shared-storage/resources/util.js"></script>
   <script>
     'use strict';
-    const same_origin_src = '/shared-storage/resources/permissions-policy-helper.html';
+    const same_origin_src = '/shared-storage/resources/shared-storage-permissions-policy-helper.html';
     const cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
       same_origin_src;
     const header = 'permissions policy header shared-storage=()';
diff --git a/third_party/blink/web_tests/external/wpt/shared-storage/permissions-policy-none.tentative.https.sub.html.headers b/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-permissions-policy-none.tentative.https.sub.html.headers
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/shared-storage/permissions-policy-none.tentative.https.sub.html.headers
rename to third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-permissions-policy-none.tentative.https.sub.html.headers
diff --git a/third_party/blink/web_tests/external/wpt/shared-storage/permissions-policy-none.tentative.https.sub.html.ini b/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-permissions-policy-none.tentative.https.sub.html.ini
similarity index 86%
rename from third_party/blink/web_tests/external/wpt/shared-storage/permissions-policy-none.tentative.https.sub.html.ini
rename to third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-permissions-policy-none.tentative.https.sub.html.ini
index 23f7b32..3abf34c 100644
--- a/third_party/blink/web_tests/external/wpt/shared-storage/permissions-policy-none.tentative.https.sub.html.ini
+++ b/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-permissions-policy-none.tentative.https.sub.html.ini
@@ -1,4 +1,4 @@
-[permissions-policy-none.tentative.https.sub.html]
+[shared-storage-permissions-policy-none.tentative.https.sub.html]
   expected:
     if product == "content_shell": ERROR
     TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/shared-storage/permissions-policy-self.tentative.https.sub.html b/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-permissions-policy-self.tentative.https.sub.html
similarity index 91%
rename from third_party/blink/web_tests/external/wpt/shared-storage/permissions-policy-self.tentative.https.sub.html
rename to third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-permissions-policy-self.tentative.https.sub.html
index bde32a5..171325cd 100644
--- a/third_party/blink/web_tests/external/wpt/shared-storage/permissions-policy-self.tentative.https.sub.html
+++ b/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-permissions-policy-self.tentative.https.sub.html
@@ -6,7 +6,7 @@
   <script src="/shared-storage/resources/util.js"></script>
   <script>
     'use strict';
-    const same_origin_src = '/shared-storage/resources/permissions-policy-helper.html';
+    const same_origin_src = '/shared-storage/resources/shared-storage-permissions-policy-helper.html';
     const cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
       same_origin_src;
     const header = 'permissions policy header shared-storage=(self)';
diff --git a/third_party/blink/web_tests/external/wpt/shared-storage/permissions-policy-self.tentative.https.sub.html.headers b/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-permissions-policy-self.tentative.https.sub.html.headers
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/shared-storage/permissions-policy-self.tentative.https.sub.html.headers
rename to third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-permissions-policy-self.tentative.https.sub.html.headers
diff --git a/third_party/blink/web_tests/external/wpt/shared-storage/permissions-policy-self.tentative.https.sub.html.ini b/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-permissions-policy-self.tentative.https.sub.html.ini
similarity index 86%
rename from third_party/blink/web_tests/external/wpt/shared-storage/permissions-policy-self.tentative.https.sub.html.ini
rename to third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-permissions-policy-self.tentative.https.sub.html.ini
index 156f910..d7f7461 100644
--- a/third_party/blink/web_tests/external/wpt/shared-storage/permissions-policy-self.tentative.https.sub.html.ini
+++ b/third_party/blink/web_tests/external/wpt/shared-storage/shared-storage-permissions-policy-self.tentative.https.sub.html.ini
@@ -1,4 +1,4 @@
-[permissions-policy-self.tentative.https.sub.html]
+[shared-storage-permissions-policy-self.tentative.https.sub.html]
   expected:
     if product == "content_shell": ERROR
     TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/csp-script-src-self.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/csp-script-src-self.html.ini
index 812723f4..03af32c 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/csp-script-src-self.html.ini
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/csp-script-src-self.html.ini
@@ -1,4 +1,4 @@
 [csp-script-src-self.html]
   expected:
-    if (os == "linux") and (flag_specific == "disable-layout-ng"): [OK, ERROR]
-    if os == "win": ERROR
+    if (flag_specific == "") and (os == "win"): ERROR
+    if flag_specific == "disable-layout-ng": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/media-autoplay.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/media-autoplay.html.ini
index dcad099..dbcd037 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/media-autoplay.html.ini
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/media-autoplay.html.ini
@@ -3,8 +3,7 @@
   disabled:
     if os == "mac": was skipped in 'TestExpectations'
   expected:
-    if (os == "linux") and (product == "chrome"): TIMEOUT
-    if os == "win": TIMEOUT
+    if product == "chrome": TIMEOUT
   [media autoplay should defer playaback]
     expected:
       if product == "chrome": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/navigator-plugins.tentative.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/navigator-plugins.tentative.html.ini
index 7e5ff8f..6d40224 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/navigator-plugins.tentative.html.ini
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/navigator-plugins.tentative.html.ini
@@ -1,7 +1,6 @@
 [navigator-plugins.tentative.html]
   expected:
-    if (os == "linux") and (product == "chrome"): TIMEOUT
-    if os == "win": TIMEOUT
+    if product == "chrome": TIMEOUT
   [prerendering page should be able to access the navigator.plugins]
     expected:
       if product == "chrome": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/referrer-policy-no-referrer.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/referrer-policy-no-referrer.html.ini
index 9c2d108..0a70c55e 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/referrer-policy-no-referrer.html.ini
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/referrer-policy-no-referrer.html.ini
@@ -1,7 +1,7 @@
 [referrer-policy-no-referrer.html]
   expected:
-    if (product == "content_shell") and (os == "win"): [OK, TIMEOUT]
-    if product == "chrome": TIMEOUT
+    if (os == "linux") and (product == "chrome"): TIMEOUT
+    if os == "win": TIMEOUT
   [no referrer]
     expected:
       if product == "chrome": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/response-code-non-successful.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/response-code-non-successful.html.ini
index f7732f9..ba0befa 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/response-code-non-successful.html.ini
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/response-code-non-successful.html.ini
@@ -1,12 +1,14 @@
 [response-code-non-successful.html?code=204]
 
 [response-code-non-successful.html?code=402]
-
-[response-code-non-successful.html?code=500]
   expected:
     if product == "chrome": [OK, ERROR]
 
+[response-code-non-successful.html?code=500]
+
 [response-code-non-successful.html?code=404]
+  expected:
+    if product == "chrome": [OK, ERROR]
 
 [response-code-non-successful.html?code=503]
 
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/response-code-successful.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/response-code-successful.html.ini
index b10e24c..b60b1de 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/response-code-successful.html.ini
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/response-code-successful.html.ini
@@ -1,10 +1,12 @@
 [response-code-successful.html?code=203]
   [Responses with code 203 should be activated]
     expected:
-      if (os == "linux") and (product == "chrome"): FAIL
+      if product == "chrome": FAIL
 
 
 [response-code-successful.html?code=200]
+  expected:
+    if product == "chrome": [OK, ERROR]
   [Responses with code 200 should be activated]
     expected:
       if product == "chrome": FAIL
@@ -17,8 +19,6 @@
 
 
 [response-code-successful.html?code=202]
-  expected:
-    if product == "chrome": [OK, ERROR]
   [Responses with code 202 should be activated]
     expected:
       if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-message-boxes.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-message-boxes.html.ini
index aeb2a55..8bd9788 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-message-boxes.html.ini
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-message-boxes.html.ini
@@ -1,5 +1,6 @@
 [restriction-message-boxes.html]
   expected:
+    if (product == "content_shell") and (os == "win"): [OK, ERROR]
     if product == "chrome": TIMEOUT
   [alert() does not display the modal and returns immediately]
     expected:
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-request-picture-in-picture.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-request-picture-in-picture.html.ini
index 745c20d..9bfa95ff 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-request-picture-in-picture.html.ini
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-request-picture-in-picture.html.ini
@@ -1,7 +1,6 @@
 [restriction-request-picture-in-picture.html]
   expected:
-    if (os == "linux") and (product == "chrome"): TIMEOUT
-    if os == "win": TIMEOUT
+    if product == "chrome": TIMEOUT
   [prerendering page cannot invokeHTMLVideoElement.requestPictureInPicture]
     expected:
       if product == "chrome": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-speech-synthesis.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-speech-synthesis.html.ini
index ad1ad4c..6984300 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-speech-synthesis.html.ini
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-speech-synthesis.html.ini
@@ -1,5 +1,6 @@
 [restriction-speech-synthesis.html]
   expected:
+    if (product == "content_shell") and (os == "win"): [OK, ERROR]
     if product == "chrome": TIMEOUT
   [speechSynthesis.speak(utterance) should be deferred until the prerendered page is activated]
     expected:
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-web-usb.https.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-web-usb.https.html.ini
index 29304100..2fb4aa2 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-web-usb.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-web-usb.https.html.ini
@@ -1,7 +1,7 @@
 [restriction-web-usb.https.html]
   expected:
-    if (product == "content_shell") and (os == "win"): [OK, ERROR]
-    if product == "chrome": TIMEOUT
+    if (os == "linux") and (product == "chrome"): TIMEOUT
+    if os == "win": ERROR
   [the access to the Web USB API should be deferred until the prerendered\n    page is activated]
     expected:
       if product == "chrome": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-web-xr-inline-session.https.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-web-xr-inline-session.https.html.ini
index de3f51bc..ea71fd8 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-web-xr-inline-session.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-web-xr-inline-session.https.html.ini
@@ -1,7 +1,6 @@
 [restriction-web-xr-inline-session.https.html]
   expected:
-    if (os == "linux") and (product == "chrome"): TIMEOUT
-    if os == "win": ERROR
+    if product == "chrome": TIMEOUT
   [The access to the WebXR inline session API should be deferred until the\n    prerendered page is activated]
     expected:
       if product == "chrome": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-window-move.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-window-move.html.ini
index 1f07b4c..241db3c 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-window-move.html.ini
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-window-move.html.ini
@@ -1,7 +1,7 @@
 [restriction-window-move.html]
   expected:
-    if (product == "content_shell") and (os == "win"): [OK, ERROR]
-    if product == "chrome": TIMEOUT
+    if (os == "linux") and (product == "chrome"): TIMEOUT
+    if os == "win": ERROR
   [a prerendering page cannot move its window by executing moveTo.]
     expected:
       if product == "chrome": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-window-resize.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-window-resize.html.ini
index 625e373b..f775869 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-window-resize.html.ini
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-window-resize.html.ini
@@ -1,7 +1,6 @@
 [restriction-window-resize.html]
   expected:
-    if (os == "linux") and (product == "chrome"): TIMEOUT
-    if os == "win": ERROR
+    if product == "chrome": TIMEOUT
   [a prerendering page cannot resize its window by executing resizeTo.]
     expected:
       if product == "chrome": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/windowclient-navigate.https.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/windowclient-navigate.https.html.ini
index f209d85e..cdaf1ae 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/windowclient-navigate.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/windowclient-navigate.https.html.ini
@@ -3,5 +3,5 @@
     if product == "chrome": TIMEOUT
   [WindowClient.navigate() for a prerendered main page should throw aTypeError]
     expected:
-      if (product == "content_shell") and (os == "win"): [PASS, FAIL]
-      if product == "chrome": TIMEOUT
+      if (os == "linux") and (product == "chrome"): TIMEOUT
+      if os == "win": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/workers.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/workers.html.ini
index 827d09d..bea4222 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/workers.html.ini
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/workers.html.ini
@@ -1,8 +1,6 @@
 [workers.html]
   expected:
-    if (flag_specific == "") and (os == "linux") and (product == "chrome"): TIMEOUT
-    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [OK, TIMEOUT]
-    if (flag_specific == "") and (os == "win"): TIMEOUT
+    if product == "chrome": TIMEOUT
   [Dedicated workers should be loaded in suspended state until activated]
     expected:
       if product == "chrome": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/storage/partitioned-estimate-usage-details-caches.tentative.https.sub.html.ini b/third_party/blink/web_tests/external/wpt/storage/partitioned-estimate-usage-details-caches.tentative.https.sub.html.ini
deleted file mode 100644
index b9d6883a..0000000
--- a/third_party/blink/web_tests/external/wpt/storage/partitioned-estimate-usage-details-caches.tentative.https.sub.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[partitioned-estimate-usage-details-caches.tentative.https.sub.html]
-  expected:
-    if flag_specific == "disable-layout-ng": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/url/a-element-xhtml.xhtml.ini b/third_party/blink/web_tests/external/wpt/url/a-element-xhtml.xhtml.ini
index 3dc8d455..a90e16b 100644
--- a/third_party/blink/web_tests/external/wpt/url/a-element-xhtml.xhtml.ini
+++ b/third_party/blink/web_tests/external/wpt/url/a-element-xhtml.xhtml.ini
@@ -963,7 +963,8 @@
 
 [a-element-xhtml.xhtml?include=file]
   expected:
-    if os == "win": TIMEOUT
+    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [OK, CRASH]
+    if flag_specific == "disable-layout-ng": [OK, CRASH]
   [Parsing: <file://example%/> against <about:blank>]
     expected: FAIL
 
@@ -974,13 +975,19 @@
     expected: FAIL
 
   [Parsing: <C|/foo/bar> against <file:///tmp/mock/path>]
-    expected: FAIL
+    expected:
+      if os == "win": PASS
+      FAIL
 
   [Parsing: </C|\\foo\\bar> against <file:///tmp/mock/path>]
-    expected: FAIL
+    expected:
+      if os == "win": PASS
+      FAIL
 
   [Parsing: <//C|/foo/bar> against <file:///tmp/mock/path>]
-    expected: FAIL
+    expected:
+      if os == "win": PASS
+      FAIL
 
   [Parsing: <file://localhost> against <file:///tmp/mock/path>]
     expected: FAIL
@@ -1007,13 +1014,19 @@
     expected: FAIL
 
   [Parsing: <..> against <file:///C:/>]
-    expected: FAIL
+    expected:
+      if os == "win": PASS
+      FAIL
 
   [Parsing: </> against <file:///C:/a/b>]
-    expected: FAIL
+    expected:
+      if os == "win": PASS
+      FAIL
 
   [Parsing: </> against <file://h/C:/a/b>]
-    expected: FAIL
+    expected:
+      if os == "win": PASS
+      FAIL
 
   [Parsing: <//d:> against <file:///C:/a/b>]
     expected: FAIL
@@ -1082,16 +1095,24 @@
     expected: FAIL
 
   [Parsing: <//C:/> against <file://host/>]
-    expected: FAIL
+    expected:
+      if os == "win": PASS
+      FAIL
 
   [Parsing: <file://C:/> against <file://host/>]
-    expected: FAIL
+    expected:
+      if os == "win": PASS
+      FAIL
 
   [Parsing: <file:/C|/> against <about:blank>]
-    expected: FAIL
+    expected:
+      if os == "win": PASS
+      FAIL
 
   [Parsing: <file://C|/> against <about:blank>]
-    expected: FAIL
+    expected:
+      if os == "win": PASS
+      FAIL
 
   [Parsing: <file://localhost//a//../..//foo> against <about:blank>]
     expected: FAIL
@@ -1117,10 +1138,80 @@
   [Parsing: <file://xn--/p> against <about:blank>]
     expected: FAIL
 
+  [Parsing: </C:/> against <file://host/>]
+    expected:
+      if os == "win": FAIL
+
+  [Parsing: <file:///y:> against <about:blank>]
+    expected:
+      if os == "win": FAIL
+
+  [Parsing: </c:/foo/bar> against <file:///c:/baz/qux>]
+    expected:
+      if os == "win": FAIL
+
+  [Parsing: <file:C:/> against <file://host/>]
+    expected:
+      if os == "win": FAIL
+
+  [Parsing: <file:/example.com/> against <http://example.org/foo/bar>]
+    expected:
+      if os == "win": FAIL
+
+  [Parsing: <file:///y:/> against <about:blank>]
+    expected:
+      if os == "win": FAIL
+
+  [Parsing: <file:?q=v> against <about:blank>]
+    expected:
+      if os == "win": FAIL
+
+  [Parsing: </c:/foo/bar> against <file://host/path>]
+    expected:
+      if os == "win": FAIL
+
+  [Parsing: <file:..> against <http://www.example.com/test>]
+    expected:
+      if os == "win": FAIL
+
+  [Parsing: <file:a> against <http://www.example.com/test>]
+    expected:
+      if os == "win": FAIL
+
+  [Parsing: <file:/.//p> against <about:blank>]
+    expected:
+      if os == "win": FAIL
+
+  [Parsing: <file:/C:/> against <file://host/>]
+    expected:
+      if os == "win": FAIL
+
+  [Parsing: <file:///./y:> against <about:blank>]
+    expected:
+      if os == "win": FAIL
+
+  [Parsing: <file:.//p> against <about:blank>]
+    expected:
+      if os == "win": FAIL
+
+  [Parsing: <file:#frag> against <about:blank>]
+    expected:
+      if os == "win": FAIL
+
+  [Parsing: <file:/example.com/> against <about:blank>]
+    expected:
+      if os == "win": FAIL
+
+  [Parsing: <file:...> against <http://www.example.com/test>]
+    expected:
+      if os == "win": FAIL
+
+  [Parsing: <file:\\c:\\foo\\bar> against <file:///c:/baz/qux>]
+    expected:
+      if os == "win": FAIL
+
 
 [a-element-xhtml.xhtml?exclude=(file|javascript|mailto)]
-  expected:
-    if flag_specific == "disable-site-isolation-trials": CRASH
   [Parsing: <non-special://test:@test/x> against <about:blank>]
     expected: FAIL
 
@@ -1972,14 +2063,15 @@
 
 [a-element-xhtml.xhtml?include=mailto]
   expected:
-    if os == "win": [OK, TIMEOUT]
+    if (os == "linux") and (product == "chrome"): OK
+    if os == "win": TIMEOUT
+    [OK, CRASH]
   [Parsing: <mailto:/../> against <about:blank>]
     expected: FAIL
 
 
 [a-element-xhtml.xhtml?include=javascript]
   expected:
-    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): CRASH
-    if flag_specific == "disable-layout-ng": [OK, CRASH]
+    if (flag_specific == "") and (os == "win"): [OK, TIMEOUT]
   [Parsing: <javascript:/../> against <about:blank>]
     expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/url/a-element.html.ini b/third_party/blink/web_tests/external/wpt/url/a-element.html.ini
index 82a23475..85ce554 100644
--- a/third_party/blink/web_tests/external/wpt/url/a-element.html.ini
+++ b/third_party/blink/web_tests/external/wpt/url/a-element.html.ini
@@ -1073,8 +1073,7 @@
 
 [a-element.html?include=file]
   expected:
-    if flag_specific == "disable-site-isolation-trials": [OK, CRASH]
-    if flag_specific == "highdpi": [OK, CRASH]
+    if flag_specific == "disable-site-isolation-trials": CRASH
   [Parsing: <file://example%/> against <about:blank>]
     expected: FAIL
 
@@ -1322,6 +1321,8 @@
 
 
 [a-element.html?include=mailto]
+  expected:
+    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [OK, CRASH]
   [Parsing: <mailto:/../> against <about:blank>]
     expected: FAIL
 
@@ -2178,7 +2179,6 @@
 
 [a-element.html?include=javascript]
   expected:
-    if (os == "linux") and (flag_specific == "") and (product == "content_shell"): [OK, CRASH]
-    if os == "win": [OK, TIMEOUT]
+    if os == "win": TIMEOUT
   [Parsing: <javascript:/../> against <about:blank>]
     expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/url/failure.html.ini b/third_party/blink/web_tests/external/wpt/url/failure.html.ini
index 5f3314d..4364c892 100644
--- a/third_party/blink/web_tests/external/wpt/url/failure.html.ini
+++ b/third_party/blink/web_tests/external/wpt/url/failure.html.ini
@@ -1,5 +1,6 @@
 [failure.html]
   expected:
+    if (product == "content_shell") and (flag_specific == "disable-layout-ng"): [OK, CRASH]
     if product == "chrome": TIMEOUT
   [Location's href: file://example:1/ should throw]
     expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/url/percent-encoding.window.js.ini b/third_party/blink/web_tests/external/wpt/url/percent-encoding.window.js.ini
index 1091bffa..36d5702 100644
--- a/third_party/blink/web_tests/external/wpt/url/percent-encoding.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/url/percent-encoding.window.js.ini
@@ -1,3 +1,3 @@
 [percent-encoding.window.html]
   expected:
-    if flag_specific == "disable-site-isolation-trials": [OK, CRASH]
+    if flag_specific == "disable-site-isolation-trials": CRASH
diff --git a/third_party/blink/web_tests/external/wpt/url/url-setters-a-area.window.js.ini b/third_party/blink/web_tests/external/wpt/url/url-setters-a-area.window.js.ini
index 763ab28..a11a7016 100644
--- a/third_party/blink/web_tests/external/wpt/url/url-setters-a-area.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/url/url-setters-a-area.window.js.ini
@@ -1162,7 +1162,8 @@
 
 [url-setters-a-area.window.html?include=javascript]
   expected:
-    if os == "win": [OK, TIMEOUT]
+    if (os == "linux") and (flag_specific == "") and (product == "content_shell"): [OK, CRASH]
+    if (os == "linux") and (flag_specific == "disable-layout-ng"): [OK, CRASH]
   [<a>: Setting <javascript://x/>.username = 'wario']
     expected: FAIL
 
@@ -1184,7 +1185,7 @@
 
 [url-setters-a-area.window.html?include=mailto]
   expected:
-    if flag_specific == "disable-site-isolation-trials": [OK, CRASH]
+    if (flag_specific == "") and (os == "win"): [OK, TIMEOUT]
   [<a>: Setting <mailto:me@example.net>.protocol = 'http' Cannot-be-a-base URL doesn’t have a host, but URL in a special scheme must.]
     expected: FAIL
 
diff --git a/third_party/blink/web_tests/external/wpt/url/url-setters-stripping.any.js.ini b/third_party/blink/web_tests/external/wpt/url/url-setters-stripping.any.js.ini
index ad2f860..5c23a98 100644
--- a/third_party/blink/web_tests/external/wpt/url/url-setters-stripping.any.js.ini
+++ b/third_party/blink/web_tests/external/wpt/url/url-setters-stripping.any.js.ini
@@ -1,4 +1,6 @@
 [url-setters-stripping.any.html]
+  expected:
+    if os == "win": [OK, TIMEOUT]
   [Setting pathname with leading U+0000 (https:)]
     expected: FAIL
 
@@ -316,8 +318,6 @@
 
 
 [url-setters-stripping.any.worker.html]
-  expected:
-    if os == "win": [OK, TIMEOUT]
   [Setting pathname with leading U+0000 (https:)]
     expected: FAIL
 
diff --git a/third_party/blink/web_tests/external/wpt/url/urlsearchparams-delete.any.js.ini b/third_party/blink/web_tests/external/wpt/url/urlsearchparams-delete.any.js.ini
index 9f22a447..e35316b 100644
--- a/third_party/blink/web_tests/external/wpt/url/urlsearchparams-delete.any.js.ini
+++ b/third_party/blink/web_tests/external/wpt/url/urlsearchparams-delete.any.js.ini
@@ -1,4 +1,6 @@
 [urlsearchparams-delete.any.html]
+  expected:
+    if flag_specific == "disable-site-isolation-trials": [OK, CRASH]
   [Changing the query of a URL with an opaque path can impact the path]
     expected: FAIL
 
diff --git a/third_party/blink/web_tests/external/wpt/url/urlsearchparams-get.any.js.ini b/third_party/blink/web_tests/external/wpt/url/urlsearchparams-get.any.js.ini
index e0afce6..9c74fd4f 100644
--- a/third_party/blink/web_tests/external/wpt/url/urlsearchparams-get.any.js.ini
+++ b/third_party/blink/web_tests/external/wpt/url/urlsearchparams-get.any.js.ini
@@ -1,5 +1,5 @@
 [urlsearchparams-get.any.worker.html]
-
-[urlsearchparams-get.any.html]
   expected:
     if flag_specific == "disable-layout-ng": [OK, CRASH]
+
+[urlsearchparams-get.any.html]
diff --git a/third_party/blink/web_tests/external/wpt/url/urlsearchparams-stringifier.any.js.ini b/third_party/blink/web_tests/external/wpt/url/urlsearchparams-stringifier.any.js.ini
new file mode 100644
index 0000000..e3259c3
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/url/urlsearchparams-stringifier.any.js.ini
@@ -0,0 +1,5 @@
+[urlsearchparams-stringifier.any.html]
+
+[urlsearchparams-stringifier.any.worker.html]
+  expected:
+    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [OK, CRASH]
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/timing-model/timelines/sibling-iframe-timeline.html.ini b/third_party/blink/web_tests/external/wpt/web-animations/timing-model/timelines/sibling-iframe-timeline.html.ini
index db1fc3d..60172dd 100644
--- a/third_party/blink/web_tests/external/wpt/web-animations/timing-model/timelines/sibling-iframe-timeline.html.ini
+++ b/third_party/blink/web_tests/external/wpt/web-animations/timing-model/timelines/sibling-iframe-timeline.html.ini
@@ -1,5 +1,5 @@
 [sibling-iframe-timeline.html]
   [animation tied to another frame's timeline runs properly]
     expected:
-      if (os == "linux") and (flag_specific == "") and (product == "content_shell"): [PASS, FAIL]
-      if os == "win": FAIL
+      if (flag_specific == "") and (os == "win"): FAIL
+      if flag_specific == "disable-layout-ng": [FAIL, PASS]
diff --git a/third_party/blink/web_tests/external/wpt/web-locks/query-ordering.tentative.https.html.ini b/third_party/blink/web_tests/external/wpt/web-locks/query-ordering.tentative.https.html.ini
index b63d722..236f81a 100644
--- a/third_party/blink/web_tests/external/wpt/web-locks/query-ordering.tentative.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/web-locks/query-ordering.tentative.https.html.ini
@@ -1,3 +1,3 @@
 [query-ordering.tentative.https.html]
   expected:
-    if flag_specific == "disable-site-isolation-trials": [OK, CRASH]
+    if flag_specific == "disable-site-isolation-trials": CRASH
diff --git a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-analysernode-interface/test-analyser-output.html.ini b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-analysernode-interface/test-analyser-output.html.ini
index 448db8f..b2da746b 100644
--- a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-analysernode-interface/test-analyser-output.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-analysernode-interface/test-analyser-output.html.ini
@@ -1,4 +1,4 @@
 [test-analyser-output.html]
   [AnalyserNode output]
     expected:
-      if os == "win": [PASS, FAIL]
+      if (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audioworklet-interface/audioworkletnode-output-channel-count.https.html.ini b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audioworklet-interface/audioworkletnode-output-channel-count.https.html.ini
deleted file mode 100644
index 97f1aa6..0000000
--- a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audioworklet-interface/audioworkletnode-output-channel-count.https.html.ini
+++ /dev/null
@@ -1,9 +0,0 @@
-[audioworkletnode-output-channel-count.https.html]
-  [X The expected output channel count is not equal to 17. Got 1.]
-    expected: FAIL
-
-  [< [Dynamically change the channel count to if unspecified.\] 1 out of 1 assertions were failed.]
-    expected: FAIL
-
-  [# AUDIT TASK RUNNER FINISHED: 1 out of 2 tasks were failed.]
-    expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-mediaelementaudiosourcenode-interface/mediaElementAudioSourceToScriptProcessorTest.html.ini b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-mediaelementaudiosourcenode-interface/mediaElementAudioSourceToScriptProcessorTest.html.ini
index 88f3f0f5..efe3d878 100644
--- a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-mediaelementaudiosourcenode-interface/mediaElementAudioSourceToScriptProcessorTest.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-mediaelementaudiosourcenode-interface/mediaElementAudioSourceToScriptProcessorTest.html.ini
@@ -1,4 +1,5 @@
 [mediaElementAudioSourceToScriptProcessorTest.html]
   [All data processed correctly]
     expected:
-      if (product == "content_shell") and (flag_specific == "") and (os == "linux"): [PASS, FAIL]
+      if (product == "content_shell") and (flag_specific == "") and (os == "linux"): FAIL
+      if product == "chrome": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-pannernode-interface/test-pannernode-automation.html.ini b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-pannernode-interface/test-pannernode-automation.html.ini
deleted file mode 100644
index a0c0660..0000000
--- a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-pannernode-interface/test-pannernode-automation.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[test-pannernode-automation.html]
-  expected:
-    if os == "win": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/webmessaging/broadcastchannel/workers.html.ini b/third_party/blink/web_tests/external/wpt/webmessaging/broadcastchannel/workers.html.ini
index 49c2787..fd51247 100644
--- a/third_party/blink/web_tests/external/wpt/webmessaging/broadcastchannel/workers.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webmessaging/broadcastchannel/workers.html.ini
@@ -1,3 +1,3 @@
 [workers.html]
   expected:
-    if flag_specific == "disable-site-isolation-trials": [OK, TIMEOUT]
+    if flag_specific == "disable-site-isolation-trials": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/webmessaging/multi-globals/broadcastchannel-incumbent.sub.html.ini b/third_party/blink/web_tests/external/wpt/webmessaging/multi-globals/broadcastchannel-incumbent.sub.html.ini
index b15baab..b7ed4395 100644
--- a/third_party/blink/web_tests/external/wpt/webmessaging/multi-globals/broadcastchannel-incumbent.sub.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webmessaging/multi-globals/broadcastchannel-incumbent.sub.html.ini
@@ -1,8 +1,7 @@
 [broadcastchannel-incumbent.sub.html]
   expected:
-    if os == "win": [OK, TIMEOUT]
+    if os == "win": TIMEOUT
   [The incumbent page being cross-origin must not prevent the BroadcastChannel message from being seen]
     expected:
-      if (flag_specific == "") and (product == "chrome"): PASS
-      if flag_specific == "disable-site-isolation-trials": PASS
-      FAIL
+      if (flag_specific == "") and (product == "content_shell"): FAIL
+      if flag_specific == "disable-layout-ng": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webmessaging/without-ports/020.html.ini b/third_party/blink/web_tests/external/wpt/webmessaging/without-ports/020.html.ini
deleted file mode 100644
index 265c7a6..0000000
--- a/third_party/blink/web_tests/external/wpt/webmessaging/without-ports/020.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[020.html]
-  [cross-origin test]
-    expected:
-      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCIceConnectionState-candidate-pair.https.html.ini b/third_party/blink/web_tests/external/wpt/webrtc/RTCIceConnectionState-candidate-pair.https.html.ini
deleted file mode 100644
index 4e15800c..0000000
--- a/third_party/blink/web_tests/external/wpt/webrtc/RTCIceConnectionState-candidate-pair.https.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[RTCIceConnectionState-candidate-pair.https.html]
-  [On ICE connected, getStats() contains a connected candidate-pair]
-    expected:
-      if (os == "linux") and (product == "content_shell") and (flag_specific == ""): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/events_referenceSpace_reset_inline.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/events_referenceSpace_reset_inline.https.html.ini
index fddaa5b..c348a52f 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/events_referenceSpace_reset_inline.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/events_referenceSpace_reset_inline.https.html.ini
@@ -1,6 +1,12 @@
 [events_referenceSpace_reset_inline.https.html]
   expected:
-    if product == "chrome": OK
+    if (os == "linux") and (product == "chrome"): [TIMEOUT, OK]
+    if os == "win": OK
     TIMEOUT
   [XRSession resetpose from a device properly fires off the right events for non-immersive sessions - webgl]
-    expected: FAIL
+    expected:
+      if os == "linux": FAIL
+
+  [XRSession resetpose from a device properly fires off the right events for non-immersive sessions - webgl2]
+    expected:
+      if os == "linux": [TIMEOUT, PASS]
diff --git a/third_party/blink/web_tests/external/wpt/webxr/hit-test/xrRay_matrix.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/hit-test/xrRay_matrix.https.html.ini
index 43d34ba..b22a17a 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/hit-test/xrRay_matrix.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/hit-test/xrRay_matrix.https.html.ini
@@ -1,3 +1,3 @@
 [xrRay_matrix.https.html]
   expected:
-    if flag_specific == "highdpi": [OK, CRASH]
+    if flag_specific == "highdpi": CRASH
diff --git a/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window.js.ini b/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window.js.ini
index ef2fbdf..ae0831a7 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window.js.ini
@@ -8,9 +8,6 @@
   [XRSession interface: attribute supportedFrameRates]
     expected: FAIL
 
-  [XRSession interface: attribute enabledFeatures]
-    expected: FAIL
-
   [XRSession interface: operation updateTargetFrameRate(float)]
     expected: FAIL
 
@@ -23,9 +20,6 @@
   [XRSession interface: xrSession must inherit property "supportedFrameRates" with the proper type]
     expected: FAIL
 
-  [XRSession interface: xrSession must inherit property "enabledFeatures" with the proper type]
-    expected: FAIL
-
   [XRSession interface: xrSession must inherit property "updateTargetFrameRate(float)" with the proper type]
     expected: FAIL
 
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_enabledFeatures.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrSession_enabledFeatures.https.html.ini
new file mode 100644
index 0000000..e77d7e7
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_enabledFeatures.https.html.ini
@@ -0,0 +1,4 @@
+[xrSession_enabledFeatures.https.html]
+  [Validate enabledFeatures on XRSession - webgl]
+    expected:
+      if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_getViewerPose.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_getViewerPose.https.html.ini
index fd22b34a..13ee403 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_getViewerPose.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_getViewerPose.https.html.ini
@@ -2,7 +2,3 @@
   [XRFrame getViewerPose updates on the next frame for non-immersive sessions - webgl]
     expected:
       if product == "chrome": FAIL
-
-  [XRFrame getViewerPose updates on the next frame for non-immersive sessions - webgl2]
-    expected:
-      if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestReferenceSpace_features.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestReferenceSpace_features.https.html.ini
index 9d84a7b..819352f 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestReferenceSpace_features.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestReferenceSpace_features.https.html.ini
@@ -1,6 +1,50 @@
 [xrSession_requestReferenceSpace_features.https.html]
   expected:
-    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): TIMEOUT
+    if product == "chrome": [OK, TIMEOUT]
   [Non-immersive session supports viewer space by default - webgl]
     expected:
       if product == "chrome": FAIL
+
+  [Non-immersive session rejects bounded-floor space even when requested - webgl2]
+    expected:
+      if product == "chrome": [PASS, NOTRUN]
+
+  [Immersive session supports local-floor space when optional - webgl]
+    expected:
+      if product == "chrome": [PASS, NOTRUN]
+
+  [Non-immersive session rejects local space if not requested - webgl2]
+    expected:
+      if product == "chrome": [PASS, NOTRUN]
+
+  [Immersive session rejects local-floor space if not requested - webgl2]
+    expected:
+      if product == "chrome": [PASS, NOTRUN]
+
+  [Immersive session rejects local-floor space if not requested - webgl]
+    expected:
+      if product == "chrome": [PASS, NOTRUN]
+
+  [Immersive session supports local-floor space when optional - webgl2]
+    expected:
+      if product == "chrome": [PASS, NOTRUN]
+
+  [Non-immersive session rejects unbounded space even when requested - webgl]
+    expected:
+      if product == "chrome": [PASS, NOTRUN]
+
+  [Non-immersive session rejects unbounded space even when requested - webgl2]
+    expected:
+      if product == "chrome": [PASS, NOTRUN]
+
+  [Non-immersive session rejects local space if not requested - webgl]
+    expected:
+      if product == "chrome": [PASS, NOTRUN]
+
+  [Immersive session supports local-floor space when required - webgl2]
+    expected:
+      if product == "chrome": [PASS, TIMEOUT]
+
+  [Non-immersive session rejects bounded-floor space even when requested - webgl]
+    expected:
+      if product == "chrome": [PASS, NOTRUN]
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrStationaryReferenceSpace_floorlevel_updates.https.html.ini b/third_party/blink/web_tests/external/wpt/webxr/xrStationaryReferenceSpace_floorlevel_updates.https.html.ini
index 66f1822a..288ec60 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrStationaryReferenceSpace_floorlevel_updates.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrStationaryReferenceSpace_floorlevel_updates.https.html.ini
@@ -2,7 +2,3 @@
   ['floor-level' XRStationaryReferenceSpace updates properly when the transform changes for immersive sessions - webgl]
     expected:
       if product == "chrome": FAIL
-
-  ['floor-level' XRStationaryReferenceSpace updates properly when the transform changes for non-immersive sessions - webgl]
-    expected:
-      if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/workers/constructors/SharedWorker/dummy-name.html.ini b/third_party/blink/web_tests/external/wpt/workers/constructors/SharedWorker/dummy-name.html.ini
deleted file mode 100644
index 2ff8507..0000000
--- a/third_party/blink/web_tests/external/wpt/workers/constructors/SharedWorker/dummy-name.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[dummy-name.html]
-  expected:
-    if flag_specific == "disable-site-isolation-trials": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/workers/interfaces/SharedWorkerGlobalScope/name/setting.html.ini b/third_party/blink/web_tests/external/wpt/workers/interfaces/SharedWorkerGlobalScope/name/setting.html.ini
index 2244b252..45a75a5 100644
--- a/third_party/blink/web_tests/external/wpt/workers/interfaces/SharedWorkerGlobalScope/name/setting.html.ini
+++ b/third_party/blink/web_tests/external/wpt/workers/interfaces/SharedWorkerGlobalScope/name/setting.html.ini
@@ -1,3 +1,3 @@
 [setting.html]
   expected:
-    if flag_specific == "disable-site-isolation-trials": [OK, TIMEOUT]
+    if flag_specific == "disable-site-isolation-trials": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/workers/interfaces/WorkerGlobalScope/location/redirect.html.ini b/third_party/blink/web_tests/external/wpt/workers/interfaces/WorkerGlobalScope/location/redirect.html.ini
new file mode 100644
index 0000000..fd33d33
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/workers/interfaces/WorkerGlobalScope/location/redirect.html.ini
@@ -0,0 +1,3 @@
+[redirect.html]
+  expected:
+    if os == "win": [OK, TIMEOUT]
diff --git a/third_party/blink/web_tests/external/wpt/workers/modules/dedicated-worker-import-meta.html.ini b/third_party/blink/web_tests/external/wpt/workers/modules/dedicated-worker-import-meta.html.ini
index f19304d..f8185f10 100644
--- a/third_party/blink/web_tests/external/wpt/workers/modules/dedicated-worker-import-meta.html.ini
+++ b/third_party/blink/web_tests/external/wpt/workers/modules/dedicated-worker-import-meta.html.ini
@@ -1,5 +1,5 @@
 [dedicated-worker-import-meta.html]
   expected:
-    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [OK, TIMEOUT]
+    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): TIMEOUT
   [Test import.meta.url on the imported module script with a fragment.]
     expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/worklets/animation-worklet-import.https.html.ini b/third_party/blink/web_tests/external/wpt/worklets/animation-worklet-import.https.html.ini
deleted file mode 100644
index 0b70485..0000000
--- a/third_party/blink/web_tests/external/wpt/worklets/animation-worklet-import.https.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[animation-worklet-import.https.html]
-  expected:
-    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): TIMEOUT
diff --git a/third_party/blink/web_tests/wpt_internal/forms/file/file-input-webkitdirectory-click.html.ini b/third_party/blink/web_tests/wpt_internal/forms/file/file-input-webkitdirectory-click.html.ini
index 1aef8ac..e9d6baf 100644
--- a/third_party/blink/web_tests/wpt_internal/forms/file/file-input-webkitdirectory-click.html.ini
+++ b/third_party/blink/web_tests/wpt_internal/forms/file/file-input-webkitdirectory-click.html.ini
@@ -1,6 +1,4 @@
 [file-input-webkitdirectory-click.html]
-  expected:
-    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): TIMEOUT
   [clicking a file input with the webkitdirectory attribute launches a file chooser]
     expected:
       if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/wpt_internal/forms/file/file-input-webkitdirectory-key-enter.html.ini b/third_party/blink/web_tests/wpt_internal/forms/file/file-input-webkitdirectory-key-enter.html.ini
index d944ed21..252ef6f54 100644
--- a/third_party/blink/web_tests/wpt_internal/forms/file/file-input-webkitdirectory-key-enter.html.ini
+++ b/third_party/blink/web_tests/wpt_internal/forms/file/file-input-webkitdirectory-key-enter.html.ini
@@ -1,6 +1,6 @@
 [file-input-webkitdirectory-key-enter.html]
   expected:
-    if (flag_specific == "") and (os == "win"): [OK, TIMEOUT]
+    if (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [OK, TIMEOUT]
   [pressing Enter with focus on a webkitdirectory file input element launches a file chooser]
     expected:
       if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/wpt_internal/prerender/session-storage.html.ini b/third_party/blink/web_tests/wpt_internal/prerender/session-storage.html.ini
index 32abeede..f3c953ba 100644
--- a/third_party/blink/web_tests/wpt_internal/prerender/session-storage.html.ini
+++ b/third_party/blink/web_tests/wpt_internal/prerender/session-storage.html.ini
@@ -3,6 +3,7 @@
   disabled:
     if flag_specific == "force-renderer-accessibility": @False
   expected:
+    if (product == "content_shell") and (os == "win"): [OK, ERROR]
     if product == "chrome": TIMEOUT
   [session-storage-carry-over-to-prerender-page.html]
     expected:
diff --git a/third_party/blink/web_tests/wpt_internal/storage/estimate-usage-details-filesystem.https.tentative.any.js.ini b/third_party/blink/web_tests/wpt_internal/storage/estimate-usage-details-filesystem.https.tentative.any.js.ini
index b2b53ea8..65d9db7 100644
--- a/third_party/blink/web_tests/wpt_internal/storage/estimate-usage-details-filesystem.https.tentative.any.js.ini
+++ b/third_party/blink/web_tests/wpt_internal/storage/estimate-usage-details-filesystem.https.tentative.any.js.ini
@@ -1,11 +1,6 @@
 [estimate-usage-details-filesystem.https.tentative.any.html]
-  [estimate() usage details reflects increase in fileSystem after write  operation]
-    expected:
-      if flag_specific == "disable-layout-ng": [PASS, FAIL]
-      if flag_specific == "disable-site-isolation-trials": [FAIL, PASS]
-
 
 [estimate-usage-details-filesystem.https.tentative.any.worker.html]
   [estimate() usage details reflects increase in fileSystem after write  operation]
     expected:
-      if (product == "content_shell") and (flag_specific == "") and (os == "linux"): [PASS, FAIL]
+      if flag_specific == "disable-layout-ng": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/wpt_internal/storage/quota/partitioned-webkitStorageInfo-persistent-quota-usage-details.tentative.sub.html.ini b/third_party/blink/web_tests/wpt_internal/storage/quota/partitioned-webkitStorageInfo-persistent-quota-usage-details.tentative.sub.html.ini
index c1311bd2..ec1dc922 100644
--- a/third_party/blink/web_tests/wpt_internal/storage/quota/partitioned-webkitStorageInfo-persistent-quota-usage-details.tentative.sub.html.ini
+++ b/third_party/blink/web_tests/wpt_internal/storage/quota/partitioned-webkitStorageInfo-persistent-quota-usage-details.tentative.sub.html.ini
@@ -1,3 +1,3 @@
 [partitioned-webkitStorageInfo-persistent-quota-usage-details.tentative.sub.html]
   expected:
-    if flag_specific == "disable-site-isolation-trials": [OK, TIMEOUT]
+    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [OK, TIMEOUT]
diff --git a/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/root-and-nested-element-transition.html.ini b/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/root-and-nested-element-transition.html.ini
index 26d0e98..e1161b9b 100644
--- a/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/root-and-nested-element-transition.html.ini
+++ b/third_party/blink/web_tests/wpt_internal/view-transition-on-navigation/root-and-nested-element-transition.html.ini
@@ -1,2 +1,4 @@
 [root-and-nested-element-transition.html]
-  expected: FAIL
+  expected:
+    if product == "chrome": [FAIL, ERROR]
+    FAIL
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium
index 0aecce94..1aa2a54e 100644
--- a/third_party/freetype/README.chromium
+++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@
 Name: FreeType
 URL: http://www.freetype.org/
-Version: VER-2-12-1-145-gace97a02a
-Revision: ace97a02a4461bbdae29da4019c105eead95e277
+Version: VER-2-12-1-146-g0bcb664de
+Revision: 0bcb664de8ea44299f57c45d01433328596bc2a7
 CPEPrefix: cpe:/a:freetype:freetype:2.12.1
 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent
          JPEG Group) licenses"
diff --git a/third_party/nearby/README.chromium b/third_party/nearby/README.chromium
index e4adc03..0d26014 100644
--- a/third_party/nearby/README.chromium
+++ b/third_party/nearby/README.chromium
@@ -1,7 +1,7 @@
 Name: Nearby Connections Library
 Short Name: Nearby
 URL: https://github.com/google/nearby
-Version: 7e82794d4da4612b1e0409faaf3a96876f11a8de
+Version: 6edd1d11b0a6d5f502cc29394eaf8ee0c62f5930
 License: Apache 2.0
 License File: LICENSE
 Security Critical: yes
diff --git a/third_party/webgpu-cts/ts_sources.txt b/third_party/webgpu-cts/ts_sources.txt
index 5c771c66..d2bbef26 100644
--- a/third_party/webgpu-cts/ts_sources.txt
+++ b/third_party/webgpu-cts/ts_sources.txt
@@ -52,6 +52,7 @@
 src/unittests/unit_test.ts
 src/demo/a.spec.ts
 src/demo/json.spec.ts
+src/demo/subcases.spec.ts
 src/demo/a/b.spec.ts
 src/demo/a/b/c.spec.ts
 src/demo/a/b/d.spec.ts
diff --git a/tools/gritsettings/resource_ids.spec b/tools/gritsettings/resource_ids.spec
index 22d3017a..2f9d16e 100644
--- a/tools/gritsettings/resource_ids.spec
+++ b/tools/gritsettings/resource_ids.spec
@@ -287,6 +287,10 @@
     "META": {"sizes": {"includes": [10]}},
     "includes": [1925],
   },
+  "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/side_panel/bookmarks/resources.grd": {
+    "META": {"sizes": {"includes": [45],}},
+    "includes": [1926],
+  },
   "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/side_panel/customize_chrome/resources.grd": {
     "META": {"sizes": {"includes": [35],}},
     "includes": [1930],
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 4e370ff6d..33f19b4 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -22181,6 +22181,11 @@
   <int value="2" label="Finished with &quot;Keep Exploring&quot; button"/>
 </enum>
 
+<enum name="CrosHealthdTelemetryResult">
+  <int value="0" label="Success"/>
+  <int value="1" label="Error"/>
+</enum>
+
 <enum name="CrosSelectToSpeakActivationMethod">
   <int value="0" label="Unknown"/>
   <int value="1" label="Canceled with menu button"/>
@@ -41854,6 +41859,8 @@
   <int value="105" label="ClientHintPrefersReducedMotion"/>
   <int value="106" label="ComputePressure"/>
   <int value="107" label="SmartCard"/>
+  <int value="108" label="SharedStorageSelectUrl"/>
+  <int value="109" label="PrivateAggregation"/>
 </enum>
 
 <enum name="FeaturePolicyImageCompressionFormat">
@@ -60998,6 +61005,7 @@
   <int value="75747474" label="disable-webview-signin-flow"/>
   <int value="77886794" label="AllowRepeatedUpdates:enabled"/>
   <int value="77946316" label="PrefixWebAppWindowsWithAppName:disabled"/>
+  <int value="78781399" label="AppDeduplicationServiceFondue:disabled"/>
   <int value="78900745"
       label="SharedHighlightingRefinedMaxContextWords:disabled"/>
   <int value="78998551" label="disable-hosted-app-shim-creation"/>
@@ -64025,6 +64033,7 @@
   <int value="1857000695" label="SendWebUIJavaScriptErrorReports:disabled"/>
   <int value="1858385315" label="ChromeHomeBottomNavLabels:enabled"/>
   <int value="1858523835" label="VerifyDidCommitParams:enabled"/>
+  <int value="1859864175" label="AppDeduplicationServiceFondue:enabled"/>
   <int value="1860597983" label="AndroidSpellChecker:disabled"/>
   <int value="1860955818" label="PowerScheduler:enabled"/>
   <int value="1861067469" label="SystemJapanesePhysicalTyping:disabled"/>
diff --git a/tools/metrics/histograms/metadata/browser/histograms.xml b/tools/metrics/histograms/metadata/browser/histograms.xml
index 808d962..19f61962 100644
--- a/tools/metrics/histograms/metadata/browser/histograms.xml
+++ b/tools/metrics/histograms/metadata/browser/histograms.xml
@@ -802,7 +802,7 @@
 </histogram>
 
 <histogram name="BrowserRenderProcessHost.SpareProcessMaybeTakeAction"
-    enum="SpareProcessMaybeTakeAction" expires_after="2023-01-15">
+    enum="SpareProcessMaybeTakeAction" expires_after="2023-12-15">
   <owner>alexmos@chromium.org</owner>
   <owner>lukasza@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/chromeos/histograms.xml b/tools/metrics/histograms/metadata/chromeos/histograms.xml
index c243813..eebd31ca 100644
--- a/tools/metrics/histograms/metadata/chromeos/histograms.xml
+++ b/tools/metrics/histograms/metadata/chromeos/histograms.xml
@@ -1091,6 +1091,40 @@
   </token>
 </histogram>
 
+<histogram name="ChromeOS.Healthd.TelemetryResult.{Category}"
+    enum="CrosHealthdTelemetryResult" expires_after="2023-12-31">
+  <owner>weiluanwang@google.com</owner>
+  <owner>dennyh@google.com</owner>
+  <owner>cros-tdm-tpe-eng@google.com</owner>
+  <summary>
+    Records the telemetry results from healthd to analyze the usage and error
+    rate. Emitted when the specific category is requested from a client.
+  </summary>
+  <token key="Category">
+    <variant name="Audio"/>
+    <variant name="AudioHardware"/>
+    <variant name="Backlight"/>
+    <variant name="Battery"/>
+    <variant name="BlockDevice"/>
+    <variant name="Bluetooth"/>
+    <variant name="BootPerformance"/>
+    <variant name="Bus"/>
+    <variant name="Cpu"/>
+    <variant name="Display"/>
+    <variant name="Fan"/>
+    <variant name="Graphics"/>
+    <variant name="Input"/>
+    <variant name="Memory"/>
+    <variant name="Network"/>
+    <variant name="NetworkInterface"/>
+    <variant name="Sensor"/>
+    <variant name="StatefulPartition"/>
+    <variant name="System"/>
+    <variant name="Timezone"/>
+    <variant name="Tpm"/>
+  </token>
+</histogram>
+
 <histogram name="ChromeOS.IioService.SensorClientConcurrent" units="clients"
     expires_after="2023-05-01">
   <owner>chenghaoyang@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/compositing/histograms.xml b/tools/metrics/histograms/metadata/compositing/histograms.xml
index ca359d596..329a835 100644
--- a/tools/metrics/histograms/metadata/compositing/histograms.xml
+++ b/tools/metrics/histograms/metadata/compositing/histograms.xml
@@ -242,7 +242,7 @@
 </histogram>
 
 <histogram name="Compositing.Display.Draw.Occlusion.Calculation.Time"
-    units="microseconds" expires_after="2022-12-18">
+    units="microseconds" expires_after="2023-12-18">
   <owner>yiyix@chromium.org</owner>
   <owner>chromeos-gfx@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/extensions/histograms.xml b/tools/metrics/histograms/metadata/extensions/histograms.xml
index 713c2d1..cbbfd231 100644
--- a/tools/metrics/histograms/metadata/extensions/histograms.xml
+++ b/tools/metrics/histograms/metadata/extensions/histograms.xml
@@ -725,7 +725,7 @@
 </histogram>
 
 <histogram name="Extensions.DeclarativeNetRequest.RequestHeaderChanged"
-    enum="WebRequest.RequestHeader" expires_after="2023-01-22">
+    enum="WebRequest.RequestHeader" expires_after="2023-12-22">
   <owner>rdevlin.cronin@chromium.org</owner>
   <owner>kelvinjiang@chromium.org</owner>
   <owner>src/extensions/OWNERS</owner>
@@ -749,7 +749,7 @@
 </histogram>
 
 <histogram name="Extensions.DeclarativeNetRequest.ResponseHeaderAdded"
-    enum="WebRequest.ResponseHeader" expires_after="2023-01-22">
+    enum="WebRequest.ResponseHeader" expires_after="2023-12-22">
   <owner>rdevlin.cronin@chromium.org</owner>
   <owner>kelvinjiang@chromium.org</owner>
   <owner>src/extensions/OWNERS</owner>
@@ -761,7 +761,7 @@
 </histogram>
 
 <histogram name="Extensions.DeclarativeNetRequest.ResponseHeaderChanged"
-    enum="WebRequest.ResponseHeader" expires_after="2023-01-22">
+    enum="WebRequest.ResponseHeader" expires_after="2023-12-22">
   <owner>rdevlin.cronin@chromium.org</owner>
   <owner>kelvinjiang@chromium.org</owner>
   <owner>src/extensions/OWNERS</owner>
@@ -773,7 +773,7 @@
 </histogram>
 
 <histogram name="Extensions.DeclarativeNetRequest.ResponseHeaderRemoved"
-    enum="WebRequest.ResponseHeader" expires_after="2023-01-22">
+    enum="WebRequest.ResponseHeader" expires_after="2023-12-22">
   <owner>rdevlin.cronin@chromium.org</owner>
   <owner>kelvinjiang@chromium.org</owner>
   <owner>src/extensions/OWNERS</owner>
diff --git a/tools/metrics/histograms/metadata/file/histograms.xml b/tools/metrics/histograms/metadata/file/histograms.xml
index 707453b..4f500d1 100644
--- a/tools/metrics/histograms/metadata/file/histograms.xml
+++ b/tools/metrics/histograms/metadata/file/histograms.xml
@@ -974,7 +974,7 @@
 </histogram>
 
 <histogram name="FileBrowser.ZipMountTime.{RootType}" units="ms"
-    expires_after="M112">
+    expires_after="2024-01-01">
   <owner>simmonsjosh@google.com</owner>
   <owner>src/ui/file_manager/OWNERS</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/histogram_suffixes_list.xml b/tools/metrics/histograms/metadata/histogram_suffixes_list.xml
index fca0461..574fd7a 100644
--- a/tools/metrics/histograms/metadata/histogram_suffixes_list.xml
+++ b/tools/metrics/histograms/metadata/histogram_suffixes_list.xml
@@ -2690,73 +2690,6 @@
   <affected-histogram name="LoadingPredictor.PreconnectLearningRedirectStatus"/>
 </histogram_suffixes>
 
-<histogram_suffixes name="LocalNetReqsLocalhostResources" separator=".">
-  <suffix base="true" name="Localhost.DbRequests"
-      label="Requests made to localhost on a database server port."/>
-  <suffix base="true" name="Localhost.DevRequests"
-      label="Requests made to localhost on a development server port."/>
-  <suffix base="true" name="Localhost.OtherRequests"
-      label="Requests made to localhost on any port not otherwise monitored
-             by the other local network request metrics."/>
-  <suffix base="true" name="Localhost.PrinterRequests"
-      label="Requests made to localhost on a printer server port."/>
-  <suffix base="true" name="Localhost.WebRequests"
-      label="Requests made to localhost on a web server port."/>
-  <affected-histogram name="LocalNetworkRequests.PrivatePage"/>
-  <affected-histogram name="LocalNetworkRequests.PublicPage"/>
-</histogram_suffixes>
-
-<histogram_suffixes name="LocalNetReqsPrivatePage" separator=".">
-  <suffix base="true" name="DifferentSubnetRequests"
-      label="Requests made to local resources on a different subnet."/>
-  <suffix base="true" name="PublicRequests"
-      label="Requests made to public resources."/>
-  <suffix base="true" name="SameSubnetRequests"
-      label="Requests made to local resources on the same reserved IP space
-             as the page."/>
-  <affected-histogram name="LocalNetworkRequests.PrivatePage"/>
-</histogram_suffixes>
-
-<histogram_suffixes name="LocalNetReqsPublicPage" separator=".">
-  <suffix base="true" name="PrivateRequests"
-      label="Requests made to private resources."/>
-  <suffix base="true" name="RouterRequests"
-      label="Requests made to resources likely to be routers."/>
-  <affected-histogram name="LocalNetworkRequests.PublicPage"/>
-</histogram_suffixes>
-
-<histogram_suffixes name="LocalNetReqsStatuses" separator=".">
-  <suffix name="Failed" label="Failed requests."/>
-  <suffix name="Successful" label="Successful requests."/>
-  <affected-histogram
-      name="LocalNetworkRequests.PrivatePage.DifferentSubnetRequests"/>
-  <affected-histogram
-      name="LocalNetworkRequests.PrivatePage.Localhost.DbRequests"/>
-  <affected-histogram
-      name="LocalNetworkRequests.PrivatePage.Localhost.DevRequests"/>
-  <affected-histogram
-      name="LocalNetworkRequests.PrivatePage.Localhost.OtherRequests"/>
-  <affected-histogram
-      name="LocalNetworkRequests.PrivatePage.Localhost.PrinterRequests"/>
-  <affected-histogram
-      name="LocalNetworkRequests.PrivatePage.Localhost.WebRequests"/>
-  <affected-histogram name="LocalNetworkRequests.PrivatePage.PublicRequests"/>
-  <affected-histogram
-      name="LocalNetworkRequests.PrivatePage.SameSubnetRequests"/>
-  <affected-histogram
-      name="LocalNetworkRequests.PublicPage.Localhost.DbRequests"/>
-  <affected-histogram
-      name="LocalNetworkRequests.PublicPage.Localhost.DevRequests"/>
-  <affected-histogram
-      name="LocalNetworkRequests.PublicPage.Localhost.OtherRequests"/>
-  <affected-histogram
-      name="LocalNetworkRequests.PublicPage.Localhost.PrinterRequests"/>
-  <affected-histogram
-      name="LocalNetworkRequests.PublicPage.Localhost.WebRequests"/>
-  <affected-histogram name="LocalNetworkRequests.PublicPage.PrivateRequests"/>
-  <affected-histogram name="LocalNetworkRequests.PublicPage.RouterRequests"/>
-</histogram_suffixes>
-
 <histogram_suffixes name="LocationAttachedStatus" separator=".">
   <suffix name="LocationAttached"
       label="This histogram is for when the location was successfully
diff --git a/tools/metrics/histograms/metadata/local/histograms.xml b/tools/metrics/histograms/metadata/local/histograms.xml
index 0efe5a5..5e8766d7 100644
--- a/tools/metrics/histograms/metadata/local/histograms.xml
+++ b/tools/metrics/histograms/metadata/local/histograms.xml
@@ -36,25 +36,6 @@
   <variant name="Under100KB" summary="DB size under 100KB."/>
 </variants>
 
-<histogram base="true" name="LocalNetworkRequests.PrivatePage" units="requests"
-    expires_after="2020-07-06">
-  <owner>uthakore@chromium.org</owner>
-  <owner>invernizzi@chromium.org</owner>
-  <summary>
-    Number of requests made by a private page to resources besides itself.
-  </summary>
-</histogram>
-
-<histogram base="true" name="LocalNetworkRequests.PublicPage" units="requests"
-    expires_after="M81">
-  <owner>uthakore@chromium.org</owner>
-  <owner>invernizzi@chromium.org</owner>
-  <summary>
-    Number of requests made by a public page to resources with reserved IP
-    addresses.
-  </summary>
-</histogram>
-
 <histogram name="LocalSearchService.BindIndexHasError" enum="Boolean"
     expires_after="2023-05-31">
   <owner>tby@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/uma/histograms.xml b/tools/metrics/histograms/metadata/uma/histograms.xml
index 551889a..e81b9d2 100644
--- a/tools/metrics/histograms/metadata/uma/histograms.xml
+++ b/tools/metrics/histograms/metadata/uma/histograms.xml
@@ -992,7 +992,7 @@
 </histogram>
 
 <histogram name="UMA.UserActionsCount" enum="Boolean"
-    expires_after="2023-02-01">
+    expires_after="2023-08-01">
   <owner>mpearson@chromium.org</owner>
   <owner>src/base/metrics/OWNERS</owner>
   <summary>
diff --git a/tools/metrics/histograms/update_histogram_enum.py b/tools/metrics/histograms/update_histogram_enum.py
index b55e773..357b2e8 100644
--- a/tools/metrics/histograms/update_histogram_enum.py
+++ b/tools/metrics/histograms/update_histogram_enum.py
@@ -16,7 +16,6 @@
 from xml.dom import minidom
 
 sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'common'))
-import diff_util
 import path_util
 
 import histogram_paths
@@ -297,11 +296,6 @@
   """
   (xml, new_xml) = _GetOldAndUpdatedXml(histogram_enum_name, source_enum_values,
                                         source_enum_path, caller_script_name)
-  if not diff_util.PromptUserToAcceptDiff(
-      xml, new_xml, 'Is the updated version acceptable?'):
-    Log('Cancelled.')
-    return
-
   with io.open(ENUMS_PATH, 'w', encoding='utf-8', newline='') as f:
     f.write(new_xml)
 
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 307d2ce..778f3f1 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -14,7 +14,7 @@
         },
         "mac": {
             "hash": "07ed4c4c0204d1b72e6d6000a419017b9e1d34c4",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/7d9bdde6f8d732767f0fce4273f492648335c77a/trace_processor_shell"
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/5d21cea244356ef7dcc225131564ecfe778348fa/trace_processor_shell"
         },
         "mac_arm64": {
             "hash": "5f47ee79e59d00bf3889d30ca52315522c158040",
@@ -22,7 +22,7 @@
         },
         "linux": {
             "hash": "e71e0b0a707f891005344f0ba5b6d7468380c2a8",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/7d9bdde6f8d732767f0fce4273f492648335c77a/trace_processor_shell"
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/5d21cea244356ef7dcc225131564ecfe778348fa/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml
index 2358dfd..dfcf08b 100644
--- a/tools/traffic_annotation/summary/annotations.xml
+++ b/tools/traffic_annotation/summary/annotations.xml
@@ -404,7 +404,7 @@
  <item id="password_sync_token_fetcher" added_in_milestone="110" content_hash_code="0451c1ff" os_list="chromeos" file_path="chrome/browser/ash/login/saml/password_sync_token_fetcher.cc" />
  <item id="projector_xhr_loader" added_in_milestone="110" content_hash_code="071c4ac5" os_list="chromeos" file_path="ash/webui/projector_app/projector_xhr_sender.cc" />
  <item id="cloud_speech_recognition" added_in_milestone="110" content_hash_code="00d56fd8" os_list="linux,windows,chromeos" file_path="components/live_caption/live_translate_controller.cc" />
- <item id="bruschetta_installer_download" added_in_milestone="110" content_hash_code="01b953f4" os_list="chromeos" file_path="chrome/browser/ash/bruschetta/bruschetta_installer.cc" />
+ <item id="bruschetta_installer_download" added_in_milestone="110" content_hash_code="01b953f4" os_list="chromeos" file_path="chrome/browser/ash/bruschetta/bruschetta_installer_impl.cc" />
  <item id="quick_start_session_auth_requester" added_in_milestone="110" content_hash_code="08353e70" os_list="chromeos" file_path="chrome/browser/ash/login/oobe_quick_start/second_device_auth_broker.cc" />
  <item id="network_diagnostics_routines" added_in_milestone="110" content_hash_code="0007b237" os_list="chromeos" file_path="chrome/browser/ash/net/network_diagnostics/http_request_manager.cc" />
  <item id="trial_group_lookup" added_in_milestone="110" content_hash_code="047aeeca" os_list="chromeos" file_path="chromeos/ash/components/trial_group/trial_group_checker.cc" />
diff --git a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc
index 1e87e1c..dc9587d 100644
--- a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc
+++ b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc
@@ -1629,6 +1629,18 @@
   SetEnd(AXNodePosition::CreateNullPosition());
 }
 
+const AXPlatformNodeTextRangeProviderWin::AXPositionInstance&
+AXPlatformNodeTextRangeProviderWin::TextRangeEndpoints::GetStart() {
+  ValidateEndpointsAfterNodeDeletionIfNeeded();
+  return start_;
+}
+
+const AXPlatformNodeTextRangeProviderWin::AXPositionInstance&
+AXPlatformNodeTextRangeProviderWin::TextRangeEndpoints::GetEnd() {
+  ValidateEndpointsAfterNodeDeletionIfNeeded();
+  return end_;
+}
+
 void AXPlatformNodeTextRangeProviderWin::TextRangeEndpoints::SetStart(
     AXPositionInstance new_start) {
   bool did_tree_change = start_->tree_id() != new_start->tree_id();
@@ -1694,6 +1706,9 @@
   DCHECK(node);
   DCHECK_EQ(tree->GetAXTreeID(), node->tree()->GetAXTreeID());
 
+  // Validate now if we haven't done so yet.
+  ValidateEndpointsAfterNodeDeletionIfNeeded();
+
   AdjustEndpointForSubtreeDeletion(tree, node, true /* is_start_endpoint */);
   AdjustEndpointForSubtreeDeletion(tree, node, false /* is_start_endpoint */);
 }
@@ -1790,27 +1805,20 @@
     AXTree* tree,
     AXNodeID node_id) {
   DCHECK(tree);
+  // We only need validation in the case where a deleted node matches the
+  // previously stored |validation_necessary_for_*|. If this is the case,
+  // mark this any needed so that we force validation before using the endpoint.
 
   if (validation_necessary_for_start_.has_value() &&
       validation_necessary_for_start_->tree_id == tree->GetAXTreeID() &&
       validation_necessary_for_start_->node_id == node_id) {
-    if (!start_->IsNullPosition() && start_->GetAnchor()->IsDataValid())
-      SetStart(start_->AsValidPosition());
-    else
-      SetStart(AXNodePosition::CreateNullPosition());
-
-    validation_necessary_for_start_ = absl::nullopt;
+    validation_necessary_for_start_->validation_needed = true;
   }
 
   if (validation_necessary_for_end_.has_value() &&
       validation_necessary_for_end_->tree_id == tree->GetAXTreeID() &&
       validation_necessary_for_end_->node_id == node_id) {
-    if (!end_->IsNullPosition() && end_->GetAnchor()->IsDataValid())
-      SetEnd(end_->AsValidPosition());
-    else
-      SetEnd(AXNodePosition::CreateNullPosition());
-
-    validation_necessary_for_end_ = absl::nullopt;
+    validation_necessary_for_end_->validation_needed = true;
   }
 }
 
@@ -1822,4 +1830,29 @@
   }
 }
 
+// Ensures that our endpoints are always valid (step 2, all scenarios). See
+// comment in header file for more details.
+void AXPlatformNodeTextRangeProviderWin::TextRangeEndpoints::
+    ValidateEndpointsAfterNodeDeletionIfNeeded() {
+  if (validation_necessary_for_start_.has_value() &&
+      validation_necessary_for_start_->validation_needed) {
+    if (!start_->IsNullPosition() && start_->GetAnchor()->IsDataValid()) {
+      SetStart(start_->AsValidPosition());
+    } else {
+      SetStart(AXNodePosition::CreateNullPosition());
+    }
+    validation_necessary_for_start_ = absl::nullopt;
+  }
+
+  if (validation_necessary_for_end_.has_value() &&
+      validation_necessary_for_end_->validation_needed) {
+    if (!end_->IsNullPosition() && end_->GetAnchor()->IsDataValid()) {
+      SetEnd(end_->AsValidPosition());
+    } else {
+      SetEnd(AXNodePosition::CreateNullPosition());
+    }
+    validation_necessary_for_end_ = absl::nullopt;
+  }
+}
+
 }  // namespace ui
diff --git a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.h b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.h
index 2b39df7..d1e0e216 100644
--- a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.h
+++ b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.h
@@ -253,12 +253,13 @@
   // before the TextRangeEndpoints does, so when the destructor of the
   // ScopedObserver calls ScopedObserver::RemoveAll on an already deleted
   // AXTreeManager, it crashes.
-  class TextRangeEndpoints : public AXTreeObserver {
+  class COMPONENT_EXPORT(AX_PLATFORM) TextRangeEndpoints
+      : public AXTreeObserver {
    public:
     TextRangeEndpoints();
     ~TextRangeEndpoints() override;
-    const AXPositionInstance& GetStart() const { return start_; }
-    const AXPositionInstance& GetEnd() const { return end_; }
+    const AXPositionInstance& GetStart();
+    const AXPositionInstance& GetEnd();
     void SetStart(AXPositionInstance new_start);
     void SetEnd(AXPositionInstance new_end);
 
@@ -272,11 +273,21 @@
     struct DeletionOfInterest {
       AXTreeID tree_id;
       AXNodeID node_id;
+      // Needed to defer validation from OnNodeDeleted to
+      // ValidateEndpointsAfterNodeDeletionIfNeeded.
+      bool validation_needed;
     };
 
     void AdjustEndpointForSubtreeDeletion(AXTree* tree,
                                           const AXNode* const node,
                                           bool is_start_endpoint);
+    // TODO(accessibility): Re-evaluate if we want to continue deferring
+    // validation after the BrowserAccessibilityManager-specific nodes have been
+    // moved to a single unified tree. At this point, deferring will no longer
+    // be necessary as there would be no danger in accessing the tree during
+    // OnNodeDeleted. However, it may still be preferable to defer the
+    // validation to keep work out of unserialize.
+    void ValidateEndpointsAfterNodeDeletionIfNeeded();
 
     AXPositionInstance start_;
     AXPositionInstance end_;
@@ -284,7 +295,9 @@
     absl::optional<DeletionOfInterest> validation_necessary_for_start_;
     absl::optional<DeletionOfInterest> validation_necessary_for_end_;
   };
-  TextRangeEndpoints endpoints_;
+  // This is marked as mutable since endpoints will lazily validate their
+  // positions after a deletion of interest was actually deleted.
+  mutable TextRangeEndpoints endpoints_;
 };
 
 }  // namespace ui
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc
index 79b86ba..72064653 100644
--- a/ui/accessibility/platform/ax_platform_node_win.cc
+++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -1532,6 +1532,7 @@
   WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_ACC_DO_DEFAULT_ACTION);
   AXPlatformNodeWin* target;
   COM_OBJECT_VALIDATE_VAR_ID_AND_GET_TARGET(var_id, target);
+
   AXActionData data;
   data.action = ax::mojom::Action::kDoDefault;
 
@@ -1549,6 +1550,7 @@
   AXPlatformNodeWin* target;
   COM_OBJECT_VALIDATE_VAR_ID_4_ARGS_AND_GET_TARGET(
       var_id, physical_pixel_left, physical_pixel_top, width, height, target);
+  NotifyObserverForMSAAUsage();
 
   gfx::Rect bounds = target->GetDelegate()->GetBoundsRect(
       AXCoordinateSystem::kScreenPhysicalPixels,
@@ -1570,6 +1572,7 @@
   WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_ACC_NAVIGATE);
   AXPlatformNodeWin* target;
   COM_OBJECT_VALIDATE_VAR_ID_1_ARG_AND_GET_TARGET(start, end, target);
+
   end->vt = VT_EMPTY;
   if ((nav_dir == NAVDIR_FIRSTCHILD || nav_dir == NAVDIR_LASTCHILD) &&
       V_VT(&start) == VT_I4 && V_I4(&start) != CHILDID_SELF) {
@@ -1688,6 +1691,7 @@
 IFACEMETHODIMP AXPlatformNodeWin::get_accChildCount(LONG* child_count) {
   WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_ACC_CHILD_COUNT);
   COM_OBJECT_VALIDATE_1_ARG(child_count);
+
   *child_count = GetDelegate()->GetChildCount();
   return S_OK;
 }
@@ -1731,6 +1735,7 @@
 IFACEMETHODIMP AXPlatformNodeWin::get_accFocus(VARIANT* focus_child) {
   WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_ACC_FOCUS);
   COM_OBJECT_VALIDATE_1_ARG(focus_child);
+
   gfx::NativeViewAccessible focus_accessible = GetDelegate()->GetFocus();
   if (focus_accessible == this) {
     focus_child->vt = VT_I4;
@@ -1766,6 +1771,7 @@
   WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_ACC_NAME);
   AXPlatformNodeWin* target;
   COM_OBJECT_VALIDATE_VAR_ID_1_ARG_AND_GET_TARGET(var_id, name_bstr, target);
+  NotifyObserverForMSAAUsage();
 
   for (WinAccessibilityAPIUsageObserver& observer :
        GetWinAccessibilityAPIUsageObserverList()) {
@@ -1801,6 +1807,7 @@
   WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_ACC_ROLE);
   AXPlatformNodeWin* target;
   COM_OBJECT_VALIDATE_VAR_ID_1_ARG_AND_GET_TARGET(var_id, role, target);
+  NotifyObserverForMSAAUsage();
 
   role->vt = VT_I4;
   role->lVal = target->MSAARole();
@@ -1811,6 +1818,8 @@
   WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_ACC_STATE);
   AXPlatformNodeWin* target;
   COM_OBJECT_VALIDATE_VAR_ID_1_ARG_AND_GET_TARGET(var_id, state, target);
+  NotifyObserverForMSAAUsage();
+
   state->vt = VT_I4;
   state->lVal = target->MSAAState();
   return S_OK;
@@ -1826,6 +1835,7 @@
   WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_ACC_VALUE);
   AXPlatformNodeWin* target;
   COM_OBJECT_VALIDATE_VAR_ID_1_ARG_AND_GET_TARGET(var_id, value, target);
+
   // Special case for indeterminate progressbar.
   if (GetRole() == ax::mojom::Role::kProgressIndicator &&
       !HasFloatAttribute(ax::mojom::FloatAttribute::kValueForRange)) {
@@ -1857,6 +1867,7 @@
 IFACEMETHODIMP AXPlatformNodeWin::get_accSelection(VARIANT* selected) {
   WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_ACC_SELECTION);
   COM_OBJECT_VALIDATE_1_ARG(selected);
+
   std::vector<Microsoft::WRL::ComPtr<IDispatch>> selected_nodes;
   for (size_t i = 0; i < GetDelegate()->GetChildCount(); ++i) {
     auto* node = static_cast<AXPlatformNodeWin*>(
@@ -1913,6 +1924,7 @@
   AXPlatformNodeWin* target;
   COM_OBJECT_VALIDATE_VAR_ID_2_ARGS_AND_GET_TARGET(var_id, help_file, topic_id,
                                                    target);
+
   if (help_file) {
     *help_file = nullptr;
   }
@@ -8127,6 +8139,13 @@
   SanitizeStringAttributeForIA2(input, output);
 }
 
+void AXPlatformNodeWin::NotifyObserverForMSAAUsage() const {
+  for (WinAccessibilityAPIUsageObserver& observer :
+       GetWinAccessibilityAPIUsageObserverList()) {
+    observer.OnMSAAUsed();
+  }
+}
+
 void AXPlatformNodeWin::NotifyAPIObserverForPatternRequest(
     PATTERNID pattern_id) const {
   // Non-web content is always enabled, if a client isn't looking for web
diff --git a/ui/accessibility/platform/ax_platform_node_win.h b/ui/accessibility/platform/ax_platform_node_win.h
index f390802..b4437c30 100644
--- a/ui/accessibility/platform/ax_platform_node_win.h
+++ b/ui/accessibility/platform/ax_platform_node_win.h
@@ -344,6 +344,7 @@
  public:
   WinAccessibilityAPIUsageObserver();
   virtual ~WinAccessibilityAPIUsageObserver();
+  virtual void OnMSAAUsed() = 0;
   virtual void OnIAccessible2Used() = 0;
   virtual void OnScreenReaderHoneyPotQueried() = 0;
   virtual void OnAccNameCalled() = 0;
@@ -1516,6 +1517,12 @@
       const std::wstring& active_composition_text,
       bool is_composition_committed);
 
+  // Notifies observers that basic MSAA usage was detected. Only some of the
+  // APIs were chosen to avoid accessibility being enabled unnecessarily or
+  // unexpectedly in a test environment, while still ensuring that clients that
+  // only use MSAA/IAccessible have a way to turn on accessibility.
+  void NotifyObserverForMSAAUsage() const;
+
   void NotifyAPIObserverForPatternRequest(PATTERNID pattern_id) const;
   void NotifyAPIObserverForPropertyRequest(PROPERTYID property_id) const;
 
diff --git a/ui/file_manager/file_manager/widgets/xf_breadcrumb.ts b/ui/file_manager/file_manager/widgets/xf_breadcrumb.ts
index c7e19a3..fbe5d4f 100644
--- a/ui/file_manager/file_manager/widgets/xf_breadcrumb.ts
+++ b/ui/file_manager/file_manager/widgets/xf_breadcrumb.ts
@@ -265,7 +265,7 @@
 }
 
 function getCSS() {
-  const commonCSS = css`
+  const legacyStyle = css`
     :host([hidden]),
     [hidden] {
       display: none !important;
@@ -286,13 +286,24 @@
       white-space: nowrap;
     }
 
+    /* No paper ripple for path button in Legacy. */
+    button paper-ripple {
+      display: none;
+    }
+
+    #elider-menu button paper-ripple {
+      display: block;
+    }
+
     span[caret] {
       -webkit-mask-image: url(/foreground/images/files/ui/arrow_right.svg);
       -webkit-mask-position: center;
       -webkit-mask-repeat: no-repeat;
+      background-color: var(--cros-icon-color-secondary);
       display: inline-flex;
       height: 20px;
       min-width: 20px;
+      padding: 8px 0;
       width: 20px;
     }
 
@@ -304,6 +315,7 @@
       /* don't use browser's background-color. */
       background-color: unset;
       border: none;
+      color: var(--cros-text-color-primary);
       cursor: pointer;
       display: inline-block;
       position: relative;
@@ -336,6 +348,7 @@
       -webkit-mask-image: url(/foreground/images/files/ui/menu_ng.svg);
       -webkit-mask-position: center;
       -webkit-mask-repeat: no-repeat;
+      background-color: var(--cros-icon-color-primary);
       height: 48px;
       margin-inline-start: var(--tap-target-shift);
       margin-top: var(--tap-target-shift);
@@ -349,55 +362,12 @@
       border-radius: 50%;
       display: inline-flex;
       height: 36px;
+      margin: 2px 0;
       min-width: 36px;
       padding: 0;
       width: 36px;
     }
 
-    #elider-menu button {
-      display: block;
-      font-family: 'Roboto';
-      font-size: 13px;
-      max-width: min(288px, 40vw);
-      min-width: 192px;  /* menu width */
-      padding: 0 16px;
-      position: relative;
-      text-align: start;
-    }
-
-    /** Reset the hover color when using keyboard to navigate the menu items. */
-    :host-context(.focus-outline-visible) #elider-menu button:hover {
-      background-color: unset;
-    }
-  `;
-
-  const legacyStyle = css`
-    /* No paper ripple for path button in Legacy. */
-    button paper-ripple {
-      display: none;
-    }
-
-    #elider-menu button paper-ripple {
-      display: block;
-    }
-
-    span[caret] {
-      background-color: var(--cros-icon-color-secondary);
-      padding: 8px 0;
-    }
-
-    span[elider] {
-      background-color: var(--cros-icon-color-primary);
-    }
-
-    button {
-      color: var(--cros-text-color-primary);
-    }
-
-    button[elider] {
-      margin: 2px 0;
-    }
-
     :host > button:not([elider]) {
       border-radius: 4px;
       height: 32px;
@@ -435,16 +405,30 @@
       background-color: var(--cros-icon-button-pressed-color);
     }
 
+
     #elider-menu button {
+      color: var(--cros-menu-label-color);
+      display: block;
+      font-family: 'Roboto';
+      font-size: 13px;
       height: 32px;
       margin: 0;
-      color: var(--cros-menu-label-color);
+      max-width: min(288px, 40vw);
+      min-width: 192px;  /* menu width */
+      padding: 0 16px;
+      position: relative;
+      text-align: start;
     }
 
     :host-context(.focus-outline-visible) #elider-menu button:focus {
       background-color: var(--cros-menu-item-background-hover);
     }
 
+    /** Reset the hover color when using keyboard to navigate the menu items. */
+    :host-context(.focus-outline-visible) #elider-menu button:hover {
+      background-color: unset;
+    }
+
     cr-action-menu {
       --cr-menu-background-color: var(--cros-bg-color-elevation-2);
       --cr-menu-background-sheen: none;
@@ -453,16 +437,95 @@
   `;
 
   const refresh23Style = css`
-    span[caret] {
-      background-color: var(--cros-sys-secondary);
+    :host([hidden]),
+    [hidden] {
+      display: none !important;
     }
 
-    span[elider] {
+    :host-context(html.col-resize) > * {
+      cursor: unset !important;
+    }
+
+    :host {
+      align-items: center;
+      display: flex;
+      font-family: 'Roboto Medium';
+      font-size: 14px;
+      outline: none;
+      overflow: hidden;
+      user-select: none;
+      white-space: nowrap;
+    }
+
+    span[caret] {
+      -webkit-mask-image: url(/foreground/images/files/ui/arrow_right.svg);
+      -webkit-mask-position: center;
+      -webkit-mask-repeat: no-repeat;
       background-color: var(--cros-sys-secondary);
+      display: inline-flex;
+      height: 20px;
+      min-width: 20px;
+      width: 20px;
+    }
+
+    :host-context(html[dir='rtl']) span[caret] {
+      transform: scaleX(-1);
     }
 
     button {
+      /* don't use browser's background-color. */
+      background-color: unset;
+      border: none;
       color: var(--cros-sys-secondary);
+      cursor: pointer;
+      display: inline-block;
+      position: relative;
+
+      /* don't use browser's button font. */
+      font: inherit;
+      margin: 0;
+
+      /* elide wide text */
+      max-width: 200px;
+      /* text rendering debounce: fix a minimum width. */
+      min-width: calc(12px + 1em);
+      outline: none;
+      overflow: hidden;
+
+      /* text rendering debounce: center. */
+      text-align: center;
+      text-overflow: ellipsis;
+    }
+
+    button[disabled] {
+      cursor: default;
+      font-weight: 500;
+      margin-inline-end: 4px;
+      pointer-events: none;
+    }
+
+    span[elider] {
+      --tap-target-shift: -6px;
+      -webkit-mask-image: url(/foreground/images/files/ui/menu_ng.svg);
+      -webkit-mask-position: center;
+      -webkit-mask-repeat: no-repeat;
+      background-color: var(--cros-sys-secondary);
+      height: 48px;
+      margin-inline-start: var(--tap-target-shift);
+      margin-top: var(--tap-target-shift);
+      min-width: 48px;
+      position: relative;
+      transform: rotate(90deg);
+      width: 48px;
+    }
+
+    button[elider] {
+      border-radius: 50%;
+      display: inline-flex;
+      height: 36px;
+      min-width: 36px;
+      padding: 0;
+      width: 36px;
     }
 
     :host > button:not([elider]) {
@@ -503,8 +566,16 @@
     }
 
     #elider-menu button {
-      height: 36px;
       color: var(--cros-sys-on_surface);
+      display: block;
+      font-family: 'Roboto';
+      font-size: 13px;
+      height: 36px;
+      max-width: min(288px, 40vw);
+      min-width: 192px;  /* menu width */
+      padding: 0 16px;
+      position: relative;
+      text-align: start;
     }
 
     :host-context(.focus-outline-visible) #elider-menu button:focus {
@@ -512,6 +583,11 @@
       outline-offset: -2px;
     }
 
+    /** Reset the hover color when using keyboard to navigate the menu items. */
+    :host-context(.focus-outline-visible) #elider-menu button:hover {
+      background-color: unset;
+    }
+
     cr-action-menu {
       --cr-menu-background-color: var(--cros-sys-app_base_elevated);
       --cr-menu-background-sheen: none;
@@ -522,7 +598,6 @@
   `;
 
   return [
-    commonCSS,
     addCSSPrefixSelector(legacyStyle, '[theme="legacy"]'),
     addCSSPrefixSelector(refresh23Style, '[theme="refresh23"]'),
   ];
diff --git a/ui/file_manager/file_manager/widgets/xf_breadcrumb_unittest.ts b/ui/file_manager/file_manager/widgets/xf_breadcrumb_unittest.ts
index 81dc9617..50755b9 100644
--- a/ui/file_manager/file_manager/widgets/xf_breadcrumb_unittest.ts
+++ b/ui/file_manager/file_manager/widgets/xf_breadcrumb_unittest.ts
@@ -15,6 +15,7 @@
  * path using the element.path getter.
  */
 export function setUp() {
+  document.body.setAttribute('theme', 'refresh23');
   document.body.innerHTML = '<xf-breadcrumb></xf-breadcrumb>';
   const breadcrumb = document.querySelector('xf-breadcrumb');
   assertEquals('', breadcrumb!.path);
diff --git a/ui/file_manager/file_manager/widgets/xf_tree_item.ts b/ui/file_manager/file_manager/widgets/xf_tree_item.ts
index 19271efc..bc51ff63 100644
--- a/ui/file_manager/file_manager/widgets/xf_tree_item.ts
+++ b/ui/file_manager/file_manager/widgets/xf_tree_item.ts
@@ -409,7 +409,175 @@
 }
 
 function getCSS() {
-  const commonCSS = css`
+  const legacyStyle = css`
+    :host {
+      --xf-tree-item-indent: 22;
+    }
+
+    ul {
+      list-style: none;
+      margin: 0;
+      outline: none;
+      padding: 0;
+    }
+
+    li {
+      display: block;
+    }
+
+    li:focus-visible {
+      outline: none;
+    }
+
+    :host([separator])::before {
+      border-bottom: 1px solid var(--cros-separator-color);
+      content: '';
+      display: block;
+      margin: 8px 0;
+      width: 100%;
+    }
+
+    .tree-row {
+      align-items: center;
+      border-inline-start-width: 0 !important;
+      border-radius: 0 20px 20px 0;
+      border: 2px solid transparent;
+      box-sizing: border-box;
+      color: var(--cros-text-color-primary);
+      cursor: pointer;
+      display: flex;
+      height: 32px;
+      margin-inline-end: 6px;
+      padding: 4px 0;
+      position: relative;
+      user-select: none;
+      white-space: nowrap;
+    }
+
+    :host-context(html[dir=rtl]) .tree-row {
+      border-radius: 20px 0 0 20px;
+    }
+
+    :host(:not([selected]):not([disabled]):not([editing]))
+        li:not(:focus-visible) .tree-row:hover {
+      background-color: var(--cros-ripple-color);
+    }
+
+    :host([selected]) .tree-row {
+      background-color: var(--cros-highlight-color);
+      color: var(--cros-text-color-selection);
+    }
+
+    :host([disabled]) .tree-row {
+      opacity: var(--cros-disabled-opacity);
+      pointer-events: none;
+    }
+
+    :host-context(.pointer-active):host(:not([selected]):not([disabled]):not([editing]))
+        li:not(:focus-visible) .tree-row:not(:hover):active {
+      background-color: var(--cros-ripple-color);
+    }
+
+    li:focus-visible .tree-row {
+      border: 2px solid var(--cros-focus-ring-color);
+      z-index: 2;
+    }
+
+    :host-context(.pointer-active) .tree-row:not(:active) {
+      cursor: default;
+    }
+
+    :host-context(.pointer-active):host(:not([selected]):not([disabled]):not([editing]))
+        li:not(:focus-visible) .tree-row:not(:active):hover {
+      background-color: unset;
+    }
+
+    .expand-icon {
+      -webkit-mask-image: url(../foreground/images/files/ui/sort_desc.svg);
+      -webkit-mask-position: center;
+      -webkit-mask-repeat: no-repeat;
+      background-color: currentColor;
+      flex: none;
+      height: 20px;
+      padding: 6px;
+      position: relative;
+      transform: rotate(-90deg);
+      transition: all 150ms;
+      visibility: hidden;
+      width: 20px;
+    }
+
+    li[aria-expanded] .expand-icon {
+      visibility: visible;
+    }
+
+    :host-context(html[dir=rtl]) .expand-icon {
+      transform: rotate(90deg);
+    }
+
+    :host([expanded]) .expand-icon {
+      transform: rotate(0);
+    }
+
+    .tree-label-icon {
+      --xf-icon-color: var(--cros-icon-color-primary);
+      flex: none;
+      left: -4px;
+      position: relative;
+      right: -4px;
+    }
+
+    :host([selected]) .tree-label-icon {
+      --xf-icon-color: var(--cros-icon-color-selection);
+    }
+
+    .tree-label {
+      display: block;
+      flex: auto;
+      font-weight: 500;
+      margin: 0 12px;
+      overflow: hidden;
+      text-overflow: ellipsis;
+      white-space: pre;
+    }
+
+    .rename {
+      background-color: var(--cros-bg-color);
+      border-radius: 2px;
+      border: none;
+      caret-color: var(--cros-textfield-cursor-color-focus);
+      color: var(--cros-text-color-primary);
+      margin: 0 10px;
+      outline: 2px solid var(--cros-focus-ring-color);
+      overflow: hidden;
+    }
+
+    paper-ripple {
+      display: none;
+    }
+
+    /* We need to ensure that even empty labels take up space */
+    .tree-label:empty::after {
+      content: ' ';
+      white-space: pre;
+    }
+
+    .tree-children {
+      display: none;
+    }
+
+    :host([expanded]) .tree-children {
+      display: block;
+    }
+
+    slot[name="trailingIcon"]::slotted(*) {
+      height: 20px;
+      margin: 0;
+      width: 20px;
+    }
+  `;
+
+  const refresh23Style = css`
     :host {
       --xf-tree-item-indent: ${TREE_ITEM_INDENT};
     }
@@ -440,27 +608,50 @@
     .tree-row {
       align-items: center;
       border-inline-start-width: 0 !important;
+      border-radius: 20px;
       box-sizing: border-box;
+      color: var(--cros-sys-on_surface);
       cursor: pointer;
       display: flex;
+      height: 40px;
+      margin: 8px 0;
       position: relative;
       user-select: none;
       white-space: nowrap;
     }
 
-    li:focus-visible .tree-row {
-      z-index: 2;
+    :host(:not([selected]):not([disabled]):not([editing]))
+        li:not(:focus-visible) .tree-row:hover {
+      background-color: var(--cros-sys-hover_on_subtle);
+    }
+
+    :host([selected]) .tree-row {
+      background-color: var(--cros-sys-primary);
+      color: var(--cros-sys-on_primary);
     }
 
     :host([disabled]) .tree-row {
+      color: var(--cros-sys-disabled);
       pointer-events: none;
     }
 
+    li:focus-visible .tree-row {
+      outline: 2px solid var(--cros-sys-focus_ring);
+      outline-offset: 2px;
+      z-index: 2;
+    }
+
+    :host-context(.pointer-active):host(:not([selected]):not([disabled]):not([editing]))
+        li:not(:focus-visible) .tree-row:not(:hover):active {
+      background-color: var(--cros-sys-hover_on_subtle);
+    }
+
     :host-context(.pointer-active) .tree-row:not(:active) {
       cursor: default;
     }
 
-    :host-context(.pointer-active):host(:not([selected]):not([disabled]):not([editing])) li:not(:focus-visible) .tree-row:not(:active):hover {
+    :host-context(.pointer-active):host(:not([selected]):not([disabled]):not([editing]))
+        li:not(:focus-visible) .tree-row:not(:active):hover {
       background-color: unset;
     }
 
@@ -471,6 +662,7 @@
       background-color: currentColor;
       flex: none;
       height: 20px;
+      margin-inline-start: 28px;
       position: relative;
       transform: rotate(-90deg);
       transition: all 150ms;
@@ -491,22 +683,51 @@
     }
 
     .tree-label-icon {
+      --xf-icon-color: var(--cros-sys-on_surface);
       flex: none;
     }
 
+    :host([selected]) .tree-label-icon {
+      --xf-icon-color: var(--cros-sys-on_primary)
+    }
+
+    :host([disabled]) .tree-label-icon {
+      --xf-icon-color: var(--cros-sys-disabled);
+    }
+
     .tree-label {
       display: block;
       flex: auto;
       font-weight: 500;
+      margin-inline-start: 8px;
       overflow: hidden;
       text-overflow: ellipsis;
       white-space: pre;
     }
 
     .rename {
+      background-color: var(--cros-sys-app_base);
+      border-radius: 4px;
       border: none;
+      color: var(--cros-sys-on_surface);
+      height: 20px;
       margin: 0 10px;
+      outline: 2px solid var(--cros-sys-focus_ring);
       overflow: hidden;
+      padding: 1px 8px;
+    }
+
+    :host([selected]) .rename {
+      outline: 2px solid var(--cros-sys-inverse_primary);
+    }
+
+    .rename::selection {
+      background-color: var(--cros-sys-highlight_text)
+    }
+
+    paper-ripple {
+      border-radius: 20px;
+      color: var(--cros-sys-ripple_primary);
     }
 
     /* We need to ensure that even empty labels take up space */
@@ -528,158 +749,9 @@
       margin: 0;
       width: 20px;
     }
-  `;
-
-  const legacyStyle = css`
-    :host {
-      --xf-tree-item-indent: 22;
-    }
-
-    .tree-row {
-      border: 2px solid transparent;
-      border-radius: 0 20px 20px 0;
-      color: var(--cros-text-color-primary);
-      height: 32px;
-      margin-inline-end: 6px;
-      padding: 4px 0;
-    }
-
-    :host-context(html[dir=rtl]) .tree-row {
-      border-radius: 20px 0 0 20px;
-    }
-
-    :host(:not([selected]):not([disabled]):not([editing]))
-        li:not(:focus-visible) .tree-row:hover {
-      background-color: var(--cros-ripple-color);
-    }
-
-    :host([selected]) .tree-row {
-      background-color: var(--cros-highlight-color);
-      color: var(--cros-text-color-selection);
-    }
-
-    :host([disabled]) .tree-row {
-      opacity: var(--cros-disabled-opacity);
-    }
-
-    :host-context(.pointer-active):host(:not([selected]):not([disabled]):not([editing]))
-        li:not(:focus-visible) .tree-row:not(:hover):active {
-      background-color: var(--cros-ripple-color);
-    }
-
-    li:focus-visible .tree-row {
-      border: 2px solid var(--cros-focus-ring-color);
-    }
-
-    .expand-icon {
-      padding: 6px;
-    }
-
-    .tree-label-icon {
-      --xf-icon-color: var(--cros-icon-color-primary);
-      left: -4px;
-      position: relative;
-      right: -4px;
-    }
-
-    :host([selected]) .tree-label-icon {
-      --xf-icon-color: var(--cros-icon-color-selection);
-    }
-
-    .tree-label {
-      margin: 0 12px;
-    }
-
-    .rename {
-      background-color: var(--cros-bg-color);
-      border-radius: 2px;
-      caret-color: var(--cros-textfield-cursor-color-focus);
-      color: var(--cros-text-color-primary);
-      outline: 2px solid var(--cros-focus-ring-color);
-    }
-
-    paper-ripple {
-      display: none;
-    }
-  `;
-
-  const refresh23Style = css`
-    .tree-row {
-      border-radius: 20px;
-      color: var(--cros-sys-on_surface);
-      height: 40px;
-      margin: 8px 0;
-    }
-
-    :host(:not([selected]):not([disabled]):not([editing]))
-        li:not(:focus-visible) .tree-row:hover {
-      background-color: var(--cros-sys-hover_on_subtle);
-    }
-
-    :host([selected]) .tree-row {
-      background-color: var(--cros-sys-primary);
-      color: var(--cros-sys-on_primary);
-    }
-
-    :host([disabled]) .tree-row {
-      color: var(--cros-sys-disabled);
-    }
-
-    li:focus-visible .tree-row {
-      outline: 2px solid var(--cros-sys-focus_ring);
-      outline-offset: 2px;
-    }
-
-    :host-context(.pointer-active):host(:not([selected]):not([disabled]):not([editing]))
-        li:not(:focus-visible) .tree-row:not(:hover):active {
-      background-color: var(--cros-sys-hover_on_subtle);
-    }
-
-    .expand-icon {
-      margin-inline-start: 28px;
-    }
-
-    .tree-label-icon {
-      --xf-icon-color: var(--cros-sys-on_surface);
-    }
-
-    :host([selected]) .tree-label-icon {
-      --xf-icon-color: var(--cros-sys-on_primary)
-    }
-
-    :host([disabled]) .tree-label-icon {
-      --xf-icon-color: var(--cros-sys-disabled);
-    }
-
-    .tree-label {
-      margin-inline-start: 8px;
-    }
-
-    .rename {
-      background-color: var(--cros-sys-app_base);
-      border-radius: 4px;
-      color: var(--cros-sys-on_surface);
-      height: 20px;
-      padding: 1px 8px;
-      outline: 2px solid var(--cros-sys-focus_ring);
-    }
-
-    :host([selected]) .rename {
-      outline: 2px solid var(--cros-sys-inverse_primary);
-    }
-
-    .rename::selection {
-      background-color: var(--cros-sys-highlight_text)
-    }
-
-    paper-ripple {
-      border-radius: 20px;
-      color: var(--cros-sys-ripple_primary);
-    }
-  `;
+    `;
 
   return [
-    commonCSS,
     addCSSPrefixSelector(legacyStyle, '[theme="legacy"]'),
     addCSSPrefixSelector(refresh23Style, '[theme="refresh23"]'),
   ];
diff --git a/ui/file_manager/file_manager/widgets/xf_tree_item_unittest.ts b/ui/file_manager/file_manager/widgets/xf_tree_item_unittest.ts
index 9f933d6..061d6da 100644
--- a/ui/file_manager/file_manager/widgets/xf_tree_item_unittest.ts
+++ b/ui/file_manager/file_manager/widgets/xf_tree_item_unittest.ts
@@ -12,6 +12,7 @@
 
 /** Construct a single tree item. */
 async function setUpSingleTreeItem() {
+  document.body.setAttribute('theme', 'refresh23');
   document.body.innerHTML =
       '<xf-tree><xf-tree-item id="item1" label="item1"></xf-tree-item></xf-tree>';
   const element = document.querySelector('xf-tree-item');
diff --git a/ui/file_manager/file_manager/widgets/xf_tree_unittest.ts b/ui/file_manager/file_manager/widgets/xf_tree_unittest.ts
index be6e908b..f76f36f 100644
--- a/ui/file_manager/file_manager/widgets/xf_tree_unittest.ts
+++ b/ui/file_manager/file_manager/widgets/xf_tree_unittest.ts
@@ -11,6 +11,7 @@
 import {TreeItemCollapsedEvent, TreeItemExpandedEvent, XfTreeItem} from './xf_tree_item.js';
 
 export function setUp() {
+  document.body.setAttribute('theme', 'refresh23');
   document.body.innerHTML = '<xf-tree></xf-tree>';
 }
 
diff --git a/ui/gtk/native_theme_gtk.cc b/ui/gtk/native_theme_gtk.cc
index dc92e4d3..1ec57a14 100644
--- a/ui/gtk/native_theme_gtk.cc
+++ b/ui/gtk/native_theme_gtk.cc
@@ -324,7 +324,7 @@
                                            : GTK_STATE_FLAG_BACKDROP);
 
   SkBitmap bitmap =
-      GetWidgetBitmap(rect.size(), context, BG_RENDER_RECURSIVE, false);
+      GetWidgetBitmap(rect.size(), context, BG_RENDER_NORMAL, false);
   bitmap.setImmutable();
   canvas->drawImage(cc::PaintImage::CreateFromBitmap(std::move(bitmap)),
                     rect.x(), rect.y());
diff --git a/ui/gtk/window_frame_provider_gtk.cc b/ui/gtk/window_frame_provider_gtk.cc
index 9180d273..e866f32 100644
--- a/ui/gtk/window_frame_provider_gtk.cc
+++ b/ui/gtk/window_frame_provider_gtk.cc
@@ -136,6 +136,33 @@
   return bitmap.width();
 }
 
+// Returns true iff any part of the header is transparent (even a single pixel).
+// This is used as an optimization hint to the compositor so that it doesn't
+// have to composite behind opaque regions.  The consequence of a false-negative
+// is rendering artifacts, but the consequence of a false-positive is only a
+// slight performance penalty, so this function is intentionally conservative
+// in deciding if the header is translucent.
+bool HeaderIsTranslucent() {
+  // The arbitrary square size to render a sample header.
+  constexpr int kHeaderSize = 32;
+  auto context = HeaderContext(false, false);
+  ApplyCssToContext(context, R"(window, headerbar {
+    box-shadow: none;
+    border: none;
+    border-radius: 0;
+  })");
+  gfx::Size size_dip{kHeaderSize, kHeaderSize};
+  auto bitmap = PaintHeaderbar(size_dip, context, 1);
+  for (int x = 0; x < kHeaderSize; x++) {
+    for (int y = 0; y < kHeaderSize; y++) {
+      if (SkColorGetA(bitmap.getColor(x, y)) != SK_AlphaOPAQUE) {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
 // Returns int(scale * 100), which essentially limits the scale to fractions of
 // 100 and secures from rounding errors.
 int ToRoundedScale(float scale) {
@@ -180,6 +207,11 @@
   return top_corner_radius_dip_;
 }
 
+bool WindowFrameProviderGtk::IsTopFrameTranslucent() {
+  MaybeUpdateBitmaps(GetDeviceScaleFactor());
+  return top_frame_is_translucent_;
+}
+
 gfx::Insets WindowFrameProviderGtk::GetFrameThicknessDip() {
   MaybeUpdateBitmaps(GetDeviceScaleFactor());
   return frame_thickness_dip_;
@@ -329,6 +361,7 @@
   };
 
   top_corner_radius_dip_ = ComputeTopCornerRadius();
+  top_frame_is_translucent_ = !solid_frame_ && HeaderIsTranslucent();
 
   const auto previous_frame_thickness_dip_ = frame_thickness_dip_;
   frame_thickness_dip_ = gfx::Insets::TLBR(
diff --git a/ui/gtk/window_frame_provider_gtk.h b/ui/gtk/window_frame_provider_gtk.h
index d8cb2c6..32c3d63 100644
--- a/ui/gtk/window_frame_provider_gtk.h
+++ b/ui/gtk/window_frame_provider_gtk.h
@@ -23,6 +23,7 @@
 
   // ui::WindowFrameProvider:
   int GetTopCornerRadiusDip() override;
+  bool IsTopFrameTranslucent() override;
   gfx::Insets GetFrameThicknessDip() override;
   void PaintWindowFrame(gfx::Canvas* canvas,
                         const gfx::Rect& rect,
@@ -67,6 +68,7 @@
   // Scale-independent metric calculated based on the bitmaps.
   gfx::Insets frame_thickness_dip_;
   int top_corner_radius_dip_ = 0;
+  bool top_frame_is_translucent_ = false;
 
   // Cached bitmaps and metrics.  The scale is rounded to percent.
   base::flat_map<int, Asset> assets_;
diff --git a/ui/linux/window_frame_provider.h b/ui/linux/window_frame_provider.h
index fbaf912..2bc99c02 100644
--- a/ui/linux/window_frame_provider.h
+++ b/ui/linux/window_frame_provider.h
@@ -24,6 +24,9 @@
   // window behind the corners.
   virtual int GetTopCornerRadiusDip() = 0;
 
+  // Returns true iff any parts of the top frame are translucent.
+  virtual bool IsTopFrameTranslucent() = 0;
+
   // Returns the shadow and border drawn around the window in DIPs.
   virtual gfx::Insets GetFrameThicknessDip() = 0;
 
diff --git a/ui/views/layout/box_layout.cc b/ui/views/layout/box_layout.cc
index 6ccb3465..ddab6c0 100644
--- a/ui/views/layout/box_layout.cc
+++ b/ui/views/layout/box_layout.cc
@@ -383,11 +383,16 @@
 }
 
 int BoxLayout::GetFlexForView(const View* view) const {
-  auto it = flex_map_.find(view);
-  if (it == flex_map_.end())
-    return default_flex_;
-
-  return it->second.flex_weight;
+  // Give precedence to flex provided via the layout.
+  if (auto it = flex_map_.find(view); it != flex_map_.end()) {
+    return it->second.flex_weight;
+  }
+  // Respect flex provided via the `kFlexBehaviorKey`.
+  if (auto* flex_behavior_key = view->GetProperty(kFlexBehaviorKey)) {
+    return flex_behavior_key->weight();
+  }
+  // Fall back to default.
+  return default_flex_;
 }
 
 int BoxLayout::GetMinimumSizeForView(const View* view) const {
diff --git a/ui/views/layout/box_layout_unittest.cc b/ui/views/layout/box_layout_unittest.cc
index 4e4795fe..a64ad8f 100644
--- a/ui/views/layout/box_layout_unittest.cc
+++ b/ui/views/layout/box_layout_unittest.cc
@@ -704,6 +704,45 @@
   }
 }
 
+TEST_F(BoxLayoutTest, FlexBehavior) {
+  BoxLayout* layout = host_->SetLayoutManager(
+      std::make_unique<views::BoxLayout>(BoxLayout::Orientation::kVertical));
+
+  View* v1 =
+      host_->AddChildView(std::make_unique<StaticSizedView>(gfx::Size(20, 20)));
+  View* v2 =
+      host_->AddChildView(std::make_unique<StaticSizedView>(gfx::Size(20, 20)));
+
+  host_->SetBounds(0, 0, 20, 100);
+
+  // Views don't fill the available space by default.
+  test::RunScheduledLayout(host_.get());
+  EXPECT_EQ(gfx::Rect(0, 0, 20, 20).ToString(), v1->bounds().ToString());
+  EXPECT_EQ(gfx::Rect(0, 20, 20, 20).ToString(), v2->bounds().ToString());
+
+  // Set default flex so that both views fill 1/2 of the available space.
+  layout->SetDefaultFlex(1);
+  HandleHostLayoutManagerChanges();
+  EXPECT_EQ(gfx::Rect(0, 0, 20, 50).ToString(), v1->bounds().ToString());
+  EXPECT_EQ(gfx::Rect(0, 50, 20, 50).ToString(), v2->bounds().ToString());
+
+  // Set `kFlexBehaviorKey` so that the first view fills 2/3 of the available
+  // space. Flex set via `kFlexBehaviorKey` takes higher precedence than default
+  // flex.
+  v1->SetProperty(kFlexBehaviorKey, FlexSpecification().WithWeight(2));
+  HandleHostLayoutManagerChanges();
+  EXPECT_EQ(gfx::Rect(0, 0, 20, 60).ToString(), v1->bounds().ToString());
+  EXPECT_EQ(gfx::Rect(0, 60, 20, 40).ToString(), v2->bounds().ToString());
+
+  // Set flex so that the first view fills 3/4 of the available space. Flex for
+  // a view set on the `layout` takes higher precedence than flex set via
+  // `kFlexBehaviorKey`.
+  layout->SetFlexForView(v1, 3);
+  HandleHostLayoutManagerChanges();
+  EXPECT_EQ(gfx::Rect(0, 0, 20, 65).ToString(), v1->bounds().ToString());
+  EXPECT_EQ(gfx::Rect(0, 65, 20, 35).ToString(), v2->bounds().ToString());
+}
+
 TEST_F(BoxLayoutTest, MinimumCrossAxisVertical) {
   BoxLayout* layout = host_->SetLayoutManager(
       std::make_unique<BoxLayout>(BoxLayout::Orientation::kVertical));
diff --git a/ui/views/view_class_properties.h b/ui/views/view_class_properties.h
index 29ea7073f..986396a 100644
--- a/ui/views/view_class_properties.h
+++ b/ui/views/view_class_properties.h
@@ -54,7 +54,7 @@
     kHighlightPathGeneratorKey;
 
 // A property to store how a view should flex when placed in a layout.
-// Currently only supported by FlexLayout.
+// Currently only fully supported by FlexLayout. BoxLayout supports weight.
 VIEWS_EXPORT extern const ui::ClassProperty<FlexSpecification*>* const
     kFlexBehaviorKey;