diff --git a/DEPS b/DEPS
index 5d0a068..3dbcf58 100644
--- a/DEPS
+++ b/DEPS
@@ -295,7 +295,7 @@
   # 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': '8bddd05680c4a1b4939d9ecb67d2f8c3a7a89519',
+  'skia_revision': 'df5a545d503a2f79b4b1b91591a3e0836feb948a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -303,15 +303,15 @@
   # 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': '64cb7bc0bde94477d4334a19d2d1075f028a9cf4',
+  'angle_revision': 'fee1f5c36dd01eb0cda416e650468acf4b26de1e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': 'fab1949ad09f24f39108e1281bc1268844e65085',
+  'swiftshader_revision': '6f73609d079a320c1d3a00475ba9c30fafeccec9',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '69d11eaac7e4ef746b5b439bb9e5cf971c9ccdd8',
+  'pdfium_revision': '4e9c5b7500a79b5c3eb065a5bd63ed67b380ae5b',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
@@ -322,7 +322,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:10.20221207.2.1',
+  'fuchsia_version': 'version:10.20221207.3.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.
@@ -366,7 +366,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '13419d2560ca3c0237bd703cd7bb178b6f04ad10',
+  'catapult_revision': '562809c7e425cf02cbbab81a9ac89313b57c10ba',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -374,7 +374,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': '101087fa6e537640b3d6e2025482d4677f2b9e70',
+  'devtools_frontend_revision': 'e337e85a6371c5020ea467e632e08012c9a4fd5a',
   # 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.
@@ -410,11 +410,11 @@
   # 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': '7017ec264ca31610c68b3bfcbcff7c8d86da9f62',
+  'dawn_revision': '190586048a7c4fa735679b56ea1749b7b9629589',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'quiche_revision': '2baa83fd486ab0b49e54ad1857be6abb40ad49ac',
+  'quiche_revision': '99ce762dba455520c792f0deb3b42c395da95daf',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ios_webkit
   # and whatever else without interference from each other.
@@ -450,15 +450,15 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'resultdb_version': 'git_revision:6cc18e2763e180929d70c786b419c1f8e6bcc66c',
+  'resultdb_version': 'git_revision:39e20ee396fe4a84eaa7f7d389e5659198c12e87',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'libcxxabi_revision':    'f46bba92c0a967f8c538f0763f9167a3ee4d06f5',
+  'libcxxabi_revision':    '25a3d07096374aeeffa3dab8b582143dde5a9ca9',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'libunwind_revision':    'fd5b3b5068cce90dd7c07964cd8cdce2695088e9',
+  'libunwind_revision':    '09a1f53060bc601b5ee821d7ab52071eed096fda',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -478,7 +478,7 @@
 
   # If you change this, also update the libc++ revision in
   # //buildtools/deps_revisions.gni.
-  'libcxx_revision':       'a9779c11d2349375be0c29f7c42d9c42633297b5',
+  'libcxx_revision':       'e4e39cee1f5e89a9f9949084ba26a6efc3cd4141',
 
   # GN CIPD package version.
   'gn_version': 'git_revision:70d6c60823c0233a0f35eccc25b2b640d2980bdc',
@@ -776,12 +776,12 @@
 
   'src/clank': {
     'url': 'https://chrome-internal.googlesource.com/clank/internal/apps.git' + '@' +
-    'cfa55329605244454f43d78f688ee46a30836e3f',
+    'c37c81a1b327a1fbe28a583d142e44a75654d494',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
   'src/docs/website': {
-    'url': Var('chromium_git') + '/website.git' + '@' + 'c0f580131043e1f228bfdc31669997e9f86cb14b',
+    'url': Var('chromium_git') + '/website.git' + '@' + '5d599f528a177175564f7b79eb3906c94ff28e68',
   },
 
   'src/ios/third_party/earl_grey2/src': {
@@ -965,7 +965,7 @@
     'packages': [
       {
           'package': 'chromium/third_party/androidx',
-          'version': '9Ik3i0VlKSVthDuv4NoO-uty6zlMOUyV3u2K1kZz6SwC',
+          'version': 'HscLs2ReHeJnHLbPuX949OD2wsLnxxiTjgFCTS4_seoC',
       },
     ],
     'condition': 'checkout_android',
@@ -1213,13 +1213,13 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '5175d18f8ab272e14aa3ac2e45c509f9ae162109',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'd259b3164494eb84d00f57a172c26633361415c8',
 
   'src/third_party/devtools-frontend/src':
     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' + '@' + '811ce6bea3093d3308d5d74228a596caaf28cbe8',
+      'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + 'e85bd7fd143cb555db72d612b9b23dd3b5dde923',
     'condition': 'checkout_src_internal',
   },
 
@@ -1783,7 +1783,7 @@
       'dep_type': 'cipd',
   },
 
-  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@0c4f620f241291f783651efcab04d8ea58571946',
+  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@7935ee7ccbc0074344db22c88702fcb0595272e5',
 
   'src/third_party/vulkan_memory_allocator':
     Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'ebe84bec02c041d28f902da0214bf442743fc907',
@@ -1820,10 +1820,10 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'd1b65aa5a88f6efd900604dfcda840154e9f16e2',
 
   'src/third_party/webgpu-cts/src':
-    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'a6b97c457e934f3f1954dccd421278d1fa87944c',
+    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '677ece7d76116e07601e0d90f7084f17b3c57d8b',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '100de339830da480c464f19c17f375849fead517',
+    Var('webrtc_git') + '/src.git' + '@' + '17e14fdf3497506c818f61f6f6415b616fb97178',
 
   # Wuffs' canonical repository is at github.com/google/wuffs, but we use
   # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file.
@@ -1893,7 +1893,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@34bf13a6b9e02bacbf0ee6ac10669aa528839a7d',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@bd6acc2f942bc4836e794ed24efbf8d93e5910d9',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index e03a1579..e112f4f 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -2836,6 +2836,7 @@
     files_to_skip = (
         _EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
         input_api.DEFAULT_FILES_TO_SKIP + (
+            r"^base/fuchsia/scoped_fx_logger\.cc$",
             r"^base/logging\.h$",
             r"^base/logging\.cc$",
             r"^base/task/thread_pool/task_tracker\.cc$",
diff --git a/WATCHLISTS b/WATCHLISTS
index c51c3a59..c0ad81d3 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -708,6 +708,7 @@
     },
     'chrome_intelligence': {
       'filepath': 'history_clusters'\
+                  '|image_service'\
                   '|ios/chrome/browser/text_selection'\
                   '|optimization_guide'\
                   '|optimization_hints'\
@@ -1553,12 +1554,12 @@
                   '|chrome/android/java/src/org/chromium/chrome/browser/offlinepages/'
     },
     'omnibox_desktop': {
-      'filepath': '^chrome/browser/autocomplete/|'\
+      'filepath': '^chrome/browser/ash/app_list/search/omnibox/|'\
+                  '^chrome/browser/autocomplete/|'\
                   '^chrome/browser/resources/new_tab_page/realbox/|'\
                   '^chrome/browser/resources/omnibox|'\
                   '^chrome/browser/ui/location_bar/|'\
                   '^chrome/browser/ui/omnibox/|'\
-                  '^chrome/browser/ui/app_list/search/omnibox/|'\
                   '^chrome/browser/ui/views/location_bar/|'\
                   '^chrome/browser/ui/views/omnibox/|'\
                   '^chrome/browser/ui/webui/omnibox/|'\
@@ -2287,8 +2288,7 @@
              'webappwatch@microsoft.com'],
     'apps_intent_helper': ['dominickn+watch-intent_helper@chromium.org',
                            'mxcai+watch-intent-helper@chromium.org'],
-    'arc': ['elijahtaylor+arcwatch@chromium.org',
-            'hidehiko+watch@chromium.org',
+    'arc': ['hidehiko+watch@chromium.org',
             'arc-reviews+chromium@google.com'],
     'arc_auth': ['khmel+watch@chromium.org'],
     'arc_ime': ['yhanada+watch@chromium.org'],
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn
index a37081b..7575e4ee 100644
--- a/android_webview/BUILD.gn
+++ b/android_webview/BUILD.gn
@@ -673,7 +673,6 @@
     "//components/variations:variations_java",
     "//components/variations/android:variations_java",
     "//components/version_info/android:version_constants_java",
-    "//components/viz/common:common_java",
     "//components/viz/service:service_java",
     "//content/public/android:content_java",
     "//device/gamepad:java",
diff --git a/android_webview/browser/gfx/display_scheduler_webview.cc b/android_webview/browser/gfx/display_scheduler_webview.cc
index f3a4608..726991f3 100644
--- a/android_webview/browser/gfx/display_scheduler_webview.cc
+++ b/android_webview/browser/gfx/display_scheduler_webview.cc
@@ -34,7 +34,6 @@
   NOTREACHED();
 }
 void DisplaySchedulerWebView::SetNeedsOneBeginFrame(bool needs_draw) {
-  // Used with De-Jelly and headless begin frames
   NOTREACHED();
 }
 void DisplaySchedulerWebView::DidSwapBuffers() {
diff --git a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
index d7f332c1..fbf7df16 100644
--- a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
+++ b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
@@ -242,6 +242,8 @@
                     "Collects metrics on when the User-Agent string is overridden and how"),
             Flag.baseFeature(GpuFeatures.CANVAS_CONTEXT_LOST_IN_BACKGROUND,
                     "Free Canvas2D resources when the webview is in the background."),
+            Flag.baseFeature(GpuFeatures.USE_GPU_SCHEDULER_DFS,
+                    "Uses the new SchedulerDFS GPU job scheduler."),
             Flag.baseFeature(VizFeatures.SURFACE_SYNC_THROTTLING,
                     "Enables throttling of Surface Sync to improve rotations"),
             Flag.baseFeature(BlinkFeatures.AUTOFILL_SHADOW_DOM,
diff --git a/android_webview/lib/aw_main_delegate.cc b/android_webview/lib/aw_main_delegate.cc
index ce96ccb..08fb47d64 100644
--- a/android_webview/lib/aw_main_delegate.cc
+++ b/android_webview/lib/aw_main_delegate.cc
@@ -285,9 +285,6 @@
 
     features.DisableIfNotSet(::features::kDynamicColorGamut);
 
-    // De-jelly is never supported on WebView.
-    features.EnableIfNotSet(::features::kDisableDeJelly);
-
     // COOP is not supported on WebView yet. See:
     // https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/XBKAGb2_7uAi.
     features.DisableIfNotSet(network::features::kCrossOriginOpenerPolicy);
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 766cdc9..5ea66c6 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1956,6 +1956,8 @@
     "touch/touch_hud_renderer.h",
     "touch/touch_observer_hud.cc",
     "touch/touch_observer_hud.h",
+    "touch/touch_selection_magnifier_runner_ash.cc",
+    "touch/touch_selection_magnifier_runner_ash.h",
     "tray_action/tray_action.cc",
     "tray_action/tray_action.h",
     "tray_action/tray_action_observer.h",
@@ -2593,6 +2595,7 @@
     "//ui/platform_window",
     "//ui/platform_window/stub",
     "//ui/snapshot",
+    "//ui/touch_selection",
     "//ui/views/window/vector_icons",
     "//ui/wm/public",
     "//url",
@@ -2977,6 +2980,7 @@
     "system/camera/autozoom_toast_controller_unittest.cc",
     "system/camera/camera_effects_controller_unittest.cc",
     "system/caps_lock_notification_controller_unittest.cc",
+    "system/cast/cast_feature_pod_controller_unittest.cc",
     "system/channel_indicator/channel_indicator_quick_settings_view_unittest.cc",
     "system/channel_indicator/channel_indicator_unittest.cc",
     "system/channel_indicator/channel_indicator_utils_unittest.cc",
@@ -3172,6 +3176,7 @@
     "tooltips/tooltip_controller_unittest.cc",
     "touch/touch_devices_controller_unittest.cc",
     "touch/touch_observer_hud_unittest.cc",
+    "touch/touch_selection_magnifier_runner_ash_unittest.cc",
     "tray_action/test_tray_action_client.cc",
     "tray_action/test_tray_action_client.h",
     "tray_action/tray_action_unittest.cc",
@@ -3459,6 +3464,7 @@
     "//ui/resources",
     "//ui/snapshot",
     "//ui/strings",
+    "//ui/touch_selection",
     "//ui/views",
     "//ui/views:test_support",
     "//ui/views/window/vector_icons",
diff --git a/ash/accessibility/caption_bubble_context_ash.cc b/ash/accessibility/caption_bubble_context_ash.cc
index b395439..588a3e7 100644
--- a/ash/accessibility/caption_bubble_context_ash.cc
+++ b/ash/accessibility/caption_bubble_context_ash.cc
@@ -7,8 +7,11 @@
 #include "ash/shell.h"
 #include "ash/wm/work_area_insets.h"
 
-namespace ash {
-namespace captions {
+namespace {
+constexpr char kAshSessionId[] = "ash";
+}  // namespace
+
+namespace ash::captions {
 
 CaptionBubbleContextAsh::CaptionBubbleContextAsh() = default;
 
@@ -19,9 +22,17 @@
       ->user_work_area_bounds();
 }
 
+const std::string CaptionBubbleContextAsh::GetSessionId() const {
+  return std::string(kAshSessionId);
+}
+
 bool CaptionBubbleContextAsh::IsActivatable() const {
   return false;
 }
 
-}  // namespace captions
-}  // namespace ash
+std::unique_ptr<::captions::CaptionBubbleSessionObserver>
+CaptionBubbleContextAsh::GetCaptionBubbleSessionObserver() {
+  return nullptr;
+}
+
+}  // namespace ash::captions
diff --git a/ash/accessibility/caption_bubble_context_ash.h b/ash/accessibility/caption_bubble_context_ash.h
index f651357b..8531456 100644
--- a/ash/accessibility/caption_bubble_context_ash.h
+++ b/ash/accessibility/caption_bubble_context_ash.h
@@ -8,8 +8,10 @@
 #include "ash/ash_export.h"
 #include "components/live_caption/caption_bubble_context.h"
 
-namespace ash {
-namespace captions {
+#include <memory>
+#include <string>
+
+namespace ash::captions {
 
 ///////////////////////////////////////////////////////////////////////////////
 // Caption Bubble Context for Ash
@@ -26,11 +28,13 @@
 
   // ::captions::CaptionBubbleContext:
   absl::optional<gfx::Rect> GetBounds() const override;
+  const std::string GetSessionId() const override;
   void Activate() override {}
   bool IsActivatable() const override;
+  std::unique_ptr<::captions::CaptionBubbleSessionObserver>
+  GetCaptionBubbleSessionObserver() override;
 };
 
-}  // namespace captions
-}  // namespace ash
+}  // namespace ash::captions
 
 #endif  // ASH_ACCESSIBILITY_CAPTION_BUBBLE_CONTEXT_ASH_H_
diff --git a/ash/app_list/DIR_METADATA b/ash/app_list/DIR_METADATA
index ec76141..feded61f 100644
--- a/ash/app_list/DIR_METADATA
+++ b/ash/app_list/DIR_METADATA
@@ -1,3 +1,10 @@
+team_email: "chromeos-launcher@google.com"
+buganizer: {
+  component_id:1288350
+}
+buganizer_public: {
+  component_id:1287811
+}
 monorail {
   component: "UI>Shell>Launcher"
 }
diff --git a/ash/app_list/OWNERS b/ash/app_list/OWNERS
index 814bba4a..45b38d6 100644
--- a/ash/app_list/OWNERS
+++ b/ash/app_list/OWNERS
@@ -1,5 +1,7 @@
+tbarzic@chromium.org
+mmourgos@chromium.org
+yulunwu@chromium.org
 jennyz@chromium.org
 khmel@chromium.org
 newcomer@chromium.org
-tbarzic@chromium.org
 xiyuan@chromium.org
diff --git a/ash/app_list/app_list_bubble_presenter.cc b/ash/app_list/app_list_bubble_presenter.cc
index 3d1da70d..dac3120 100644
--- a/ash/app_list/app_list_bubble_presenter.cc
+++ b/ash/app_list/app_list_bubble_presenter.cc
@@ -28,6 +28,7 @@
 #include "base/bind.h"
 #include "base/check.h"
 #include "base/check_op.h"
+#include "base/cxx17_backports.h"
 #include "base/i18n/rtl.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_functions.h"
diff --git a/ash/capture_mode/capture_mode_feature_pod_controller.cc b/ash/capture_mode/capture_mode_feature_pod_controller.cc
index ae13785..aa5c807c 100644
--- a/ash/capture_mode/capture_mode_feature_pod_controller.cc
+++ b/ash/capture_mode/capture_mode_feature_pod_controller.cc
@@ -49,8 +49,9 @@
 std::unique_ptr<FeatureTile> CaptureModeFeaturePodController::CreateTile() {
   DCHECK(features::IsQsRevampEnabled());
   auto feature_tile = std::make_unique<FeatureTile>(
-      /*controller=*/this, /*is_togglable=*/false,
-      FeatureTile::TileType::kCompact);
+      base::BindRepeating(&FeaturePodControllerBase::OnIconPressed,
+                          weak_ptr_factory_.GetWeakPtr()),
+      /*is_togglable=*/false, FeatureTile::TileType::kCompact);
   feature_tile->SetVectorIcon(kCaptureModeIcon);
   const auto label_text =
       l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_CAPTURE_MODE_BUTTON_LABEL);
diff --git a/ash/capture_mode/capture_mode_feature_pod_controller.h b/ash/capture_mode/capture_mode_feature_pod_controller.h
index d502a5a1..eb22b97 100644
--- a/ash/capture_mode/capture_mode_feature_pod_controller.h
+++ b/ash/capture_mode/capture_mode_feature_pod_controller.h
@@ -9,6 +9,7 @@
 
 #include "ash/constants/quick_settings_catalogs.h"
 #include "ash/system/unified/feature_pod_controller_base.h"
+#include "base/memory/weak_ptr.h"
 
 namespace ash {
 
@@ -36,6 +37,8 @@
   UnifiedSystemTrayController* const tray_controller_;
 
   FeaturePodButton* button_ = nullptr;
+
+  base::WeakPtrFactory<CaptureModeFeaturePodController> weak_ptr_factory_{this};
 };
 
 }  // namespace ash
diff --git a/ash/components/arc/session/BUILD.gn b/ash/components/arc/session/BUILD.gn
index d0891d3..803bc2b 100644
--- a/ash/components/arc/session/BUILD.gn
+++ b/ash/components/arc/session/BUILD.gn
@@ -44,6 +44,7 @@
   deps = [
     ":arc_base_enums",
     ":connection_holder",
+    "//ash",
     "//ash/components/arc:arc_base_utils",
     "//ash/components/arc:arc_features",
     "//ash/components/arc:prefs",
@@ -66,6 +67,7 @@
     "//components/prefs:prefs",
     "//components/user_manager",
     "//components/version_info",
+    "//ui/display/manager",
   ]
 }
 
diff --git a/ash/components/arc/session/arc_vm_client_adapter.cc b/ash/components/arc/session/arc_vm_client_adapter.cc
index 22ae89e..ef39c1b 100644
--- a/ash/components/arc/session/arc_vm_client_adapter.cc
+++ b/ash/components/arc/session/arc_vm_client_adapter.cc
@@ -28,6 +28,7 @@
 #include "ash/components/arc/session/file_system_status.h"
 #include "ash/constants/ash_features.h"
 #include "ash/constants/ash_switches.h"
+#include "ash/shell.h"
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/callback_helpers.h"
@@ -66,6 +67,7 @@
 #include "components/version_info/version_info.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/display/display.h"
+#include "ui/display/manager/display_manager.h"
 #include "ui/display/screen.h"
 
 namespace arc {
@@ -402,21 +404,26 @@
   else
     request.set_vm_memory_psi_period(-1);
 
-  auto orientation = display::Display::ROTATE_0;
-  if (auto* screen = display::Screen::GetScreen())
-    orientation = screen->GetPrimaryDisplay().panel_rotation();
+  auto orientation = display::PanelOrientation::kNormal;
+  if (auto* screen = display::Screen::GetScreen()) {
+    const auto display_id = screen->GetPrimaryDisplay().id();
+    if (auto* shell = ash::Shell::Get()) {
+      const auto& info = shell->display_manager()->GetDisplayInfo(display_id);
+      orientation = info.panel_orientation();
+    }
+  }
   switch (orientation) {
     using StartArcVmRequest = vm_tools::concierge::StartArcVmRequest;
-    case display::Display::ROTATE_0:
+    case display::PanelOrientation::kNormal:
       request.set_panel_orientation(StartArcVmRequest::ORIENTATION_0);
       break;
-    case display::Display::ROTATE_90:
+    case display::PanelOrientation::kRightUp:
       request.set_panel_orientation(StartArcVmRequest::ORIENTATION_90);
       break;
-    case display::Display::ROTATE_180:
+    case display::PanelOrientation::kBottomUp:
       request.set_panel_orientation(StartArcVmRequest::ORIENTATION_180);
       break;
-    case display::Display::ROTATE_270:
+    case display::PanelOrientation::kLeftUp:
       request.set_panel_orientation(StartArcVmRequest::ORIENTATION_270);
       break;
   }
diff --git a/ash/constants/ash_switches.cc b/ash/constants/ash_switches.cc
index 52ba4f78..4a66f425 100644
--- a/ash/constants/ash_switches.cc
+++ b/ash/constants/ash_switches.cc
@@ -779,8 +779,10 @@
     "oobe-trigger-sync-timeout-for-tests";
 
 // Removes the condition that a network has had to existed for at least two
-// weeks and increase the frequency at which the HiddenNetworkHandler class
-// checks for and removes wrongly hidden networks.
+// weeks and allows the user to provide the frequency at which the
+// HiddenNetworkHandler class checks for and removes wrongly hidden networks.
+// The frequency should be provided in seconds, should follow the format
+// "--force-hidden-network-migration=#", and should be >= 1.
 const char kForceHiddenNetworkMigration[] = "force-hidden-network-migration";
 
 // If set to "true", the profile requires policy during restart (policy load
@@ -795,6 +797,9 @@
 // Adds fake Bluetooth devices to the quick settings menu for UI testing.
 const char kQsAddFakeBluetoothDevices[] = "qs-add-fake-bluetooth-devices";
 
+// Adds fake Cast devices to the quick settings menu for UI testing.
+const char kQsAddFakeCastDevices[] = "qs-add-fake-cast-devices";
+
 // The name of the per-model directory which contains per-region
 // subdirectories with regulatory label files for this model.
 // The per-model directories (if there are any) are located under
diff --git a/ash/constants/ash_switches.h b/ash/constants/ash_switches.h
index 225f90c..fe338ace 100644
--- a/ash/constants/ash_switches.h
+++ b/ash/constants/ash_switches.h
@@ -257,6 +257,7 @@
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kProfileRequiresPolicy[];
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kPublicAccountsSamlAclUrl[];
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kQsAddFakeBluetoothDevices[];
+COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kQsAddFakeCastDevices[];
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kRegulatoryLabelDir[];
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kRevenBranding[];
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kRlzPingDelay[];
diff --git a/ash/public/cpp/app_list/DIR_METADATA b/ash/public/cpp/app_list/DIR_METADATA
index ec76141..feded61f 100644
--- a/ash/public/cpp/app_list/DIR_METADATA
+++ b/ash/public/cpp/app_list/DIR_METADATA
@@ -1,3 +1,10 @@
+team_email: "chromeos-launcher@google.com"
+buganizer: {
+  component_id:1288350
+}
+buganizer_public: {
+  component_id:1287811
+}
 monorail {
   component: "UI>Shell>Launcher"
 }
diff --git a/ash/public/cpp/ash_view_ids.h b/ash/public/cpp/ash_view_ids.h
index 611b1ac..ec6244d7 100644
--- a/ash/public/cpp/ash_view_ids.h
+++ b/ash/public/cpp/ash_view_ids.h
@@ -49,6 +49,12 @@
   VIEW_ID_QS_VERSION_BUTTON,
   VIEW_ID_QS_MAX = VIEW_ID_QS_VERSION_BUTTON,
 
+  // Status area trays:
+  VIEW_ID_SA_MIN,
+  VIEW_ID_SA_DATE_TRAY = VIEW_ID_SA_MIN,
+  VIEW_ID_SA_NOTIFICATION_TRAY,
+  VIEW_ID_SA_MAX = VIEW_ID_SA_NOTIFICATION_TRAY,
+
   // Sticky header rows in a scroll view.
   VIEW_ID_STICKY_HEADER,
   // System tray up-arrow icon that shows an update is available.
diff --git a/ash/public/cpp/cast_config_controller.h b/ash/public/cpp/cast_config_controller.h
index 25239dd..ee46218 100644
--- a/ash/public/cpp/cast_config_controller.h
+++ b/ash/public/cpp/cast_config_controller.h
@@ -81,6 +81,10 @@
   virtual void AddObserver(Observer* observer) = 0;
   virtual void RemoveObserver(Observer* observer) = 0;
 
+  // Returns true if the C++ MediaRouter service exists for the primary profile
+  // and is not disabled by policy.
+  virtual bool HasMediaRouterForPrimaryProfile() const = 0;
+
   // Return true if there are available cast devices.
   virtual bool HasSinksAndRoutes() const = 0;
 
diff --git a/ash/shelf/DIR_METADATA b/ash/shelf/DIR_METADATA
index ea973a0..d7dbd167 100644
--- a/ash/shelf/DIR_METADATA
+++ b/ash/shelf/DIR_METADATA
@@ -1,3 +1,10 @@
+team_email: "chromeos-launcher@google.com"
+buganizer: {
+  component_id:1288352
+}
+buganizer_public: {
+  component_id:1288369
+}
 monorail {
   component: "UI>Shell>Shelf"
 }
diff --git a/ash/shelf/shelf_layout_manager_unittest.cc b/ash/shelf/shelf_layout_manager_unittest.cc
index 866ea581..30aa3190 100644
--- a/ash/shelf/shelf_layout_manager_unittest.cc
+++ b/ash/shelf/shelf_layout_manager_unittest.cc
@@ -106,6 +106,7 @@
 #include "ui/events/gesture_detection/gesture_configuration.h"
 #include "ui/events/test/event_generator.h"
 #include "ui/events/types/event_type.h"
+#include "ui/gfx/image/image_skia_rep.h"
 #include "ui/views/animation/bounds_animator.h"
 #include "ui/views/test/widget_animation_waiter.h"
 #include "ui/views/view.h"
diff --git a/ash/shell.cc b/ash/shell.cc
index df056be7..f6d8964b 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -163,6 +163,7 @@
 #include "ash/system/video_conference/fake_video_conference_tray_controller.h"
 #include "ash/touch/ash_touch_transform_controller.h"
 #include "ash/touch/touch_devices_controller.h"
+#include "ash/touch/touch_selection_magnifier_runner_ash.h"
 #include "ash/tray_action/tray_action.h"
 #include "ash/utility/occlusion_tracker_pauser.h"
 #include "ash/wallpaper/wallpaper_controller_impl.h"
@@ -944,6 +945,8 @@
 
   partial_magnifier_controller_.reset();
 
+  touch_selection_magnifier_runner_ash_.reset();
+
   laser_pointer_controller_.reset();
 
   if (display_change_observer_)
@@ -1332,6 +1335,10 @@
   partial_magnifier_controller_ =
       std::make_unique<PartialMagnifierController>();
   highlighter_controller_ = std::make_unique<HighlighterController>();
+  if (base::FeatureList::IsEnabled(features::kTouchTextEditingRedesign)) {
+    touch_selection_magnifier_runner_ash_ =
+        std::make_unique<TouchSelectionMagnifierRunnerAsh>();
+  }
 
   fullscreen_magnifier_controller_ =
       std::make_unique<FullscreenMagnifierController>();
diff --git a/ash/shell.h b/ash/shell.h
index 8d0e740..67301eb 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -221,6 +221,7 @@
 class ToplevelWindowEventHandler;
 class ClipboardHistoryControllerImpl;
 class TouchDevicesController;
+class TouchSelectionMagnifierRunnerAsh;
 class TrayAction;
 class UserMetricsRecorder;
 class VideoActivityNotifier;
@@ -1043,6 +1044,9 @@
 
   std::unique_ptr<DockedMagnifierController> docked_magnifier_controller_;
 
+  std::unique_ptr<TouchSelectionMagnifierRunnerAsh>
+      touch_selection_magnifier_runner_ash_;
+
   std::unique_ptr<chromeos::SnapController> snap_controller_;
 
   std::unique_ptr<WmModeController> wm_mode_controller_;
diff --git a/ash/system/accessibility/accessibility_feature_pod_controller.cc b/ash/system/accessibility/accessibility_feature_pod_controller.cc
index fc615f92..699cadd18 100644
--- a/ash/system/accessibility/accessibility_feature_pod_controller.cc
+++ b/ash/system/accessibility/accessibility_feature_pod_controller.cc
@@ -51,8 +51,10 @@
 
 std::unique_ptr<FeatureTile> AccessibilityFeaturePodController::CreateTile() {
   DCHECK(features::IsQsRevampEnabled());
-  auto feature_tile = std::make_unique<FeatureTile>(/*controller=*/this,
-                                                    /*is_togglable=*/false);
+  auto feature_tile = std::make_unique<FeatureTile>(
+      base::BindRepeating(&FeaturePodControllerBase::OnIconPressed,
+                          weak_ptr_factory_.GetWeakPtr()),
+      /*is_togglable=*/false);
   feature_tile->SetVectorIcon(kUnifiedMenuAccessibilityIcon);
   feature_tile->SetLabel(
       l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ACCESSIBILITY));
@@ -60,7 +62,10 @@
   const std::u16string tooltip_text =
       l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ACCESSIBILITY_TOOLTIP);
   feature_tile->SetTooltipText(tooltip_text);
-  feature_tile->SetDrillInButtonTooltipText(tooltip_text);
+  feature_tile->CreateDrillInButton(
+      base::BindRepeating(&FeaturePodControllerBase::OnLabelPressed,
+                          weak_ptr_factory_.GetWeakPtr()),
+      tooltip_text);
   return feature_tile;
 }
 
diff --git a/ash/system/accessibility/accessibility_feature_pod_controller.h b/ash/system/accessibility/accessibility_feature_pod_controller.h
index 721996a..020d074 100644
--- a/ash/system/accessibility/accessibility_feature_pod_controller.h
+++ b/ash/system/accessibility/accessibility_feature_pod_controller.h
@@ -10,6 +10,7 @@
 #include "ash/ash_export.h"
 #include "ash/constants/quick_settings_catalogs.h"
 #include "ash/system/unified/feature_pod_controller_base.h"
+#include "base/memory/weak_ptr.h"
 
 namespace ash {
 
@@ -39,6 +40,9 @@
  private:
   // Unowned.
   UnifiedSystemTrayController* const tray_controller_;
+
+  base::WeakPtrFactory<AccessibilityFeaturePodController> weak_ptr_factory_{
+      this};
 };
 
 }  // namespace ash
diff --git a/ash/system/accessibility/autoclick_menu_bubble_controller.cc b/ash/system/accessibility/autoclick_menu_bubble_controller.cc
index 724d59a..92e99680 100644
--- a/ash/system/accessibility/autoclick_menu_bubble_controller.cc
+++ b/ash/system/accessibility/autoclick_menu_bubble_controller.cc
@@ -107,12 +107,14 @@
   if (bubble_widget_->GetWindowBoundsInScreen() == resting_bounds)
     return;
 
-  ui::ScopedLayerAnimationSettings settings(
-      bubble_widget_->GetLayer()->GetAnimator());
-  settings.SetPreemptionStrategy(
-      ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
-  settings.SetTransitionDuration(base::Milliseconds(kAnimationDurationMs));
-  settings.SetTweenType(gfx::Tween::EASE_OUT);
+  if (animate_) {
+    ui::ScopedLayerAnimationSettings settings(
+        bubble_widget_->GetLayer()->GetAnimator());
+    settings.SetPreemptionStrategy(
+        ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
+    settings.SetTransitionDuration(base::Milliseconds(kAnimationDurationMs));
+    settings.SetTweenType(gfx::Tween::EASE_OUT);
+  }
   bubble_widget_->SetBounds(resting_bounds);
 
   if (!scroll_bubble_controller_)
diff --git a/ash/system/accessibility/autoclick_menu_bubble_controller.h b/ash/system/accessibility/autoclick_menu_bubble_controller.h
index 0993ee9..342d3f2 100644
--- a/ash/system/accessibility/autoclick_menu_bubble_controller.h
+++ b/ash/system/accessibility/autoclick_menu_bubble_controller.h
@@ -77,11 +77,13 @@
 
   // For tests only.
   views::Widget* GetBubbleWidgetForTesting() { return bubble_widget_; }
+  void SetAnimateForTesting(bool animate) { animate_ = animate; }
 
  private:
   friend class AutoclickMenuBubbleControllerTest;
   friend class AutoclickTest;
   friend class FloatingAccessibilityControllerTest;
+  friend class AutoclickBrowserTest;
 
   // Owned by views hierarchy.
   TrayBubbleView* bubble_view_ = nullptr;
@@ -94,6 +96,9 @@
   // by this class so that positioning calculations can take place using both
   // classes at once.
   std::unique_ptr<AutoclickScrollBubbleController> scroll_bubble_controller_;
+
+  // Whether to animate position changes. Can be set to false for testing.
+  bool animate_ = true;
 };
 
 }  // namespace ash
diff --git a/ash/system/cast/cast_feature_pod_controller.cc b/ash/system/cast/cast_feature_pod_controller.cc
index b924bba..0f002fa 100644
--- a/ash/system/cast/cast_feature_pod_controller.cc
+++ b/ash/system/cast/cast_feature_pod_controller.cc
@@ -4,16 +4,22 @@
 
 #include "ash/system/cast/cast_feature_pod_controller.h"
 
+#include <string>
+
+#include "ash/constants/ash_features.h"
 #include "ash/constants/quick_settings_catalogs.h"
 #include "ash/public/cpp/ash_view_ids.h"
+#include "ash/public/cpp/cast_config_controller.h"
 #include "ash/public/cpp/system_tray_client.h"
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/system/model/system_tray_model.h"
 #include "ash/system/unified/feature_pod_button.h"
+#include "ash/system/unified/feature_tile.h"
 #include "ash/system/unified/quick_settings_metrics_util.h"
 #include "ash/system/unified/unified_system_tray_controller.h"
+#include "base/functional/bind.h"
 #include "components/access_code_cast/common/access_code_cast_metrics.h"
 #include "ui/base/l10n/l10n_util.h"
 
@@ -29,6 +35,7 @@
 }
 
 FeaturePodButton* CastFeaturePodController::CreateButton() {
+  DCHECK(!features::IsQsRevampEnabled());
   button_ = new FeaturePodButton(this);
   button_->SetVectorIcon(kUnifiedMenuCastIcon);
   button_->SetLabel(l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_CAST_SHORT));
@@ -49,6 +56,35 @@
   return button_;
 }
 
+std::unique_ptr<FeatureTile> CastFeaturePodController::CreateTile() {
+  DCHECK(features::IsQsRevampEnabled());
+  auto tile = std::make_unique<FeatureTile>(base::BindRepeating(
+      &CastFeaturePodController::OnIconPressed, weak_factory_.GetWeakPtr()));
+  tile->SetVectorIcon(kUnifiedMenuCastIcon);
+  tile->SetLabel(l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_CAST));
+  // TODO(b/252872586): Show sublabel with cast device availability.
+  tile->SetSubLabelVisibility(false);
+  const std::u16string tooltip =
+      l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_CAST_TOOLTIP);
+  tile->SetTooltipText(tooltip);
+  tile->CreateDrillInButton(
+      base::BindRepeating(&CastFeaturePodController::OnLabelPressed,
+                          weak_factory_.GetWeakPtr()),
+      tooltip);
+  tile->SetID(VIEW_ID_CAST_MAIN_VIEW);
+
+  // The tile is visible if there is a primary profile (e.g. after login) and
+  // that profile has a media router (e.g. it is not disabled by policy).
+  // QsRevamp shows the tile even if there are no media sinks.
+  auto* cast_config = CastConfigController::Get();
+  bool visible = cast_config && cast_config->HasMediaRouterForPrimaryProfile();
+  if (visible)
+    TrackVisibilityUMA();
+  tile->SetVisible(visible);
+
+  return tile;
+}
+
 QsFeatureCatalogName CastFeaturePodController::GetCatalogName() {
   return QsFeatureCatalogName::kCast;
 }
@@ -80,18 +116,17 @@
 
 void CastFeaturePodController::OnDevicesUpdated(
     const std::vector<SinkAndRoute>& devices) {
+  DCHECK(!features::IsQsRevampEnabled());
   Update();
 }
 
 void CastFeaturePodController::Update() {
+  DCHECK(!features::IsQsRevampEnabled());
   auto* cast_config = CastConfigController::Get();
-  // The cast feature tile will always be shown on the QS bubble if the revamped
-  // view is enabled.
-  const bool visible = features::IsQsRevampEnabled() ||
-                       (cast_config &&
-                        (cast_config->HasSinksAndRoutes() ||
-                         cast_config->AccessCodeCastingEnabled()) &&
-                        !cast_config->HasActiveRoute());
+  const bool visible = cast_config &&
+                       (cast_config->HasSinksAndRoutes() ||
+                        cast_config->AccessCodeCastingEnabled()) &&
+                       !cast_config->HasActiveRoute();
   if (!button_->GetVisible() && visible)
     TrackVisibilityUMA();
   button_->SetVisible(visible);
diff --git a/ash/system/cast/cast_feature_pod_controller.h b/ash/system/cast/cast_feature_pod_controller.h
index f7c4bbf..159fc60c 100644
--- a/ash/system/cast/cast_feature_pod_controller.h
+++ b/ash/system/cast/cast_feature_pod_controller.h
@@ -9,6 +9,7 @@
 #include "ash/constants/quick_settings_catalogs.h"
 #include "ash/public/cpp/cast_config_controller.h"
 #include "ash/system/unified/feature_pod_controller_base.h"
+#include "base/memory/weak_ptr.h"
 
 namespace ash {
 
@@ -29,6 +30,7 @@
 
   // FeaturePodControllerBase:
   FeaturePodButton* CreateButton() override;
+  std::unique_ptr<FeatureTile> CreateTile() override;
   QsFeatureCatalogName GetCatalogName() override;
   void OnIconPressed() override;
   void OnLabelPressed() override;
@@ -42,6 +44,8 @@
   // Unowned.
   UnifiedSystemTrayController* const tray_controller_;
   FeaturePodButton* button_ = nullptr;
+
+  base::WeakPtrFactory<CastFeaturePodController> weak_factory_{this};
 };
 
 }  // namespace ash
diff --git a/ash/system/cast/cast_feature_pod_controller_unittest.cc b/ash/system/cast/cast_feature_pod_controller_unittest.cc
new file mode 100644
index 0000000..7e26df9
--- /dev/null
+++ b/ash/system/cast/cast_feature_pod_controller_unittest.cc
@@ -0,0 +1,83 @@
+// 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 "ash/system/cast/cast_feature_pod_controller.h"
+
+#include "ash/constants/ash_features.h"
+#include "ash/public/cpp/cast_config_controller.h"
+#include "ash/system/unified/feature_tile.h"
+#include "ash/system/unified/unified_system_tray.h"
+#include "ash/system/unified/unified_system_tray_bubble.h"
+#include "ash/test/ash_test_base.h"
+#include "base/test/scoped_feature_list.h"
+
+namespace ash {
+namespace {
+
+class TestCastConfigController : public CastConfigController {
+ public:
+  TestCastConfigController() = default;
+  TestCastConfigController(const TestCastConfigController&) = delete;
+  TestCastConfigController& operator=(const TestCastConfigController&) = delete;
+  ~TestCastConfigController() override = default;
+
+  // CastConfigController:
+  void AddObserver(Observer* observer) override {}
+  void RemoveObserver(Observer* observer) override {}
+  bool HasMediaRouterForPrimaryProfile() const override {
+    return has_media_router_;
+  }
+  bool HasSinksAndRoutes() const override { return false; }
+  bool HasActiveRoute() const override { return false; }
+  bool AccessCodeCastingEnabled() const override { return false; }
+  void RequestDeviceRefresh() override {}
+  const std::vector<SinkAndRoute>& GetSinksAndRoutes() override {
+    return sinks_and_routes_;
+  }
+  void CastToSink(const std::string& sink_id) override {}
+  void StopCasting(const std::string& route_id) override {}
+
+  bool has_media_router_ = true;
+  std::vector<SinkAndRoute> sinks_and_routes_;
+};
+
+class CastFeaturePodControllerTest : public AshTestBase {
+ public:
+  CastFeaturePodControllerTest() {
+    feature_list_.InitWithFeatures(
+        /*enabled_features=*/{features::kQsRevamp, features::kQsRevampWip},
+        /*disabled_features=*/{});
+  }
+
+  // AshTestBase:
+  void SetUp() override {
+    AshTestBase::SetUp();
+    GetPrimaryUnifiedSystemTray()->ShowBubble();
+    controller_ = std::make_unique<CastFeaturePodController>(
+        GetPrimaryUnifiedSystemTray()
+            ->bubble()
+            ->unified_system_tray_controller());
+  }
+
+  base::test::ScopedFeatureList feature_list_;
+  TestCastConfigController cast_config_;
+  std::unique_ptr<CastFeaturePodController> controller_;
+};
+
+TEST_F(CastFeaturePodControllerTest, CreateTile) {
+  std::unique_ptr<FeatureTile> tile = controller_->CreateTile();
+  EXPECT_TRUE(tile->GetVisible());
+  EXPECT_EQ(tile->GetTooltipText(), u"Show cast devices");
+  EXPECT_TRUE(tile->drill_in_button()->GetVisible());
+  EXPECT_EQ(tile->drill_in_button()->GetTooltipText(), u"Show cast devices");
+}
+
+TEST_F(CastFeaturePodControllerTest, TileNotVisibleWhenNoMediaRouter) {
+  cast_config_.has_media_router_ = false;
+  std::unique_ptr<FeatureTile> tile = controller_->CreateTile();
+  EXPECT_FALSE(tile->GetVisible());
+}
+
+}  // namespace
+}  // namespace ash
diff --git a/ash/system/cast/tray_cast.cc b/ash/system/cast/tray_cast.cc
index 62f72df..47be705 100644
--- a/ash/system/cast/tray_cast.cc
+++ b/ash/system/cast/tray_cast.cc
@@ -132,12 +132,6 @@
     view_to_sink_map_[container] = sink.id;
   }
 
-  if (features::IsQsRevampEnabled()) {
-    // TODO(b/252872586): Implement an empty state of the cast detailed view.
-    // The following line shows a fake entry.
-    AddScrollListItem(scroll_content(), kSystemMenuCastGenericIcon, u"Device");
-  }
-
   scroll_content()->SizeToPreferredSize();
   scroller()->Layout();
 }
diff --git a/ash/system/network/vpn_feature_pod_controller.cc b/ash/system/network/vpn_feature_pod_controller.cc
index 2ea1a5e..5e14fe9 100644
--- a/ash/system/network/vpn_feature_pod_controller.cc
+++ b/ash/system/network/vpn_feature_pod_controller.cc
@@ -73,15 +73,19 @@
 std::unique_ptr<FeatureTile> VPNFeaturePodController::CreateTile() {
   DCHECK(features::IsQsRevampEnabled());
   DCHECK(!tile_);
-  auto tile =
-      std::make_unique<FeatureTile>(/*controller=*/this, /*is_togglable=*/true);
+  auto tile = std::make_unique<FeatureTile>(
+      base::BindRepeating(&FeaturePodControllerBase::OnIconPressed,
+                          weak_ptr_factory_.GetWeakPtr()));
   tile_ = tile.get();
   tile_->SetVectorIcon(kUnifiedMenuVpnIcon);
   tile_->SetLabel(l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_VPN_SHORT));
   const std::u16string tooltip =
       l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_VPN_TOOLTIP);
   tile_->SetTooltipText(tooltip);
-  tile_->SetDrillInButtonTooltipText(tooltip);
+  tile_->CreateDrillInButton(
+      base::BindRepeating(&FeaturePodControllerBase::OnLabelPressed,
+                          weak_ptr_factory_.GetWeakPtr()),
+      tooltip);
   // Init the tile with invisible state. `Update()` will update visibility.
   tile_->SetVisible(false);
   Update();
diff --git a/ash/system/network/vpn_feature_pod_controller.h b/ash/system/network/vpn_feature_pod_controller.h
index 222c042..7488860 100644
--- a/ash/system/network/vpn_feature_pod_controller.h
+++ b/ash/system/network/vpn_feature_pod_controller.h
@@ -9,6 +9,7 @@
 #include "ash/constants/quick_settings_catalogs.h"
 #include "ash/system/network/tray_network_state_observer.h"
 #include "ash/system/unified/feature_pod_controller_base.h"
+#include "base/memory/weak_ptr.h"
 
 namespace ash {
 
@@ -43,6 +44,8 @@
   // Owned by views hierarchy.
   FeaturePodButton* button_ = nullptr;
   FeatureTile* tile_ = nullptr;
+
+  base::WeakPtrFactory<VPNFeaturePodController> weak_ptr_factory_{this};
 };
 
 }  // namespace ash
diff --git a/ash/system/network/vpn_feature_pod_controller_unittest.cc b/ash/system/network/vpn_feature_pod_controller_unittest.cc
index 0efb02c0..0db066e 100644
--- a/ash/system/network/vpn_feature_pod_controller_unittest.cc
+++ b/ash/system/network/vpn_feature_pod_controller_unittest.cc
@@ -83,8 +83,8 @@
   CreateTile();
   EXPECT_TRUE(feature_tile_->GetVisible());
   EXPECT_EQ(feature_tile_->GetTooltipText(), u"Show VPN settings");
-  EXPECT_TRUE(feature_tile_->drill_container()->GetVisible());
-  EXPECT_EQ(feature_tile_->drill_container()->GetTooltipText(),
+  EXPECT_TRUE(feature_tile_->drill_in_button()->GetVisible());
+  EXPECT_EQ(feature_tile_->drill_in_button()->GetTooltipText(),
             u"Show VPN settings");
 }
 
diff --git a/ash/system/notification_center/notification_center_tray.cc b/ash/system/notification_center/notification_center_tray.cc
index 74972fb..930ea4b3 100644
--- a/ash/system/notification_center/notification_center_tray.cc
+++ b/ash/system/notification_center/notification_center_tray.cc
@@ -7,6 +7,7 @@
 #include <string>
 
 #include "ash/constants/tray_background_view_catalog.h"
+#include "ash/public/cpp/ash_view_ids.h"
 #include "ash/public/cpp/shelf_config.h"
 #include "ash/shelf/shelf.h"
 #include "ash/system/notification_center/notification_center_bubble.h"
@@ -27,6 +28,7 @@
                          RoundedCornerBehavior::kStartRounded),
       notification_icons_controller_(
           std::make_unique<NotificationIconsController>(shelf)) {
+  SetID(VIEW_ID_SA_NOTIFICATION_TRAY);
   SetLayoutManager(std::make_unique<views::FlexLayout>());
   set_use_bounce_in_animation(false);
 
diff --git a/ash/system/status_area_widget_delegate.cc b/ash/system/status_area_widget_delegate.cc
index d303dcc..ab7d002 100644
--- a/ash/system/status_area_widget_delegate.cc
+++ b/ash/system/status_area_widget_delegate.cc
@@ -6,6 +6,7 @@
 
 #include "ash/focus_cycler.h"
 #include "ash/login/ui/lock_screen.h"
+#include "ash/public/cpp/ash_view_ids.h"
 #include "ash/public/cpp/login_screen.h"
 #include "ash/public/cpp/shell_window_ids.h"
 #include "ash/root_window_controller.h"
@@ -13,10 +14,8 @@
 #include "ash/shelf/shelf_layout_manager.h"
 #include "ash/shelf/shelf_widget.h"
 #include "ash/shell.h"
-#include "ash/system/notification_center/notification_center_tray.h"
 #include "ash/system/status_area_widget.h"
 #include "ash/system/tray/tray_constants.h"
-#include "ash/system/unified/date_tray.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "base/containers/adapters.h"
 #include "base/ranges/algorithm.h"
@@ -35,8 +34,8 @@
 
 namespace {
 
-constexpr int kPaddingBetweenItems = 8;
-constexpr int kSystemTraysRightPaddingOffset = -4;
+constexpr int kPaddingBetweenTrayItems = 8;
+constexpr int kPaddingBetweenPrimaryTraySetItems = kPaddingBetweenTrayItems - 4;
 
 class StatusAreaWidgetDelegateAnimationSettings
     : public ui::ScopedLayerAnimationSettings {
@@ -258,24 +257,24 @@
   int top_edge = vertical_padding;
   int left_edge = 0;
   int bottom_edge = vertical_padding;
+
   // Add some extra space so that borders don't overlap. This padding between
   // items also takes care of padding at the edge of the shelf (unless hotseat
   // is enabled).
-  int right_edge = kPaddingBetweenItems;
-
-  // TODO(crbug/1354354): Refactor this hack to make it more efficient and less
-  // of a hack.
-  // If this view is `DateTray` or `NotificationCenterTray`, apply
-  // the offset `kSystemTraysRightPaddingOffset` between it and the tray on it's
-  // right.
-  if (child->GetClassName() == DateTray::kViewClassName ||
-      child->GetClassName() == NotificationCenterTray::kViewClassName) {
-    right_edge += kSystemTraysRightPaddingOffset;
-  }
-
+  int right_edge;
   if (is_child_on_edge) {
     right_edge = ShelfConfig::Get()->control_button_edge_spacing(
         true /* is_primary_axis_edge */);
+  } else {
+    // The primary tray set contains the notification tray, the date tray and
+    // the status tray. The status tray is always on the edge, so that case is
+    // covered in the `if` condition.
+    const bool is_in_primary_tray_set =
+        child->GetID() == VIEW_ID_SA_DATE_TRAY ||
+        child->GetID() == VIEW_ID_SA_NOTIFICATION_TRAY;
+
+    right_edge = is_in_primary_tray_set ? kPaddingBetweenPrimaryTraySetItems
+                                        : kPaddingBetweenTrayItems;
   }
 
   // Swap edges if alignment is not horizontal (bottom-to-top).
diff --git a/ash/system/unified/date_tray.cc b/ash/system/unified/date_tray.cc
index 400209ec..16f634fd8 100644
--- a/ash/system/unified/date_tray.cc
+++ b/ash/system/unified/date_tray.cc
@@ -5,6 +5,7 @@
 #include "ash/system/unified/date_tray.h"
 
 #include "ash/constants/tray_background_view_catalog.h"
+#include "ash/public/cpp/ash_view_ids.h"
 #include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/system/model/clock_model.h"
@@ -28,6 +29,7 @@
       time_view_(tray_container()->AddChildView(
           std::make_unique<TimeTrayItemView>(shelf, TimeView::Type::kDate))),
       unified_system_tray_(tray) {
+  SetID(VIEW_ID_SA_DATE_TRAY);
   SetPressedCallback(
       base::BindRepeating(&DateTray::OnButtonPressed, base::Unretained(this)));
 
diff --git a/ash/system/unified/feature_tile.cc b/ash/system/unified/feature_tile.cc
index 34d14b1..3773d73 100644
--- a/ash/system/unified/feature_tile.cc
+++ b/ash/system/unified/feature_tile.cc
@@ -8,8 +8,8 @@
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/style/ash_color_id.h"
+#include "ash/style/icon_button.h"
 #include "ash/system/tray/tray_constants.h"
-#include "ash/system/unified/feature_pod_controller_base.h"
 #include "components/vector_icons/vector_icons.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/gfx/paint_vector_icon.h"
@@ -49,8 +49,8 @@
 
 }  // namespace
 
-// Constructor for prototype tile without a controller.
-// TODO(b/252871301): Remove when applying controllers to each feature tile.
+// Constructor for prototype tiles without a callback.
+// TODO(b/252871301): Remove when having implemented each feature tile.
 FeatureTile::FeatureTile(TileType type)
     : Button(PressedCallback()), type_(type) {
   UpdateColors();
@@ -68,40 +68,14 @@
   SetVectorIcon(vector_icons::kDogfoodIcon);
 }
 
-FeatureTile::FeatureTile(FeaturePodControllerBase* controller,
+FeatureTile::FeatureTile(base::RepeatingCallback<void()> callback,
                          bool is_togglable,
                          TileType type)
-    : Button(base::BindRepeating(&FeaturePodControllerBase::OnIconPressed,
-                                 base::Unretained(controller))),
-      is_togglable_(is_togglable),
-      type_(type) {
-  DCHECK(controller);
+    : Button(callback), is_togglable_(is_togglable), type_(type) {
   UpdateColors();
   views::InstallRoundRectHighlightPathGenerator(this, gfx::Insets(),
                                                 kButtonRadius);
   CreateChildViews();
-
-  if (type == TileType::kCompact)
-    return;
-
-  drill_container_ = AddChildView(std::make_unique<views::LabelButton>(
-      base::BindRepeating(&FeaturePodControllerBase::OnLabelPressed,
-                          base::Unretained(controller))));
-  drill_container_->SetLayoutManager(std::make_unique<FlexLayout>())
-      ->SetMainAxisAlignment(views::LayoutAlignment::kCenter)
-      .SetCrossAxisAlignment(views::LayoutAlignment::kCenter);
-  drill_container_->SetPreferredSize(kDrillContainerSize);
-  drill_container_->SetFocusBehavior(FocusBehavior::NEVER);
-  // TODO(b/259280052): Make the `drill_in_button_` an ImageView so we do not
-  // receive a callback since it is already applied to `drill_container_`.
-  // Apply focus to the view only when the button type is "Toggle + Drill-in".
-  drill_in_button_ =
-      drill_container_->AddChildView(std::make_unique<IconButton>(
-          base::BindRepeating(&FeaturePodControllerBase::OnLabelPressed,
-                              base::Unretained(controller)),
-          IconButton::Type::kSmall, &kQuickSettingsRightArrowIcon,
-          /*togglable=*/false,
-          /*has_border=*/false));
 }
 
 void FeatureTile::CreateChildViews() {
@@ -162,6 +136,36 @@
   }
 }
 
+void FeatureTile::CreateDrillInButton(base::RepeatingCallback<void()> callback,
+                                      const std::u16string& tooltip_text) {
+  DCHECK_EQ(type_, TileType::kPrimary);
+
+  auto drill_in_button = std::make_unique<views::LabelButton>(callback);
+  drill_in_button->SetLayoutManager(std::make_unique<FlexLayout>())
+      ->SetMainAxisAlignment(views::LayoutAlignment::kCenter)
+      .SetCrossAxisAlignment(views::LayoutAlignment::kCenter);
+  drill_in_button->SetPreferredSize(kDrillContainerSize);
+  drill_in_button->SetFocusBehavior(FocusBehavior::NEVER);
+  drill_in_button->SetTooltipText(tooltip_text);
+
+  auto drill_in_arrow =
+      std::make_unique<IconButton>(callback, IconButton::Type::kXSmall,
+                                   &kQuickSettingsRightArrowIcon, tooltip_text,
+                                   /*togglable=*/false,
+                                   /*has_border=*/false);
+
+  // Focus behavior is set on this view, but we let its parent view
+  // `drill_in_button_` handle the button events.
+  drill_in_arrow->SetCanProcessEventsWithinSubtree(false);
+
+  // Only buttons with Toggle + Drill-in behavior can focus the drill-in arrow.
+  if (!is_togglable_)
+    drill_in_arrow->SetFocusBehavior(FocusBehavior::NEVER);
+
+  drill_in_button_ = AddChildView(std::move(drill_in_button));
+  drill_in_button_->AddChildView(std::move(drill_in_arrow));
+}
+
 void FeatureTile::UpdateColors() {
   ui::ColorId background_color_id =
       toggled_ ? cros_tokens::kCrosSysSystemPrimaryContainer
@@ -204,15 +208,9 @@
 void FeatureTile::SetDrillInButtonTooltipText(const std::u16string& text) {
   // Only primary tiles have a drill-in button.
   DCHECK(drill_in_button_);
-  drill_container_->SetTooltipText(text);
   drill_in_button_->SetTooltipText(text);
 }
 
-void FeatureTile::SetDrillInButtonVisibility(bool visible) {
-  DCHECK(drill_in_button_);
-  drill_container_->SetVisible(visible);
-}
-
 BEGIN_METADATA(FeatureTile, views::Button)
 END_METADATA
 
diff --git a/ash/system/unified/feature_tile.h b/ash/system/unified/feature_tile.h
index 2f36d37..d060004 100644
--- a/ash/system/unified/feature_tile.h
+++ b/ash/system/unified/feature_tile.h
@@ -6,15 +6,12 @@
 #define ASH_SYSTEM_UNIFIED_FEATURE_TILE_H_
 
 #include "ash/ash_export.h"
-#include "ash/style/icon_button.h"
 #include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/controls/button/label_button.h"
 
 namespace ash {
 
-class FeaturePodControllerBase;
-
 // The main button used in FeatureTilesContainerView, which acts as an entry
 // point for features in QuickSettingsView.
 
@@ -45,13 +42,17 @@
     kMaxValue = kCompact,
   };
 
-  // Constructor that doesn't receive a controller and applies placeholder icons
-  // and titles.
-  // TODO(b/252871301): Remove when applying controllers to each feature tile.
+  // Constructor for prototype tiles without a callback. Applies placeholder
+  // icons and titles.
+  // TODO(b/252871301): Remove when having implemented each feature tile.
   explicit FeatureTile(TileType type = TileType::kPrimary);
 
-  // The controller must outlive this object.
-  explicit FeatureTile(FeaturePodControllerBase* controller,
+  // Constructor for FeatureTiles. `callback` will be called when interacting
+  // with the main part of the button, which accounts for the whole tile.
+  // For primary tiles with drill-in, `callback` is called when interacting with
+  // the left side of the button, since the right side holds the drill-in
+  // button.
+  explicit FeatureTile(base::RepeatingCallback<void()> callback,
                        bool is_togglable = true,
                        TileType type = TileType::kPrimary);
   FeatureTile(const FeatureTile&) = delete;
@@ -62,6 +63,12 @@
   // depending on the button's `type_`.
   void CreateChildViews();
 
+  // Creates the `drill_container_` which holds the `drill_in_button_`.
+  // `callback` is called when interacting with the right side of the button
+  // where the drill-in button exists.
+  void CreateDrillInButton(base::RepeatingCallback<void()> callback,
+                           const std::u16string& tooltip_text);
+
   TileType tile_type() { return type_; }
 
   // Updates the colors of the background and elements of the button.
@@ -87,10 +94,7 @@
   // Sets the tooltip text of `drill_container_` and `drill_in_button_`.
   void SetDrillInButtonTooltipText(const std::u16string& text);
 
-  // Sets visibility of `drill_container_` and `drill_in_button_`.
-  void SetDrillInButtonVisibility(bool visible);
-
-  views::LabelButton* drill_container() { return drill_container_; }
+  views::LabelButton* drill_in_button() { return drill_in_button_; }
 
  private:
   friend class NotificationCounterViewTest;
@@ -99,8 +103,7 @@
   views::ImageView* icon_ = nullptr;
   views::Label* label_ = nullptr;
   views::Label* sub_label_ = nullptr;
-  views::LabelButton* drill_container_ = nullptr;
-  IconButton* drill_in_button_ = nullptr;
+  views::LabelButton* drill_in_button_ = nullptr;
 
   // Whether this button is togglable.
   bool is_togglable_ = false;
diff --git a/ash/system/unified/feature_tile_unittest.cc b/ash/system/unified/feature_tile_unittest.cc
index 6f9c420e..b697932 100644
--- a/ash/system/unified/feature_tile_unittest.cc
+++ b/ash/system/unified/feature_tile_unittest.cc
@@ -11,6 +11,7 @@
 #include "ash/system/unified/feature_pod_controller_base.h"
 #include "ash/system/unified/feature_tile.h"
 #include "ash/test/ash_test_base.h"
+#include "base/memory/weak_ptr.h"
 #include "base/test/scoped_feature_list.h"
 #include "components/vector_icons/vector_icons.h"
 #include "ui/views/test/views_test_utils.h"
@@ -37,8 +38,10 @@
   }
 
   std::unique_ptr<FeatureTile> CreateTile() override {
-    auto tile =
-        std::make_unique<FeatureTile>(/*controller=*/this, togglable_, type_);
+    auto tile = std::make_unique<FeatureTile>(
+        base::BindRepeating(&FeaturePodControllerBase::OnIconPressed,
+                            weak_ptr_factory_.GetWeakPtr()),
+        togglable_, type_);
     tile->SetVectorIcon(vector_icons::kDogfoodIcon);
     tile_ = tile.get();
     return tile;
@@ -68,6 +71,15 @@
     was_label_pressed_ = true;
   }
 
+  // FeaturePodController elements in production know if they need to create a
+  // drill-in button, but here we create it after creating the base button.
+  void CreateDrillInButton() {
+    tile_->CreateDrillInButton(
+        base::BindRepeating(&FeaturePodControllerBase::OnLabelPressed,
+                            weak_ptr_factory_.GetWeakPtr()),
+        u"Tooltip text");
+  }
+
   bool WasIconPressed() { return was_icon_pressed_; }
   bool WasLabelPressed() { return was_label_pressed_; }
 
@@ -78,6 +90,8 @@
   bool togglable_ = false;
   bool toggled_ = false;
   FeatureTile::TileType type_ = FeatureTile::TileType::kPrimary;
+
+  base::WeakPtrFactory<MockFeaturePodController> weak_ptr_factory_{this};
 };
 
 }  // namespace
@@ -116,11 +130,7 @@
       /*togglable=*/false, FeatureTile::TileType::kPrimary);
   auto* tile = widget_->SetContentsView(mock_controller->CreateTile());
 
-  // Hide drill-in button.
-  tile->SetDrillInButtonVisibility(false);
-
-  ASSERT_TRUE(tile->drill_container());
-  EXPECT_FALSE(tile->drill_container()->GetVisible());
+  EXPECT_FALSE(tile->drill_in_button());
 
   // Ensure icon hasn't been pressed.
   EXPECT_FALSE(tile->IsToggled());
@@ -138,11 +148,7 @@
       /*togglable=*/true, FeatureTile::TileType::kPrimary);
   auto* tile = widget_->SetContentsView(mock_controller->CreateTile());
 
-  // Hide drill-in button.
-  tile->SetDrillInButtonVisibility(false);
-
-  ASSERT_TRUE(tile->drill_container());
-  EXPECT_FALSE(tile->drill_container()->GetVisible());
+  EXPECT_FALSE(tile->drill_in_button());
 
   // Ensure icon hasn't been pressed.
   EXPECT_FALSE(tile->IsToggled());
@@ -165,15 +171,16 @@
       /*togglable=*/false, FeatureTile::TileType::kPrimary);
   auto* tile = widget_->SetContentsView(mock_controller->CreateTile());
 
-  // Expect drill-in button visible.
-  ASSERT_TRUE(tile->drill_container());
-  EXPECT_TRUE(tile->drill_container()->GetVisible());
+  mock_controller->CreateDrillInButton();
+  views::test::RunScheduledLayout(tile);
+  ASSERT_TRUE(tile->drill_in_button());
+  EXPECT_TRUE(tile->drill_in_button()->GetVisible());
 
   // Ensure icon hasn't been pressed.
   EXPECT_FALSE(tile->IsToggled());
   EXPECT_FALSE(mock_controller->WasIconPressed());
 
-  LeftClickOn(tile->drill_container());
+  LeftClickOn(tile->drill_in_button());
 
   // Ensure icon was pressed and button does not toggle after clicking it.
   EXPECT_TRUE(mock_controller->WasIconPressed());
@@ -187,9 +194,10 @@
       /*togglable=*/true, FeatureTile::TileType::kPrimary);
   auto* tile = widget_->SetContentsView(mock_controller->CreateTile());
 
-  // Expect drill-in button visible.
-  ASSERT_TRUE(tile->drill_container());
-  EXPECT_TRUE(tile->drill_container()->GetVisible());
+  mock_controller->CreateDrillInButton();
+  views::test::RunScheduledLayout(tile);
+  ASSERT_TRUE(tile->drill_in_button());
+  EXPECT_TRUE(tile->drill_in_button()->GetVisible());
 
   // Ensure icon is not pressed or toggled.
   EXPECT_FALSE(tile->IsToggled());
@@ -203,7 +211,7 @@
 
   EXPECT_FALSE(mock_controller->WasLabelPressed());
 
-  LeftClickOn(tile->drill_container());
+  LeftClickOn(tile->drill_in_button());
 
   // Ensure `WasLabelPressed` after clicking drill-in button.
   EXPECT_TRUE(mock_controller->WasLabelPressed());
diff --git a/ash/system/unified/feature_tiles_container_view_unittest.cc b/ash/system/unified/feature_tiles_container_view_unittest.cc
index c328ffa8..89f6eda 100644
--- a/ash/system/unified/feature_tiles_container_view_unittest.cc
+++ b/ash/system/unified/feature_tiles_container_view_unittest.cc
@@ -14,6 +14,7 @@
 #include "ash/system/unified/unified_system_tray_bubble.h"
 #include "ash/system/unified/unified_system_tray_controller.h"
 #include "ash/test/ash_test_base.h"
+#include "base/memory/weak_ptr.h"
 #include "base/test/scoped_feature_list.h"
 #include "components/vector_icons/vector_icons.h"
 #include "ui/views/test/views_test_utils.h"
@@ -36,8 +37,10 @@
   }
 
   std::unique_ptr<FeatureTile> CreateTile() override {
-    auto tile = std::make_unique<FeatureTile>(/*controller=*/this,
-                                              /*togglable=*/true, type_);
+    auto tile = std::make_unique<FeatureTile>(
+        base::BindRepeating(&FeaturePodControllerBase::OnIconPressed,
+                            weak_ptr_factory_.GetWeakPtr()),
+        /*togglable=*/true, type_);
     tile->SetVectorIcon(vector_icons::kDogfoodIcon);
     return tile;
   }
@@ -51,6 +54,8 @@
 
  private:
   FeatureTile::TileType type_;
+
+  base::WeakPtrFactory<MockFeaturePodController> weak_ptr_factory_{this};
 };
 
 }  // namespace
diff --git a/ash/system/unified/unified_system_tray_controller.cc b/ash/system/unified/unified_system_tray_controller.cc
index bb603b9..fafd6f4 100644
--- a/ash/system/unified/unified_system_tray_controller.cc
+++ b/ash/system/unified/unified_system_tray_controller.cc
@@ -651,6 +651,7 @@
       std::make_unique<AccessibilityFeaturePodController>(this);
   auto screen_capture_controller =
       std::make_unique<CaptureModeFeaturePodController>(this);
+  auto cast_controller = std::make_unique<CastFeaturePodController>(this);
   auto vpn_controller = std::make_unique<VPNFeaturePodController>(this);
 
   std::vector<std::unique_ptr<FeatureTile>> tiles;
@@ -661,6 +662,7 @@
   tiles.push_back(
       std::make_unique<FeatureTile>(FeatureTile::TileType::kCompact));
 
+  tiles.push_back(cast_controller->CreateTile());
   tiles.push_back(vpn_controller->CreateTile());
 
   // More placeholder tiles.
@@ -672,6 +674,7 @@
   // Transfer ownership of controllers to this.
   feature_pod_controllers_.push_back(std::move(accessibility_controller));
   feature_pod_controllers_.push_back(std::move(screen_capture_controller));
+  feature_pod_controllers_.push_back(std::move(cast_controller));
   feature_pod_controllers_.push_back(std::move(vpn_controller));
 }
 
diff --git a/ash/touch/touch_selection_magnifier_runner_ash.cc b/ash/touch/touch_selection_magnifier_runner_ash.cc
new file mode 100644
index 0000000..cf02de1
--- /dev/null
+++ b/ash/touch/touch_selection_magnifier_runner_ash.cc
@@ -0,0 +1,98 @@
+// 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 "ash/touch/touch_selection_magnifier_runner_ash.h"
+
+#include "ash/constants/ash_features.h"
+#include "ash/public/cpp/shell_window_ids.h"
+#include "ui/aura/window.h"
+#include "ui/compositor/layer.h"
+#include "ui/gfx/geometry/point_conversions.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace ash {
+
+namespace {
+
+constexpr float kMagnifierScale = 2.0f;
+
+constexpr gfx::RoundedCornersF kMagnifierRoundedCorners(20);
+
+constexpr gfx::Size kMagnifierLayerSize(100, 48);
+
+gfx::Rect GetBounds(const gfx::Point& point) {
+  return gfx::Rect(gfx::Point(point.x() - kMagnifierLayerSize.width() / 2,
+                              point.y() - kMagnifierLayerSize.height() / 2),
+                   kMagnifierLayerSize);
+}
+
+// Returns the child container in `root` that should parent the magnifier layer.
+aura::Window* GetMagnifierParentContainerForRoot(aura::Window* root) {
+  return root->GetChildById(kShellWindowId_ImeWindowParentContainer);
+}
+
+}  // namespace
+
+TouchSelectionMagnifierRunnerAsh::TouchSelectionMagnifierRunnerAsh() = default;
+
+TouchSelectionMagnifierRunnerAsh::~TouchSelectionMagnifierRunnerAsh() = default;
+
+void TouchSelectionMagnifierRunnerAsh::ShowMagnifier(
+    aura::Window* context,
+    const gfx::PointF& position) {
+  DCHECK(context);
+  DCHECK(!current_context_ || current_context_ == context);
+  if (!current_context_) {
+    current_context_ = context;
+  }
+
+  aura::Window* root_window = current_context_->GetRootWindow();
+  DCHECK(root_window);
+  gfx::PointF position_in_root(position);
+  aura::Window::ConvertPointToTarget(context, root_window, &position_in_root);
+
+  if (!magnifier_layer_) {
+    CreateMagnifierLayer(root_window, position_in_root);
+  } else {
+    magnifier_layer_->SetBounds(
+        GetBounds(gfx::ToRoundedPoint(position_in_root)));
+  }
+}
+
+void TouchSelectionMagnifierRunnerAsh::CloseMagnifier() {
+  current_context_ = nullptr;
+  magnifier_layer_ = nullptr;
+}
+
+bool TouchSelectionMagnifierRunnerAsh::IsRunning() const {
+  return current_context_ != nullptr;
+}
+
+const aura::Window*
+TouchSelectionMagnifierRunnerAsh::GetCurrentContextForTesting() const {
+  return current_context_;
+}
+
+const ui::Layer* TouchSelectionMagnifierRunnerAsh::GetMagnifierLayerForTesting()
+    const {
+  return magnifier_layer_.get();
+}
+
+void TouchSelectionMagnifierRunnerAsh::CreateMagnifierLayer(
+    aura::Window* root_window,
+    const gfx::PointF& position_in_root) {
+  aura::Window* parent_container =
+      GetMagnifierParentContainerForRoot(root_window);
+
+  ui::Layer* parent_layer = parent_container->layer();
+  magnifier_layer_ = std::make_unique<ui::Layer>(ui::LAYER_SOLID_COLOR);
+  magnifier_layer_->SetBounds(GetBounds(gfx::ToRoundedPoint(position_in_root)));
+  magnifier_layer_->SetBackgroundZoom(kMagnifierScale, 0);
+  magnifier_layer_->SetFillsBoundsOpaquely(false);
+  magnifier_layer_->SetRoundedCornerRadius(kMagnifierRoundedCorners);
+  parent_layer->Add(magnifier_layer_.get());
+}
+
+}  // namespace ash
diff --git a/ash/touch/touch_selection_magnifier_runner_ash.h b/ash/touch/touch_selection_magnifier_runner_ash.h
new file mode 100644
index 0000000..c5b61d35
--- /dev/null
+++ b/ash/touch/touch_selection_magnifier_runner_ash.h
@@ -0,0 +1,63 @@
+// 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 ASH_TOUCH_TOUCH_SELECTION_MAGNIFIER_RUNNER_ASH_H_
+#define ASH_TOUCH_TOUCH_SELECTION_MAGNIFIER_RUNNER_ASH_H_
+
+#include "ash/ash_export.h"
+#include "base/memory/raw_ptr.h"
+#include "ui/touch_selection/touch_selection_magnifier_runner.h"
+
+namespace aura {
+class Window;
+}  // namespace aura
+
+namespace gfx {
+class PointF;
+}  // namespace gfx
+
+namespace ui {
+class Layer;
+}  // namespace ui
+
+namespace ash {
+
+// Ash implementation for TouchSelectionMagnifierRunner.
+class ASH_EXPORT TouchSelectionMagnifierRunnerAsh
+    : public ui::TouchSelectionMagnifierRunner {
+ public:
+  TouchSelectionMagnifierRunnerAsh();
+
+  TouchSelectionMagnifierRunnerAsh(const TouchSelectionMagnifierRunnerAsh&) =
+      delete;
+  TouchSelectionMagnifierRunnerAsh& operator=(
+      const TouchSelectionMagnifierRunnerAsh&) = delete;
+
+  ~TouchSelectionMagnifierRunnerAsh() override;
+
+  // ui::TouchSelectionMagnifierRunner:
+  void ShowMagnifier(aura::Window* context,
+                     const gfx::PointF& position) override;
+  void CloseMagnifier() override;
+  bool IsRunning() const override;
+
+  const aura::Window* GetCurrentContextForTesting() const;
+
+  const ui::Layer* GetMagnifierLayerForTesting() const;
+
+ private:
+  void CreateMagnifierLayer(aura::Window* root_window,
+                            const gfx::PointF& position_in_root);
+
+  // Current context window in which the magnifier is being shown, or `nullptr`
+  // if no magnifier is running.
+  raw_ptr<aura::Window> current_context_ = nullptr;
+
+  // The magnifier layer, which draws the background with a zoom filter applied.
+  std::unique_ptr<ui::Layer> magnifier_layer_;
+};
+
+}  // namespace ash
+
+#endif  // ASH_TOUCH_TOUCH_SELECTION_MAGNIFIER_RUNNER_ASH_H_
diff --git a/ash/touch/touch_selection_magnifier_runner_ash_unittest.cc b/ash/touch/touch_selection_magnifier_runner_ash_unittest.cc
new file mode 100644
index 0000000..efa017b
--- /dev/null
+++ b/ash/touch/touch_selection_magnifier_runner_ash_unittest.cc
@@ -0,0 +1,175 @@
+// 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 "ash/touch/touch_selection_magnifier_runner_ash.h"
+
+#include "ash/constants/ash_features.h"
+#include "ash/test/ash_test_base.h"
+#include "base/test/scoped_feature_list.h"
+#include "ui/aura/window.h"
+#include "ui/compositor/layer.h"
+#include "ui/events/event_utils.h"
+#include "ui/touch_selection/touch_selection_magnifier_runner.h"
+#include "ui/views/widget/widget.h"
+
+namespace ash {
+
+namespace {
+
+// Should match `kMagnifierLayerSize` in
+// touch_selection_magnifier_runner_ash.cc.
+constexpr gfx::Size kMagnifierLayerSize(100, 48);
+
+TouchSelectionMagnifierRunnerAsh* GetMagnifierRunner() {
+  return static_cast<TouchSelectionMagnifierRunnerAsh*>(
+      ui::TouchSelectionMagnifierRunner::GetInstance());
+}
+
+void RunPendingMessages() {
+  base::RunLoop().RunUntilIdle();
+}
+
+class TouchSelectionMagnifierRunnerAshTest : public NoSessionAshTestBase {
+ public:
+  TouchSelectionMagnifierRunnerAshTest() = default;
+
+  TouchSelectionMagnifierRunnerAshTest(
+      const TouchSelectionMagnifierRunnerAshTest&) = delete;
+  TouchSelectionMagnifierRunnerAshTest& operator=(
+      const TouchSelectionMagnifierRunnerAshTest&) = delete;
+
+  ~TouchSelectionMagnifierRunnerAshTest() override = default;
+
+  void SetUp() override {
+    scoped_feature_list_.InitAndEnableFeature(
+        features::kTouchTextEditingRedesign);
+    NoSessionAshTestBase::SetUp();
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+// Tests that the default touch selection magnifier runner is installed and runs
+// when a magnifier should be shown.
+TEST_F(TouchSelectionMagnifierRunnerAshTest, InstalledAndRuns) {
+  TouchSelectionMagnifierRunnerAsh* magnifier_runner = GetMagnifierRunner();
+
+  // Magnifier runner instance should be installed, but magnifier should not be
+  // running initially.
+  ASSERT_TRUE(magnifier_runner);
+  EXPECT_FALSE(magnifier_runner->IsRunning());
+
+  magnifier_runner->ShowMagnifier(GetContext(), gfx::PointF(300, 200));
+  EXPECT_TRUE(magnifier_runner->IsRunning());
+  EXPECT_EQ(magnifier_runner->GetCurrentContextForTesting(), GetContext());
+
+  magnifier_runner->CloseMagnifier();
+  RunPendingMessages();
+  EXPECT_FALSE(magnifier_runner->IsRunning());
+  EXPECT_FALSE(magnifier_runner->GetCurrentContextForTesting());
+
+  // Show magnifier again.
+  magnifier_runner->ShowMagnifier(GetContext(), gfx::PointF(300, 200));
+  EXPECT_TRUE(magnifier_runner->IsRunning());
+  EXPECT_EQ(magnifier_runner->GetCurrentContextForTesting(), GetContext());
+
+  magnifier_runner->CloseMagnifier();
+  RunPendingMessages();
+  EXPECT_FALSE(magnifier_runner->IsRunning());
+  EXPECT_FALSE(magnifier_runner->GetCurrentContextForTesting());
+}
+
+// Tests that the touch selection magnifier runner can run again with a
+// different context after it is closed.
+TEST_F(TouchSelectionMagnifierRunnerAshTest, NewContext) {
+  TouchSelectionMagnifierRunnerAsh* magnifier_runner = GetMagnifierRunner();
+  ASSERT_TRUE(magnifier_runner);
+
+  std::unique_ptr<aura::Window> window1(CreateTestWindow());
+  std::unique_ptr<aura::Window> window2(CreateTestWindow());
+
+  magnifier_runner->ShowMagnifier(window1.get(), gfx::PointF(300, 200));
+  EXPECT_TRUE(magnifier_runner->IsRunning());
+  EXPECT_EQ(magnifier_runner->GetCurrentContextForTesting(), window1.get());
+
+  magnifier_runner->CloseMagnifier();
+  RunPendingMessages();
+  EXPECT_FALSE(magnifier_runner->IsRunning());
+  EXPECT_FALSE(magnifier_runner->GetCurrentContextForTesting());
+
+  // Show magnifier with different context window.
+  magnifier_runner->ShowMagnifier(window2.get(), gfx::PointF(300, 200));
+  EXPECT_TRUE(magnifier_runner->IsRunning());
+  EXPECT_EQ(magnifier_runner->GetCurrentContextForTesting(), window2.get());
+
+  magnifier_runner->CloseMagnifier();
+  RunPendingMessages();
+  EXPECT_FALSE(magnifier_runner->IsRunning());
+  EXPECT_FALSE(magnifier_runner->GetCurrentContextForTesting());
+}
+
+// Tests that the magnifier layer is created and destroyed.
+TEST_F(TouchSelectionMagnifierRunnerAshTest, Layer) {
+  TouchSelectionMagnifierRunnerAsh* magnifier_runner = GetMagnifierRunner();
+  ASSERT_TRUE(magnifier_runner);
+
+  magnifier_runner->ShowMagnifier(GetContext(), gfx::PointF(300, 200));
+  ASSERT_TRUE(magnifier_runner->GetMagnifierLayerForTesting());
+
+  magnifier_runner->CloseMagnifier();
+  RunPendingMessages();
+  EXPECT_FALSE(magnifier_runner->GetMagnifierLayerForTesting());
+}
+
+// Tests that the magnifier layer is positioned with the correct bounds.
+TEST_F(TouchSelectionMagnifierRunnerAshTest, LayerBounds) {
+  TouchSelectionMagnifierRunnerAsh* magnifier_runner = GetMagnifierRunner();
+  ASSERT_TRUE(magnifier_runner);
+
+  gfx::PointF position(300, 200);
+  magnifier_runner->ShowMagnifier(GetContext(), position);
+  const ui::Layer* magnifier_layer =
+      magnifier_runner->GetMagnifierLayerForTesting();
+  ASSERT_TRUE(magnifier_layer);
+
+  gfx::Rect bounds = magnifier_layer->bounds();
+  EXPECT_EQ(bounds.size(), kMagnifierLayerSize);
+  EXPECT_EQ(bounds.CenterPoint(), gfx::Point(position.x(), position.y()));
+
+  magnifier_runner->CloseMagnifier();
+  RunPendingMessages();
+}
+
+// Tests that the magnifier layer bounds update correctly.
+TEST_F(TouchSelectionMagnifierRunnerAshTest, LayerUpdatesBounds) {
+  TouchSelectionMagnifierRunnerAsh* magnifier_runner = GetMagnifierRunner();
+  ASSERT_TRUE(magnifier_runner);
+
+  gfx::PointF position(300, 200);
+  magnifier_runner->ShowMagnifier(GetContext(), position);
+  const ui::Layer* magnifier_layer =
+      magnifier_runner->GetMagnifierLayerForTesting();
+  ASSERT_TRUE(magnifier_layer);
+
+  gfx::Rect bounds = magnifier_layer->bounds();
+  EXPECT_EQ(bounds.size(), kMagnifierLayerSize);
+  EXPECT_EQ(bounds.CenterPoint(), gfx::Point(position.x(), position.y()));
+
+  // Move the magnifier.
+  position = gfx::PointF(400, 150);
+  magnifier_runner->ShowMagnifier(GetContext(), position);
+  EXPECT_EQ(magnifier_layer, magnifier_runner->GetMagnifierLayerForTesting());
+
+  bounds = magnifier_layer->bounds();
+  EXPECT_EQ(bounds.size(), kMagnifierLayerSize);
+  EXPECT_EQ(bounds.CenterPoint(), gfx::Point(position.x(), position.y()));
+
+  magnifier_runner->CloseMagnifier();
+  RunPendingMessages();
+}
+
+}  // namespace
+
+}  // namespace ash
diff --git a/ash/wallpaper/wallpaper_controller_unittest.cc b/ash/wallpaper/wallpaper_controller_unittest.cc
index b9b850a..703f6c8 100644
--- a/ash/wallpaper/wallpaper_controller_unittest.cc
+++ b/ash/wallpaper/wallpaper_controller_unittest.cc
@@ -70,6 +70,7 @@
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/codec/jpeg_codec.h"
 #include "ui/gfx/color_analysis.h"
+#include "ui/gfx/image/image_skia_rep.h"
 #include "ui/views/view_tracker.h"
 #include "ui/views/widget/widget.h"
 
diff --git a/ash/webui/common/resources/keyboard_key.html b/ash/webui/common/resources/keyboard_key.html
index 09f82ff5..45d7864e 100644
--- a/ash/webui/common/resources/keyboard_key.html
+++ b/ash/webui/common/resources/keyboard_key.html
@@ -51,7 +51,7 @@
         var(--keyboard-key-top-radii, 4px)
         var(--keyboard-key-bottom-right-radius, 4px)
         4px;
-    --icon-size: var(--keyboard-key-icon-size, 100%);
+    --icon-size: min(100%, var(--keyboard-key-icon-size, 100%));
     --travel: var(--keyboard-key-travel, 4px);
     --text-color-unpressed: var(--cros-icon-color-prominent);
     --text-color-pressed: var(--cros-button-icon-color-primary);
diff --git a/ash/webui/personalization_app/mojom/BUILD.gn b/ash/webui/personalization_app/mojom/BUILD.gn
index dba4334..31de432 100644
--- a/ash/webui/personalization_app/mojom/BUILD.gn
+++ b/ash/webui/personalization_app/mojom/BUILD.gn
@@ -72,6 +72,10 @@
           mojom = "ash.personalization_app.mojom.AmbientUiVisibility"
           cpp = "ash::AmbientUiVisibility"
         },
+        {
+          mojom = "ash.personalization_app.mojom.ColorScheme"
+          cpp = "ash::ColorScheme"
+        },
       ]
       traits_headers = [ "personalization_app_mojom_traits.h" ]
       traits_sources = [ "personalization_app_mojom_traits.cc" ]
diff --git a/ash/webui/personalization_app/mojom/personalization_app.mojom b/ash/webui/personalization_app/mojom/personalization_app.mojom
index 686d9635..9ad230e 100644
--- a/ash/webui/personalization_app/mojom/personalization_app.mojom
+++ b/ash/webui/personalization_app/mojom/personalization_app.mojom
@@ -324,6 +324,14 @@
     CancelPreviewWallpaper();
 };
 
+enum ColorScheme {
+  kStatic = 0,
+  kTonalSpot = 1,
+  kNeutral = 2,
+  kExpressive = 3,
+  kVibrant = 4,
+};
+
 // Receives information whenever there are theme related changes such as color
 // mode.
 interface ThemeObserver {
@@ -346,6 +354,14 @@
   // Disables or enables dark color mode auto scheduler.
   SetColorModeAutoScheduleEnabled(bool enabled);
 
+  // Sets the color scheme for dynamic color.
+  // @see //ash/style/color_palette_controller.h
+  SetColorScheme(ColorScheme colorScheme);
+
+  // Sets the seed color for dynamic color.
+  // @see //ash/style/color_palette_controller.h
+  SetStaticColor(skia.mojom.SkColor static_color);
+
   // Returns whether color mode auto scheduler is enabled.
   IsColorModeAutoScheduleEnabled() => (bool enabled);
 
diff --git a/ash/webui/personalization_app/mojom/personalization_app_mojom_traits.cc b/ash/webui/personalization_app/mojom/personalization_app_mojom_traits.cc
index 1ee095e6..3e517d4 100644
--- a/ash/webui/personalization_app/mojom/personalization_app_mojom_traits.cc
+++ b/ash/webui/personalization_app/mojom/personalization_app_mojom_traits.cc
@@ -35,6 +35,7 @@
 using MojomTemperatureUnit = ash::personalization_app::mojom::TemperatureUnit;
 using MojomAmbientUiVisibility =
     ash::personalization_app::mojom::AmbientUiVisibility;
+using MojomColorScheme = ash::personalization_app::mojom::ColorScheme;
 
 MojomWallpaperLayout
 EnumTraits<MojomWallpaperLayout, ash::WallpaperLayout>::ToMojom(
@@ -464,4 +465,44 @@
   return false;
 }
 
+MojomColorScheme EnumTraits<MojomColorScheme, ash::ColorScheme>::ToMojom(
+    ash::ColorScheme input) {
+  switch (input) {
+    case ash::ColorScheme::kTonalSpot:
+      return MojomColorScheme::kTonalSpot;
+    case ash::ColorScheme::kNeutral:
+      return MojomColorScheme::kNeutral;
+    case ash::ColorScheme::kExpressive:
+      return MojomColorScheme::kExpressive;
+    case ash::ColorScheme::kVibrant:
+      return MojomColorScheme::kVibrant;
+    case ash::ColorScheme::kStatic:
+      return MojomColorScheme::kStatic;
+  }
+}
+
+bool EnumTraits<MojomColorScheme, ash::ColorScheme>::FromMojom(
+    MojomColorScheme input,
+    ash::ColorScheme* output) {
+  switch (input) {
+    case MojomColorScheme::kTonalSpot:
+      *output = ash::ColorScheme::kTonalSpot;
+      return true;
+    case MojomColorScheme::kNeutral:
+      *output = ash::ColorScheme::kNeutral;
+      return true;
+    case MojomColorScheme::kExpressive:
+      *output = ash::ColorScheme::kExpressive;
+      return true;
+    case MojomColorScheme::kVibrant:
+      *output = ash::ColorScheme::kVibrant;
+      return true;
+    case MojomColorScheme::kStatic:
+      *output = ash::ColorScheme::kStatic;
+      return true;
+  }
+  NOTREACHED();
+  return false;
+}
+
 }  // namespace mojo
diff --git a/ash/webui/personalization_app/mojom/personalization_app_mojom_traits.h b/ash/webui/personalization_app/mojom/personalization_app_mojom_traits.h
index 906ac8f..e8daa39 100644
--- a/ash/webui/personalization_app/mojom/personalization_app_mojom_traits.h
+++ b/ash/webui/personalization_app/mojom/personalization_app_mojom_traits.h
@@ -14,6 +14,7 @@
 #include "ash/public/cpp/default_user_image.h"
 #include "ash/public/cpp/personalization_app/user_display_info.h"
 #include "ash/public/cpp/wallpaper/wallpaper_types.h"
+#include "ash/style/color_palette_controller.h"
 #include "ash/webui/personalization_app/mojom/personalization_app.mojom-forward.h"
 #include "ash/webui/personalization_app/proto/backdrop_wallpaper.pb.h"
 #include "base/unguessable_token.h"
@@ -161,6 +162,14 @@
                         ash::AmbientUiVisibility* output);
 };
 
+template <>
+struct EnumTraits<ash::personalization_app::mojom::ColorScheme,
+                  ash::ColorScheme> {
+  using MojomColorScheme = ::ash::personalization_app::mojom::ColorScheme;
+  static MojomColorScheme ToMojom(ash::ColorScheme input);
+  static bool FromMojom(MojomColorScheme input, ash::ColorScheme* output);
+};
+
 }  // namespace mojo
 
 #endif  // ASH_WEBUI_PERSONALIZATION_APP_MOJOM_PERSONALIZATION_APP_MOJOM_TRAITS_H_
diff --git a/ash/webui/personalization_app/resources/js/personalization_app.ts b/ash/webui/personalization_app/resources/js/personalization_app.ts
index d4d9c682..20fa489 100644
--- a/ash/webui/personalization_app/resources/js/personalization_app.ts
+++ b/ash/webui/personalization_app/resources/js/personalization_app.ts
@@ -78,7 +78,7 @@
 export {PersonalizationStore} from './personalization_store.js';
 export {PersonalizationThemeElement} from './theme/personalization_theme_element.js';
 export {PersonalizationToastElement} from './personalization_toast_element.js';
-export {setDarkModeEnabledAction, SetDarkModeEnabledAction, ThemeActionName, ThemeActions} from './theme/theme_actions.js';
+export {setDarkModeEnabledAction, SetDarkModeEnabledAction, setColorSchemeAction, setStaticColorAction, SetStaticColorPrefAction, SetColorSchemePrefAction, ThemeActionName, ThemeActions} from './theme/theme_actions.js';
 export {setThemeProviderForTesting} from './theme/theme_interface_provider.js';
 export {ColorSchemeIconSvgElement} from './theme/color_scheme_icon_svg_element.js';
 export {DynamicColorElement} from './theme/dynamic_color_element.js';
diff --git a/ash/webui/personalization_app/resources/js/theme/dynamic_color_element.html b/ash/webui/personalization_app/resources/js/theme/dynamic_color_element.html
index dcc9b7b..c42345e 100644
--- a/ash/webui/personalization_app/resources/js/theme/dynamic_color_element.html
+++ b/ash/webui/personalization_app/resources/js/theme/dynamic_color_element.html
@@ -50,7 +50,7 @@
     <!-- TODO(b/253089237): Add the final translated text. -->
     <div id="dynamicColorToggleDescription">[temp]Auto</div>
     <!-- TODO(b/253089237): Add the translated aria label. -->
-    <cr-toggle checked="{{automaticSeedColorEnabled}}">
+    <cr-toggle checked="{{automaticSeedColorEnabled}}" on-click="onClickToggle_">
     </cr-toggle>
   </div>
   <iron-a11y-keys id="colorSchemeKeys" keys="left right" on-keys-pressed="onColorSchemeKeysPress_">
@@ -60,21 +60,27 @@
   <iron-selector
       id="colorSchemeSelector"
       selected="0"
-      selected-item="{{colorSchemeSelectedButton_}}"
+      selected-item="{{colorSchemeHighlightedButton_}}"
       hidden="[[!automaticSeedColorEnabled]]">
-    <template is="dom-repeat" items="[[schemes_]]" as="scheme">
-      <cr-button tabindex$="[[getTabIndex_(scheme.id)]]">
-        <color-scheme-icon-svg scheme="[[scheme]]"></color-scheme-icon-svg>
+    <template is="dom-repeat" items="[[colorSchemes_]]" as="colorScheme">
+      <cr-button 
+          tabindex$="[[getTabIndex_(colorScheme.id)]]"
+          on-click="onClickColorSchemeButton_"
+          data-color-scheme-id$="[[colorScheme.id]]">
+        <color-scheme-icon-svg scheme="[[colorScheme]]"></color-scheme-icon-svg>
       </cr-button>
     </template>
   </iron-selector>
   <iron-selector
       id="staticColorSelector"
       selected="0"
-      selected-item="{{staticColorSelectedButton_}}"
+      selected-item="{{staticColorHighlightedButton_}}"
       hidden="[[automaticSeedColorEnabled]]">
     <template is="dom-repeat" items="[[staticColors_]]" as="staticColor">
-      <cr-button tabindex$="[[getTabIndex_(staticColor)]]">
+      <cr-button
+          tabindex$="[[getTabIndex_(staticColor)]]"
+          on-click="onClickStaticColorButton_"
+          data-static-color$="[[staticColor]]">
         <svg>
           <circle style$="fill: [[staticColor]]" cx="24" cy="24" r="24"></circle>
         </svg>
diff --git a/ash/webui/personalization_app/resources/js/theme/dynamic_color_element.ts b/ash/webui/personalization_app/resources/js/theme/dynamic_color_element.ts
index c280c49..57c26bd 100644
--- a/ash/webui/personalization_app/resources/js/theme/dynamic_color_element.ts
+++ b/ash/webui/personalization_app/resources/js/theme/dynamic_color_element.ts
@@ -13,15 +13,20 @@
 import 'chrome://resources/polymer/v3_0/iron-selector/iron-selector.js';
 
 import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.js';
+import {hexColorToSkColor} from 'chrome://resources/js/color_utils.js';
+import {SkColor} from 'chrome://resources/mojo/skia/public/mojom/skcolor.mojom-webui.js';
 import {IronA11yKeysElement} from 'chrome://resources/polymer/v3_0/iron-a11y-keys/iron-a11y-keys.js';
 import {IronSelectorElement} from 'chrome://resources/polymer/v3_0/iron-selector/iron-selector.js';
 
+import {ColorScheme} from '../personalization_app.mojom-webui.js';
 import {WithPersonalizationStore} from '../personalization_store.js';
 
 import {getTemplate} from './dynamic_color_element.html.js';
+import {setColorSchemePref, setStaticColorPref} from './theme_controller.js';
+import {getThemeProvider} from './theme_interface_provider.js';
 
 export interface DynamicColorScheme {
-  id: string;
+  id: ColorScheme;
   primaryColor: string;
   secondaryColor: string;
   tertiaryColor: string;
@@ -36,6 +41,9 @@
   };
 }
 
+const DEFAULT_STATIC_COLOR = hexColorToSkColor('#4285f4');
+const DEFAULT_COLOR_SCHEME = ColorScheme.kTonalSpot;
+
 export class DynamicColorElement extends WithPersonalizationStore {
   static get is() {
     return 'dynamic-color';
@@ -54,18 +62,28 @@
         notify: true,
         reflectToAttribute: true,
       },
+      // The static color stored in the backend.
+      staticColorSelected_: {
+        type: Object,
+        value: DEFAULT_STATIC_COLOR,
+      },
+      // The color scheme stored in the backend.
+      colorSchemeSelected_: {
+        type: Object,
+        value: DEFAULT_COLOR_SCHEME,
+      },
       staticColors_: {
         type: Object,
         readOnly: true,
         value: [
           // TODO(b/254479499): Replace colors when the spec is ready.
-          'var(--google-blue-500)',
-          'var(--google-grey-400)',
-          '#EDD0E4',
-          '#EADECD',
+          '#4285f4',
+          '#bdc1c6',
+          '#edd0e4',
+          '#eadecd',
         ],
       },
-      schemes_: {
+      colorSchemes_: {
         type: Object,
         readOnly: true,
         value(): DynamicColorScheme[] {
@@ -73,25 +91,25 @@
             // TODO(254479725): Replace with colors fetched from the
             // backend.
             {
-              id: 'tonal',
+              id: ColorScheme.kTonalSpot,
               primaryColor: 'var(--google-blue-500)',
               secondaryColor: 'var(--google-red-500)',
               tertiaryColor: 'var(--google-green-500)',
             },
             {
-              id: 'neutral',
+              id: ColorScheme.kNeutral,
               primaryColor: 'var(--google-red-500)',
               secondaryColor: 'var(--google-blue-500)',
               tertiaryColor: 'var(--google-green-500)',
             },
             {
-              id: 'vibrant',
+              id: ColorScheme.kVibrant,
               primaryColor: 'var(--google-green-500)',
               secondaryColor: 'var(--google-red-500)',
               tertiaryColor: 'var(--google-blue-500)',
             },
             {
-              id: 'expressive',
+              id: ColorScheme.kExpressive,
               primaryColor: 'var(--google-orange-500)',
               secondaryColor: 'var(--google-red-500)',
               tertiaryColor: 'var(--google-green-500)',
@@ -100,12 +118,12 @@
         },
       },
       // The color scheme button currently highlighted by keyboard navigation.
-      colorSchemeSelectedButton_: {
+      colorSchemeHighlightedButton_: {
         type: Object,
         notify: true,
       },
       // The static color button currently highlighted by keyboard navigation.
-      staticColorSelectedButton_: {
+      staticColorHighlightedButton_: {
         type: Object,
         notify: true,
       },
@@ -113,10 +131,12 @@
   }
 
   automaticSeedColorEnabled: boolean;
+  private staticColorSelected_: SkColor|null;
+  private colorSchemeSelected_: ColorScheme|null;
   private staticColors_: string[];
-  private schemes_: DynamicColorScheme[];
-  private colorSchemeSelectedButton_: CrButtonElement;
-  private staticColorSelectedButton_: CrButtonElement;
+  private colorSchemes_: DynamicColorScheme[];
+  private colorSchemeHighlightedButton_: CrButtonElement;
+  private staticColorHighlightedButton_: CrButtonElement;
 
   override ready() {
     super.ready();
@@ -124,16 +144,41 @@
     this.$.colorSchemeKeys.target = this.$.colorSchemeSelector;
   }
 
+  private onClickColorSchemeButton_(event: Event) {
+    const eventTarget = event.currentTarget as HTMLElement;
+    const colorScheme = Number(eventTarget.dataset['colorSchemeId']);
+    this.colorSchemeSelected_ = colorScheme;
+    setColorSchemePref(colorScheme, getThemeProvider(), this.getStore());
+  }
+
+  private onClickStaticColorButton_(event: Event) {
+    const eventTarget = event.currentTarget as HTMLElement;
+    const staticColorHexStr = String(eventTarget.dataset['staticColor']);
+    const staticColor = hexColorToSkColor(staticColorHexStr);
+    this.staticColorSelected_ = staticColor;
+    setStaticColorPref(staticColor, getThemeProvider(), this.getStore());
+  }
+
+  private onClickToggle_() {
+    if (this.automaticSeedColorEnabled) {
+      const staticColor = this.staticColorSelected_ || DEFAULT_STATIC_COLOR;
+      setStaticColorPref(staticColor, getThemeProvider(), this.getStore());
+    } else {
+      const colorScheme = this.colorSchemeSelected_ || DEFAULT_COLOR_SCHEME;
+      setColorSchemePref(colorScheme, getThemeProvider(), this.getStore());
+    }
+  }
+
   private onStaticColorKeysPress_(
       e: CustomEvent<{key: string, keyboardEvent: KeyboardEvent}>) {
     this.onKeysPress_(
-        e, this.$.staticColorSelector, this.staticColorSelectedButton_);
+        e, this.$.staticColorSelector, this.staticColorHighlightedButton_);
   }
 
   private onColorSchemeKeysPress_(
       e: CustomEvent<{key: string, keyboardEvent: KeyboardEvent}>) {
     this.onKeysPress_(
-        e, this.$.colorSchemeSelector, this.colorSchemeSelectedButton_);
+        e, this.$.colorSchemeSelector, this.colorSchemeHighlightedButton_);
   }
 
   /** Handle keyboard navigation. */
@@ -156,17 +201,20 @@
     }
 
     // Add focus state for new button.
-    const selectedButton = this.automaticSeedColorEnabled ?
-        this.colorSchemeSelectedButton_ :
-        this.staticColorSelectedButton_;
-    selectedButton.setAttribute('tabindex', '0');
-    selectedButton.focus();
+    const highlightedButton = this.automaticSeedColorEnabled ?
+        this.colorSchemeHighlightedButton_ :
+        this.staticColorHighlightedButton_;
+    highlightedButton.setAttribute('tabindex', '0');
+    highlightedButton.focus();
 
     e.detail.keyboardEvent.preventDefault();
   }
 
   private getTabIndex_(id: string): string {
-    return id === 'tonal' || id === 'var(--google-blue-500)' ? '0' : '-1';
+    return id === String(DEFAULT_COLOR_SCHEME) ||
+            hexColorToSkColor(id) === DEFAULT_STATIC_COLOR ?
+        '0' :
+        '-1';
   }
 }
 
diff --git a/ash/webui/personalization_app/resources/js/theme/theme_actions.ts b/ash/webui/personalization_app/resources/js/theme/theme_actions.ts
index 9d475e3..5c51a65 100644
--- a/ash/webui/personalization_app/resources/js/theme/theme_actions.ts
+++ b/ash/webui/personalization_app/resources/js/theme/theme_actions.ts
@@ -3,6 +3,9 @@
 // found in the LICENSE file.
 
 import {Action} from 'chrome://resources/ash/common/store/store.js';
+import {SkColor} from 'chrome://resources/mojo/skia/public/mojom/skcolor.mojom-webui.js';
+
+import {ColorScheme} from '../personalization_app.mojom-webui.js';
 
 /**
  * @fileoverview Defines the actions to change theme state.
@@ -11,10 +14,12 @@
 export enum ThemeActionName {
   SET_DARK_MODE_ENABLED = 'set_dark_mode_enabled',
   SET_COLOR_MODE_AUTO_SCHEDULE_ENABLED = 'set_color_mode_auto_schedule_enabled',
+  SET_COLOR_SCHEME = 'set_color_scheme',
+  SET_STATIC_COLOR = 'set_static_color',
 }
 
-export type ThemeActions =
-    SetColorModeAutoScheduleAction|SetDarkModeEnabledAction;
+export type ThemeActions = SetColorModeAutoScheduleAction|
+    SetDarkModeEnabledAction|SetColorSchemePrefAction|SetStaticColorPrefAction;
 
 export type SetDarkModeEnabledAction = Action&{
   name: ThemeActionName.SET_DARK_MODE_ENABLED,
@@ -26,6 +31,16 @@
   enabled: boolean,
 };
 
+export type SetColorSchemePrefAction = Action&{
+  name: ThemeActionName.SET_COLOR_SCHEME,
+  colorScheme: ColorScheme,
+};
+
+export type SetStaticColorPrefAction = Action&{
+  name: ThemeActionName.SET_STATIC_COLOR,
+  staticColor: SkColor,
+};
+
 export function setDarkModeEnabledAction(enabled: boolean):
     SetDarkModeEnabledAction {
   return {name: ThemeActionName.SET_DARK_MODE_ENABLED, enabled};
@@ -35,3 +50,13 @@
     SetColorModeAutoScheduleAction {
   return {name: ThemeActionName.SET_COLOR_MODE_AUTO_SCHEDULE_ENABLED, enabled};
 }
+
+export function setColorSchemeAction(colorScheme: ColorScheme):
+    SetColorSchemePrefAction {
+  return {name: ThemeActionName.SET_COLOR_SCHEME, colorScheme};
+}
+
+export function setStaticColorAction(staticColor: SkColor):
+    SetStaticColorPrefAction {
+  return {name: ThemeActionName.SET_STATIC_COLOR, staticColor};
+}
diff --git a/ash/webui/personalization_app/resources/js/theme/theme_controller.ts b/ash/webui/personalization_app/resources/js/theme/theme_controller.ts
index ff6f9f0..e9f039ef 100644
--- a/ash/webui/personalization_app/resources/js/theme/theme_controller.ts
+++ b/ash/webui/personalization_app/resources/js/theme/theme_controller.ts
@@ -2,10 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {ThemeProviderInterface} from '../personalization_app.mojom-webui.js';
+import {SkColor} from 'chrome://resources/mojo/skia/public/mojom/skcolor.mojom-webui.js';
+
+import {ColorScheme, ThemeProviderInterface} from '../personalization_app.mojom-webui.js';
 import {PersonalizationStore} from '../personalization_store.js';
 
-import {setColorModeAutoScheduleEnabledAction, setDarkModeEnabledAction} from './theme_actions.js';
+import {setColorModeAutoScheduleEnabledAction, setColorSchemeAction, setDarkModeEnabledAction, setStaticColorAction} from './theme_actions.js';
 
 /**
  * @fileoverview contains all of the functions to interact with C++ side through
@@ -41,3 +43,17 @@
   // Dispatch action to highlight auto color mode.
   store.dispatch(setColorModeAutoScheduleEnabledAction(enabled));
 }
+
+export function setColorSchemePref(
+    colorScheme: ColorScheme, provider: ThemeProviderInterface,
+    store: PersonalizationStore) {
+  provider.setColorScheme(colorScheme);
+  store.dispatch(setColorSchemeAction(colorScheme));
+}
+
+export function setStaticColorPref(
+    staticColor: SkColor, provider: ThemeProviderInterface,
+    store: PersonalizationStore) {
+  provider.setStaticColor(staticColor);
+  store.dispatch(setStaticColorAction(staticColor));
+}
diff --git a/ash/webui/personalization_app/test/fake_personalization_app_theme_provider.cc b/ash/webui/personalization_app/test/fake_personalization_app_theme_provider.cc
index d442613..c6936eb 100644
--- a/ash/webui/personalization_app/test/fake_personalization_app_theme_provider.cc
+++ b/ash/webui/personalization_app/test/fake_personalization_app_theme_provider.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "ash/webui/personalization_app/test/fake_personalization_app_theme_provider.h"
+#include "fake_personalization_app_theme_provider.h"
 
 namespace ash::personalization_app {
 
@@ -43,4 +44,13 @@
   std::move(callback).Run(/*enabled=*/false);
 }
 
+void FakePersonalizationAppThemeProvider::SetColorScheme(
+    ash::ColorScheme color_scheme) {
+  return;
+}
+
+void FakePersonalizationAppThemeProvider::SetStaticColor(
+    ::SkColor static_color) {
+  return;
+}
 }  // namespace ash::personalization_app
diff --git a/ash/webui/personalization_app/test/fake_personalization_app_theme_provider.h b/ash/webui/personalization_app/test/fake_personalization_app_theme_provider.h
index 4761dde..3e4c3acb 100644
--- a/ash/webui/personalization_app/test/fake_personalization_app_theme_provider.h
+++ b/ash/webui/personalization_app/test/fake_personalization_app_theme_provider.h
@@ -45,6 +45,10 @@
 
   void SetColorModeAutoScheduleEnabled(bool enabled) override;
 
+  void SetColorScheme(ash::ColorScheme color_scheme) override;
+
+  void SetStaticColor(::SkColor static_color) override;
+
   void IsDarkModeEnabled(IsDarkModeEnabledCallback callback) override;
 
   void IsColorModeAutoScheduleEnabled(
diff --git a/ash/webui/personalization_app/test/personalization_app_mojom_banned_browsertest_fixture.cc b/ash/webui/personalization_app/test/personalization_app_mojom_banned_browsertest_fixture.cc
index 8ccea8b..5099cdc 100644
--- a/ash/webui/personalization_app/test/personalization_app_mojom_banned_browsertest_fixture.cc
+++ b/ash/webui/personalization_app/test/personalization_app_mojom_banned_browsertest_fixture.cc
@@ -98,6 +98,11 @@
               (override));
   MOCK_METHOD(void, SetColorModePref, (bool dark_mode_enabled), (override));
   MOCK_METHOD(void,
+              SetColorScheme,
+              (ash::ColorScheme color_scheme),
+              (override));
+  MOCK_METHOD(void, SetStaticColor, (::SkColor static_color), (override));
+  MOCK_METHOD(void,
               SetColorModeAutoScheduleEnabled,
               (bool enabled),
               (override));
diff --git a/ash/wm/window_cycle/window_cycle_item_view.cc b/ash/wm/window_cycle/window_cycle_item_view.cc
index a221c466..29774134 100644
--- a/ash/wm/window_cycle/window_cycle_item_view.cc
+++ b/ash/wm/window_cycle/window_cycle_item_view.cc
@@ -7,6 +7,7 @@
 #include "ash/shell.h"
 #include "ash/wm/window_cycle/window_cycle_controller.h"
 #include "ash/wm/window_preview_view.h"
+#include "base/cxx17_backports.h"
 #include "ui/accessibility/ax_action_data.h"
 #include "ui/accessibility/ax_enums.mojom.h"
 #include "ui/aura/window.h"
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 5f075f6f..904eaff4 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -425,6 +425,7 @@
     "memory/platform_shared_memory_region.cc",
     "memory/platform_shared_memory_region.h",
     "memory/ptr_util.h",
+    "memory/raw_ptr.cc",
     "memory/raw_ptr.h",
     "memory/raw_ptr_asan_bound_arg_tracker.cc",
     "memory/raw_ptr_asan_bound_arg_tracker.h",
@@ -1209,6 +1210,8 @@
       "win/scoped_windows_thread_environment.h",
       "win/scoped_winrt_initializer.cc",
       "win/scoped_winrt_initializer.h",
+      "win/security_descriptor.cc",
+      "win/security_descriptor.h",
       "win/security_util.cc",
       "win/security_util.h",
       "win/shlwapi.h",
@@ -1472,7 +1475,13 @@
   }
 
   all_dependent_configs = []
-  defines = [ "BASE_IMPLEMENTATION" ]
+  defines = [
+    "BASE_IMPLEMENTATION",
+
+    # Temporary placement for `raw_ptr` using PA's `component_export.h`;
+    # will be moved: crbug.com/1371729
+    "IS_RAW_PTR_IMPL",
+  ]
   data = []
   data_deps = []
   libs = []
@@ -1521,7 +1530,6 @@
     ":synchronization_buildflags",
     ":tracing_buildflags",
     "//base/allocator/partition_allocator:buildflags",
-    "//base/allocator/partition_allocator:raw_ptr",
     "//base/numerics:base_numerics",
     "//build:chromecast_buildflags",
     "//build:chromeos_buildflags",
@@ -3531,6 +3539,7 @@
       "win/scoped_safearray_unittest.cc",
       "win/scoped_variant_unittest.cc",
       "win/scoped_winrt_initializer_unittest.cc",
+      "win/security_descriptor_unittest.cc",
       "win/security_util_unittest.cc",
       "win/shortcut_unittest.cc",
       "win/sid_unittest.cc",
diff --git a/base/allocator/partition_allocator/BUILD.gn b/base/allocator/partition_allocator/BUILD.gn
index 27972c8c..0a6bb25 100644
--- a/base/allocator/partition_allocator/BUILD.gn
+++ b/base/allocator/partition_allocator/BUILD.gn
@@ -367,24 +367,6 @@
   }
 }
 
-source_set("raw_ptr") {
-  # `gn check` is unhappy with most `#includes` when PA isn't
-  # actually built.
-  check_includes = false
-  public = [
-    "pointers/raw_ptr.h",
-    "pointers/raw_ref.h",
-  ]
-  sources = [ "pointers/raw_ptr.cc" ]
-  if (use_partition_alloc) {
-    public_deps = [ ":partition_alloc" ]
-  }
-  deps = [ ":buildflags" ]
-
-  # See also: `partition_alloc_base/component_export.h`
-  defines = [ "IS_RAW_PTR_IMPL" ]
-}
-
 buildflag_header("partition_alloc_buildflags") {
   header = "partition_alloc_buildflags.h"
 
diff --git a/base/allocator/partition_allocator/DEPS b/base/allocator/partition_allocator/DEPS
index efb8437..1e2b78b 100644
--- a/base/allocator/partition_allocator/DEPS
+++ b/base/allocator/partition_allocator/DEPS
@@ -154,7 +154,4 @@
   "gtest_prod_util\.h$": [
     "+testing/gtest/include/gtest/gtest_prod.h",
   ],
-  "raw_ptr\.cc$": [
-    "+base",
-  ]
 }
diff --git a/base/allocator/partition_allocator/pointers/raw_ptr.h b/base/allocator/partition_allocator/pointers/raw_ptr.h
deleted file mode 100644
index 8723ada..0000000
--- a/base/allocator/partition_allocator/pointers/raw_ptr.h
+++ /dev/null
@@ -1,1620 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_POINTERS_RAW_PTR_H_
-#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_POINTERS_RAW_PTR_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <climits>
-#include <cstddef>
-#include <functional>
-#include <type_traits>
-#include <utility>
-
-#include "base/allocator/partition_allocator/partition_alloc_base/compiler_specific.h"
-#include "base/allocator/partition_allocator/partition_alloc_base/component_export.h"
-#include "base/allocator/partition_allocator/partition_alloc_base/debug/debugging_buildflags.h"
-#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
-#include "base/allocator/partition_allocator/partition_alloc_config.h"
-#include "build/build_config.h"
-#include "build/buildflag.h"
-
-#if defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
-#include "base/allocator/partition_allocator/partition_tag.h"
-#include "base/allocator/partition_allocator/partition_tag_types.h"
-#include "base/allocator/partition_allocator/tagging.h"
-#endif  // defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
-
-#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) || \
-    defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
-// USE_BACKUP_REF_PTR implies USE_PARTITION_ALLOC, needed for code under
-// allocator/partition_allocator/ to be built.
-#include "base/allocator/partition_allocator/address_pool_manager_bitmap.h"
-#include "base/allocator/partition_allocator/partition_address_space.h"
-#include "base/allocator/partition_allocator/partition_alloc_constants.h"
-#endif  // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) ||
-        // defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
-
-#if BUILDFLAG(IS_WIN)
-#include "base/allocator/partition_allocator/partition_alloc_base/win/win_handle_types.h"
-#endif
-
-#if BUILDFLAG(USE_PARTITION_ALLOC)
-#include "base/allocator/partition_allocator/partition_alloc_base/check.h"
-// Live implementation of MiraclePtr being built.
-#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) || \
-    BUILDFLAG(USE_ASAN_BACKUP_REF_PTR) ||       \
-    defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
-#define PA_RAW_PTR_CHECK(condition) PA_BASE_CHECK(condition)
-#else
-// No-op implementation of MiraclePtr being built.
-// Note that `PA_BASE_DCHECK()` evaporates from non-DCHECK builds,
-// minimizing impact of generated code.
-#define PA_RAW_PTR_CHECK(condition) PA_BASE_DCHECK(condition)
-#endif  // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) ||
-        // BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
-        // || defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
-#else   // BUILDFLAG(USE_PARTITION_ALLOC
-// Without PartitionAlloc, there's no `PA_BASE_D?CHECK()` implementation
-// available.
-#define PA_RAW_PTR_CHECK(condition)
-#endif  // BUILDFLAG(USE_PARTITION_ALLOC)
-
-namespace cc {
-class Scheduler;
-}
-namespace base::internal {
-class DelayTimerBase;
-}
-namespace content::responsiveness {
-class Calculator;
-}
-
-namespace base {
-
-// NOTE: All methods should be `PA_ALWAYS_INLINE`. raw_ptr is meant to be a
-// lightweight replacement of a raw pointer, hence performance is critical.
-
-// The following types are the different RawPtrType template option possible for
-// a `raw_ptr`:
-// - RawPtrMayDangle disables dangling pointers check when the object is
-//   released.
-// - RawPtrBanDanglingIfSupported may enable dangling pointers check on object
-//   destruction.
-//
-// We describe those types here so that they can be used outside of `raw_ptr` as
-// object markers, and their meaning might vary depending on where those markers
-// are being used. For instance, we are using those in `UnretainedWrapper` to
-// change behavior depending on RawPtrType.
-struct RawPtrMayDangle {};
-struct RawPtrBanDanglingIfSupported {};
-
-struct RawPtrNoOp {};
-
-namespace raw_ptr_traits {
-template <typename T>
-struct RawPtrTypeToImpl;
-}
-
-namespace internal {
-// These classes/structures are part of the raw_ptr implementation.
-// DO NOT USE THESE CLASSES DIRECTLY YOURSELF.
-
-// This type trait verifies a type can be used as a pointer offset.
-//
-// We support pointer offsets in signed (ptrdiff_t) or unsigned (size_t) values.
-// Smaller types are also allowed.
-template <typename Z>
-static constexpr bool offset_type =
-    std::is_integral_v<Z> && sizeof(Z) <= sizeof(ptrdiff_t);
-
-struct RawPtrNoOpImpl {
-  // Wraps a pointer.
-  template <typename T>
-  static PA_ALWAYS_INLINE T* WrapRawPtr(T* ptr) {
-    return ptr;
-  }
-
-  // Notifies the allocator when a wrapped pointer is being removed or replaced.
-  template <typename T>
-  static PA_ALWAYS_INLINE void ReleaseWrappedPtr(T*) {}
-
-  // Unwraps the pointer, while asserting that memory hasn't been freed. The
-  // function is allowed to crash on nullptr.
-  template <typename T>
-  static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForDereference(T* wrapped_ptr) {
-    return wrapped_ptr;
-  }
-
-  // Unwraps the pointer, while asserting that memory hasn't been freed. The
-  // function must handle nullptr gracefully.
-  template <typename T>
-  static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForExtraction(T* wrapped_ptr) {
-    return wrapped_ptr;
-  }
-
-  // Unwraps the pointer, without making an assertion on whether memory was
-  // freed or not.
-  template <typename T>
-  static PA_ALWAYS_INLINE T* UnsafelyUnwrapPtrForComparison(T* wrapped_ptr) {
-    return wrapped_ptr;
-  }
-
-  // Upcasts the wrapped pointer.
-  template <typename To, typename From>
-  static PA_ALWAYS_INLINE constexpr To* Upcast(From* wrapped_ptr) {
-    static_assert(std::is_convertible<From*, To*>::value,
-                  "From must be convertible to To.");
-    // Note, this cast may change the address if upcasting to base that lies in
-    // the middle of the derived object.
-    return wrapped_ptr;
-  }
-
-  // Advance the wrapped pointer by `delta_elems`.
-  template <typename T,
-            typename Z,
-            typename = std::enable_if_t<offset_type<Z>, void>>
-  static PA_ALWAYS_INLINE T* Advance(T* wrapped_ptr, Z delta_elems) {
-    return wrapped_ptr + delta_elems;
-  }
-
-  template <typename T>
-  static PA_ALWAYS_INLINE ptrdiff_t GetDeltaElems(T* wrapped_ptr1,
-                                                  T* wrapped_ptr2) {
-    return wrapped_ptr1 - wrapped_ptr2;
-  }
-
-  // Returns a copy of a wrapped pointer, without making an assertion on whether
-  // memory was freed or not.
-  template <typename T>
-  static PA_ALWAYS_INLINE T* Duplicate(T* wrapped_ptr) {
-    return wrapped_ptr;
-  }
-
-  // This is for accounting only, used by unit tests.
-  static PA_ALWAYS_INLINE void IncrementSwapCountForTest() {}
-  static PA_ALWAYS_INLINE void IncrementLessCountForTest() {}
-  static PA_ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {}
-};
-
-#if defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
-
-constexpr int kValidAddressBits = 48;
-constexpr uintptr_t kAddressMask = (1ull << kValidAddressBits) - 1;
-constexpr int kTagBits = sizeof(uintptr_t) * 8 - kValidAddressBits;
-
-// MTECheckedPtr has no business with the topmost bits reserved for the
-// tag used by true ARM MTE, so we strip it out here.
-constexpr uintptr_t kTagMask =
-    ~kAddressMask & partition_alloc::internal::kPtrUntagMask;
-
-constexpr int kTopBitShift = 63;
-constexpr uintptr_t kTopBit = 1ull << kTopBitShift;
-static_assert(kTopBit << 1 == 0, "kTopBit should really be the top bit");
-static_assert((kTopBit & kTagMask) > 0,
-              "kTopBit bit must be inside the tag region");
-
-// This functionality is outside of MTECheckedPtrImpl, so that it can be
-// overridden by tests.
-struct MTECheckedPtrImplPartitionAllocSupport {
-  // Checks if the necessary support is enabled in PartitionAlloc for `ptr`.
-  template <typename T>
-  static PA_ALWAYS_INLINE bool EnabledForPtr(T* ptr) {
-    // Disambiguation: UntagPtr removes the hardware MTE tag, whereas this class
-    // is responsible for handling the software MTE tag.
-    auto addr = partition_alloc::UntagPtr(ptr);
-    return partition_alloc::IsManagedByPartitionAlloc(addr);
-  }
-
-  // Returns pointer to the tag that protects are pointed by |addr|.
-  static PA_ALWAYS_INLINE void* TagPointer(uintptr_t addr) {
-    return partition_alloc::PartitionTagPointer(addr);
-  }
-};
-
-template <typename PartitionAllocSupport>
-struct MTECheckedPtrImpl {
-  // This implementation assumes that pointers are 64 bits long and at least 16
-  // top bits are unused. The latter is harder to verify statically, but this is
-  // true for all currently supported 64-bit architectures (PA_DCHECK when
-  // wrapping will verify that).
-  static_assert(sizeof(void*) >= 8, "Need 64-bit pointers");
-
-  // Wraps a pointer, and returns its uintptr_t representation.
-  template <typename T>
-  static PA_ALWAYS_INLINE T* WrapRawPtr(T* ptr) {
-    // Disambiguation: UntagPtr removes the hardware MTE tag, whereas this
-    // function is responsible for adding the software MTE tag.
-    uintptr_t addr = partition_alloc::UntagPtr(ptr);
-    PA_BASE_DCHECK(ExtractTag(addr) == 0ull);
-
-    // Return a not-wrapped |addr|, if it's either nullptr or if the protection
-    // for this pointer is disabled.
-    if (!PartitionAllocSupport::EnabledForPtr(ptr)) {
-      return ptr;
-    }
-
-    // Read the tag and place it in the top bits of the address.
-    // Even if PartitionAlloc's tag has less than kTagBits, we'll read
-    // what's given and pad the rest with 0s.
-    static_assert(sizeof(partition_alloc::PartitionTag) * 8 <= kTagBits, "");
-    uintptr_t tag = *(static_cast<volatile partition_alloc::PartitionTag*>(
-        PartitionAllocSupport::TagPointer(addr)));
-    PA_BASE_DCHECK(tag);
-
-    tag <<= kValidAddressBits;
-    addr |= tag;
-    // See the disambiguation comment above.
-    // TODO(kdlee): Ensure that ptr's hardware MTE tag is preserved.
-    // TODO(kdlee): Ensure that hardware and software MTE tags don't conflict.
-    return static_cast<T*>(partition_alloc::internal::TagAddr(addr));
-  }
-
-  // Notifies the allocator when a wrapped pointer is being removed or replaced.
-  // No-op for MTECheckedPtrImpl.
-  template <typename T>
-  static PA_ALWAYS_INLINE void ReleaseWrappedPtr(T*) {}
-
-  // Unwraps the pointer's uintptr_t representation, while asserting that memory
-  // hasn't been freed. The function is allowed to crash on nullptr.
-  template <typename T>
-  static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForDereference(T* wrapped_ptr) {
-    // Disambiguation: UntagPtr removes the hardware MTE tag, whereas this
-    // function is responsible for removing the software MTE tag.
-    uintptr_t wrapped_addr = partition_alloc::UntagPtr(wrapped_ptr);
-    uintptr_t tag = ExtractTag(wrapped_addr);
-    if (tag > 0) {
-      // Read the tag provided by PartitionAlloc.
-      //
-      // Cast to volatile to ensure memory is read. E.g. in a tight loop, the
-      // compiler could cache the value in a register and thus could miss that
-      // another thread freed memory and changed tag.
-      uintptr_t read_tag =
-          *static_cast<volatile partition_alloc::PartitionTag*>(
-              PartitionAllocSupport::TagPointer(ExtractAddress(wrapped_addr)));
-      if (PA_UNLIKELY(tag != read_tag))
-        PA_IMMEDIATE_CRASH();
-      // See the disambiguation comment above.
-      // TODO(kdlee): Ensure that ptr's hardware MTE tag is preserved.
-      // TODO(kdlee): Ensure that hardware and software MTE tags don't conflict.
-      return static_cast<T*>(
-          partition_alloc::internal::TagAddr(ExtractAddress(wrapped_addr)));
-    }
-    return wrapped_ptr;
-  }
-
-  // Unwraps the pointer's uintptr_t representation, while asserting that memory
-  // hasn't been freed. The function must handle nullptr gracefully.
-  template <typename T>
-  static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForExtraction(T* wrapped_ptr) {
-    // SafelyUnwrapPtrForDereference handles nullptr case well.
-    return SafelyUnwrapPtrForDereference(wrapped_ptr);
-  }
-
-  // Unwraps the pointer's uintptr_t representation, without making an assertion
-  // on whether memory was freed or not.
-  template <typename T>
-  static PA_ALWAYS_INLINE T* UnsafelyUnwrapPtrForComparison(T* wrapped_ptr) {
-    return ExtractPtr(wrapped_ptr);
-  }
-
-  // Upcasts the wrapped pointer.
-  template <typename To, typename From>
-  static PA_ALWAYS_INLINE constexpr To* Upcast(From* wrapped_ptr) {
-    static_assert(std::is_convertible<From*, To*>::value,
-                  "From must be convertible to To.");
-
-    // The top-bit tag must not affect the result of upcast.
-    return static_cast<To*>(wrapped_ptr);
-  }
-
-  // Advance the wrapped pointer by `delta_elems`.
-  template <typename T,
-            typename Z,
-            typename = std::enable_if_t<offset_type<Z>, void>>
-  static PA_ALWAYS_INLINE T* Advance(T* wrapped_ptr, Z delta_elems) {
-    return wrapped_ptr + delta_elems;
-  }
-
-  template <typename T>
-  static PA_ALWAYS_INLINE ptrdiff_t GetDeltaElems(T* wrapped_ptr1,
-                                                  T* wrapped_ptr2) {
-    // Ensure that both pointers come from the same allocation.
-    //
-    // Disambiguation: UntagPtr removes the hardware MTE tag, whereas this
-    // class is responsible for handling the software MTE tag.
-    //
-    // MTECheckedPtr doesn't use 0 as a valid tag; depending on which
-    // subtraction operator is called, we may be getting the actual
-    // untagged T* or the wrapped pointer (passed as a T*) in one or
-    // both args. We can only check slot cohabitation when both args
-    // come with tags.
-    const uintptr_t tag1 = ExtractTag(partition_alloc::UntagPtr(wrapped_ptr1));
-    const uintptr_t tag2 = ExtractTag(partition_alloc::UntagPtr(wrapped_ptr2));
-    if (tag1 && tag2) {
-      PA_BASE_CHECK(tag1 == tag2);
-      return wrapped_ptr1 - wrapped_ptr2;
-    }
-
-    // If one or the other arg come untagged, we have to perform the
-    // subtraction entirely without tags.
-    return reinterpret_cast<T*>(
-               ExtractAddress(partition_alloc::UntagPtr(wrapped_ptr1))) -
-           reinterpret_cast<T*>(
-               ExtractAddress(partition_alloc::UntagPtr(wrapped_ptr2)));
-  }
-
-  // Returns a copy of a wrapped pointer, without making an assertion
-  // on whether memory was freed or not.
-  template <typename T>
-  static PA_ALWAYS_INLINE T* Duplicate(T* wrapped_ptr) {
-    return wrapped_ptr;
-  }
-
-  // This is for accounting only, used by unit tests.
-  static PA_ALWAYS_INLINE void IncrementSwapCountForTest() {}
-  static PA_ALWAYS_INLINE void IncrementLessCountForTest() {}
-  static PA_ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {}
-
- private:
-  static PA_ALWAYS_INLINE uintptr_t ExtractAddress(uintptr_t wrapped_ptr) {
-    return wrapped_ptr & kAddressMask;
-  }
-
-  template <typename T>
-  static PA_ALWAYS_INLINE T* ExtractPtr(T* wrapped_ptr) {
-    // Disambiguation: UntagPtr/TagAddr handle the hardware MTE tag, whereas
-    // this function is responsible for removing the software MTE tag.
-    // TODO(kdlee): Ensure that wrapped_ptr's hardware MTE tag is preserved.
-    // TODO(kdlee): Ensure that hardware and software MTE tags don't conflict.
-    return static_cast<T*>(partition_alloc::internal::TagAddr(
-        ExtractAddress(partition_alloc::UntagPtr(wrapped_ptr))));
-  }
-
-  static PA_ALWAYS_INLINE uintptr_t ExtractTag(uintptr_t wrapped_ptr) {
-    return (wrapped_ptr & kTagMask) >> kValidAddressBits;
-  }
-};
-
-#endif  // defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
-
-#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
-
-#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
-PA_COMPONENT_EXPORT(RAW_PTR)
-void CheckThatAddressIsntWithinFirstPartitionPage(uintptr_t address);
-#endif
-
-template <bool AllowDangling = false>
-struct BackupRefPtrImpl {
-  // Note that `BackupRefPtrImpl` itself is not thread-safe. If multiple threads
-  // modify the same smart pointer object without synchronization, a data race
-  // will occur.
-
-  static PA_ALWAYS_INLINE bool IsSupportedAndNotNull(uintptr_t address) {
-    // There are many situations where the compiler can prove that
-    // `ReleaseWrappedPtr` is called on a value that is always nullptr, but the
-    // way `IsManagedByPartitionAllocBRPPool` is written, the compiler can't
-    // prove that nullptr is not managed by PartitionAlloc; and so the compiler
-    // has to emit a useless check and dead code. To avoid that without making
-    // the runtime check slower, tell the compiler to skip
-    // `IsManagedByPartitionAllocBRPPool` when it can statically determine that
-    // address is nullptr.
-#if PA_HAS_BUILTIN(__builtin_constant_p)
-    if (__builtin_constant_p(address == 0) && (address == 0)) {
-#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
-      PA_BASE_CHECK(
-          !partition_alloc::IsManagedByPartitionAllocBRPPool(address));
-#endif  // BUILDFLAG(PA_DCHECK_IS_ON) ||
-        // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
-      return false;
-    }
-#endif  // PA_HAS_BUILTIN(__builtin_constant_p)
-
-    // This covers the nullptr case, as address 0 is never in any
-    // PartitionAlloc pool.
-    bool is_in_brp_pool =
-        partition_alloc::IsManagedByPartitionAllocBRPPool(address);
-
-    // There may be pointers immediately after the allocation, e.g.
-    //   {
-    //     // Assume this allocation happens outside of PartitionAlloc.
-    //     raw_ptr<T> ptr = new T[20];
-    //     for (size_t i = 0; i < 20; i ++) { ptr++; }
-    //   }
-    //
-    // Such pointers are *not* at risk of accidentally falling into BRP pool,
-    // because:
-    // 1) On 64-bit systems, BRP pool is preceded by a forbidden region.
-    // 2) On 32-bit systems, the guard pages and metadata of super pages in BRP
-    //    pool aren't considered to be part of that pool.
-    //
-    // This allows us to make a stronger assertion that if
-    // IsManagedByPartitionAllocBRPPool returns true for a valid pointer,
-    // it must be at least partition page away from the beginning of a super
-    // page.
-#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
-    if (is_in_brp_pool) {
-      CheckThatAddressIsntWithinFirstPartitionPage(address);
-    }
-#endif
-
-    return is_in_brp_pool;
-  }
-
-#if defined(PA_USE_OOB_POISON)
-  // Out-Of-Bounds (OOB) poison bit is set when the pointer has overflowed by
-  // one byte.
-#if defined(ARCH_CPU_X86_64)
-  // Bit 63 is the only pointer bit that will work as the poison bit across both
-  // LAM48 and LAM57. It also works when all unused linear address bits are
-  // checked for canonicality.
-  static constexpr uintptr_t OOB_POISON_BIT = static_cast<uintptr_t>(1) << 63;
-#else
-  // Avoid ARM's Top-Byte Ignore.
-  static constexpr uintptr_t OOB_POISON_BIT = static_cast<uintptr_t>(1) << 55;
-#endif
-
-  template <typename T>
-  static PA_ALWAYS_INLINE T* UnpoisonPtr(T* ptr) {
-    return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(ptr) &
-                                ~OOB_POISON_BIT);
-  }
-
-  template <typename T>
-  static PA_ALWAYS_INLINE bool IsPtrOOB(T* ptr) {
-    return (reinterpret_cast<uintptr_t>(ptr) & OOB_POISON_BIT) ==
-           OOB_POISON_BIT;
-  }
-
-  template <typename T>
-  static PA_ALWAYS_INLINE T* PoisonOOBPtr(T* ptr) {
-    return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(ptr) |
-                                OOB_POISON_BIT);
-  }
-#else   // PA_USE_OOB_POISON
-  template <typename T>
-  static PA_ALWAYS_INLINE T* UnpoisonPtr(T* ptr) {
-    return ptr;
-  }
-#endif  // PA_USE_OOB_POISON
-
-  // Wraps a pointer.
-  template <typename T>
-  static PA_ALWAYS_INLINE T* WrapRawPtr(T* ptr) {
-    uintptr_t address = partition_alloc::UntagPtr(UnpoisonPtr(ptr));
-    if (IsSupportedAndNotNull(address)) {
-#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
-      PA_BASE_CHECK(ptr != nullptr);
-#endif
-      AcquireInternal(address);
-    } else {
-#if !defined(PA_HAS_64_BITS_POINTERS)
-#if PA_HAS_BUILTIN(__builtin_constant_p)
-      // Similarly to `IsSupportedAndNotNull` above, elide the
-      // `BanSuperPageFromBRPPool` call if the compiler can prove that `address`
-      // is zero since PA won't be able to map anything at that address anyway.
-      bool known_constant_zero =
-          __builtin_constant_p(address == 0) && (address == 0);
-#else   // PA_HAS_BUILTIN(__builtin_constant_p)
-      bool known_constant_zero = false;
-#endif  // PA_HAS_BUILTIN(__builtin_constant_p)
-
-      if (!known_constant_zero) {
-        partition_alloc::internal::AddressPoolManagerBitmap::
-            BanSuperPageFromBRPPool(address);
-      }
-#endif  // !defined(PA_HAS_64_BITS_POINTERS)
-    }
-
-    return ptr;
-  }
-
-  // Notifies the allocator when a wrapped pointer is being removed or replaced.
-  template <typename T>
-  static PA_ALWAYS_INLINE void ReleaseWrappedPtr(T* wrapped_ptr) {
-    uintptr_t address = partition_alloc::UntagPtr(UnpoisonPtr(wrapped_ptr));
-    if (IsSupportedAndNotNull(address)) {
-#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
-      PA_BASE_CHECK(wrapped_ptr != nullptr);
-#endif
-      ReleaseInternal(address);
-    }
-    // We are unable to counteract BanSuperPageFromBRPPool(), called from
-    // WrapRawPtr(). We only use one bit per super-page and, thus can't tell if
-    // there's more than one associated raw_ptr<T> at a given time. The risk of
-    // exhausting the entire address space is minuscule, therefore, we couldn't
-    // resist the perf gain of a single relaxed store (in the above mentioned
-    // function) over much more expensive two CAS operations, which we'd have to
-    // use if we were to un-ban a super-page.
-  }
-
-  // Unwraps the pointer, while asserting that memory hasn't been freed. The
-  // function is allowed to crash on nullptr.
-  template <typename T>
-  static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForDereference(T* wrapped_ptr) {
-#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
-    uintptr_t address = partition_alloc::UntagPtr(wrapped_ptr);
-    if (IsSupportedAndNotNull(address)) {
-      PA_BASE_CHECK(wrapped_ptr != nullptr);
-      PA_BASE_CHECK(IsPointeeAlive(address));
-    }
-#endif
-    return wrapped_ptr;
-  }
-
-  // Unwraps the pointer, while asserting that memory hasn't been freed. The
-  // function must handle nullptr gracefully.
-  template <typename T>
-  static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForExtraction(T* wrapped_ptr) {
-    // This may be used for extracting an end-of-allocation pointer to be used
-    // as an endpoint in an iterative algorithm, so this removes the OOB poison
-    // bit.
-    return UnpoisonPtr(wrapped_ptr);
-  }
-
-  // Unwraps the pointer, without making an assertion on whether memory was
-  // freed or not.
-  template <typename T>
-  static PA_ALWAYS_INLINE T* UnsafelyUnwrapPtrForComparison(T* wrapped_ptr) {
-    return UnpoisonPtr(wrapped_ptr);
-  }
-
-  // Upcasts the wrapped pointer.
-  template <typename To, typename From>
-  static PA_ALWAYS_INLINE constexpr To* Upcast(From* wrapped_ptr) {
-    static_assert(std::is_convertible<From*, To*>::value,
-                  "From must be convertible to To.");
-    // Note, this cast may change the address if upcasting to base that lies in
-    // the middle of the derived object.
-    return wrapped_ptr;
-  }
-
-  // Advance the wrapped pointer by `delta_elems`.
-  template <typename T,
-            typename Z,
-            typename = std::enable_if_t<offset_type<Z>, void>>
-  static PA_ALWAYS_INLINE T* Advance(T* wrapped_ptr, Z delta_elems) {
-#if BUILDFLAG(PUT_REF_COUNT_IN_PREVIOUS_SLOT)
-    T* new_ptr = UnpoisonPtr(wrapped_ptr) + delta_elems;
-    // First check if the new address didn't migrate in/out the BRP pool, and
-    // that it lands within the same allocation. An end-of-allocation address is
-    // ok, too, and that may lead to the pointer being poisoned if the relevant
-    // feature is enabled. These checks add a non-trivial cost, but they're
-    // cheaper and more secure than the previous implementation that rewrapped
-    // the pointer (wrapped the new pointer and unwrapped the old one).
-    //
-    // Note, the value of these checks goes beyond OOB protection. They're
-    // important for integrity of the BRP algorithm. Without these, an attacker
-    // could make the pointer point to another allocation, and cause its
-    // ref-count to go to 0 upon this pointer's destruction, even though there
-    // may be another pointer still pointing to it, thus making it lose the BRP
-    // protection prematurely.
-    uintptr_t address = partition_alloc::UntagPtr(UnpoisonPtr(wrapped_ptr));
-    // TODO(bartekn): Consider adding support for non-BRP pools too (without
-    // removing the cross-pool migration check).
-    if (IsSupportedAndNotNull(address)) {
-      auto ptr_pos_within_alloc =
-          IsValidDelta(address, delta_elems * static_cast<Z>(sizeof(T)));
-      // No need to check that |new_ptr| is in the same pool, as IsValidDeta()
-      // checks that it's within the same allocation, so must be the same pool.
-      PA_BASE_CHECK(ptr_pos_within_alloc !=
-                    partition_alloc::PtrPosWithinAlloc::kFarOOB);
-#if defined(PA_USE_OOB_POISON)
-      if (ptr_pos_within_alloc == partition_alloc::PtrPosWithinAlloc::kAllocEnd)
-        new_ptr = PoisonOOBPtr(new_ptr);
-#endif
-    } else {
-      // Check that the new address didn't migrate into the BRP pool, as it
-      // would result in more pointers pointing to an allocation than its
-      // ref-count reflects.
-      PA_BASE_CHECK(!IsSupportedAndNotNull(partition_alloc::UntagPtr(new_ptr)));
-    }
-    return new_ptr;
-#else   // BUILDFLAG(PUT_REF_COUNT_IN_PREVIOUS_SLOT)
-    // In the "before allocation" mode, on 32-bit, we can run into a problem
-    // that the end-of-allocation address could fall outside of
-    // PartitionAlloc's pools, if this is the last slot of the super page,
-    // thus pointing to the guard page. This means the ref-count won't be
-    // decreased when the pointer is released (leak).
-    //
-    // We could possibly solve it in a few different ways:
-    // - Add the trailing guard page to the pool, but we'd have to think very
-    //   hard if this doesn't create another hole.
-    // - Add an address adjustment to "is in pool?" check, similar as the one in
-    //   PartitionAllocGetSlotStartInBRPPool(), but that seems fragile, not to
-    //   mention adding an extra instruction to an inlined hot path.
-    // - Let the leak happen, since it should a very rare condition.
-    // - Go back to the previous solution of rewrapping the pointer, but that
-    //   had an issue of losing BRP protection in case the pointer ever gets
-    //   shifted back before the end of allocation.
-    //
-    // We decided to cross that bridge once we get there... if we ever get
-    // there. Currently there are no plans to switch back to the "before
-    // allocation" mode.
-    //
-    // This problem doesn't exist in the "previous slot" mode, or any mode that
-    // involves putting extras after the allocation, because the
-    // end-of-allocation address belongs to the same slot.
-    static_assert(false);
-#endif  // BUILDFLAG(PUT_REF_COUNT_IN_PREVIOUS_SLOT)
-  }
-
-  template <typename T>
-  static PA_ALWAYS_INLINE ptrdiff_t GetDeltaElems(T* wrapped_ptr1,
-                                                  T* wrapped_ptr2) {
-    T* unpoisoned_ptr1 = UnpoisonPtr(wrapped_ptr1);
-    T* unpoisoned_ptr2 = UnpoisonPtr(wrapped_ptr2);
-    uintptr_t address1 = partition_alloc::UntagPtr(unpoisoned_ptr1);
-    uintptr_t address2 = partition_alloc::UntagPtr(unpoisoned_ptr2);
-    // Ensure that both pointers are within the same slot, and pool!
-    // TODO(bartekn): Consider adding support for non-BRP pool too.
-    if (IsSupportedAndNotNull(address1)) {
-      PA_BASE_CHECK(IsSupportedAndNotNull(address2));
-      PA_BASE_CHECK(IsValidDelta(address2, address1 - address2) !=
-                    partition_alloc::PtrPosWithinAlloc::kFarOOB);
-    } else {
-      PA_BASE_CHECK(!IsSupportedAndNotNull(address2));
-    }
-    return unpoisoned_ptr1 - unpoisoned_ptr2;
-  }
-
-  // Returns a copy of a wrapped pointer, without making an assertion on whether
-  // memory was freed or not.
-  // This method increments the reference count of the allocation slot.
-  template <typename T>
-  static PA_ALWAYS_INLINE T* Duplicate(T* wrapped_ptr) {
-    return WrapRawPtr(wrapped_ptr);
-  }
-
-  // Report the current wrapped pointer if pointee isn't alive anymore.
-  template <typename T>
-  static PA_ALWAYS_INLINE void ReportIfDangling(T* wrapped_ptr) {
-    ReportIfDanglingInternal(partition_alloc::UntagPtr(wrapped_ptr));
-  }
-
-  // This is for accounting only, used by unit tests.
-  static PA_ALWAYS_INLINE void IncrementSwapCountForTest() {}
-  static PA_ALWAYS_INLINE void IncrementLessCountForTest() {}
-  static PA_ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {}
-
- private:
-  // We've evaluated several strategies (inline nothing, various parts, or
-  // everything in |Wrap()| and |Release()|) using the Speedometer2 benchmark
-  // to measure performance. The best results were obtained when only the
-  // lightweight |IsManagedByPartitionAllocBRPPool()| check was inlined.
-  // Therefore, we've extracted the rest into the functions below and marked
-  // them as PA_NOINLINE to prevent unintended LTO effects.
-  static PA_COMPONENT_EXPORT(RAW_PTR) PA_NOINLINE
-      void AcquireInternal(uintptr_t address);
-  static PA_COMPONENT_EXPORT(RAW_PTR) PA_NOINLINE
-      void ReleaseInternal(uintptr_t address);
-  static PA_COMPONENT_EXPORT(RAW_PTR) PA_NOINLINE
-      bool IsPointeeAlive(uintptr_t address);
-  static PA_COMPONENT_EXPORT(RAW_PTR) PA_NOINLINE
-      void ReportIfDanglingInternal(uintptr_t address);
-  template <typename Z, typename = std::enable_if_t<offset_type<Z>, void>>
-  static PA_ALWAYS_INLINE partition_alloc::PtrPosWithinAlloc IsValidDelta(
-      uintptr_t address,
-      Z delta_in_bytes) {
-    if constexpr (std::is_signed_v<Z>)
-      return IsValidSignedDelta(address, ptrdiff_t{delta_in_bytes});
-    else
-      return IsValidUnsignedDelta(address, size_t{delta_in_bytes});
-  }
-  static PA_COMPONENT_EXPORT(RAW_PTR)
-      PA_NOINLINE partition_alloc::PtrPosWithinAlloc
-      IsValidSignedDelta(uintptr_t address, ptrdiff_t delta_in_bytes);
-  static PA_COMPONENT_EXPORT(RAW_PTR)
-      PA_NOINLINE partition_alloc::PtrPosWithinAlloc
-      IsValidUnsignedDelta(uintptr_t address, size_t delta_in_bytes);
-};
-
-#endif  // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
-
-#if BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
-// Implementation that allows us to detect BackupRefPtr problems in ASan builds.
-struct AsanBackupRefPtrImpl {
-  // Wraps a pointer.
-  template <typename T>
-  static PA_ALWAYS_INLINE T* WrapRawPtr(T* ptr) {
-    AsanCheckIfValidInstantiation(ptr);
-    return ptr;
-  }
-
-  // Notifies the allocator when a wrapped pointer is being removed or replaced.
-  template <typename T>
-  static PA_ALWAYS_INLINE void ReleaseWrappedPtr(T*) {}
-
-  // Unwraps the pointer, while asserting that memory hasn't been freed. The
-  // function is allowed to crash on nullptr.
-  template <typename T>
-  static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForDereference(T* wrapped_ptr) {
-    AsanCheckIfValidDereference(wrapped_ptr);
-    return wrapped_ptr;
-  }
-
-  // Unwraps the pointer, while asserting that memory hasn't been freed. The
-  // function must handle nullptr gracefully.
-  template <typename T>
-  static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForExtraction(T* wrapped_ptr) {
-    AsanCheckIfValidExtraction(wrapped_ptr);
-    return wrapped_ptr;
-  }
-
-  // Unwraps the pointer, without making an assertion on whether memory was
-  // freed or not.
-  template <typename T>
-  static PA_ALWAYS_INLINE T* UnsafelyUnwrapPtrForComparison(T* wrapped_ptr) {
-    return wrapped_ptr;
-  }
-
-  // Upcasts the wrapped pointer.
-  template <typename To, typename From>
-  static PA_ALWAYS_INLINE constexpr To* Upcast(From* wrapped_ptr) {
-    static_assert(std::is_convertible<From*, To*>::value,
-                  "From must be convertible to To.");
-    // Note, this cast may change the address if upcasting to base that lies in
-    // the middle of the derived object.
-    return wrapped_ptr;
-  }
-
-  // Advance the wrapped pointer by `delta_elems`.
-  template <typename T,
-            typename Z,
-            typename = std::enable_if_t<offset_type<Z>, void>>
-  static PA_ALWAYS_INLINE T* Advance(T* wrapped_ptr, Z delta_elems) {
-    return wrapped_ptr + delta_elems;
-  }
-
-  template <typename T>
-  static PA_ALWAYS_INLINE ptrdiff_t GetDeltaElems(T* wrapped_ptr1,
-                                                  T* wrapped_ptr2) {
-    return wrapped_ptr1 - wrapped_ptr2;
-  }
-
-  // Returns a copy of a wrapped pointer, without making an assertion on whether
-  // memory was freed or not.
-  template <typename T>
-  static PA_ALWAYS_INLINE T* Duplicate(T* wrapped_ptr) {
-    return wrapped_ptr;
-  }
-
-  // This is for accounting only, used by unit tests.
-  static PA_ALWAYS_INLINE void IncrementSwapCountForTest() {}
-  static PA_ALWAYS_INLINE void IncrementLessCountForTest() {}
-  static PA_ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {}
-
- private:
-  static PA_COMPONENT_EXPORT(RAW_PTR) PA_NOINLINE
-      void AsanCheckIfValidInstantiation(void const volatile* ptr);
-  static PA_COMPONENT_EXPORT(RAW_PTR) PA_NOINLINE
-      void AsanCheckIfValidDereference(void const volatile* ptr);
-  static PA_COMPONENT_EXPORT(RAW_PTR) PA_NOINLINE
-      void AsanCheckIfValidExtraction(void const volatile* ptr);
-};
-#endif  // BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
-
-template <class Super>
-struct RawPtrCountingImplWrapperForTest
-    : public raw_ptr_traits::RawPtrTypeToImpl<Super>::Impl {
-  using SuperImpl = typename raw_ptr_traits::RawPtrTypeToImpl<Super>::Impl;
-  template <typename T>
-  static PA_ALWAYS_INLINE T* WrapRawPtr(T* ptr) {
-    ++wrap_raw_ptr_cnt;
-    return SuperImpl::WrapRawPtr(ptr);
-  }
-
-  template <typename T>
-  static PA_ALWAYS_INLINE void ReleaseWrappedPtr(T* ptr) {
-    ++release_wrapped_ptr_cnt;
-    SuperImpl::ReleaseWrappedPtr(ptr);
-  }
-
-  template <typename T>
-  static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForDereference(T* wrapped_ptr) {
-    ++get_for_dereference_cnt;
-    return SuperImpl::SafelyUnwrapPtrForDereference(wrapped_ptr);
-  }
-
-  template <typename T>
-  static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForExtraction(T* wrapped_ptr) {
-    ++get_for_extraction_cnt;
-    return SuperImpl::SafelyUnwrapPtrForExtraction(wrapped_ptr);
-  }
-
-  template <typename T>
-  static PA_ALWAYS_INLINE T* UnsafelyUnwrapPtrForComparison(T* wrapped_ptr) {
-    ++get_for_comparison_cnt;
-    return SuperImpl::UnsafelyUnwrapPtrForComparison(wrapped_ptr);
-  }
-
-  static PA_ALWAYS_INLINE void IncrementSwapCountForTest() {
-    ++wrapped_ptr_swap_cnt;
-  }
-
-  static PA_ALWAYS_INLINE void IncrementLessCountForTest() {
-    ++wrapped_ptr_less_cnt;
-  }
-
-  static PA_ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {
-    ++pointer_to_member_operator_cnt;
-  }
-
-  static void ClearCounters() {
-    wrap_raw_ptr_cnt = 0;
-    release_wrapped_ptr_cnt = 0;
-    get_for_dereference_cnt = 0;
-    get_for_extraction_cnt = 0;
-    get_for_comparison_cnt = 0;
-    wrapped_ptr_swap_cnt = 0;
-    wrapped_ptr_less_cnt = 0;
-    pointer_to_member_operator_cnt = 0;
-  }
-
-  static inline int wrap_raw_ptr_cnt = INT_MIN;
-  static inline int release_wrapped_ptr_cnt = INT_MIN;
-  static inline int get_for_dereference_cnt = INT_MIN;
-  static inline int get_for_extraction_cnt = INT_MIN;
-  static inline int get_for_comparison_cnt = INT_MIN;
-  static inline int wrapped_ptr_swap_cnt = INT_MIN;
-  static inline int wrapped_ptr_less_cnt = INT_MIN;
-  static inline int pointer_to_member_operator_cnt = INT_MIN;
-};
-
-}  // namespace internal
-
-namespace raw_ptr_traits {
-
-// IsSupportedType<T>::value answers whether raw_ptr<T> 1) compiles and 2) is
-// always safe at runtime.  Templates that may end up using `raw_ptr<T>` should
-// use IsSupportedType to ensure that raw_ptr is not used with unsupported
-// types.  As an example, see how base::internal::StorageTraits uses
-// IsSupportedType as a condition for using base::internal::UnretainedWrapper
-// (which has a `ptr_` field that will become `raw_ptr<T>` after the Big
-// Rewrite).
-template <typename T, typename SFINAE = void>
-struct IsSupportedType {
-  static constexpr bool value = true;
-};
-
-// raw_ptr<T> is not compatible with function pointer types. Also, they don't
-// even need the raw_ptr protection, because they don't point on heap.
-template <typename T>
-struct IsSupportedType<T, std::enable_if_t<std::is_function<T>::value>> {
-  static constexpr bool value = false;
-};
-
-// This section excludes some types from raw_ptr<T> to avoid them from being
-// used inside base::Unretained in performance sensitive places. These were
-// identified from sampling profiler data. See crbug.com/1287151 for more info.
-template <>
-struct IsSupportedType<cc::Scheduler> {
-  static constexpr bool value = false;
-};
-template <>
-struct IsSupportedType<base::internal::DelayTimerBase> {
-  static constexpr bool value = false;
-};
-template <>
-struct IsSupportedType<content::responsiveness::Calculator> {
-  static constexpr bool value = false;
-};
-
-// IsRawPtrCountingImpl<T>::value answers whether T is a specialization of
-// RawPtrCountingImplWrapperForTest, to know whether Impl is for testing
-// purposes.
-template <typename T>
-struct IsRawPtrCountingImpl : std::false_type {};
-
-template <typename T>
-struct IsRawPtrCountingImpl<internal::RawPtrCountingImplWrapperForTest<T>>
-    : std::true_type {};
-
-#if __OBJC__
-// raw_ptr<T> is not compatible with pointers to Objective-C classes for a
-// multitude of reasons. They may fail to compile in many cases, and wouldn't
-// work well with tagged pointers. Anyway, Objective-C objects have their own
-// way of tracking lifespan, hence don't need the raw_ptr protection as much.
-//
-// Such pointers are detected by checking if they're convertible to |id| type.
-template <typename T>
-struct IsSupportedType<T,
-                       std::enable_if_t<std::is_convertible<T*, id>::value>> {
-  static constexpr bool value = false;
-};
-#endif  // __OBJC__
-
-#if BUILDFLAG(IS_WIN)
-// raw_ptr<HWND__> is unsafe at runtime - if the handle happens to also
-// represent a valid pointer into a PartitionAlloc-managed region then it can
-// lead to manipulating random memory when treating it as BackupRefPtr
-// ref-count.  See also https://crbug.com/1262017.
-//
-// TODO(https://crbug.com/1262017): Cover other handle types like HANDLE,
-// HLOCAL, HINTERNET, or HDEVINFO.  Maybe we should avoid using raw_ptr<T> when
-// T=void (as is the case in these handle types).  OTOH, explicit,
-// non-template-based raw_ptr<void> should be allowed.  Maybe this can be solved
-// by having 2 traits: IsPointeeAlwaysSafe (to be used in templates) and
-// IsPointeeUsuallySafe (to be used in the static_assert in raw_ptr).  The
-// upside of this approach is that it will safely handle base::Bind closing over
-// HANDLE.  The downside of this approach is that base::Bind closing over a
-// void* pointer will not get UaF protection.
-#define PA_WINDOWS_HANDLE_TYPE(name)       \
-  template <>                              \
-  struct IsSupportedType<name##__, void> { \
-    static constexpr bool value = false;   \
-  };
-#include "base/allocator/partition_allocator/partition_alloc_base/win/win_handle_types_list.inc"
-#undef PA_WINDOWS_HANDLE_TYPE
-#endif
-
-template <typename T>
-struct RawPtrTypeToImpl {};
-
-template <typename T>
-struct RawPtrTypeToImpl<internal::RawPtrCountingImplWrapperForTest<T>> {
-  using Impl = internal::RawPtrCountingImplWrapperForTest<T>;
-};
-
-template <>
-struct RawPtrTypeToImpl<RawPtrMayDangle> {
-#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
-  using Impl = internal::BackupRefPtrImpl</*AllowDangling=*/true>;
-#elif BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
-  using Impl = internal::AsanBackupRefPtrImpl;
-#elif defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
-  using Impl = internal::MTECheckedPtrImpl<
-      internal::MTECheckedPtrImplPartitionAllocSupport>;
-#else
-  using Impl = internal::RawPtrNoOpImpl;
-#endif
-};
-
-template <>
-struct RawPtrTypeToImpl<RawPtrBanDanglingIfSupported> {
-#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
-  using Impl = internal::BackupRefPtrImpl</*AllowDangling=*/false>;
-#elif BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
-  using Impl = internal::AsanBackupRefPtrImpl;
-#elif defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
-  using Impl = internal::MTECheckedPtrImpl<
-      internal::MTECheckedPtrImplPartitionAllocSupport>;
-#else
-  using Impl = internal::RawPtrNoOpImpl;
-#endif
-};
-
-template <>
-struct RawPtrTypeToImpl<RawPtrNoOp> {
-  using Impl = internal::RawPtrNoOpImpl;
-};
-
-}  // namespace raw_ptr_traits
-
-// `raw_ptr<T>` is a non-owning smart pointer that has improved memory-safety
-// over raw pointers.  It behaves just like a raw pointer on platforms where
-// USE_BACKUP_REF_PTR is off, and almost like one when it's on (the main
-// difference is that it's zero-initialized and cleared on destruction and
-// move). Unlike `std::unique_ptr<T>`, `base::scoped_refptr<T>`, etc., it
-// doesn’t manage ownership or lifetime of an allocated object - you are still
-// responsible for freeing the object when no longer used, just as you would
-// with a raw C++ pointer.
-//
-// Compared to a raw C++ pointer, on platforms where USE_BACKUP_REF_PTR is on,
-// `raw_ptr<T>` incurs additional performance overhead for initialization,
-// destruction, and assignment (including `ptr++` and `ptr += ...`).  There is
-// no overhead when dereferencing a pointer.
-//
-// `raw_ptr<T>` is beneficial for security, because it can prevent a significant
-// percentage of Use-after-Free (UaF) bugs from being exploitable.  `raw_ptr<T>`
-// has limited impact on stability - dereferencing a dangling pointer remains
-// Undefined Behavior.  Note that the security protection is not yet enabled by
-// default.
-//
-// raw_ptr<T> is marked as [[gsl::Pointer]] which allows the compiler to catch
-// some bugs where the raw_ptr holds a dangling pointer to a temporary object.
-// However the [[gsl::Pointer]] analysis expects that such types do not have a
-// non-default move constructor/assignment. Thus, it's possible to get an error
-// where the pointer is not actually dangling, and have to work around the
-// compiler. We have not managed to construct such an example in Chromium yet.
-
-using DefaultRawPtrType = RawPtrBanDanglingIfSupported;
-
-template <typename T, typename RawPtrType = DefaultRawPtrType>
-class PA_TRIVIAL_ABI PA_GSL_POINTER raw_ptr {
-  using Impl = typename raw_ptr_traits::RawPtrTypeToImpl<RawPtrType>::Impl;
-  using DanglingRawPtr = std::conditional_t<
-      raw_ptr_traits::IsRawPtrCountingImpl<Impl>::value,
-      raw_ptr<T, internal::RawPtrCountingImplWrapperForTest<RawPtrMayDangle>>,
-      raw_ptr<T, RawPtrMayDangle>>;
-
-#if !BUILDFLAG(USE_PARTITION_ALLOC)
-  // See comment at top about `PA_RAW_PTR_CHECK()`.
-  static_assert(std::is_same_v<Impl, internal::RawPtrNoOpImpl>);
-#endif  // !BUILDFLAG(USE_PARTITION_ALLOC)
-
- public:
-  static_assert(raw_ptr_traits::IsSupportedType<T>::value,
-                "raw_ptr<T> doesn't work with this kind of pointee type T");
-
-#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
-  // BackupRefPtr requires a non-trivial default constructor, destructor, etc.
-  constexpr PA_ALWAYS_INLINE raw_ptr() noexcept : wrapped_ptr_(nullptr) {}
-
-  PA_ALWAYS_INLINE raw_ptr(const raw_ptr& p) noexcept
-      : wrapped_ptr_(Impl::Duplicate(p.wrapped_ptr_)) {}
-
-  PA_ALWAYS_INLINE raw_ptr(raw_ptr&& p) noexcept {
-    wrapped_ptr_ = p.wrapped_ptr_;
-    p.wrapped_ptr_ = nullptr;
-  }
-
-  PA_ALWAYS_INLINE raw_ptr& operator=(const raw_ptr& p) noexcept {
-    // Duplicate before releasing, in case the pointer is assigned to itself.
-    //
-    // Unlike the move version of this operator, don't add |this != &p| branch,
-    // for performance reasons. Even though Duplicate() is not cheap, we
-    // practically never assign a raw_ptr<T> to itself. We suspect that a
-    // cumulative cost of a conditional branch, even if always correctly
-    // predicted, would exceed that.
-    T* new_ptr = Impl::Duplicate(p.wrapped_ptr_);
-    Impl::ReleaseWrappedPtr(wrapped_ptr_);
-    wrapped_ptr_ = new_ptr;
-    return *this;
-  }
-
-  PA_ALWAYS_INLINE raw_ptr& operator=(raw_ptr&& p) noexcept {
-    // Unlike the the copy version of this operator, this branch is necessaty
-    // for correctness.
-    if (PA_LIKELY(this != &p)) {
-      Impl::ReleaseWrappedPtr(wrapped_ptr_);
-      wrapped_ptr_ = p.wrapped_ptr_;
-      p.wrapped_ptr_ = nullptr;
-    }
-    return *this;
-  }
-
-  PA_ALWAYS_INLINE ~raw_ptr() noexcept {
-    Impl::ReleaseWrappedPtr(wrapped_ptr_);
-    // Work around external issues where raw_ptr is used after destruction.
-    wrapped_ptr_ = nullptr;
-  }
-
-#else  // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
-
-  // raw_ptr can be trivially default constructed (leaving |wrapped_ptr_|
-  // uninitialized).  This is needed for compatibility with raw pointers.
-  //
-  // TODO(lukasza): Always initialize |wrapped_ptr_|.  Fix resulting build
-  // errors.  Analyze performance impact.
-  constexpr PA_ALWAYS_INLINE raw_ptr() noexcept = default;
-
-  // In addition to nullptr_t ctor above, raw_ptr needs to have these
-  // as |=default| or |constexpr| to avoid hitting -Wglobal-constructors in
-  // cases like this:
-  //     struct SomeStruct { int int_field; raw_ptr<int> ptr_field; };
-  //     SomeStruct g_global_var = { 123, nullptr };
-  PA_ALWAYS_INLINE raw_ptr(const raw_ptr&) noexcept = default;
-  PA_ALWAYS_INLINE raw_ptr(raw_ptr&&) noexcept = default;
-  PA_ALWAYS_INLINE raw_ptr& operator=(const raw_ptr&) noexcept = default;
-  PA_ALWAYS_INLINE raw_ptr& operator=(raw_ptr&&) noexcept = default;
-
-  PA_ALWAYS_INLINE ~raw_ptr() noexcept = default;
-
-#endif  // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
-
-  // Deliberately implicit, because raw_ptr is supposed to resemble raw ptr.
-  // NOLINTNEXTLINE(google-explicit-constructor)
-  constexpr PA_ALWAYS_INLINE raw_ptr(std::nullptr_t) noexcept
-      : wrapped_ptr_(nullptr) {}
-
-  // Deliberately implicit, because raw_ptr is supposed to resemble raw ptr.
-  // NOLINTNEXTLINE(google-explicit-constructor)
-  PA_ALWAYS_INLINE raw_ptr(T* p) noexcept : wrapped_ptr_(Impl::WrapRawPtr(p)) {}
-
-  // Deliberately implicit in order to support implicit upcast.
-  template <typename U,
-            typename Unused = std::enable_if_t<
-                std::is_convertible<U*, T*>::value &&
-                !std::is_void<typename std::remove_cv<T>::type>::value>>
-  // NOLINTNEXTLINE(google-explicit-constructor)
-  PA_ALWAYS_INLINE raw_ptr(const raw_ptr<U, RawPtrType>& ptr) noexcept
-      : wrapped_ptr_(
-            Impl::Duplicate(Impl::template Upcast<T, U>(ptr.wrapped_ptr_))) {}
-  // Deliberately implicit in order to support implicit upcast.
-  template <typename U,
-            typename Unused = std::enable_if_t<
-                std::is_convertible<U*, T*>::value &&
-                !std::is_void<typename std::remove_cv<T>::type>::value>>
-  // NOLINTNEXTLINE(google-explicit-constructor)
-  PA_ALWAYS_INLINE raw_ptr(raw_ptr<U, RawPtrType>&& ptr) noexcept
-      : wrapped_ptr_(Impl::template Upcast<T, U>(ptr.wrapped_ptr_)) {
-#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
-    ptr.wrapped_ptr_ = nullptr;
-#endif
-  }
-
-  PA_ALWAYS_INLINE raw_ptr& operator=(std::nullptr_t) noexcept {
-    Impl::ReleaseWrappedPtr(wrapped_ptr_);
-    wrapped_ptr_ = nullptr;
-    return *this;
-  }
-  PA_ALWAYS_INLINE raw_ptr& operator=(T* p) noexcept {
-    Impl::ReleaseWrappedPtr(wrapped_ptr_);
-    wrapped_ptr_ = Impl::WrapRawPtr(p);
-    return *this;
-  }
-
-  // Upcast assignment
-  template <typename U,
-            typename Unused = std::enable_if_t<
-                std::is_convertible<U*, T*>::value &&
-                !std::is_void<typename std::remove_cv<T>::type>::value>>
-  PA_ALWAYS_INLINE raw_ptr& operator=(
-      const raw_ptr<U, RawPtrType>& ptr) noexcept {
-    // Make sure that pointer isn't assigned to itself (look at pointer address,
-    // not its value).
-#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
-    PA_RAW_PTR_CHECK(reinterpret_cast<uintptr_t>(this) !=
-                     reinterpret_cast<uintptr_t>(&ptr));
-#endif
-    Impl::ReleaseWrappedPtr(wrapped_ptr_);
-    wrapped_ptr_ =
-        Impl::Duplicate(Impl::template Upcast<T, U>(ptr.wrapped_ptr_));
-    return *this;
-  }
-  template <typename U,
-            typename Unused = std::enable_if_t<
-                std::is_convertible<U*, T*>::value &&
-                !std::is_void<typename std::remove_cv<T>::type>::value>>
-  PA_ALWAYS_INLINE raw_ptr& operator=(raw_ptr<U, RawPtrType>&& ptr) noexcept {
-    // Make sure that pointer isn't assigned to itself (look at pointer address,
-    // not its value).
-#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
-    PA_RAW_PTR_CHECK(reinterpret_cast<uintptr_t>(this) !=
-                     reinterpret_cast<uintptr_t>(&ptr));
-#endif
-    Impl::ReleaseWrappedPtr(wrapped_ptr_);
-    wrapped_ptr_ = Impl::template Upcast<T, U>(ptr.wrapped_ptr_);
-#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
-    ptr.wrapped_ptr_ = nullptr;
-#endif
-    return *this;
-  }
-
-  // Avoid using. The goal of raw_ptr is to be as close to raw pointer as
-  // possible, so use it only if absolutely necessary (e.g. for const_cast).
-  PA_ALWAYS_INLINE T* get() const { return GetForExtraction(); }
-
-  explicit PA_ALWAYS_INLINE operator bool() const { return !!wrapped_ptr_; }
-
-  template <typename U = T,
-            typename Unused = std::enable_if_t<
-                !std::is_void<typename std::remove_cv<U>::type>::value>>
-  PA_ALWAYS_INLINE U& operator*() const {
-    return *GetForDereference();
-  }
-  PA_ALWAYS_INLINE T* operator->() const { return GetForDereference(); }
-
-  // Disables `(my_raw_ptr->*pmf)(...)` as a workaround for
-  // the ICE in GCC parsing the code, reported at
-  // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103455
-  template <typename PMF>
-  void operator->*(PMF) const = delete;
-
-  // Deliberately implicit, because raw_ptr is supposed to resemble raw ptr.
-  // NOLINTNEXTLINE(runtime/explicit)
-  PA_ALWAYS_INLINE operator T*() const { return GetForExtraction(); }
-  template <typename U>
-  explicit PA_ALWAYS_INLINE operator U*() const {
-    // This operator may be invoked from static_cast, meaning the types may not
-    // be implicitly convertible, hence the need for static_cast here.
-    return static_cast<U*>(GetForExtraction());
-  }
-
-  PA_ALWAYS_INLINE raw_ptr& operator++() {
-    wrapped_ptr_ = Impl::Advance(wrapped_ptr_, 1);
-    return *this;
-  }
-  PA_ALWAYS_INLINE raw_ptr& operator--() {
-    wrapped_ptr_ = Impl::Advance(wrapped_ptr_, -1);
-    return *this;
-  }
-  PA_ALWAYS_INLINE raw_ptr operator++(int /* post_increment */) {
-    raw_ptr result = *this;
-    ++(*this);
-    return result;
-  }
-  PA_ALWAYS_INLINE raw_ptr operator--(int /* post_decrement */) {
-    raw_ptr result = *this;
-    --(*this);
-    return result;
-  }
-  template <typename Z, typename = std::enable_if_t<internal::offset_type<Z>>>
-  PA_ALWAYS_INLINE raw_ptr& operator+=(Z delta_elems) {
-    wrapped_ptr_ = Impl::Advance(wrapped_ptr_, delta_elems);
-    return *this;
-  }
-  template <typename Z, typename = std::enable_if_t<internal::offset_type<Z>>>
-  PA_ALWAYS_INLINE raw_ptr& operator-=(Z delta_elems) {
-    return *this += -delta_elems;
-  }
-
-  template <typename Z, typename = std::enable_if_t<internal::offset_type<Z>>>
-  friend PA_ALWAYS_INLINE raw_ptr operator+(const raw_ptr& p, Z delta_elems) {
-    raw_ptr result = p;
-    return result += delta_elems;
-  }
-  template <typename Z, typename = std::enable_if_t<internal::offset_type<Z>>>
-  friend PA_ALWAYS_INLINE raw_ptr operator-(const raw_ptr& p, Z delta_elems) {
-    raw_ptr result = p;
-    return result -= delta_elems;
-  }
-  friend PA_ALWAYS_INLINE ptrdiff_t operator-(const raw_ptr& p1,
-                                              const raw_ptr& p2) {
-    return Impl::GetDeltaElems(p1.wrapped_ptr_, p2.wrapped_ptr_);
-  }
-  friend PA_ALWAYS_INLINE ptrdiff_t operator-(T* p1, const raw_ptr& p2) {
-    return Impl::GetDeltaElems(p1, p2.wrapped_ptr_);
-  }
-  friend PA_ALWAYS_INLINE ptrdiff_t operator-(const raw_ptr& p1, T* p2) {
-    return Impl::GetDeltaElems(p1.wrapped_ptr_, p2);
-  }
-
-  // Stop referencing the underlying pointer and free its memory. Compared to
-  // raw delete calls, this avoids the raw_ptr to be temporarily dangling
-  // during the free operation, which will lead to taking the slower path that
-  // involves quarantine.
-  PA_ALWAYS_INLINE void ClearAndDelete() noexcept {
-    delete GetForExtractionAndReset();
-  }
-  PA_ALWAYS_INLINE void ClearAndDeleteArray() noexcept {
-    delete[] GetForExtractionAndReset();
-  }
-
-  // Clear the underlying pointer and return another raw_ptr instance
-  // that is allowed to dangle.
-  // This can be useful in cases such as:
-  // ```
-  //  ptr.ExtractAsDangling()->SelfDestroy();
-  // ```
-  // ```
-  //  c_style_api_do_something_and_destroy(ptr.ExtractAsDangling());
-  // ```
-  // NOTE, avoid using this method as it indicates an error-prone memory
-  // ownership pattern. If possible, use smart pointers like std::unique_ptr<>
-  // instead of raw_ptr<>.
-  // If you have to use it, avoid saving the return value in a long-lived
-  // variable (or worse, a field)! It's meant to be used as a temporary, to be
-  // passed into a cleanup & freeing function, and destructed at the end of the
-  // statement.
-  PA_ALWAYS_INLINE DanglingRawPtr ExtractAsDangling() noexcept {
-    if constexpr (std::is_same_v<
-                      typename std::remove_reference<decltype(*this)>::type,
-                      DanglingRawPtr>) {
-      DanglingRawPtr res(std::move(*this));
-      // Not all implementation clear the source pointer on move, so do it
-      // here just in case. Should be cheap.
-      operator=(nullptr);
-      return res;
-    } else {
-      T* ptr = GetForExtraction();
-      DanglingRawPtr res(ptr);
-      operator=(nullptr);
-      return res;
-    }
-  }
-
-  // Comparison operators between raw_ptr and raw_ptr<U>/U*/std::nullptr_t.
-  // Strictly speaking, it is not necessary to provide these: the compiler can
-  // use the conversion operator implicitly to allow comparisons to fall back to
-  // comparisons between raw pointers. However, `operator T*`/`operator U*` may
-  // perform safety checks with a higher runtime cost, so to avoid this, provide
-  // explicit comparison operators for all combinations of parameters.
-
-  // Comparisons between `raw_ptr`s. This unusual declaration and separate
-  // definition below is because `GetForComparison()` is a private method. The
-  // more conventional approach of defining a comparison operator between
-  // `raw_ptr` and `raw_ptr<U>` in the friend declaration itself does not work,
-  // because a comparison operator defined inline would not be allowed to call
-  // `raw_ptr<U>`'s private `GetForComparison()` method.
-  template <typename U, typename V, typename I>
-  friend PA_ALWAYS_INLINE bool operator==(const raw_ptr<U, I>& lhs,
-                                          const raw_ptr<V, I>& rhs);
-  template <typename U>
-  friend PA_ALWAYS_INLINE bool operator!=(const raw_ptr& lhs,
-                                          const raw_ptr<U, Impl>& rhs) {
-    return !(lhs == rhs);
-  }
-  template <typename U, typename V, typename I>
-  friend PA_ALWAYS_INLINE bool operator<(const raw_ptr<U, I>& lhs,
-                                         const raw_ptr<V, I>& rhs);
-  template <typename U, typename V, typename I>
-  friend PA_ALWAYS_INLINE bool operator>(const raw_ptr<U, I>& lhs,
-                                         const raw_ptr<V, I>& rhs);
-  template <typename U, typename V, typename I>
-  friend PA_ALWAYS_INLINE bool operator<=(const raw_ptr<U, I>& lhs,
-                                          const raw_ptr<V, I>& rhs);
-  template <typename U, typename V, typename I>
-  friend PA_ALWAYS_INLINE bool operator>=(const raw_ptr<U, I>& lhs,
-                                          const raw_ptr<V, I>& rhs);
-
-  // Comparisons with U*. These operators also handle the case where the RHS is
-  // T*.
-  template <typename U>
-  friend PA_ALWAYS_INLINE bool operator==(const raw_ptr& lhs, U* rhs) {
-    return lhs.GetForComparison() == rhs;
-  }
-  template <typename U>
-  friend PA_ALWAYS_INLINE bool operator!=(const raw_ptr& lhs, U* rhs) {
-    return !(lhs == rhs);
-  }
-  template <typename U>
-  friend PA_ALWAYS_INLINE bool operator==(U* lhs, const raw_ptr& rhs) {
-    return rhs == lhs;  // Reverse order to call the operator above.
-  }
-  template <typename U>
-  friend PA_ALWAYS_INLINE bool operator!=(U* lhs, const raw_ptr& rhs) {
-    return rhs != lhs;  // Reverse order to call the operator above.
-  }
-  template <typename U>
-  friend PA_ALWAYS_INLINE bool operator<(const raw_ptr& lhs, U* rhs) {
-    return lhs.GetForComparison() < rhs;
-  }
-  template <typename U>
-  friend PA_ALWAYS_INLINE bool operator<=(const raw_ptr& lhs, U* rhs) {
-    return lhs.GetForComparison() <= rhs;
-  }
-  template <typename U>
-  friend PA_ALWAYS_INLINE bool operator>(const raw_ptr& lhs, U* rhs) {
-    return lhs.GetForComparison() > rhs;
-  }
-  template <typename U>
-  friend PA_ALWAYS_INLINE bool operator>=(const raw_ptr& lhs, U* rhs) {
-    return lhs.GetForComparison() >= rhs;
-  }
-  template <typename U>
-  friend PA_ALWAYS_INLINE bool operator<(U* lhs, const raw_ptr& rhs) {
-    return lhs < rhs.GetForComparison();
-  }
-  template <typename U>
-  friend PA_ALWAYS_INLINE bool operator<=(U* lhs, const raw_ptr& rhs) {
-    return lhs <= rhs.GetForComparison();
-  }
-  template <typename U>
-  friend PA_ALWAYS_INLINE bool operator>(U* lhs, const raw_ptr& rhs) {
-    return lhs > rhs.GetForComparison();
-  }
-  template <typename U>
-  friend PA_ALWAYS_INLINE bool operator>=(U* lhs, const raw_ptr& rhs) {
-    return lhs >= rhs.GetForComparison();
-  }
-
-  // Comparisons with `std::nullptr_t`.
-  friend PA_ALWAYS_INLINE bool operator==(const raw_ptr& lhs, std::nullptr_t) {
-    return !lhs;
-  }
-  friend PA_ALWAYS_INLINE bool operator!=(const raw_ptr& lhs, std::nullptr_t) {
-    return !!lhs;  // Use !! otherwise the costly implicit cast will be used.
-  }
-  friend PA_ALWAYS_INLINE bool operator==(std::nullptr_t, const raw_ptr& rhs) {
-    return !rhs;
-  }
-  friend PA_ALWAYS_INLINE bool operator!=(std::nullptr_t, const raw_ptr& rhs) {
-    return !!rhs;  // Use !! otherwise the costly implicit cast will be used.
-  }
-
-  friend PA_ALWAYS_INLINE void swap(raw_ptr& lhs, raw_ptr& rhs) noexcept {
-    Impl::IncrementSwapCountForTest();
-    std::swap(lhs.wrapped_ptr_, rhs.wrapped_ptr_);
-  }
-
-  PA_ALWAYS_INLINE void ReportIfDangling() const noexcept {
-#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
-    Impl::ReportIfDangling(wrapped_ptr_);
-#endif
-  }
-
- private:
-  // This getter is meant for situations where the pointer is meant to be
-  // dereferenced. It is allowed to crash on nullptr (it may or may not),
-  // because it knows that the caller will crash on nullptr.
-  PA_ALWAYS_INLINE T* GetForDereference() const {
-    return Impl::SafelyUnwrapPtrForDereference(wrapped_ptr_);
-  }
-  // This getter is meant for situations where the raw pointer is meant to be
-  // extracted outside of this class, but not necessarily with an intention to
-  // dereference. It mustn't crash on nullptr.
-  PA_ALWAYS_INLINE T* GetForExtraction() const {
-    return Impl::SafelyUnwrapPtrForExtraction(wrapped_ptr_);
-  }
-  // This getter is meant *only* for situations where the pointer is meant to be
-  // compared (guaranteeing no dereference or extraction outside of this class).
-  // Any verifications can and should be skipped for performance reasons.
-  PA_ALWAYS_INLINE T* GetForComparison() const {
-    return Impl::UnsafelyUnwrapPtrForComparison(wrapped_ptr_);
-  }
-
-  PA_ALWAYS_INLINE T* GetForExtractionAndReset() {
-    T* ptr = GetForExtraction();
-    operator=(nullptr);
-    return ptr;
-  }
-
-  T* wrapped_ptr_;
-
-  template <typename U, typename V>
-  friend class raw_ptr;
-};
-
-template <typename U, typename V, typename I>
-PA_ALWAYS_INLINE bool operator==(const raw_ptr<U, I>& lhs,
-                                 const raw_ptr<V, I>& rhs) {
-  return lhs.GetForComparison() == rhs.GetForComparison();
-}
-
-template <typename U, typename V, typename I>
-PA_ALWAYS_INLINE bool operator<(const raw_ptr<U, I>& lhs,
-                                const raw_ptr<V, I>& rhs) {
-  return lhs.GetForComparison() < rhs.GetForComparison();
-}
-
-template <typename U, typename V, typename I>
-PA_ALWAYS_INLINE bool operator>(const raw_ptr<U, I>& lhs,
-                                const raw_ptr<V, I>& rhs) {
-  return lhs.GetForComparison() > rhs.GetForComparison();
-}
-
-template <typename U, typename V, typename I>
-PA_ALWAYS_INLINE bool operator<=(const raw_ptr<U, I>& lhs,
-                                 const raw_ptr<V, I>& rhs) {
-  return lhs.GetForComparison() <= rhs.GetForComparison();
-}
-
-template <typename U, typename V, typename I>
-PA_ALWAYS_INLINE bool operator>=(const raw_ptr<U, I>& lhs,
-                                 const raw_ptr<V, I>& rhs) {
-  return lhs.GetForComparison() >= rhs.GetForComparison();
-}
-
-template <typename T>
-struct IsRawPtr : std::false_type {};
-
-template <typename T, typename I>
-struct IsRawPtr<raw_ptr<T, I>> : std::true_type {};
-
-template <typename T>
-inline constexpr bool IsRawPtrV = IsRawPtr<T>::value;
-
-// Template helpers for working with T* or raw_ptr<T>.
-template <typename T>
-struct IsPointer : std::false_type {};
-
-template <typename T>
-struct IsPointer<T*> : std::true_type {};
-
-template <typename T, typename I>
-struct IsPointer<raw_ptr<T, I>> : std::true_type {};
-
-template <typename T>
-inline constexpr bool IsPointerV = IsPointer<T>::value;
-
-template <typename T>
-struct RemovePointer {
-  using type = T;
-};
-
-template <typename T>
-struct RemovePointer<T*> {
-  using type = T;
-};
-
-template <typename T, typename I>
-struct RemovePointer<raw_ptr<T, I>> {
-  using type = T;
-};
-
-template <typename T>
-using RemovePointerT = typename RemovePointer<T>::type;
-
-}  // namespace base
-
-using base::raw_ptr;
-
-// DisableDanglingPtrDetection option for raw_ptr annotates
-// "intentional-and-safe" dangling pointers. It is meant to be used at the
-// margin, only if there is no better way to re-architecture the code.
-//
-// Usage:
-// raw_ptr<T, DisableDanglingPtrDetection> dangling_ptr;
-//
-// When using it, please provide a justification about what guarantees it will
-// never be dereferenced after becoming dangling.
-using DisableDanglingPtrDetection = base::RawPtrMayDangle;
-
-// See `docs/dangling_ptr.md`
-// Annotates known dangling raw_ptr. Those haven't been triaged yet. All the
-// occurrences are meant to be removed. See https://crbug.com/1291138.
-using DanglingUntriaged = DisableDanglingPtrDetection;
-
-// The following template parameters are only meaningful when `raw_ptr`
-// is `MTECheckedPtr` (never the case unless a particular GN arg is set
-// true.) `raw_ptr` users need not worry about this and can refer solely
-// to `DisableDanglingPtrDetection` and `DanglingUntriaged` above.
-//
-// The `raw_ptr` definition allows users to specify an implementation.
-// When `MTECheckedPtr` is in play, we need to augment this
-// implementation setting with another layer that allows the `raw_ptr`
-// to degrade into the no-op version.
-#if defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
-
-// Direct pass-through to no-op implementation.
-using DegradeToNoOpWhenMTE = base::RawPtrNoOp;
-
-// As above, but with the "untriaged dangling" annotation.
-using DanglingUntriagedDegradeToNoOpWhenMTE = base::RawPtrNoOp;
-
-// As above, but with the "explicitly disable protection" annotation.
-using DisableDanglingPtrDetectionDegradeToNoOpWhenMTE = base::RawPtrNoOp;
-
-#else
-
-// Direct pass-through to default implementation specified by `raw_ptr`
-// template.
-using DegradeToNoOpWhenMTE = base::RawPtrBanDanglingIfSupported;
-
-// Direct pass-through to `DanglingUntriaged`.
-using DanglingUntriagedDegradeToNoOpWhenMTE = DanglingUntriaged;
-
-// Direct pass-through to `DisableDanglingPtrDetection`.
-using DisableDanglingPtrDetectionDegradeToNoOpWhenMTE =
-    DisableDanglingPtrDetection;
-
-#endif  // defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
-
-namespace std {
-
-// Override so set/map lookups do not create extra raw_ptr. This also allows
-// dangling pointers to be used for lookup.
-template <typename T, typename RawPtrType>
-struct less<raw_ptr<T, RawPtrType>> {
-  using Impl =
-      typename base::raw_ptr_traits::RawPtrTypeToImpl<RawPtrType>::Impl;
-  using is_transparent = void;
-
-  bool operator()(const raw_ptr<T, RawPtrType>& lhs,
-                  const raw_ptr<T, RawPtrType>& rhs) const {
-    Impl::IncrementLessCountForTest();
-    return lhs < rhs;
-  }
-
-  bool operator()(T* lhs, const raw_ptr<T, RawPtrType>& rhs) const {
-    Impl::IncrementLessCountForTest();
-    return lhs < rhs;
-  }
-
-  bool operator()(const raw_ptr<T, RawPtrType>& lhs, T* rhs) const {
-    Impl::IncrementLessCountForTest();
-    return lhs < rhs;
-  }
-};
-
-// Define for cases where raw_ptr<T> holds a pointer to an array of type T.
-// This is consistent with definition of std::iterator_traits<T*>.
-// Algorithms like std::binary_search need that.
-template <typename T, typename Impl>
-struct iterator_traits<raw_ptr<T, Impl>> {
-  using difference_type = ptrdiff_t;
-  using value_type = std::remove_cv_t<T>;
-  using pointer = T*;
-  using reference = T&;
-  using iterator_category = std::random_access_iterator_tag;
-};
-
-}  // namespace std
-
-#endif  // BASE_ALLOCATOR_PARTITION_ALLOCATOR_POINTERS_RAW_PTR_H_
diff --git a/base/allocator/partition_allocator/pointers/raw_ref.h b/base/allocator/partition_allocator/pointers/raw_ref.h
deleted file mode 100644
index 52c51792..0000000
--- a/base/allocator/partition_allocator/pointers/raw_ref.h
+++ /dev/null
@@ -1,363 +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 BASE_ALLOCATOR_PARTITION_ALLOCATOR_POINTERS_RAW_REF_H_
-#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_POINTERS_RAW_REF_H_
-
-#include <memory>
-#include <type_traits>
-#include <utility>
-
-#include "base/allocator/partition_allocator/partition_alloc_base/augmentations/compiler_specific.h"
-#include "base/allocator/partition_allocator/partition_alloc_base/compiler_specific.h"
-#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
-#include "base/allocator/partition_allocator/partition_alloc_config.h"
-#include "base/allocator/partition_allocator/pointers/raw_ptr.h"
-
-namespace base {
-
-template <class T, class RawPtrType>
-class raw_ref;
-
-namespace internal {
-
-template <class T>
-struct is_raw_ref : std::false_type {};
-
-template <class T, class I>
-struct is_raw_ref<::base::raw_ref<T, I>> : std::true_type {};
-
-template <class T>
-constexpr inline bool is_raw_ref_v = is_raw_ref<T>::value;
-
-}  // namespace internal
-
-// A smart pointer for a pointer which can not be null, and which provides
-// Use-after-Free protection in the same ways as raw_ptr. This class acts like a
-// combination of std::reference_wrapper and raw_ptr.
-//
-// See raw_ptr and //base/memory/raw_ptr.md for more details on the
-// Use-after-Free protection.
-//
-// # Use after move
-//
-// The raw_ref type will abort if used after being moved.
-//
-// # Constness
-//
-// Use a `const raw_ref<T>` when the smart pointer should not be able to rebind
-// to a new reference. Use a `const raw_ref<const T>` do the same for a const
-// reference, which is like `const T&`.
-//
-// Unlike a native `T&` reference, a mutable `raw_ref<T>` can be changed
-// independent of the underlying `T`, similar to `std::reference_wrapper`. That
-// means the reference inside it can be moved and reassigned.
-template <class T, class RawPtrType = DefaultRawPtrType>
-class PA_TRIVIAL_ABI PA_GSL_POINTER raw_ref {
-  // operator* is used with the expectation of GetForExtraction semantics:
-  //
-  // raw_ref<Foo> foo_raw_ref = something;
-  // Foo& foo_ref = *foo_raw_ref;
-  //
-  // The implementation of operator* provides GetForDereference semantics, and
-  // this results in spurious crashes in BRP-ASan builds, so we need to disable
-  // BRP-ASan instrumentation for raw_ref.
-#if BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
-  using Inner = raw_ptr<T, RawPtrNoOp>;
-#else
-  using Inner = raw_ptr<T, RawPtrType>;
-#endif  // BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
-
-  using Impl = typename raw_ptr_traits::RawPtrTypeToImpl<RawPtrType>::Impl;
-  // These impls do not clear on move, which produces an inconsistent behaviour.
-  // We want consistent behaviour such that using a raw_ref after move is caught
-  // and aborts. Failure to clear would be indicated by the related death tests
-  // not CHECKing appropriately.
-  static constexpr bool need_clear_after_move =
-#if defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
-      std::is_same_v<Impl,
-                     internal::MTECheckedPtrImpl<
-                         internal::MTECheckedPtrImplPartitionAllocSupport>> ||
-#endif  // defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
-#if BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
-      std::is_same_v<Impl, internal::AsanBackupRefPtrImpl> ||
-#endif  // BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
-      std::is_same_v<Impl, internal::RawPtrNoOpImpl>;
-
- public:
-  PA_ALWAYS_INLINE explicit raw_ref(T& p) noexcept
-      : inner_(std::addressof(p)) {}
-
-  PA_ALWAYS_INLINE raw_ref& operator=(T& p) noexcept {
-    inner_.operator=(&p);
-    return *this;
-  }
-
-  // Disallow holding references to temporaries.
-  raw_ref(const T&& p) = delete;
-  raw_ref& operator=(const T&& p) = delete;
-
-  PA_ALWAYS_INLINE raw_ref(const raw_ref& p) noexcept : inner_(p.inner_) {
-    PA_RAW_PTR_CHECK(inner_.get());  // Catch use-after-move.
-  }
-
-  PA_ALWAYS_INLINE raw_ref(raw_ref&& p) noexcept : inner_(std::move(p.inner_)) {
-    PA_RAW_PTR_CHECK(inner_.get());  // Catch use-after-move.
-    if constexpr (need_clear_after_move)
-      p.inner_ = nullptr;
-  }
-
-  PA_ALWAYS_INLINE raw_ref& operator=(const raw_ref& p) noexcept {
-    PA_RAW_PTR_CHECK(p.inner_.get());  // Catch use-after-move.
-    inner_.operator=(p.inner_);
-    return *this;
-  }
-
-  PA_ALWAYS_INLINE raw_ref& operator=(raw_ref&& p) noexcept {
-    PA_RAW_PTR_CHECK(p.inner_.get());  // Catch use-after-move.
-    inner_.operator=(std::move(p.inner_));
-    if constexpr (need_clear_after_move)
-      p.inner_ = nullptr;
-    return *this;
-  }
-
-  // Deliberately implicit in order to support implicit upcast.
-  template <class U, class = std::enable_if_t<std::is_convertible_v<U&, T&>>>
-  // NOLINTNEXTLINE(google-explicit-constructor)
-  PA_ALWAYS_INLINE raw_ref(const raw_ref<U, RawPtrType>& p) noexcept
-      : inner_(p.inner_) {
-    PA_RAW_PTR_CHECK(inner_.get());  // Catch use-after-move.
-  }
-  // Deliberately implicit in order to support implicit upcast.
-  template <class U, class = std::enable_if_t<std::is_convertible_v<U&, T&>>>
-  // NOLINTNEXTLINE(google-explicit-constructor)
-  PA_ALWAYS_INLINE raw_ref(raw_ref<U, RawPtrType>&& p) noexcept
-      : inner_(std::move(p.inner_)) {
-    PA_RAW_PTR_CHECK(inner_.get());  // Catch use-after-move.
-    if constexpr (need_clear_after_move)
-      p.inner_ = nullptr;
-  }
-
-  static PA_ALWAYS_INLINE raw_ref from_ptr(T* ptr) noexcept {
-    PA_RAW_PTR_CHECK(ptr);
-    return raw_ref(*ptr);
-  }
-
-  // Upcast assignment
-  template <class U, class = std::enable_if_t<std::is_convertible_v<U&, T&>>>
-  PA_ALWAYS_INLINE raw_ref& operator=(
-      const raw_ref<U, RawPtrType>& p) noexcept {
-    PA_RAW_PTR_CHECK(p.inner_.get());  // Catch use-after-move.
-    inner_.operator=(p.inner_);
-    return *this;
-  }
-  template <class U, class = std::enable_if_t<std::is_convertible_v<U&, T&>>>
-  PA_ALWAYS_INLINE raw_ref& operator=(raw_ref<U, RawPtrType>&& p) noexcept {
-    PA_RAW_PTR_CHECK(p.inner_.get());  // Catch use-after-move.
-    inner_.operator=(std::move(p.inner_));
-    if constexpr (need_clear_after_move)
-      p.inner_ = nullptr;
-    return *this;
-  }
-
-  PA_ALWAYS_INLINE T& operator*() const {
-    PA_RAW_PTR_CHECK(inner_.get());  // Catch use-after-move.
-    return inner_.operator*();
-  }
-
-  // This is an equivalent to operator*() that provides GetForExtraction rather
-  // rather than GetForDereference semantics (see raw_ptr.h). This should be
-  // used in place of operator*() when the memory referred to by the reference
-  // is not immediately going to be accessed.
-  PA_ALWAYS_INLINE T& get() const {
-    PA_RAW_PTR_CHECK(inner_.get());  // Catch use-after-move.
-    return *inner_.get();
-  }
-
-  PA_ALWAYS_INLINE T* operator->() const PA_ATTRIBUTE_RETURNS_NONNULL {
-    PA_RAW_PTR_CHECK(inner_.get());  // Catch use-after-move.
-    return inner_.operator->();
-  }
-
-  friend PA_ALWAYS_INLINE void swap(raw_ref& lhs, raw_ref& rhs) noexcept {
-    PA_RAW_PTR_CHECK(lhs.inner_.get());  // Catch use-after-move.
-    PA_RAW_PTR_CHECK(rhs.inner_.get());  // Catch use-after-move.
-    swap(lhs.inner_, rhs.inner_);
-  }
-
-  template <class U>
-  friend PA_ALWAYS_INLINE bool operator==(const raw_ref& lhs,
-                                          const raw_ref<U, RawPtrType>& rhs) {
-    PA_RAW_PTR_CHECK(lhs.inner_.get());  // Catch use-after-move.
-    PA_RAW_PTR_CHECK(rhs.inner_.get());  // Catch use-after-move.
-    return lhs.inner_ == rhs.inner_;
-  }
-  template <class U>
-  friend PA_ALWAYS_INLINE bool operator!=(const raw_ref& lhs,
-                                          const raw_ref<U, RawPtrType>& rhs) {
-    PA_RAW_PTR_CHECK(lhs.inner_.get());  // Catch use-after-move.
-    PA_RAW_PTR_CHECK(rhs.inner_.get());  // Catch use-after-move.
-    return lhs.inner_ != rhs.inner_;
-  }
-  template <class U>
-  friend PA_ALWAYS_INLINE bool operator<(const raw_ref& lhs,
-                                         const raw_ref<U, RawPtrType>& rhs) {
-    PA_RAW_PTR_CHECK(lhs.inner_.get());  // Catch use-after-move.
-    PA_RAW_PTR_CHECK(rhs.inner_.get());  // Catch use-after-move.
-    return lhs.inner_ < rhs.inner_;
-  }
-  template <class U>
-  friend PA_ALWAYS_INLINE bool operator>(const raw_ref& lhs,
-                                         const raw_ref<U, RawPtrType>& rhs) {
-    PA_RAW_PTR_CHECK(lhs.inner_.get());  // Catch use-after-move.
-    PA_RAW_PTR_CHECK(rhs.inner_.get());  // Catch use-after-move.
-    return lhs.inner_ > rhs.inner_;
-  }
-  template <class U>
-  friend PA_ALWAYS_INLINE bool operator<=(const raw_ref& lhs,
-                                          const raw_ref<U, RawPtrType>& rhs) {
-    PA_RAW_PTR_CHECK(lhs.inner_.get());  // Catch use-after-move.
-    PA_RAW_PTR_CHECK(rhs.inner_.get());  // Catch use-after-move.
-    return lhs.inner_ <= rhs.inner_;
-  }
-  template <class U>
-  friend PA_ALWAYS_INLINE bool operator>=(const raw_ref& lhs,
-                                          const raw_ref<U, RawPtrType>& rhs) {
-    PA_RAW_PTR_CHECK(lhs.inner_.get());  // Catch use-after-move.
-    PA_RAW_PTR_CHECK(rhs.inner_.get());  // Catch use-after-move.
-    return lhs.inner_ >= rhs.inner_;
-  }
-
-  template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
-  friend PA_ALWAYS_INLINE bool operator==(const raw_ref& lhs, const U& rhs) {
-    PA_RAW_PTR_CHECK(lhs.inner_.get());  // Catch use-after-move.
-    return lhs.inner_ == &rhs;
-  }
-  template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
-  friend PA_ALWAYS_INLINE bool operator!=(const raw_ref& lhs, const U& rhs) {
-    PA_RAW_PTR_CHECK(lhs.inner_.get());  // Catch use-after-move.
-    return lhs.inner_ != &rhs;
-  }
-  template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
-  friend PA_ALWAYS_INLINE bool operator<(const raw_ref& lhs, const U& rhs) {
-    PA_RAW_PTR_CHECK(lhs.inner_.get());  // Catch use-after-move.
-    return lhs.inner_ < &rhs;
-  }
-  template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
-  friend PA_ALWAYS_INLINE bool operator>(const raw_ref& lhs, const U& rhs) {
-    PA_RAW_PTR_CHECK(lhs.inner_.get());  // Catch use-after-move.
-    return lhs.inner_ > &rhs;
-  }
-  template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
-  friend PA_ALWAYS_INLINE bool operator<=(const raw_ref& lhs, const U& rhs) {
-    PA_RAW_PTR_CHECK(lhs.inner_.get());  // Catch use-after-move.
-    return lhs.inner_ <= &rhs;
-  }
-  template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
-  friend PA_ALWAYS_INLINE bool operator>=(const raw_ref& lhs, const U& rhs) {
-    PA_RAW_PTR_CHECK(lhs.inner_.get());  // Catch use-after-move.
-    return lhs.inner_ >= &rhs;
-  }
-
-  template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
-  friend PA_ALWAYS_INLINE bool operator==(const U& lhs, const raw_ref& rhs) {
-    PA_RAW_PTR_CHECK(rhs.inner_.get());  // Catch use-after-move.
-    return &lhs == rhs.inner_;
-  }
-  template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
-  friend PA_ALWAYS_INLINE bool operator!=(const U& lhs, const raw_ref& rhs) {
-    PA_RAW_PTR_CHECK(rhs.inner_.get());  // Catch use-after-move.
-    return &lhs != rhs.inner_;
-  }
-  template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
-  friend PA_ALWAYS_INLINE bool operator<(const U& lhs, const raw_ref& rhs) {
-    PA_RAW_PTR_CHECK(rhs.inner_.get());  // Catch use-after-move.
-    return &lhs < rhs.inner_;
-  }
-  template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
-  friend PA_ALWAYS_INLINE bool operator>(const U& lhs, const raw_ref& rhs) {
-    PA_RAW_PTR_CHECK(rhs.inner_.get());  // Catch use-after-move.
-    return &lhs > rhs.inner_;
-  }
-  template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
-  friend PA_ALWAYS_INLINE bool operator<=(const U& lhs, const raw_ref& rhs) {
-    PA_RAW_PTR_CHECK(rhs.inner_.get());  // Catch use-after-move.
-    return &lhs <= rhs.inner_;
-  }
-  template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
-  friend PA_ALWAYS_INLINE bool operator>=(const U& lhs, const raw_ref& rhs) {
-    PA_RAW_PTR_CHECK(rhs.inner_.get());  // Catch use-after-move.
-    return &lhs >= rhs.inner_;
-  }
-
- private:
-  template <class U, class J>
-  friend class raw_ref;
-
-  Inner inner_;
-};
-
-// CTAD deduction guide.
-template <class T>
-raw_ref(T&) -> raw_ref<T>;
-template <class T>
-raw_ref(const T&) -> raw_ref<const T>;
-
-// Template helpers for working with raw_ref<T>.
-template <typename T>
-struct IsRawRef : std::false_type {};
-
-template <typename T, typename I>
-struct IsRawRef<raw_ref<T, I>> : std::true_type {};
-
-template <typename T>
-inline constexpr bool IsRawRefV = IsRawRef<T>::value;
-
-template <typename T>
-struct RemoveRawRef {
-  using type = T;
-};
-
-template <typename T, typename I>
-struct RemoveRawRef<raw_ref<T, I>> {
-  using type = T;
-};
-
-template <typename T>
-using RemoveRawRefT = typename RemoveRawRef<T>::type;
-
-}  // namespace base
-
-using base::raw_ref;
-
-namespace std {
-
-// Override so set/map lookups do not create extra raw_ref. This also
-// allows C++ references to be used for lookup.
-template <typename T, typename RawPtrType>
-struct less<raw_ref<T, RawPtrType>> {
-  using Impl =
-      typename base::raw_ptr_traits::RawPtrTypeToImpl<RawPtrType>::Impl;
-  using is_transparent = void;
-
-  bool operator()(const raw_ref<T, RawPtrType>& lhs,
-                  const raw_ref<T, RawPtrType>& rhs) const {
-    Impl::IncrementLessCountForTest();
-    return lhs < rhs;
-  }
-
-  bool operator()(T& lhs, const raw_ref<T, RawPtrType>& rhs) const {
-    Impl::IncrementLessCountForTest();
-    return lhs < rhs;
-  }
-
-  bool operator()(const raw_ref<T, RawPtrType>& lhs, T& rhs) const {
-    Impl::IncrementLessCountForTest();
-    return lhs < rhs;
-  }
-};
-
-}  // namespace std
-
-#endif  // BASE_ALLOCATOR_PARTITION_ALLOCATOR_POINTERS_RAW_REF_H_
diff --git a/base/fuchsia/scoped_fx_logger.cc b/base/fuchsia/scoped_fx_logger.cc
index da26cad..e415d9d 100644
--- a/base/fuchsia/scoped_fx_logger.cc
+++ b/base/fuchsia/scoped_fx_logger.cc
@@ -5,6 +5,7 @@
 #include "base/fuchsia/scoped_fx_logger.h"
 
 #include <lib/fdio/directory.h>
+#include <stdio.h>
 
 #include "base/command_line.h"
 #include "base/files/file_path.h"
@@ -92,7 +93,8 @@
   for (const auto& tag : tags_) {
     buffer.WriteKeyValue("tag", tag);
   }
-  buffer.FlushRecord();
+  if (!buffer.FlushRecord())
+    fprintf(stderr, "fuchsia_syslog.LogBuffer.FlushRecord() failed\n");
 }
 
 ScopedFxLogger::ScopedFxLogger(std::vector<base::StringPiece> tags,
diff --git a/base/allocator/partition_allocator/pointers/raw_ptr.cc b/base/memory/raw_ptr.cc
similarity index 98%
rename from base/allocator/partition_allocator/pointers/raw_ptr.cc
rename to base/memory/raw_ptr.cc
index 04debf9..276b7d1 100644
--- a/base/allocator/partition_allocator/pointers/raw_ptr.cc
+++ b/base/memory/raw_ptr.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 "base/allocator/partition_allocator/pointers/raw_ptr.h"
+#include "base/memory/raw_ptr.h"
 #include <cstdint>
 
 #include "base/allocator/partition_allocator/dangling_raw_ptr_checks.h"
diff --git a/base/memory/raw_ptr.h b/base/memory/raw_ptr.h
index 971983c..155905fe 100644
--- a/base/memory/raw_ptr.h
+++ b/base/memory/raw_ptr.h
@@ -1,12 +1,1620 @@
-// Copyright 2022 The Chromium Authors
+// Copyright 2020 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #ifndef BASE_MEMORY_RAW_PTR_H_
 #define BASE_MEMORY_RAW_PTR_H_
 
-// Facade header to allow us time to slowly rewrite `raw_ptr` users
-// to refer to the new location.
-#include "base/allocator/partition_allocator/pointers/raw_ptr.h"
+#include <stddef.h>
+#include <stdint.h>
+
+#include <climits>
+#include <cstddef>
+#include <functional>
+#include <type_traits>
+#include <utility>
+
+#include "base/allocator/partition_allocator/partition_alloc_base/compiler_specific.h"
+#include "base/allocator/partition_allocator/partition_alloc_base/component_export.h"
+#include "base/allocator/partition_allocator/partition_alloc_base/debug/debugging_buildflags.h"
+#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
+#include "base/allocator/partition_allocator/partition_alloc_config.h"
+#include "build/build_config.h"
+#include "build/buildflag.h"
+
+#if defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
+#include "base/allocator/partition_allocator/partition_tag.h"
+#include "base/allocator/partition_allocator/partition_tag_types.h"
+#include "base/allocator/partition_allocator/tagging.h"
+#endif  // defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
+
+#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) || \
+    defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
+// USE_BACKUP_REF_PTR implies USE_PARTITION_ALLOC, needed for code under
+// allocator/partition_allocator/ to be built.
+#include "base/allocator/partition_allocator/address_pool_manager_bitmap.h"
+#include "base/allocator/partition_allocator/partition_address_space.h"
+#include "base/allocator/partition_allocator/partition_alloc_constants.h"
+#endif  // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) ||
+        // defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
+
+#if BUILDFLAG(IS_WIN)
+#include "base/allocator/partition_allocator/partition_alloc_base/win/win_handle_types.h"
+#endif
+
+#if BUILDFLAG(USE_PARTITION_ALLOC)
+#include "base/allocator/partition_allocator/partition_alloc_base/check.h"
+// Live implementation of MiraclePtr being built.
+#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) || \
+    BUILDFLAG(USE_ASAN_BACKUP_REF_PTR) ||       \
+    defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
+#define PA_RAW_PTR_CHECK(condition) PA_BASE_CHECK(condition)
+#else
+// No-op implementation of MiraclePtr being built.
+// Note that `PA_BASE_DCHECK()` evaporates from non-DCHECK builds,
+// minimizing impact of generated code.
+#define PA_RAW_PTR_CHECK(condition) PA_BASE_DCHECK(condition)
+#endif  // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) ||
+        // BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
+        // || defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
+#else   // BUILDFLAG(USE_PARTITION_ALLOC
+// Without PartitionAlloc, there's no `PA_BASE_D?CHECK()` implementation
+// available.
+#define PA_RAW_PTR_CHECK(condition)
+#endif  // BUILDFLAG(USE_PARTITION_ALLOC)
+
+namespace cc {
+class Scheduler;
+}
+namespace base::internal {
+class DelayTimerBase;
+}
+namespace content::responsiveness {
+class Calculator;
+}
+
+namespace base {
+
+// NOTE: All methods should be `PA_ALWAYS_INLINE`. raw_ptr is meant to be a
+// lightweight replacement of a raw pointer, hence performance is critical.
+
+// The following types are the different RawPtrType template option possible for
+// a `raw_ptr`:
+// - RawPtrMayDangle disables dangling pointers check when the object is
+//   released.
+// - RawPtrBanDanglingIfSupported may enable dangling pointers check on object
+//   destruction.
+//
+// We describe those types here so that they can be used outside of `raw_ptr` as
+// object markers, and their meaning might vary depending on where those markers
+// are being used. For instance, we are using those in `UnretainedWrapper` to
+// change behavior depending on RawPtrType.
+struct RawPtrMayDangle {};
+struct RawPtrBanDanglingIfSupported {};
+
+struct RawPtrNoOp {};
+
+namespace raw_ptr_traits {
+template <typename T>
+struct RawPtrTypeToImpl;
+}
+
+namespace internal {
+// These classes/structures are part of the raw_ptr implementation.
+// DO NOT USE THESE CLASSES DIRECTLY YOURSELF.
+
+// This type trait verifies a type can be used as a pointer offset.
+//
+// We support pointer offsets in signed (ptrdiff_t) or unsigned (size_t) values.
+// Smaller types are also allowed.
+template <typename Z>
+static constexpr bool offset_type =
+    std::is_integral_v<Z> && sizeof(Z) <= sizeof(ptrdiff_t);
+
+struct RawPtrNoOpImpl {
+  // Wraps a pointer.
+  template <typename T>
+  static PA_ALWAYS_INLINE T* WrapRawPtr(T* ptr) {
+    return ptr;
+  }
+
+  // Notifies the allocator when a wrapped pointer is being removed or replaced.
+  template <typename T>
+  static PA_ALWAYS_INLINE void ReleaseWrappedPtr(T*) {}
+
+  // Unwraps the pointer, while asserting that memory hasn't been freed. The
+  // function is allowed to crash on nullptr.
+  template <typename T>
+  static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForDereference(T* wrapped_ptr) {
+    return wrapped_ptr;
+  }
+
+  // Unwraps the pointer, while asserting that memory hasn't been freed. The
+  // function must handle nullptr gracefully.
+  template <typename T>
+  static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForExtraction(T* wrapped_ptr) {
+    return wrapped_ptr;
+  }
+
+  // Unwraps the pointer, without making an assertion on whether memory was
+  // freed or not.
+  template <typename T>
+  static PA_ALWAYS_INLINE T* UnsafelyUnwrapPtrForComparison(T* wrapped_ptr) {
+    return wrapped_ptr;
+  }
+
+  // Upcasts the wrapped pointer.
+  template <typename To, typename From>
+  static PA_ALWAYS_INLINE constexpr To* Upcast(From* wrapped_ptr) {
+    static_assert(std::is_convertible<From*, To*>::value,
+                  "From must be convertible to To.");
+    // Note, this cast may change the address if upcasting to base that lies in
+    // the middle of the derived object.
+    return wrapped_ptr;
+  }
+
+  // Advance the wrapped pointer by `delta_elems`.
+  template <typename T,
+            typename Z,
+            typename = std::enable_if_t<offset_type<Z>, void>>
+  static PA_ALWAYS_INLINE T* Advance(T* wrapped_ptr, Z delta_elems) {
+    return wrapped_ptr + delta_elems;
+  }
+
+  template <typename T>
+  static PA_ALWAYS_INLINE ptrdiff_t GetDeltaElems(T* wrapped_ptr1,
+                                                  T* wrapped_ptr2) {
+    return wrapped_ptr1 - wrapped_ptr2;
+  }
+
+  // Returns a copy of a wrapped pointer, without making an assertion on whether
+  // memory was freed or not.
+  template <typename T>
+  static PA_ALWAYS_INLINE T* Duplicate(T* wrapped_ptr) {
+    return wrapped_ptr;
+  }
+
+  // This is for accounting only, used by unit tests.
+  static PA_ALWAYS_INLINE void IncrementSwapCountForTest() {}
+  static PA_ALWAYS_INLINE void IncrementLessCountForTest() {}
+  static PA_ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {}
+};
+
+#if defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
+
+constexpr int kValidAddressBits = 48;
+constexpr uintptr_t kAddressMask = (1ull << kValidAddressBits) - 1;
+constexpr int kTagBits = sizeof(uintptr_t) * 8 - kValidAddressBits;
+
+// MTECheckedPtr has no business with the topmost bits reserved for the
+// tag used by true ARM MTE, so we strip it out here.
+constexpr uintptr_t kTagMask =
+    ~kAddressMask & partition_alloc::internal::kPtrUntagMask;
+
+constexpr int kTopBitShift = 63;
+constexpr uintptr_t kTopBit = 1ull << kTopBitShift;
+static_assert(kTopBit << 1 == 0, "kTopBit should really be the top bit");
+static_assert((kTopBit & kTagMask) > 0,
+              "kTopBit bit must be inside the tag region");
+
+// This functionality is outside of MTECheckedPtrImpl, so that it can be
+// overridden by tests.
+struct MTECheckedPtrImplPartitionAllocSupport {
+  // Checks if the necessary support is enabled in PartitionAlloc for `ptr`.
+  template <typename T>
+  static PA_ALWAYS_INLINE bool EnabledForPtr(T* ptr) {
+    // Disambiguation: UntagPtr removes the hardware MTE tag, whereas this class
+    // is responsible for handling the software MTE tag.
+    auto addr = partition_alloc::UntagPtr(ptr);
+    return partition_alloc::IsManagedByPartitionAlloc(addr);
+  }
+
+  // Returns pointer to the tag that protects are pointed by |addr|.
+  static PA_ALWAYS_INLINE void* TagPointer(uintptr_t addr) {
+    return partition_alloc::PartitionTagPointer(addr);
+  }
+};
+
+template <typename PartitionAllocSupport>
+struct MTECheckedPtrImpl {
+  // This implementation assumes that pointers are 64 bits long and at least 16
+  // top bits are unused. The latter is harder to verify statically, but this is
+  // true for all currently supported 64-bit architectures (PA_DCHECK when
+  // wrapping will verify that).
+  static_assert(sizeof(void*) >= 8, "Need 64-bit pointers");
+
+  // Wraps a pointer, and returns its uintptr_t representation.
+  template <typename T>
+  static PA_ALWAYS_INLINE T* WrapRawPtr(T* ptr) {
+    // Disambiguation: UntagPtr removes the hardware MTE tag, whereas this
+    // function is responsible for adding the software MTE tag.
+    uintptr_t addr = partition_alloc::UntagPtr(ptr);
+    PA_BASE_DCHECK(ExtractTag(addr) == 0ull);
+
+    // Return a not-wrapped |addr|, if it's either nullptr or if the protection
+    // for this pointer is disabled.
+    if (!PartitionAllocSupport::EnabledForPtr(ptr)) {
+      return ptr;
+    }
+
+    // Read the tag and place it in the top bits of the address.
+    // Even if PartitionAlloc's tag has less than kTagBits, we'll read
+    // what's given and pad the rest with 0s.
+    static_assert(sizeof(partition_alloc::PartitionTag) * 8 <= kTagBits, "");
+    uintptr_t tag = *(static_cast<volatile partition_alloc::PartitionTag*>(
+        PartitionAllocSupport::TagPointer(addr)));
+    PA_BASE_DCHECK(tag);
+
+    tag <<= kValidAddressBits;
+    addr |= tag;
+    // See the disambiguation comment above.
+    // TODO(kdlee): Ensure that ptr's hardware MTE tag is preserved.
+    // TODO(kdlee): Ensure that hardware and software MTE tags don't conflict.
+    return static_cast<T*>(partition_alloc::internal::TagAddr(addr));
+  }
+
+  // Notifies the allocator when a wrapped pointer is being removed or replaced.
+  // No-op for MTECheckedPtrImpl.
+  template <typename T>
+  static PA_ALWAYS_INLINE void ReleaseWrappedPtr(T*) {}
+
+  // Unwraps the pointer's uintptr_t representation, while asserting that memory
+  // hasn't been freed. The function is allowed to crash on nullptr.
+  template <typename T>
+  static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForDereference(T* wrapped_ptr) {
+    // Disambiguation: UntagPtr removes the hardware MTE tag, whereas this
+    // function is responsible for removing the software MTE tag.
+    uintptr_t wrapped_addr = partition_alloc::UntagPtr(wrapped_ptr);
+    uintptr_t tag = ExtractTag(wrapped_addr);
+    if (tag > 0) {
+      // Read the tag provided by PartitionAlloc.
+      //
+      // Cast to volatile to ensure memory is read. E.g. in a tight loop, the
+      // compiler could cache the value in a register and thus could miss that
+      // another thread freed memory and changed tag.
+      uintptr_t read_tag =
+          *static_cast<volatile partition_alloc::PartitionTag*>(
+              PartitionAllocSupport::TagPointer(ExtractAddress(wrapped_addr)));
+      if (PA_UNLIKELY(tag != read_tag))
+        PA_IMMEDIATE_CRASH();
+      // See the disambiguation comment above.
+      // TODO(kdlee): Ensure that ptr's hardware MTE tag is preserved.
+      // TODO(kdlee): Ensure that hardware and software MTE tags don't conflict.
+      return static_cast<T*>(
+          partition_alloc::internal::TagAddr(ExtractAddress(wrapped_addr)));
+    }
+    return wrapped_ptr;
+  }
+
+  // Unwraps the pointer's uintptr_t representation, while asserting that memory
+  // hasn't been freed. The function must handle nullptr gracefully.
+  template <typename T>
+  static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForExtraction(T* wrapped_ptr) {
+    // SafelyUnwrapPtrForDereference handles nullptr case well.
+    return SafelyUnwrapPtrForDereference(wrapped_ptr);
+  }
+
+  // Unwraps the pointer's uintptr_t representation, without making an assertion
+  // on whether memory was freed or not.
+  template <typename T>
+  static PA_ALWAYS_INLINE T* UnsafelyUnwrapPtrForComparison(T* wrapped_ptr) {
+    return ExtractPtr(wrapped_ptr);
+  }
+
+  // Upcasts the wrapped pointer.
+  template <typename To, typename From>
+  static PA_ALWAYS_INLINE constexpr To* Upcast(From* wrapped_ptr) {
+    static_assert(std::is_convertible<From*, To*>::value,
+                  "From must be convertible to To.");
+
+    // The top-bit tag must not affect the result of upcast.
+    return static_cast<To*>(wrapped_ptr);
+  }
+
+  // Advance the wrapped pointer by `delta_elems`.
+  template <typename T,
+            typename Z,
+            typename = std::enable_if_t<offset_type<Z>, void>>
+  static PA_ALWAYS_INLINE T* Advance(T* wrapped_ptr, Z delta_elems) {
+    return wrapped_ptr + delta_elems;
+  }
+
+  template <typename T>
+  static PA_ALWAYS_INLINE ptrdiff_t GetDeltaElems(T* wrapped_ptr1,
+                                                  T* wrapped_ptr2) {
+    // Ensure that both pointers come from the same allocation.
+    //
+    // Disambiguation: UntagPtr removes the hardware MTE tag, whereas this
+    // class is responsible for handling the software MTE tag.
+    //
+    // MTECheckedPtr doesn't use 0 as a valid tag; depending on which
+    // subtraction operator is called, we may be getting the actual
+    // untagged T* or the wrapped pointer (passed as a T*) in one or
+    // both args. We can only check slot cohabitation when both args
+    // come with tags.
+    const uintptr_t tag1 = ExtractTag(partition_alloc::UntagPtr(wrapped_ptr1));
+    const uintptr_t tag2 = ExtractTag(partition_alloc::UntagPtr(wrapped_ptr2));
+    if (tag1 && tag2) {
+      PA_BASE_CHECK(tag1 == tag2);
+      return wrapped_ptr1 - wrapped_ptr2;
+    }
+
+    // If one or the other arg come untagged, we have to perform the
+    // subtraction entirely without tags.
+    return reinterpret_cast<T*>(
+               ExtractAddress(partition_alloc::UntagPtr(wrapped_ptr1))) -
+           reinterpret_cast<T*>(
+               ExtractAddress(partition_alloc::UntagPtr(wrapped_ptr2)));
+  }
+
+  // Returns a copy of a wrapped pointer, without making an assertion
+  // on whether memory was freed or not.
+  template <typename T>
+  static PA_ALWAYS_INLINE T* Duplicate(T* wrapped_ptr) {
+    return wrapped_ptr;
+  }
+
+  // This is for accounting only, used by unit tests.
+  static PA_ALWAYS_INLINE void IncrementSwapCountForTest() {}
+  static PA_ALWAYS_INLINE void IncrementLessCountForTest() {}
+  static PA_ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {}
+
+ private:
+  static PA_ALWAYS_INLINE uintptr_t ExtractAddress(uintptr_t wrapped_ptr) {
+    return wrapped_ptr & kAddressMask;
+  }
+
+  template <typename T>
+  static PA_ALWAYS_INLINE T* ExtractPtr(T* wrapped_ptr) {
+    // Disambiguation: UntagPtr/TagAddr handle the hardware MTE tag, whereas
+    // this function is responsible for removing the software MTE tag.
+    // TODO(kdlee): Ensure that wrapped_ptr's hardware MTE tag is preserved.
+    // TODO(kdlee): Ensure that hardware and software MTE tags don't conflict.
+    return static_cast<T*>(partition_alloc::internal::TagAddr(
+        ExtractAddress(partition_alloc::UntagPtr(wrapped_ptr))));
+  }
+
+  static PA_ALWAYS_INLINE uintptr_t ExtractTag(uintptr_t wrapped_ptr) {
+    return (wrapped_ptr & kTagMask) >> kValidAddressBits;
+  }
+};
+
+#endif  // defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
+
+#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
+
+#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
+PA_COMPONENT_EXPORT(RAW_PTR)
+void CheckThatAddressIsntWithinFirstPartitionPage(uintptr_t address);
+#endif
+
+template <bool AllowDangling = false>
+struct BackupRefPtrImpl {
+  // Note that `BackupRefPtrImpl` itself is not thread-safe. If multiple threads
+  // modify the same smart pointer object without synchronization, a data race
+  // will occur.
+
+  static PA_ALWAYS_INLINE bool IsSupportedAndNotNull(uintptr_t address) {
+    // There are many situations where the compiler can prove that
+    // `ReleaseWrappedPtr` is called on a value that is always nullptr, but the
+    // way `IsManagedByPartitionAllocBRPPool` is written, the compiler can't
+    // prove that nullptr is not managed by PartitionAlloc; and so the compiler
+    // has to emit a useless check and dead code. To avoid that without making
+    // the runtime check slower, tell the compiler to skip
+    // `IsManagedByPartitionAllocBRPPool` when it can statically determine that
+    // address is nullptr.
+#if PA_HAS_BUILTIN(__builtin_constant_p)
+    if (__builtin_constant_p(address == 0) && (address == 0)) {
+#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
+      PA_BASE_CHECK(
+          !partition_alloc::IsManagedByPartitionAllocBRPPool(address));
+#endif  // BUILDFLAG(PA_DCHECK_IS_ON) ||
+        // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
+      return false;
+    }
+#endif  // PA_HAS_BUILTIN(__builtin_constant_p)
+
+    // This covers the nullptr case, as address 0 is never in any
+    // PartitionAlloc pool.
+    bool is_in_brp_pool =
+        partition_alloc::IsManagedByPartitionAllocBRPPool(address);
+
+    // There may be pointers immediately after the allocation, e.g.
+    //   {
+    //     // Assume this allocation happens outside of PartitionAlloc.
+    //     raw_ptr<T> ptr = new T[20];
+    //     for (size_t i = 0; i < 20; i ++) { ptr++; }
+    //   }
+    //
+    // Such pointers are *not* at risk of accidentally falling into BRP pool,
+    // because:
+    // 1) On 64-bit systems, BRP pool is preceded by a forbidden region.
+    // 2) On 32-bit systems, the guard pages and metadata of super pages in BRP
+    //    pool aren't considered to be part of that pool.
+    //
+    // This allows us to make a stronger assertion that if
+    // IsManagedByPartitionAllocBRPPool returns true for a valid pointer,
+    // it must be at least partition page away from the beginning of a super
+    // page.
+#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
+    if (is_in_brp_pool) {
+      CheckThatAddressIsntWithinFirstPartitionPage(address);
+    }
+#endif
+
+    return is_in_brp_pool;
+  }
+
+#if defined(PA_USE_OOB_POISON)
+  // Out-Of-Bounds (OOB) poison bit is set when the pointer has overflowed by
+  // one byte.
+#if defined(ARCH_CPU_X86_64)
+  // Bit 63 is the only pointer bit that will work as the poison bit across both
+  // LAM48 and LAM57. It also works when all unused linear address bits are
+  // checked for canonicality.
+  static constexpr uintptr_t OOB_POISON_BIT = static_cast<uintptr_t>(1) << 63;
+#else
+  // Avoid ARM's Top-Byte Ignore.
+  static constexpr uintptr_t OOB_POISON_BIT = static_cast<uintptr_t>(1) << 55;
+#endif
+
+  template <typename T>
+  static PA_ALWAYS_INLINE T* UnpoisonPtr(T* ptr) {
+    return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(ptr) &
+                                ~OOB_POISON_BIT);
+  }
+
+  template <typename T>
+  static PA_ALWAYS_INLINE bool IsPtrOOB(T* ptr) {
+    return (reinterpret_cast<uintptr_t>(ptr) & OOB_POISON_BIT) ==
+           OOB_POISON_BIT;
+  }
+
+  template <typename T>
+  static PA_ALWAYS_INLINE T* PoisonOOBPtr(T* ptr) {
+    return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(ptr) |
+                                OOB_POISON_BIT);
+  }
+#else   // PA_USE_OOB_POISON
+  template <typename T>
+  static PA_ALWAYS_INLINE T* UnpoisonPtr(T* ptr) {
+    return ptr;
+  }
+#endif  // PA_USE_OOB_POISON
+
+  // Wraps a pointer.
+  template <typename T>
+  static PA_ALWAYS_INLINE T* WrapRawPtr(T* ptr) {
+    uintptr_t address = partition_alloc::UntagPtr(UnpoisonPtr(ptr));
+    if (IsSupportedAndNotNull(address)) {
+#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
+      PA_BASE_CHECK(ptr != nullptr);
+#endif
+      AcquireInternal(address);
+    } else {
+#if !defined(PA_HAS_64_BITS_POINTERS)
+#if PA_HAS_BUILTIN(__builtin_constant_p)
+      // Similarly to `IsSupportedAndNotNull` above, elide the
+      // `BanSuperPageFromBRPPool` call if the compiler can prove that `address`
+      // is zero since PA won't be able to map anything at that address anyway.
+      bool known_constant_zero =
+          __builtin_constant_p(address == 0) && (address == 0);
+#else   // PA_HAS_BUILTIN(__builtin_constant_p)
+      bool known_constant_zero = false;
+#endif  // PA_HAS_BUILTIN(__builtin_constant_p)
+
+      if (!known_constant_zero) {
+        partition_alloc::internal::AddressPoolManagerBitmap::
+            BanSuperPageFromBRPPool(address);
+      }
+#endif  // !defined(PA_HAS_64_BITS_POINTERS)
+    }
+
+    return ptr;
+  }
+
+  // Notifies the allocator when a wrapped pointer is being removed or replaced.
+  template <typename T>
+  static PA_ALWAYS_INLINE void ReleaseWrappedPtr(T* wrapped_ptr) {
+    uintptr_t address = partition_alloc::UntagPtr(UnpoisonPtr(wrapped_ptr));
+    if (IsSupportedAndNotNull(address)) {
+#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
+      PA_BASE_CHECK(wrapped_ptr != nullptr);
+#endif
+      ReleaseInternal(address);
+    }
+    // We are unable to counteract BanSuperPageFromBRPPool(), called from
+    // WrapRawPtr(). We only use one bit per super-page and, thus can't tell if
+    // there's more than one associated raw_ptr<T> at a given time. The risk of
+    // exhausting the entire address space is minuscule, therefore, we couldn't
+    // resist the perf gain of a single relaxed store (in the above mentioned
+    // function) over much more expensive two CAS operations, which we'd have to
+    // use if we were to un-ban a super-page.
+  }
+
+  // Unwraps the pointer, while asserting that memory hasn't been freed. The
+  // function is allowed to crash on nullptr.
+  template <typename T>
+  static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForDereference(T* wrapped_ptr) {
+#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
+    uintptr_t address = partition_alloc::UntagPtr(wrapped_ptr);
+    if (IsSupportedAndNotNull(address)) {
+      PA_BASE_CHECK(wrapped_ptr != nullptr);
+      PA_BASE_CHECK(IsPointeeAlive(address));
+    }
+#endif
+    return wrapped_ptr;
+  }
+
+  // Unwraps the pointer, while asserting that memory hasn't been freed. The
+  // function must handle nullptr gracefully.
+  template <typename T>
+  static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForExtraction(T* wrapped_ptr) {
+    // This may be used for extracting an end-of-allocation pointer to be used
+    // as an endpoint in an iterative algorithm, so this removes the OOB poison
+    // bit.
+    return UnpoisonPtr(wrapped_ptr);
+  }
+
+  // Unwraps the pointer, without making an assertion on whether memory was
+  // freed or not.
+  template <typename T>
+  static PA_ALWAYS_INLINE T* UnsafelyUnwrapPtrForComparison(T* wrapped_ptr) {
+    return UnpoisonPtr(wrapped_ptr);
+  }
+
+  // Upcasts the wrapped pointer.
+  template <typename To, typename From>
+  static PA_ALWAYS_INLINE constexpr To* Upcast(From* wrapped_ptr) {
+    static_assert(std::is_convertible<From*, To*>::value,
+                  "From must be convertible to To.");
+    // Note, this cast may change the address if upcasting to base that lies in
+    // the middle of the derived object.
+    return wrapped_ptr;
+  }
+
+  // Advance the wrapped pointer by `delta_elems`.
+  template <typename T,
+            typename Z,
+            typename = std::enable_if_t<offset_type<Z>, void>>
+  static PA_ALWAYS_INLINE T* Advance(T* wrapped_ptr, Z delta_elems) {
+#if BUILDFLAG(PUT_REF_COUNT_IN_PREVIOUS_SLOT)
+    T* new_ptr = UnpoisonPtr(wrapped_ptr) + delta_elems;
+    // First check if the new address didn't migrate in/out the BRP pool, and
+    // that it lands within the same allocation. An end-of-allocation address is
+    // ok, too, and that may lead to the pointer being poisoned if the relevant
+    // feature is enabled. These checks add a non-trivial cost, but they're
+    // cheaper and more secure than the previous implementation that rewrapped
+    // the pointer (wrapped the new pointer and unwrapped the old one).
+    //
+    // Note, the value of these checks goes beyond OOB protection. They're
+    // important for integrity of the BRP algorithm. Without these, an attacker
+    // could make the pointer point to another allocation, and cause its
+    // ref-count to go to 0 upon this pointer's destruction, even though there
+    // may be another pointer still pointing to it, thus making it lose the BRP
+    // protection prematurely.
+    uintptr_t address = partition_alloc::UntagPtr(UnpoisonPtr(wrapped_ptr));
+    // TODO(bartekn): Consider adding support for non-BRP pools too (without
+    // removing the cross-pool migration check).
+    if (IsSupportedAndNotNull(address)) {
+      auto ptr_pos_within_alloc =
+          IsValidDelta(address, delta_elems * static_cast<Z>(sizeof(T)));
+      // No need to check that |new_ptr| is in the same pool, as IsValidDeta()
+      // checks that it's within the same allocation, so must be the same pool.
+      PA_BASE_CHECK(ptr_pos_within_alloc !=
+                    partition_alloc::PtrPosWithinAlloc::kFarOOB);
+#if defined(PA_USE_OOB_POISON)
+      if (ptr_pos_within_alloc == partition_alloc::PtrPosWithinAlloc::kAllocEnd)
+        new_ptr = PoisonOOBPtr(new_ptr);
+#endif
+    } else {
+      // Check that the new address didn't migrate into the BRP pool, as it
+      // would result in more pointers pointing to an allocation than its
+      // ref-count reflects.
+      PA_BASE_CHECK(!IsSupportedAndNotNull(partition_alloc::UntagPtr(new_ptr)));
+    }
+    return new_ptr;
+#else   // BUILDFLAG(PUT_REF_COUNT_IN_PREVIOUS_SLOT)
+    // In the "before allocation" mode, on 32-bit, we can run into a problem
+    // that the end-of-allocation address could fall outside of
+    // PartitionAlloc's pools, if this is the last slot of the super page,
+    // thus pointing to the guard page. This means the ref-count won't be
+    // decreased when the pointer is released (leak).
+    //
+    // We could possibly solve it in a few different ways:
+    // - Add the trailing guard page to the pool, but we'd have to think very
+    //   hard if this doesn't create another hole.
+    // - Add an address adjustment to "is in pool?" check, similar as the one in
+    //   PartitionAllocGetSlotStartInBRPPool(), but that seems fragile, not to
+    //   mention adding an extra instruction to an inlined hot path.
+    // - Let the leak happen, since it should a very rare condition.
+    // - Go back to the previous solution of rewrapping the pointer, but that
+    //   had an issue of losing BRP protection in case the pointer ever gets
+    //   shifted back before the end of allocation.
+    //
+    // We decided to cross that bridge once we get there... if we ever get
+    // there. Currently there are no plans to switch back to the "before
+    // allocation" mode.
+    //
+    // This problem doesn't exist in the "previous slot" mode, or any mode that
+    // involves putting extras after the allocation, because the
+    // end-of-allocation address belongs to the same slot.
+    static_assert(false);
+#endif  // BUILDFLAG(PUT_REF_COUNT_IN_PREVIOUS_SLOT)
+  }
+
+  template <typename T>
+  static PA_ALWAYS_INLINE ptrdiff_t GetDeltaElems(T* wrapped_ptr1,
+                                                  T* wrapped_ptr2) {
+    T* unpoisoned_ptr1 = UnpoisonPtr(wrapped_ptr1);
+    T* unpoisoned_ptr2 = UnpoisonPtr(wrapped_ptr2);
+    uintptr_t address1 = partition_alloc::UntagPtr(unpoisoned_ptr1);
+    uintptr_t address2 = partition_alloc::UntagPtr(unpoisoned_ptr2);
+    // Ensure that both pointers are within the same slot, and pool!
+    // TODO(bartekn): Consider adding support for non-BRP pool too.
+    if (IsSupportedAndNotNull(address1)) {
+      PA_BASE_CHECK(IsSupportedAndNotNull(address2));
+      PA_BASE_CHECK(IsValidDelta(address2, address1 - address2) !=
+                    partition_alloc::PtrPosWithinAlloc::kFarOOB);
+    } else {
+      PA_BASE_CHECK(!IsSupportedAndNotNull(address2));
+    }
+    return unpoisoned_ptr1 - unpoisoned_ptr2;
+  }
+
+  // Returns a copy of a wrapped pointer, without making an assertion on whether
+  // memory was freed or not.
+  // This method increments the reference count of the allocation slot.
+  template <typename T>
+  static PA_ALWAYS_INLINE T* Duplicate(T* wrapped_ptr) {
+    return WrapRawPtr(wrapped_ptr);
+  }
+
+  // Report the current wrapped pointer if pointee isn't alive anymore.
+  template <typename T>
+  static PA_ALWAYS_INLINE void ReportIfDangling(T* wrapped_ptr) {
+    ReportIfDanglingInternal(partition_alloc::UntagPtr(wrapped_ptr));
+  }
+
+  // This is for accounting only, used by unit tests.
+  static PA_ALWAYS_INLINE void IncrementSwapCountForTest() {}
+  static PA_ALWAYS_INLINE void IncrementLessCountForTest() {}
+  static PA_ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {}
+
+ private:
+  // We've evaluated several strategies (inline nothing, various parts, or
+  // everything in |Wrap()| and |Release()|) using the Speedometer2 benchmark
+  // to measure performance. The best results were obtained when only the
+  // lightweight |IsManagedByPartitionAllocBRPPool()| check was inlined.
+  // Therefore, we've extracted the rest into the functions below and marked
+  // them as PA_NOINLINE to prevent unintended LTO effects.
+  static PA_COMPONENT_EXPORT(RAW_PTR) PA_NOINLINE
+      void AcquireInternal(uintptr_t address);
+  static PA_COMPONENT_EXPORT(RAW_PTR) PA_NOINLINE
+      void ReleaseInternal(uintptr_t address);
+  static PA_COMPONENT_EXPORT(RAW_PTR) PA_NOINLINE
+      bool IsPointeeAlive(uintptr_t address);
+  static PA_COMPONENT_EXPORT(RAW_PTR) PA_NOINLINE
+      void ReportIfDanglingInternal(uintptr_t address);
+  template <typename Z, typename = std::enable_if_t<offset_type<Z>, void>>
+  static PA_ALWAYS_INLINE partition_alloc::PtrPosWithinAlloc IsValidDelta(
+      uintptr_t address,
+      Z delta_in_bytes) {
+    if constexpr (std::is_signed_v<Z>)
+      return IsValidSignedDelta(address, ptrdiff_t{delta_in_bytes});
+    else
+      return IsValidUnsignedDelta(address, size_t{delta_in_bytes});
+  }
+  static PA_COMPONENT_EXPORT(RAW_PTR)
+      PA_NOINLINE partition_alloc::PtrPosWithinAlloc
+      IsValidSignedDelta(uintptr_t address, ptrdiff_t delta_in_bytes);
+  static PA_COMPONENT_EXPORT(RAW_PTR)
+      PA_NOINLINE partition_alloc::PtrPosWithinAlloc
+      IsValidUnsignedDelta(uintptr_t address, size_t delta_in_bytes);
+};
+
+#endif  // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
+
+#if BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
+// Implementation that allows us to detect BackupRefPtr problems in ASan builds.
+struct AsanBackupRefPtrImpl {
+  // Wraps a pointer.
+  template <typename T>
+  static PA_ALWAYS_INLINE T* WrapRawPtr(T* ptr) {
+    AsanCheckIfValidInstantiation(ptr);
+    return ptr;
+  }
+
+  // Notifies the allocator when a wrapped pointer is being removed or replaced.
+  template <typename T>
+  static PA_ALWAYS_INLINE void ReleaseWrappedPtr(T*) {}
+
+  // Unwraps the pointer, while asserting that memory hasn't been freed. The
+  // function is allowed to crash on nullptr.
+  template <typename T>
+  static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForDereference(T* wrapped_ptr) {
+    AsanCheckIfValidDereference(wrapped_ptr);
+    return wrapped_ptr;
+  }
+
+  // Unwraps the pointer, while asserting that memory hasn't been freed. The
+  // function must handle nullptr gracefully.
+  template <typename T>
+  static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForExtraction(T* wrapped_ptr) {
+    AsanCheckIfValidExtraction(wrapped_ptr);
+    return wrapped_ptr;
+  }
+
+  // Unwraps the pointer, without making an assertion on whether memory was
+  // freed or not.
+  template <typename T>
+  static PA_ALWAYS_INLINE T* UnsafelyUnwrapPtrForComparison(T* wrapped_ptr) {
+    return wrapped_ptr;
+  }
+
+  // Upcasts the wrapped pointer.
+  template <typename To, typename From>
+  static PA_ALWAYS_INLINE constexpr To* Upcast(From* wrapped_ptr) {
+    static_assert(std::is_convertible<From*, To*>::value,
+                  "From must be convertible to To.");
+    // Note, this cast may change the address if upcasting to base that lies in
+    // the middle of the derived object.
+    return wrapped_ptr;
+  }
+
+  // Advance the wrapped pointer by `delta_elems`.
+  template <typename T,
+            typename Z,
+            typename = std::enable_if_t<offset_type<Z>, void>>
+  static PA_ALWAYS_INLINE T* Advance(T* wrapped_ptr, Z delta_elems) {
+    return wrapped_ptr + delta_elems;
+  }
+
+  template <typename T>
+  static PA_ALWAYS_INLINE ptrdiff_t GetDeltaElems(T* wrapped_ptr1,
+                                                  T* wrapped_ptr2) {
+    return wrapped_ptr1 - wrapped_ptr2;
+  }
+
+  // Returns a copy of a wrapped pointer, without making an assertion on whether
+  // memory was freed or not.
+  template <typename T>
+  static PA_ALWAYS_INLINE T* Duplicate(T* wrapped_ptr) {
+    return wrapped_ptr;
+  }
+
+  // This is for accounting only, used by unit tests.
+  static PA_ALWAYS_INLINE void IncrementSwapCountForTest() {}
+  static PA_ALWAYS_INLINE void IncrementLessCountForTest() {}
+  static PA_ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {}
+
+ private:
+  static PA_COMPONENT_EXPORT(RAW_PTR) PA_NOINLINE
+      void AsanCheckIfValidInstantiation(void const volatile* ptr);
+  static PA_COMPONENT_EXPORT(RAW_PTR) PA_NOINLINE
+      void AsanCheckIfValidDereference(void const volatile* ptr);
+  static PA_COMPONENT_EXPORT(RAW_PTR) PA_NOINLINE
+      void AsanCheckIfValidExtraction(void const volatile* ptr);
+};
+#endif  // BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
+
+template <class Super>
+struct RawPtrCountingImplWrapperForTest
+    : public raw_ptr_traits::RawPtrTypeToImpl<Super>::Impl {
+  using SuperImpl = typename raw_ptr_traits::RawPtrTypeToImpl<Super>::Impl;
+  template <typename T>
+  static PA_ALWAYS_INLINE T* WrapRawPtr(T* ptr) {
+    ++wrap_raw_ptr_cnt;
+    return SuperImpl::WrapRawPtr(ptr);
+  }
+
+  template <typename T>
+  static PA_ALWAYS_INLINE void ReleaseWrappedPtr(T* ptr) {
+    ++release_wrapped_ptr_cnt;
+    SuperImpl::ReleaseWrappedPtr(ptr);
+  }
+
+  template <typename T>
+  static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForDereference(T* wrapped_ptr) {
+    ++get_for_dereference_cnt;
+    return SuperImpl::SafelyUnwrapPtrForDereference(wrapped_ptr);
+  }
+
+  template <typename T>
+  static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForExtraction(T* wrapped_ptr) {
+    ++get_for_extraction_cnt;
+    return SuperImpl::SafelyUnwrapPtrForExtraction(wrapped_ptr);
+  }
+
+  template <typename T>
+  static PA_ALWAYS_INLINE T* UnsafelyUnwrapPtrForComparison(T* wrapped_ptr) {
+    ++get_for_comparison_cnt;
+    return SuperImpl::UnsafelyUnwrapPtrForComparison(wrapped_ptr);
+  }
+
+  static PA_ALWAYS_INLINE void IncrementSwapCountForTest() {
+    ++wrapped_ptr_swap_cnt;
+  }
+
+  static PA_ALWAYS_INLINE void IncrementLessCountForTest() {
+    ++wrapped_ptr_less_cnt;
+  }
+
+  static PA_ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {
+    ++pointer_to_member_operator_cnt;
+  }
+
+  static void ClearCounters() {
+    wrap_raw_ptr_cnt = 0;
+    release_wrapped_ptr_cnt = 0;
+    get_for_dereference_cnt = 0;
+    get_for_extraction_cnt = 0;
+    get_for_comparison_cnt = 0;
+    wrapped_ptr_swap_cnt = 0;
+    wrapped_ptr_less_cnt = 0;
+    pointer_to_member_operator_cnt = 0;
+  }
+
+  static inline int wrap_raw_ptr_cnt = INT_MIN;
+  static inline int release_wrapped_ptr_cnt = INT_MIN;
+  static inline int get_for_dereference_cnt = INT_MIN;
+  static inline int get_for_extraction_cnt = INT_MIN;
+  static inline int get_for_comparison_cnt = INT_MIN;
+  static inline int wrapped_ptr_swap_cnt = INT_MIN;
+  static inline int wrapped_ptr_less_cnt = INT_MIN;
+  static inline int pointer_to_member_operator_cnt = INT_MIN;
+};
+
+}  // namespace internal
+
+namespace raw_ptr_traits {
+
+// IsSupportedType<T>::value answers whether raw_ptr<T> 1) compiles and 2) is
+// always safe at runtime.  Templates that may end up using `raw_ptr<T>` should
+// use IsSupportedType to ensure that raw_ptr is not used with unsupported
+// types.  As an example, see how base::internal::StorageTraits uses
+// IsSupportedType as a condition for using base::internal::UnretainedWrapper
+// (which has a `ptr_` field that will become `raw_ptr<T>` after the Big
+// Rewrite).
+template <typename T, typename SFINAE = void>
+struct IsSupportedType {
+  static constexpr bool value = true;
+};
+
+// raw_ptr<T> is not compatible with function pointer types. Also, they don't
+// even need the raw_ptr protection, because they don't point on heap.
+template <typename T>
+struct IsSupportedType<T, std::enable_if_t<std::is_function<T>::value>> {
+  static constexpr bool value = false;
+};
+
+// This section excludes some types from raw_ptr<T> to avoid them from being
+// used inside base::Unretained in performance sensitive places. These were
+// identified from sampling profiler data. See crbug.com/1287151 for more info.
+template <>
+struct IsSupportedType<cc::Scheduler> {
+  static constexpr bool value = false;
+};
+template <>
+struct IsSupportedType<base::internal::DelayTimerBase> {
+  static constexpr bool value = false;
+};
+template <>
+struct IsSupportedType<content::responsiveness::Calculator> {
+  static constexpr bool value = false;
+};
+
+// IsRawPtrCountingImpl<T>::value answers whether T is a specialization of
+// RawPtrCountingImplWrapperForTest, to know whether Impl is for testing
+// purposes.
+template <typename T>
+struct IsRawPtrCountingImpl : std::false_type {};
+
+template <typename T>
+struct IsRawPtrCountingImpl<internal::RawPtrCountingImplWrapperForTest<T>>
+    : std::true_type {};
+
+#if __OBJC__
+// raw_ptr<T> is not compatible with pointers to Objective-C classes for a
+// multitude of reasons. They may fail to compile in many cases, and wouldn't
+// work well with tagged pointers. Anyway, Objective-C objects have their own
+// way of tracking lifespan, hence don't need the raw_ptr protection as much.
+//
+// Such pointers are detected by checking if they're convertible to |id| type.
+template <typename T>
+struct IsSupportedType<T,
+                       std::enable_if_t<std::is_convertible<T*, id>::value>> {
+  static constexpr bool value = false;
+};
+#endif  // __OBJC__
+
+#if BUILDFLAG(IS_WIN)
+// raw_ptr<HWND__> is unsafe at runtime - if the handle happens to also
+// represent a valid pointer into a PartitionAlloc-managed region then it can
+// lead to manipulating random memory when treating it as BackupRefPtr
+// ref-count.  See also https://crbug.com/1262017.
+//
+// TODO(https://crbug.com/1262017): Cover other handle types like HANDLE,
+// HLOCAL, HINTERNET, or HDEVINFO.  Maybe we should avoid using raw_ptr<T> when
+// T=void (as is the case in these handle types).  OTOH, explicit,
+// non-template-based raw_ptr<void> should be allowed.  Maybe this can be solved
+// by having 2 traits: IsPointeeAlwaysSafe (to be used in templates) and
+// IsPointeeUsuallySafe (to be used in the static_assert in raw_ptr).  The
+// upside of this approach is that it will safely handle base::Bind closing over
+// HANDLE.  The downside of this approach is that base::Bind closing over a
+// void* pointer will not get UaF protection.
+#define PA_WINDOWS_HANDLE_TYPE(name)       \
+  template <>                              \
+  struct IsSupportedType<name##__, void> { \
+    static constexpr bool value = false;   \
+  };
+#include "base/allocator/partition_allocator/partition_alloc_base/win/win_handle_types_list.inc"
+#undef PA_WINDOWS_HANDLE_TYPE
+#endif
+
+template <typename T>
+struct RawPtrTypeToImpl {};
+
+template <typename T>
+struct RawPtrTypeToImpl<internal::RawPtrCountingImplWrapperForTest<T>> {
+  using Impl = internal::RawPtrCountingImplWrapperForTest<T>;
+};
+
+template <>
+struct RawPtrTypeToImpl<RawPtrMayDangle> {
+#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
+  using Impl = internal::BackupRefPtrImpl</*AllowDangling=*/true>;
+#elif BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
+  using Impl = internal::AsanBackupRefPtrImpl;
+#elif defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
+  using Impl = internal::MTECheckedPtrImpl<
+      internal::MTECheckedPtrImplPartitionAllocSupport>;
+#else
+  using Impl = internal::RawPtrNoOpImpl;
+#endif
+};
+
+template <>
+struct RawPtrTypeToImpl<RawPtrBanDanglingIfSupported> {
+#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
+  using Impl = internal::BackupRefPtrImpl</*AllowDangling=*/false>;
+#elif BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
+  using Impl = internal::AsanBackupRefPtrImpl;
+#elif defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
+  using Impl = internal::MTECheckedPtrImpl<
+      internal::MTECheckedPtrImplPartitionAllocSupport>;
+#else
+  using Impl = internal::RawPtrNoOpImpl;
+#endif
+};
+
+template <>
+struct RawPtrTypeToImpl<RawPtrNoOp> {
+  using Impl = internal::RawPtrNoOpImpl;
+};
+
+}  // namespace raw_ptr_traits
+
+// `raw_ptr<T>` is a non-owning smart pointer that has improved memory-safety
+// over raw pointers.  It behaves just like a raw pointer on platforms where
+// USE_BACKUP_REF_PTR is off, and almost like one when it's on (the main
+// difference is that it's zero-initialized and cleared on destruction and
+// move). Unlike `std::unique_ptr<T>`, `base::scoped_refptr<T>`, etc., it
+// doesn’t manage ownership or lifetime of an allocated object - you are still
+// responsible for freeing the object when no longer used, just as you would
+// with a raw C++ pointer.
+//
+// Compared to a raw C++ pointer, on platforms where USE_BACKUP_REF_PTR is on,
+// `raw_ptr<T>` incurs additional performance overhead for initialization,
+// destruction, and assignment (including `ptr++` and `ptr += ...`).  There is
+// no overhead when dereferencing a pointer.
+//
+// `raw_ptr<T>` is beneficial for security, because it can prevent a significant
+// percentage of Use-after-Free (UaF) bugs from being exploitable.  `raw_ptr<T>`
+// has limited impact on stability - dereferencing a dangling pointer remains
+// Undefined Behavior.  Note that the security protection is not yet enabled by
+// default.
+//
+// raw_ptr<T> is marked as [[gsl::Pointer]] which allows the compiler to catch
+// some bugs where the raw_ptr holds a dangling pointer to a temporary object.
+// However the [[gsl::Pointer]] analysis expects that such types do not have a
+// non-default move constructor/assignment. Thus, it's possible to get an error
+// where the pointer is not actually dangling, and have to work around the
+// compiler. We have not managed to construct such an example in Chromium yet.
+
+using DefaultRawPtrType = RawPtrBanDanglingIfSupported;
+
+template <typename T, typename RawPtrType = DefaultRawPtrType>
+class PA_TRIVIAL_ABI PA_GSL_POINTER raw_ptr {
+  using Impl = typename raw_ptr_traits::RawPtrTypeToImpl<RawPtrType>::Impl;
+  using DanglingRawPtr = std::conditional_t<
+      raw_ptr_traits::IsRawPtrCountingImpl<Impl>::value,
+      raw_ptr<T, internal::RawPtrCountingImplWrapperForTest<RawPtrMayDangle>>,
+      raw_ptr<T, RawPtrMayDangle>>;
+
+#if !BUILDFLAG(USE_PARTITION_ALLOC)
+  // See comment at top about `PA_RAW_PTR_CHECK()`.
+  static_assert(std::is_same_v<Impl, internal::RawPtrNoOpImpl>);
+#endif  // !BUILDFLAG(USE_PARTITION_ALLOC)
+
+ public:
+  static_assert(raw_ptr_traits::IsSupportedType<T>::value,
+                "raw_ptr<T> doesn't work with this kind of pointee type T");
+
+#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
+  // BackupRefPtr requires a non-trivial default constructor, destructor, etc.
+  constexpr PA_ALWAYS_INLINE raw_ptr() noexcept : wrapped_ptr_(nullptr) {}
+
+  PA_ALWAYS_INLINE raw_ptr(const raw_ptr& p) noexcept
+      : wrapped_ptr_(Impl::Duplicate(p.wrapped_ptr_)) {}
+
+  PA_ALWAYS_INLINE raw_ptr(raw_ptr&& p) noexcept {
+    wrapped_ptr_ = p.wrapped_ptr_;
+    p.wrapped_ptr_ = nullptr;
+  }
+
+  PA_ALWAYS_INLINE raw_ptr& operator=(const raw_ptr& p) noexcept {
+    // Duplicate before releasing, in case the pointer is assigned to itself.
+    //
+    // Unlike the move version of this operator, don't add |this != &p| branch,
+    // for performance reasons. Even though Duplicate() is not cheap, we
+    // practically never assign a raw_ptr<T> to itself. We suspect that a
+    // cumulative cost of a conditional branch, even if always correctly
+    // predicted, would exceed that.
+    T* new_ptr = Impl::Duplicate(p.wrapped_ptr_);
+    Impl::ReleaseWrappedPtr(wrapped_ptr_);
+    wrapped_ptr_ = new_ptr;
+    return *this;
+  }
+
+  PA_ALWAYS_INLINE raw_ptr& operator=(raw_ptr&& p) noexcept {
+    // Unlike the the copy version of this operator, this branch is necessaty
+    // for correctness.
+    if (PA_LIKELY(this != &p)) {
+      Impl::ReleaseWrappedPtr(wrapped_ptr_);
+      wrapped_ptr_ = p.wrapped_ptr_;
+      p.wrapped_ptr_ = nullptr;
+    }
+    return *this;
+  }
+
+  PA_ALWAYS_INLINE ~raw_ptr() noexcept {
+    Impl::ReleaseWrappedPtr(wrapped_ptr_);
+    // Work around external issues where raw_ptr is used after destruction.
+    wrapped_ptr_ = nullptr;
+  }
+
+#else  // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
+
+  // raw_ptr can be trivially default constructed (leaving |wrapped_ptr_|
+  // uninitialized).  This is needed for compatibility with raw pointers.
+  //
+  // TODO(lukasza): Always initialize |wrapped_ptr_|.  Fix resulting build
+  // errors.  Analyze performance impact.
+  constexpr PA_ALWAYS_INLINE raw_ptr() noexcept = default;
+
+  // In addition to nullptr_t ctor above, raw_ptr needs to have these
+  // as |=default| or |constexpr| to avoid hitting -Wglobal-constructors in
+  // cases like this:
+  //     struct SomeStruct { int int_field; raw_ptr<int> ptr_field; };
+  //     SomeStruct g_global_var = { 123, nullptr };
+  PA_ALWAYS_INLINE raw_ptr(const raw_ptr&) noexcept = default;
+  PA_ALWAYS_INLINE raw_ptr(raw_ptr&&) noexcept = default;
+  PA_ALWAYS_INLINE raw_ptr& operator=(const raw_ptr&) noexcept = default;
+  PA_ALWAYS_INLINE raw_ptr& operator=(raw_ptr&&) noexcept = default;
+
+  PA_ALWAYS_INLINE ~raw_ptr() noexcept = default;
+
+#endif  // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
+
+  // Deliberately implicit, because raw_ptr is supposed to resemble raw ptr.
+  // NOLINTNEXTLINE(google-explicit-constructor)
+  constexpr PA_ALWAYS_INLINE raw_ptr(std::nullptr_t) noexcept
+      : wrapped_ptr_(nullptr) {}
+
+  // Deliberately implicit, because raw_ptr is supposed to resemble raw ptr.
+  // NOLINTNEXTLINE(google-explicit-constructor)
+  PA_ALWAYS_INLINE raw_ptr(T* p) noexcept : wrapped_ptr_(Impl::WrapRawPtr(p)) {}
+
+  // Deliberately implicit in order to support implicit upcast.
+  template <typename U,
+            typename Unused = std::enable_if_t<
+                std::is_convertible<U*, T*>::value &&
+                !std::is_void<typename std::remove_cv<T>::type>::value>>
+  // NOLINTNEXTLINE(google-explicit-constructor)
+  PA_ALWAYS_INLINE raw_ptr(const raw_ptr<U, RawPtrType>& ptr) noexcept
+      : wrapped_ptr_(
+            Impl::Duplicate(Impl::template Upcast<T, U>(ptr.wrapped_ptr_))) {}
+  // Deliberately implicit in order to support implicit upcast.
+  template <typename U,
+            typename Unused = std::enable_if_t<
+                std::is_convertible<U*, T*>::value &&
+                !std::is_void<typename std::remove_cv<T>::type>::value>>
+  // NOLINTNEXTLINE(google-explicit-constructor)
+  PA_ALWAYS_INLINE raw_ptr(raw_ptr<U, RawPtrType>&& ptr) noexcept
+      : wrapped_ptr_(Impl::template Upcast<T, U>(ptr.wrapped_ptr_)) {
+#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
+    ptr.wrapped_ptr_ = nullptr;
+#endif
+  }
+
+  PA_ALWAYS_INLINE raw_ptr& operator=(std::nullptr_t) noexcept {
+    Impl::ReleaseWrappedPtr(wrapped_ptr_);
+    wrapped_ptr_ = nullptr;
+    return *this;
+  }
+  PA_ALWAYS_INLINE raw_ptr& operator=(T* p) noexcept {
+    Impl::ReleaseWrappedPtr(wrapped_ptr_);
+    wrapped_ptr_ = Impl::WrapRawPtr(p);
+    return *this;
+  }
+
+  // Upcast assignment
+  template <typename U,
+            typename Unused = std::enable_if_t<
+                std::is_convertible<U*, T*>::value &&
+                !std::is_void<typename std::remove_cv<T>::type>::value>>
+  PA_ALWAYS_INLINE raw_ptr& operator=(
+      const raw_ptr<U, RawPtrType>& ptr) noexcept {
+    // Make sure that pointer isn't assigned to itself (look at pointer address,
+    // not its value).
+#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
+    PA_RAW_PTR_CHECK(reinterpret_cast<uintptr_t>(this) !=
+                     reinterpret_cast<uintptr_t>(&ptr));
+#endif
+    Impl::ReleaseWrappedPtr(wrapped_ptr_);
+    wrapped_ptr_ =
+        Impl::Duplicate(Impl::template Upcast<T, U>(ptr.wrapped_ptr_));
+    return *this;
+  }
+  template <typename U,
+            typename Unused = std::enable_if_t<
+                std::is_convertible<U*, T*>::value &&
+                !std::is_void<typename std::remove_cv<T>::type>::value>>
+  PA_ALWAYS_INLINE raw_ptr& operator=(raw_ptr<U, RawPtrType>&& ptr) noexcept {
+    // Make sure that pointer isn't assigned to itself (look at pointer address,
+    // not its value).
+#if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
+    PA_RAW_PTR_CHECK(reinterpret_cast<uintptr_t>(this) !=
+                     reinterpret_cast<uintptr_t>(&ptr));
+#endif
+    Impl::ReleaseWrappedPtr(wrapped_ptr_);
+    wrapped_ptr_ = Impl::template Upcast<T, U>(ptr.wrapped_ptr_);
+#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
+    ptr.wrapped_ptr_ = nullptr;
+#endif
+    return *this;
+  }
+
+  // Avoid using. The goal of raw_ptr is to be as close to raw pointer as
+  // possible, so use it only if absolutely necessary (e.g. for const_cast).
+  PA_ALWAYS_INLINE T* get() const { return GetForExtraction(); }
+
+  explicit PA_ALWAYS_INLINE operator bool() const { return !!wrapped_ptr_; }
+
+  template <typename U = T,
+            typename Unused = std::enable_if_t<
+                !std::is_void<typename std::remove_cv<U>::type>::value>>
+  PA_ALWAYS_INLINE U& operator*() const {
+    return *GetForDereference();
+  }
+  PA_ALWAYS_INLINE T* operator->() const { return GetForDereference(); }
+
+  // Disables `(my_raw_ptr->*pmf)(...)` as a workaround for
+  // the ICE in GCC parsing the code, reported at
+  // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103455
+  template <typename PMF>
+  void operator->*(PMF) const = delete;
+
+  // Deliberately implicit, because raw_ptr is supposed to resemble raw ptr.
+  // NOLINTNEXTLINE(runtime/explicit)
+  PA_ALWAYS_INLINE operator T*() const { return GetForExtraction(); }
+  template <typename U>
+  explicit PA_ALWAYS_INLINE operator U*() const {
+    // This operator may be invoked from static_cast, meaning the types may not
+    // be implicitly convertible, hence the need for static_cast here.
+    return static_cast<U*>(GetForExtraction());
+  }
+
+  PA_ALWAYS_INLINE raw_ptr& operator++() {
+    wrapped_ptr_ = Impl::Advance(wrapped_ptr_, 1);
+    return *this;
+  }
+  PA_ALWAYS_INLINE raw_ptr& operator--() {
+    wrapped_ptr_ = Impl::Advance(wrapped_ptr_, -1);
+    return *this;
+  }
+  PA_ALWAYS_INLINE raw_ptr operator++(int /* post_increment */) {
+    raw_ptr result = *this;
+    ++(*this);
+    return result;
+  }
+  PA_ALWAYS_INLINE raw_ptr operator--(int /* post_decrement */) {
+    raw_ptr result = *this;
+    --(*this);
+    return result;
+  }
+  template <typename Z, typename = std::enable_if_t<internal::offset_type<Z>>>
+  PA_ALWAYS_INLINE raw_ptr& operator+=(Z delta_elems) {
+    wrapped_ptr_ = Impl::Advance(wrapped_ptr_, delta_elems);
+    return *this;
+  }
+  template <typename Z, typename = std::enable_if_t<internal::offset_type<Z>>>
+  PA_ALWAYS_INLINE raw_ptr& operator-=(Z delta_elems) {
+    return *this += -delta_elems;
+  }
+
+  template <typename Z, typename = std::enable_if_t<internal::offset_type<Z>>>
+  friend PA_ALWAYS_INLINE raw_ptr operator+(const raw_ptr& p, Z delta_elems) {
+    raw_ptr result = p;
+    return result += delta_elems;
+  }
+  template <typename Z, typename = std::enable_if_t<internal::offset_type<Z>>>
+  friend PA_ALWAYS_INLINE raw_ptr operator-(const raw_ptr& p, Z delta_elems) {
+    raw_ptr result = p;
+    return result -= delta_elems;
+  }
+  friend PA_ALWAYS_INLINE ptrdiff_t operator-(const raw_ptr& p1,
+                                              const raw_ptr& p2) {
+    return Impl::GetDeltaElems(p1.wrapped_ptr_, p2.wrapped_ptr_);
+  }
+  friend PA_ALWAYS_INLINE ptrdiff_t operator-(T* p1, const raw_ptr& p2) {
+    return Impl::GetDeltaElems(p1, p2.wrapped_ptr_);
+  }
+  friend PA_ALWAYS_INLINE ptrdiff_t operator-(const raw_ptr& p1, T* p2) {
+    return Impl::GetDeltaElems(p1.wrapped_ptr_, p2);
+  }
+
+  // Stop referencing the underlying pointer and free its memory. Compared to
+  // raw delete calls, this avoids the raw_ptr to be temporarily dangling
+  // during the free operation, which will lead to taking the slower path that
+  // involves quarantine.
+  PA_ALWAYS_INLINE void ClearAndDelete() noexcept {
+    delete GetForExtractionAndReset();
+  }
+  PA_ALWAYS_INLINE void ClearAndDeleteArray() noexcept {
+    delete[] GetForExtractionAndReset();
+  }
+
+  // Clear the underlying pointer and return another raw_ptr instance
+  // that is allowed to dangle.
+  // This can be useful in cases such as:
+  // ```
+  //  ptr.ExtractAsDangling()->SelfDestroy();
+  // ```
+  // ```
+  //  c_style_api_do_something_and_destroy(ptr.ExtractAsDangling());
+  // ```
+  // NOTE, avoid using this method as it indicates an error-prone memory
+  // ownership pattern. If possible, use smart pointers like std::unique_ptr<>
+  // instead of raw_ptr<>.
+  // If you have to use it, avoid saving the return value in a long-lived
+  // variable (or worse, a field)! It's meant to be used as a temporary, to be
+  // passed into a cleanup & freeing function, and destructed at the end of the
+  // statement.
+  PA_ALWAYS_INLINE DanglingRawPtr ExtractAsDangling() noexcept {
+    if constexpr (std::is_same_v<
+                      typename std::remove_reference<decltype(*this)>::type,
+                      DanglingRawPtr>) {
+      DanglingRawPtr res(std::move(*this));
+      // Not all implementation clear the source pointer on move, so do it
+      // here just in case. Should be cheap.
+      operator=(nullptr);
+      return res;
+    } else {
+      T* ptr = GetForExtraction();
+      DanglingRawPtr res(ptr);
+      operator=(nullptr);
+      return res;
+    }
+  }
+
+  // Comparison operators between raw_ptr and raw_ptr<U>/U*/std::nullptr_t.
+  // Strictly speaking, it is not necessary to provide these: the compiler can
+  // use the conversion operator implicitly to allow comparisons to fall back to
+  // comparisons between raw pointers. However, `operator T*`/`operator U*` may
+  // perform safety checks with a higher runtime cost, so to avoid this, provide
+  // explicit comparison operators for all combinations of parameters.
+
+  // Comparisons between `raw_ptr`s. This unusual declaration and separate
+  // definition below is because `GetForComparison()` is a private method. The
+  // more conventional approach of defining a comparison operator between
+  // `raw_ptr` and `raw_ptr<U>` in the friend declaration itself does not work,
+  // because a comparison operator defined inline would not be allowed to call
+  // `raw_ptr<U>`'s private `GetForComparison()` method.
+  template <typename U, typename V, typename I>
+  friend PA_ALWAYS_INLINE bool operator==(const raw_ptr<U, I>& lhs,
+                                          const raw_ptr<V, I>& rhs);
+  template <typename U>
+  friend PA_ALWAYS_INLINE bool operator!=(const raw_ptr& lhs,
+                                          const raw_ptr<U, Impl>& rhs) {
+    return !(lhs == rhs);
+  }
+  template <typename U, typename V, typename I>
+  friend PA_ALWAYS_INLINE bool operator<(const raw_ptr<U, I>& lhs,
+                                         const raw_ptr<V, I>& rhs);
+  template <typename U, typename V, typename I>
+  friend PA_ALWAYS_INLINE bool operator>(const raw_ptr<U, I>& lhs,
+                                         const raw_ptr<V, I>& rhs);
+  template <typename U, typename V, typename I>
+  friend PA_ALWAYS_INLINE bool operator<=(const raw_ptr<U, I>& lhs,
+                                          const raw_ptr<V, I>& rhs);
+  template <typename U, typename V, typename I>
+  friend PA_ALWAYS_INLINE bool operator>=(const raw_ptr<U, I>& lhs,
+                                          const raw_ptr<V, I>& rhs);
+
+  // Comparisons with U*. These operators also handle the case where the RHS is
+  // T*.
+  template <typename U>
+  friend PA_ALWAYS_INLINE bool operator==(const raw_ptr& lhs, U* rhs) {
+    return lhs.GetForComparison() == rhs;
+  }
+  template <typename U>
+  friend PA_ALWAYS_INLINE bool operator!=(const raw_ptr& lhs, U* rhs) {
+    return !(lhs == rhs);
+  }
+  template <typename U>
+  friend PA_ALWAYS_INLINE bool operator==(U* lhs, const raw_ptr& rhs) {
+    return rhs == lhs;  // Reverse order to call the operator above.
+  }
+  template <typename U>
+  friend PA_ALWAYS_INLINE bool operator!=(U* lhs, const raw_ptr& rhs) {
+    return rhs != lhs;  // Reverse order to call the operator above.
+  }
+  template <typename U>
+  friend PA_ALWAYS_INLINE bool operator<(const raw_ptr& lhs, U* rhs) {
+    return lhs.GetForComparison() < rhs;
+  }
+  template <typename U>
+  friend PA_ALWAYS_INLINE bool operator<=(const raw_ptr& lhs, U* rhs) {
+    return lhs.GetForComparison() <= rhs;
+  }
+  template <typename U>
+  friend PA_ALWAYS_INLINE bool operator>(const raw_ptr& lhs, U* rhs) {
+    return lhs.GetForComparison() > rhs;
+  }
+  template <typename U>
+  friend PA_ALWAYS_INLINE bool operator>=(const raw_ptr& lhs, U* rhs) {
+    return lhs.GetForComparison() >= rhs;
+  }
+  template <typename U>
+  friend PA_ALWAYS_INLINE bool operator<(U* lhs, const raw_ptr& rhs) {
+    return lhs < rhs.GetForComparison();
+  }
+  template <typename U>
+  friend PA_ALWAYS_INLINE bool operator<=(U* lhs, const raw_ptr& rhs) {
+    return lhs <= rhs.GetForComparison();
+  }
+  template <typename U>
+  friend PA_ALWAYS_INLINE bool operator>(U* lhs, const raw_ptr& rhs) {
+    return lhs > rhs.GetForComparison();
+  }
+  template <typename U>
+  friend PA_ALWAYS_INLINE bool operator>=(U* lhs, const raw_ptr& rhs) {
+    return lhs >= rhs.GetForComparison();
+  }
+
+  // Comparisons with `std::nullptr_t`.
+  friend PA_ALWAYS_INLINE bool operator==(const raw_ptr& lhs, std::nullptr_t) {
+    return !lhs;
+  }
+  friend PA_ALWAYS_INLINE bool operator!=(const raw_ptr& lhs, std::nullptr_t) {
+    return !!lhs;  // Use !! otherwise the costly implicit cast will be used.
+  }
+  friend PA_ALWAYS_INLINE bool operator==(std::nullptr_t, const raw_ptr& rhs) {
+    return !rhs;
+  }
+  friend PA_ALWAYS_INLINE bool operator!=(std::nullptr_t, const raw_ptr& rhs) {
+    return !!rhs;  // Use !! otherwise the costly implicit cast will be used.
+  }
+
+  friend PA_ALWAYS_INLINE void swap(raw_ptr& lhs, raw_ptr& rhs) noexcept {
+    Impl::IncrementSwapCountForTest();
+    std::swap(lhs.wrapped_ptr_, rhs.wrapped_ptr_);
+  }
+
+  PA_ALWAYS_INLINE void ReportIfDangling() const noexcept {
+#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
+    Impl::ReportIfDangling(wrapped_ptr_);
+#endif
+  }
+
+ private:
+  // This getter is meant for situations where the pointer is meant to be
+  // dereferenced. It is allowed to crash on nullptr (it may or may not),
+  // because it knows that the caller will crash on nullptr.
+  PA_ALWAYS_INLINE T* GetForDereference() const {
+    return Impl::SafelyUnwrapPtrForDereference(wrapped_ptr_);
+  }
+  // This getter is meant for situations where the raw pointer is meant to be
+  // extracted outside of this class, but not necessarily with an intention to
+  // dereference. It mustn't crash on nullptr.
+  PA_ALWAYS_INLINE T* GetForExtraction() const {
+    return Impl::SafelyUnwrapPtrForExtraction(wrapped_ptr_);
+  }
+  // This getter is meant *only* for situations where the pointer is meant to be
+  // compared (guaranteeing no dereference or extraction outside of this class).
+  // Any verifications can and should be skipped for performance reasons.
+  PA_ALWAYS_INLINE T* GetForComparison() const {
+    return Impl::UnsafelyUnwrapPtrForComparison(wrapped_ptr_);
+  }
+
+  PA_ALWAYS_INLINE T* GetForExtractionAndReset() {
+    T* ptr = GetForExtraction();
+    operator=(nullptr);
+    return ptr;
+  }
+
+  T* wrapped_ptr_;
+
+  template <typename U, typename V>
+  friend class raw_ptr;
+};
+
+template <typename U, typename V, typename I>
+PA_ALWAYS_INLINE bool operator==(const raw_ptr<U, I>& lhs,
+                                 const raw_ptr<V, I>& rhs) {
+  return lhs.GetForComparison() == rhs.GetForComparison();
+}
+
+template <typename U, typename V, typename I>
+PA_ALWAYS_INLINE bool operator<(const raw_ptr<U, I>& lhs,
+                                const raw_ptr<V, I>& rhs) {
+  return lhs.GetForComparison() < rhs.GetForComparison();
+}
+
+template <typename U, typename V, typename I>
+PA_ALWAYS_INLINE bool operator>(const raw_ptr<U, I>& lhs,
+                                const raw_ptr<V, I>& rhs) {
+  return lhs.GetForComparison() > rhs.GetForComparison();
+}
+
+template <typename U, typename V, typename I>
+PA_ALWAYS_INLINE bool operator<=(const raw_ptr<U, I>& lhs,
+                                 const raw_ptr<V, I>& rhs) {
+  return lhs.GetForComparison() <= rhs.GetForComparison();
+}
+
+template <typename U, typename V, typename I>
+PA_ALWAYS_INLINE bool operator>=(const raw_ptr<U, I>& lhs,
+                                 const raw_ptr<V, I>& rhs) {
+  return lhs.GetForComparison() >= rhs.GetForComparison();
+}
+
+template <typename T>
+struct IsRawPtr : std::false_type {};
+
+template <typename T, typename I>
+struct IsRawPtr<raw_ptr<T, I>> : std::true_type {};
+
+template <typename T>
+inline constexpr bool IsRawPtrV = IsRawPtr<T>::value;
+
+// Template helpers for working with T* or raw_ptr<T>.
+template <typename T>
+struct IsPointer : std::false_type {};
+
+template <typename T>
+struct IsPointer<T*> : std::true_type {};
+
+template <typename T, typename I>
+struct IsPointer<raw_ptr<T, I>> : std::true_type {};
+
+template <typename T>
+inline constexpr bool IsPointerV = IsPointer<T>::value;
+
+template <typename T>
+struct RemovePointer {
+  using type = T;
+};
+
+template <typename T>
+struct RemovePointer<T*> {
+  using type = T;
+};
+
+template <typename T, typename I>
+struct RemovePointer<raw_ptr<T, I>> {
+  using type = T;
+};
+
+template <typename T>
+using RemovePointerT = typename RemovePointer<T>::type;
+
+}  // namespace base
+
+using base::raw_ptr;
+
+// DisableDanglingPtrDetection option for raw_ptr annotates
+// "intentional-and-safe" dangling pointers. It is meant to be used at the
+// margin, only if there is no better way to re-architecture the code.
+//
+// Usage:
+// raw_ptr<T, DisableDanglingPtrDetection> dangling_ptr;
+//
+// When using it, please provide a justification about what guarantees it will
+// never be dereferenced after becoming dangling.
+using DisableDanglingPtrDetection = base::RawPtrMayDangle;
+
+// See `docs/dangling_ptr.md`
+// Annotates known dangling raw_ptr. Those haven't been triaged yet. All the
+// occurrences are meant to be removed. See https://crbug.com/1291138.
+using DanglingUntriaged = DisableDanglingPtrDetection;
+
+// The following template parameters are only meaningful when `raw_ptr`
+// is `MTECheckedPtr` (never the case unless a particular GN arg is set
+// true.) `raw_ptr` users need not worry about this and can refer solely
+// to `DisableDanglingPtrDetection` and `DanglingUntriaged` above.
+//
+// The `raw_ptr` definition allows users to specify an implementation.
+// When `MTECheckedPtr` is in play, we need to augment this
+// implementation setting with another layer that allows the `raw_ptr`
+// to degrade into the no-op version.
+#if defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
+
+// Direct pass-through to no-op implementation.
+using DegradeToNoOpWhenMTE = base::RawPtrNoOp;
+
+// As above, but with the "untriaged dangling" annotation.
+using DanglingUntriagedDegradeToNoOpWhenMTE = base::RawPtrNoOp;
+
+// As above, but with the "explicitly disable protection" annotation.
+using DisableDanglingPtrDetectionDegradeToNoOpWhenMTE = base::RawPtrNoOp;
+
+#else
+
+// Direct pass-through to default implementation specified by `raw_ptr`
+// template.
+using DegradeToNoOpWhenMTE = base::RawPtrBanDanglingIfSupported;
+
+// Direct pass-through to `DanglingUntriaged`.
+using DanglingUntriagedDegradeToNoOpWhenMTE = DanglingUntriaged;
+
+// Direct pass-through to `DisableDanglingPtrDetection`.
+using DisableDanglingPtrDetectionDegradeToNoOpWhenMTE =
+    DisableDanglingPtrDetection;
+
+#endif  // defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
+
+namespace std {
+
+// Override so set/map lookups do not create extra raw_ptr. This also allows
+// dangling pointers to be used for lookup.
+template <typename T, typename RawPtrType>
+struct less<raw_ptr<T, RawPtrType>> {
+  using Impl =
+      typename base::raw_ptr_traits::RawPtrTypeToImpl<RawPtrType>::Impl;
+  using is_transparent = void;
+
+  bool operator()(const raw_ptr<T, RawPtrType>& lhs,
+                  const raw_ptr<T, RawPtrType>& rhs) const {
+    Impl::IncrementLessCountForTest();
+    return lhs < rhs;
+  }
+
+  bool operator()(T* lhs, const raw_ptr<T, RawPtrType>& rhs) const {
+    Impl::IncrementLessCountForTest();
+    return lhs < rhs;
+  }
+
+  bool operator()(const raw_ptr<T, RawPtrType>& lhs, T* rhs) const {
+    Impl::IncrementLessCountForTest();
+    return lhs < rhs;
+  }
+};
+
+// Define for cases where raw_ptr<T> holds a pointer to an array of type T.
+// This is consistent with definition of std::iterator_traits<T*>.
+// Algorithms like std::binary_search need that.
+template <typename T, typename Impl>
+struct iterator_traits<raw_ptr<T, Impl>> {
+  using difference_type = ptrdiff_t;
+  using value_type = std::remove_cv_t<T>;
+  using pointer = T*;
+  using reference = T&;
+  using iterator_category = std::random_access_iterator_tag;
+};
+
+}  // namespace std
 
 #endif  // BASE_MEMORY_RAW_PTR_H_
diff --git a/base/memory/raw_ref.h b/base/memory/raw_ref.h
index f271d3e..ed556a5 100644
--- a/base/memory/raw_ref.h
+++ b/base/memory/raw_ref.h
@@ -5,8 +5,359 @@
 #ifndef BASE_MEMORY_RAW_REF_H_
 #define BASE_MEMORY_RAW_REF_H_
 
-// Facade header to allow us time to slowly rewrite `raw_ref` users
-// to refer to the new location.
-#include "base/allocator/partition_allocator/pointers/raw_ref.h"
+#include <memory>
+#include <type_traits>
+#include <utility>
+
+#include "base/allocator/partition_allocator/partition_alloc_base/augmentations/compiler_specific.h"
+#include "base/allocator/partition_allocator/partition_alloc_base/compiler_specific.h"
+#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
+#include "base/allocator/partition_allocator/partition_alloc_config.h"
+#include "base/memory/raw_ptr.h"
+
+namespace base {
+
+template <class T, class RawPtrType>
+class raw_ref;
+
+namespace internal {
+
+template <class T>
+struct is_raw_ref : std::false_type {};
+
+template <class T, class I>
+struct is_raw_ref<::base::raw_ref<T, I>> : std::true_type {};
+
+template <class T>
+constexpr inline bool is_raw_ref_v = is_raw_ref<T>::value;
+
+}  // namespace internal
+
+// A smart pointer for a pointer which can not be null, and which provides
+// Use-after-Free protection in the same ways as raw_ptr. This class acts like a
+// combination of std::reference_wrapper and raw_ptr.
+//
+// See raw_ptr and //base/memory/raw_ptr.md for more details on the
+// Use-after-Free protection.
+//
+// # Use after move
+//
+// The raw_ref type will abort if used after being moved.
+//
+// # Constness
+//
+// Use a `const raw_ref<T>` when the smart pointer should not be able to rebind
+// to a new reference. Use a `const raw_ref<const T>` do the same for a const
+// reference, which is like `const T&`.
+//
+// Unlike a native `T&` reference, a mutable `raw_ref<T>` can be changed
+// independent of the underlying `T`, similar to `std::reference_wrapper`. That
+// means the reference inside it can be moved and reassigned.
+template <class T, class RawPtrType = DefaultRawPtrType>
+class PA_TRIVIAL_ABI PA_GSL_POINTER raw_ref {
+  // operator* is used with the expectation of GetForExtraction semantics:
+  //
+  // raw_ref<Foo> foo_raw_ref = something;
+  // Foo& foo_ref = *foo_raw_ref;
+  //
+  // The implementation of operator* provides GetForDereference semantics, and
+  // this results in spurious crashes in BRP-ASan builds, so we need to disable
+  // BRP-ASan instrumentation for raw_ref.
+#if BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
+  using Inner = raw_ptr<T, RawPtrNoOp>;
+#else
+  using Inner = raw_ptr<T, RawPtrType>;
+#endif  // BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
+
+  using Impl = typename raw_ptr_traits::RawPtrTypeToImpl<RawPtrType>::Impl;
+  // These impls do not clear on move, which produces an inconsistent behaviour.
+  // We want consistent behaviour such that using a raw_ref after move is caught
+  // and aborts. Failure to clear would be indicated by the related death tests
+  // not CHECKing appropriately.
+  static constexpr bool need_clear_after_move =
+#if defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
+      std::is_same_v<Impl,
+                     internal::MTECheckedPtrImpl<
+                         internal::MTECheckedPtrImplPartitionAllocSupport>> ||
+#endif  // defined(PA_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
+#if BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
+      std::is_same_v<Impl, internal::AsanBackupRefPtrImpl> ||
+#endif  // BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
+      std::is_same_v<Impl, internal::RawPtrNoOpImpl>;
+
+ public:
+  PA_ALWAYS_INLINE explicit raw_ref(T& p) noexcept
+      : inner_(std::addressof(p)) {}
+
+  PA_ALWAYS_INLINE raw_ref& operator=(T& p) noexcept {
+    inner_.operator=(&p);
+    return *this;
+  }
+
+  // Disallow holding references to temporaries.
+  raw_ref(const T&& p) = delete;
+  raw_ref& operator=(const T&& p) = delete;
+
+  PA_ALWAYS_INLINE raw_ref(const raw_ref& p) noexcept : inner_(p.inner_) {
+    PA_RAW_PTR_CHECK(inner_.get());  // Catch use-after-move.
+  }
+
+  PA_ALWAYS_INLINE raw_ref(raw_ref&& p) noexcept : inner_(std::move(p.inner_)) {
+    PA_RAW_PTR_CHECK(inner_.get());  // Catch use-after-move.
+    if constexpr (need_clear_after_move)
+      p.inner_ = nullptr;
+  }
+
+  PA_ALWAYS_INLINE raw_ref& operator=(const raw_ref& p) noexcept {
+    PA_RAW_PTR_CHECK(p.inner_.get());  // Catch use-after-move.
+    inner_.operator=(p.inner_);
+    return *this;
+  }
+
+  PA_ALWAYS_INLINE raw_ref& operator=(raw_ref&& p) noexcept {
+    PA_RAW_PTR_CHECK(p.inner_.get());  // Catch use-after-move.
+    inner_.operator=(std::move(p.inner_));
+    if constexpr (need_clear_after_move)
+      p.inner_ = nullptr;
+    return *this;
+  }
+
+  // Deliberately implicit in order to support implicit upcast.
+  template <class U, class = std::enable_if_t<std::is_convertible_v<U&, T&>>>
+  // NOLINTNEXTLINE(google-explicit-constructor)
+  PA_ALWAYS_INLINE raw_ref(const raw_ref<U, RawPtrType>& p) noexcept
+      : inner_(p.inner_) {
+    PA_RAW_PTR_CHECK(inner_.get());  // Catch use-after-move.
+  }
+  // Deliberately implicit in order to support implicit upcast.
+  template <class U, class = std::enable_if_t<std::is_convertible_v<U&, T&>>>
+  // NOLINTNEXTLINE(google-explicit-constructor)
+  PA_ALWAYS_INLINE raw_ref(raw_ref<U, RawPtrType>&& p) noexcept
+      : inner_(std::move(p.inner_)) {
+    PA_RAW_PTR_CHECK(inner_.get());  // Catch use-after-move.
+    if constexpr (need_clear_after_move)
+      p.inner_ = nullptr;
+  }
+
+  static PA_ALWAYS_INLINE raw_ref from_ptr(T* ptr) noexcept {
+    PA_RAW_PTR_CHECK(ptr);
+    return raw_ref(*ptr);
+  }
+
+  // Upcast assignment
+  template <class U, class = std::enable_if_t<std::is_convertible_v<U&, T&>>>
+  PA_ALWAYS_INLINE raw_ref& operator=(
+      const raw_ref<U, RawPtrType>& p) noexcept {
+    PA_RAW_PTR_CHECK(p.inner_.get());  // Catch use-after-move.
+    inner_.operator=(p.inner_);
+    return *this;
+  }
+  template <class U, class = std::enable_if_t<std::is_convertible_v<U&, T&>>>
+  PA_ALWAYS_INLINE raw_ref& operator=(raw_ref<U, RawPtrType>&& p) noexcept {
+    PA_RAW_PTR_CHECK(p.inner_.get());  // Catch use-after-move.
+    inner_.operator=(std::move(p.inner_));
+    if constexpr (need_clear_after_move)
+      p.inner_ = nullptr;
+    return *this;
+  }
+
+  PA_ALWAYS_INLINE T& operator*() const {
+    PA_RAW_PTR_CHECK(inner_.get());  // Catch use-after-move.
+    return inner_.operator*();
+  }
+
+  // This is an equivalent to operator*() that provides GetForExtraction rather
+  // rather than GetForDereference semantics (see raw_ptr.h). This should be
+  // used in place of operator*() when the memory referred to by the reference
+  // is not immediately going to be accessed.
+  PA_ALWAYS_INLINE T& get() const {
+    PA_RAW_PTR_CHECK(inner_.get());  // Catch use-after-move.
+    return *inner_.get();
+  }
+
+  PA_ALWAYS_INLINE T* operator->() const PA_ATTRIBUTE_RETURNS_NONNULL {
+    PA_RAW_PTR_CHECK(inner_.get());  // Catch use-after-move.
+    return inner_.operator->();
+  }
+
+  friend PA_ALWAYS_INLINE void swap(raw_ref& lhs, raw_ref& rhs) noexcept {
+    PA_RAW_PTR_CHECK(lhs.inner_.get());  // Catch use-after-move.
+    PA_RAW_PTR_CHECK(rhs.inner_.get());  // Catch use-after-move.
+    swap(lhs.inner_, rhs.inner_);
+  }
+
+  template <class U>
+  friend PA_ALWAYS_INLINE bool operator==(const raw_ref& lhs,
+                                          const raw_ref<U, RawPtrType>& rhs) {
+    PA_RAW_PTR_CHECK(lhs.inner_.get());  // Catch use-after-move.
+    PA_RAW_PTR_CHECK(rhs.inner_.get());  // Catch use-after-move.
+    return lhs.inner_ == rhs.inner_;
+  }
+  template <class U>
+  friend PA_ALWAYS_INLINE bool operator!=(const raw_ref& lhs,
+                                          const raw_ref<U, RawPtrType>& rhs) {
+    PA_RAW_PTR_CHECK(lhs.inner_.get());  // Catch use-after-move.
+    PA_RAW_PTR_CHECK(rhs.inner_.get());  // Catch use-after-move.
+    return lhs.inner_ != rhs.inner_;
+  }
+  template <class U>
+  friend PA_ALWAYS_INLINE bool operator<(const raw_ref& lhs,
+                                         const raw_ref<U, RawPtrType>& rhs) {
+    PA_RAW_PTR_CHECK(lhs.inner_.get());  // Catch use-after-move.
+    PA_RAW_PTR_CHECK(rhs.inner_.get());  // Catch use-after-move.
+    return lhs.inner_ < rhs.inner_;
+  }
+  template <class U>
+  friend PA_ALWAYS_INLINE bool operator>(const raw_ref& lhs,
+                                         const raw_ref<U, RawPtrType>& rhs) {
+    PA_RAW_PTR_CHECK(lhs.inner_.get());  // Catch use-after-move.
+    PA_RAW_PTR_CHECK(rhs.inner_.get());  // Catch use-after-move.
+    return lhs.inner_ > rhs.inner_;
+  }
+  template <class U>
+  friend PA_ALWAYS_INLINE bool operator<=(const raw_ref& lhs,
+                                          const raw_ref<U, RawPtrType>& rhs) {
+    PA_RAW_PTR_CHECK(lhs.inner_.get());  // Catch use-after-move.
+    PA_RAW_PTR_CHECK(rhs.inner_.get());  // Catch use-after-move.
+    return lhs.inner_ <= rhs.inner_;
+  }
+  template <class U>
+  friend PA_ALWAYS_INLINE bool operator>=(const raw_ref& lhs,
+                                          const raw_ref<U, RawPtrType>& rhs) {
+    PA_RAW_PTR_CHECK(lhs.inner_.get());  // Catch use-after-move.
+    PA_RAW_PTR_CHECK(rhs.inner_.get());  // Catch use-after-move.
+    return lhs.inner_ >= rhs.inner_;
+  }
+
+  template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
+  friend PA_ALWAYS_INLINE bool operator==(const raw_ref& lhs, const U& rhs) {
+    PA_RAW_PTR_CHECK(lhs.inner_.get());  // Catch use-after-move.
+    return lhs.inner_ == &rhs;
+  }
+  template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
+  friend PA_ALWAYS_INLINE bool operator!=(const raw_ref& lhs, const U& rhs) {
+    PA_RAW_PTR_CHECK(lhs.inner_.get());  // Catch use-after-move.
+    return lhs.inner_ != &rhs;
+  }
+  template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
+  friend PA_ALWAYS_INLINE bool operator<(const raw_ref& lhs, const U& rhs) {
+    PA_RAW_PTR_CHECK(lhs.inner_.get());  // Catch use-after-move.
+    return lhs.inner_ < &rhs;
+  }
+  template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
+  friend PA_ALWAYS_INLINE bool operator>(const raw_ref& lhs, const U& rhs) {
+    PA_RAW_PTR_CHECK(lhs.inner_.get());  // Catch use-after-move.
+    return lhs.inner_ > &rhs;
+  }
+  template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
+  friend PA_ALWAYS_INLINE bool operator<=(const raw_ref& lhs, const U& rhs) {
+    PA_RAW_PTR_CHECK(lhs.inner_.get());  // Catch use-after-move.
+    return lhs.inner_ <= &rhs;
+  }
+  template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
+  friend PA_ALWAYS_INLINE bool operator>=(const raw_ref& lhs, const U& rhs) {
+    PA_RAW_PTR_CHECK(lhs.inner_.get());  // Catch use-after-move.
+    return lhs.inner_ >= &rhs;
+  }
+
+  template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
+  friend PA_ALWAYS_INLINE bool operator==(const U& lhs, const raw_ref& rhs) {
+    PA_RAW_PTR_CHECK(rhs.inner_.get());  // Catch use-after-move.
+    return &lhs == rhs.inner_;
+  }
+  template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
+  friend PA_ALWAYS_INLINE bool operator!=(const U& lhs, const raw_ref& rhs) {
+    PA_RAW_PTR_CHECK(rhs.inner_.get());  // Catch use-after-move.
+    return &lhs != rhs.inner_;
+  }
+  template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
+  friend PA_ALWAYS_INLINE bool operator<(const U& lhs, const raw_ref& rhs) {
+    PA_RAW_PTR_CHECK(rhs.inner_.get());  // Catch use-after-move.
+    return &lhs < rhs.inner_;
+  }
+  template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
+  friend PA_ALWAYS_INLINE bool operator>(const U& lhs, const raw_ref& rhs) {
+    PA_RAW_PTR_CHECK(rhs.inner_.get());  // Catch use-after-move.
+    return &lhs > rhs.inner_;
+  }
+  template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
+  friend PA_ALWAYS_INLINE bool operator<=(const U& lhs, const raw_ref& rhs) {
+    PA_RAW_PTR_CHECK(rhs.inner_.get());  // Catch use-after-move.
+    return &lhs <= rhs.inner_;
+  }
+  template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
+  friend PA_ALWAYS_INLINE bool operator>=(const U& lhs, const raw_ref& rhs) {
+    PA_RAW_PTR_CHECK(rhs.inner_.get());  // Catch use-after-move.
+    return &lhs >= rhs.inner_;
+  }
+
+ private:
+  template <class U, class J>
+  friend class raw_ref;
+
+  Inner inner_;
+};
+
+// CTAD deduction guide.
+template <class T>
+raw_ref(T&) -> raw_ref<T>;
+template <class T>
+raw_ref(const T&) -> raw_ref<const T>;
+
+// Template helpers for working with raw_ref<T>.
+template <typename T>
+struct IsRawRef : std::false_type {};
+
+template <typename T, typename I>
+struct IsRawRef<raw_ref<T, I>> : std::true_type {};
+
+template <typename T>
+inline constexpr bool IsRawRefV = IsRawRef<T>::value;
+
+template <typename T>
+struct RemoveRawRef {
+  using type = T;
+};
+
+template <typename T, typename I>
+struct RemoveRawRef<raw_ref<T, I>> {
+  using type = T;
+};
+
+template <typename T>
+using RemoveRawRefT = typename RemoveRawRef<T>::type;
+
+}  // namespace base
+
+using base::raw_ref;
+
+namespace std {
+
+// Override so set/map lookups do not create extra raw_ref. This also
+// allows C++ references to be used for lookup.
+template <typename T, typename RawPtrType>
+struct less<raw_ref<T, RawPtrType>> {
+  using Impl =
+      typename base::raw_ptr_traits::RawPtrTypeToImpl<RawPtrType>::Impl;
+  using is_transparent = void;
+
+  bool operator()(const raw_ref<T, RawPtrType>& lhs,
+                  const raw_ref<T, RawPtrType>& rhs) const {
+    Impl::IncrementLessCountForTest();
+    return lhs < rhs;
+  }
+
+  bool operator()(T& lhs, const raw_ref<T, RawPtrType>& rhs) const {
+    Impl::IncrementLessCountForTest();
+    return lhs < rhs;
+  }
+
+  bool operator()(const raw_ref<T, RawPtrType>& lhs, T& rhs) const {
+    Impl::IncrementLessCountForTest();
+    return lhs < rhs;
+  }
+};
+
+}  // namespace std
 
 #endif  // BASE_MEMORY_RAW_REF_H_
diff --git a/base/values.cc b/base/values.cc
index 052eb4b..3072cf1 100644
--- a/base/values.cc
+++ b/base/values.cc
@@ -1601,12 +1601,12 @@
 // static
 std::unique_ptr<DictionaryValue> DictionaryValue::From(
     std::unique_ptr<Value> value) {
-  DictionaryValue* out;
-  if (value && value->GetAsDictionary(&out)) {
-    std::ignore = value.release();
-    return WrapUnique(out);
+  if (!value || !value->is_dict()) {
+    return nullptr;
   }
-  return nullptr;
+
+  DictionaryValue* out = static_cast<DictionaryValue*>(value.release());
+  return WrapUnique(out);
 }
 
 DictionaryValue::DictionaryValue() : Value(Type::DICTIONARY) {}
diff --git a/base/win/security_descriptor.cc b/base/win/security_descriptor.cc
new file mode 100644
index 0000000..cccac9b
--- /dev/null
+++ b/base/win/security_descriptor.cc
@@ -0,0 +1,344 @@
+// 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 "base/win/security_descriptor.h"
+
+#include <aclapi.h>
+#include <sddl.h>
+#include <windows.h>
+
+#include <utility>
+#include <vector>
+
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/notreached.h"
+#include "base/numerics/checked_math.h"
+#include "base/win/scoped_localalloc.h"
+
+namespace base::win {
+
+namespace {
+template <typename T>
+absl::optional<T> CloneValue(const absl::optional<T>& value) {
+  if (!value)
+    return absl::nullopt;
+  return value->Clone();
+}
+
+PSID UnwrapSid(const absl::optional<Sid>& sid) {
+  if (!sid)
+    return nullptr;
+  return sid->GetPSID();
+}
+
+PACL UnwrapAcl(const absl::optional<AccessControlList>& acl) {
+  if (!acl)
+    return nullptr;
+  return acl->get();
+}
+
+SE_OBJECT_TYPE ConvertObjectType(SecurityObjectType object_type) {
+  switch (object_type) {
+    case SecurityObjectType::kFile:
+      return SE_FILE_OBJECT;
+    case SecurityObjectType::kRegistry:
+      return SE_REGISTRY_KEY;
+    case SecurityObjectType::kWindow:
+      return SE_WINDOW_OBJECT;
+    case SecurityObjectType::kKernel:
+      return SE_KERNEL_OBJECT;
+  }
+  return SE_UNKNOWN_OBJECT_TYPE;
+}
+
+template <typename T>
+absl::optional<SecurityDescriptor> GetSecurityDescriptor(
+    T object,
+    SecurityObjectType object_type,
+    SECURITY_INFORMATION security_info,
+    DWORD(WINAPI* get_sd)(T,
+                          SE_OBJECT_TYPE,
+                          SECURITY_INFORMATION,
+                          PSID*,
+                          PSID*,
+                          PACL*,
+                          PACL*,
+                          PSECURITY_DESCRIPTOR*)) {
+  PSECURITY_DESCRIPTOR sd = nullptr;
+
+  DWORD error = get_sd(object, ConvertObjectType(object_type), security_info,
+                       nullptr, nullptr, nullptr, nullptr, &sd);
+  if (error != ERROR_SUCCESS) {
+    ::SetLastError(error);
+    DPLOG(ERROR) << "Failed getting security descriptor for object.";
+    return absl::nullopt;
+  }
+  auto sd_ptr = TakeLocalAlloc(sd);
+  return SecurityDescriptor::FromPointer(sd_ptr.get());
+}
+
+template <typename T>
+bool SetSecurityDescriptor(const SecurityDescriptor& sd,
+                           T object,
+                           SecurityObjectType object_type,
+                           SECURITY_INFORMATION security_info,
+                           DWORD(WINAPI* set_sd)(T,
+                                                 SE_OBJECT_TYPE,
+                                                 SECURITY_INFORMATION,
+                                                 PSID,
+                                                 PSID,
+                                                 PACL,
+                                                 PACL)) {
+  security_info &= ~(PROTECTED_DACL_SECURITY_INFORMATION |
+                     UNPROTECTED_DACL_SECURITY_INFORMATION |
+                     PROTECTED_SACL_SECURITY_INFORMATION |
+                     UNPROTECTED_SACL_SECURITY_INFORMATION);
+  if (security_info & DACL_SECURITY_INFORMATION) {
+    if (sd.dacl_protected()) {
+      security_info |= PROTECTED_DACL_SECURITY_INFORMATION;
+    } else {
+      security_info |= UNPROTECTED_DACL_SECURITY_INFORMATION;
+    }
+  }
+  if (security_info & SACL_SECURITY_INFORMATION) {
+    if (sd.sacl_protected()) {
+      security_info |= PROTECTED_SACL_SECURITY_INFORMATION;
+    } else {
+      security_info |= UNPROTECTED_SACL_SECURITY_INFORMATION;
+    }
+  }
+  DWORD error = set_sd(object, ConvertObjectType(object_type), security_info,
+                       UnwrapSid(sd.owner()), UnwrapSid(sd.group()),
+                       UnwrapAcl(sd.dacl()), UnwrapAcl(sd.sacl()));
+  if (error != ERROR_SUCCESS) {
+    ::SetLastError(error);
+    DPLOG(ERROR) << "Failed setting DACL for object.";
+    return false;
+  }
+  return true;
+}
+
+absl::optional<Sid> GetSecurityDescriptorSid(
+    PSECURITY_DESCRIPTOR sd,
+    BOOL(WINAPI* get_sid)(PSECURITY_DESCRIPTOR, PSID*, LPBOOL)) {
+  PSID sid;
+  BOOL defaulted;
+  if (!get_sid(sd, &sid, &defaulted) || !sid) {
+    return absl::nullopt;
+  }
+  return Sid::FromPSID(sid);
+}
+
+absl::optional<AccessControlList> GetSecurityDescriptorAcl(
+    PSECURITY_DESCRIPTOR sd,
+    BOOL(WINAPI* get_acl)(PSECURITY_DESCRIPTOR, LPBOOL, PACL*, LPBOOL)) {
+  PACL acl;
+  BOOL present;
+  BOOL defaulted;
+  if (!get_acl(sd, &present, &acl, &defaulted) || !present) {
+    return absl::nullopt;
+  }
+  return AccessControlList::FromPACL(acl);
+}
+
+}  // namespace
+
+SecurityDescriptor::SelfRelative::SelfRelative(const SelfRelative&) = default;
+SecurityDescriptor::SelfRelative::~SelfRelative() = default;
+SecurityDescriptor::SelfRelative::SelfRelative(std::vector<uint8_t>&& sd)
+    : sd_(sd) {}
+
+absl::optional<SecurityDescriptor> SecurityDescriptor::FromPointer(
+    PSECURITY_DESCRIPTOR sd) {
+  if (!sd || !::IsValidSecurityDescriptor(sd)) {
+    ::SetLastError(ERROR_INVALID_SECURITY_DESCR);
+    return absl::nullopt;
+  }
+
+  SECURITY_DESCRIPTOR_CONTROL control;
+  DWORD revision;
+  if (!::GetSecurityDescriptorControl(sd, &control, &revision)) {
+    return absl::nullopt;
+  }
+
+  return SecurityDescriptor{
+      GetSecurityDescriptorSid(sd, ::GetSecurityDescriptorOwner),
+      GetSecurityDescriptorSid(sd, ::GetSecurityDescriptorGroup),
+      GetSecurityDescriptorAcl(sd, ::GetSecurityDescriptorDacl),
+      !!(control & SE_DACL_PROTECTED),
+      GetSecurityDescriptorAcl(sd, ::GetSecurityDescriptorSacl),
+      !!(control & SE_SACL_PROTECTED)};
+}
+
+absl::optional<SecurityDescriptor> SecurityDescriptor::FromFile(
+    const base::FilePath& path,
+    SECURITY_INFORMATION security_info) {
+  return FromName(path.value().c_str(), SecurityObjectType::kFile,
+                  security_info);
+}
+
+absl::optional<SecurityDescriptor> SecurityDescriptor::FromName(
+    const std::wstring& name,
+    SecurityObjectType object_type,
+    SECURITY_INFORMATION security_info) {
+  return GetSecurityDescriptor(name.c_str(), object_type, security_info,
+                               ::GetNamedSecurityInfo);
+}
+
+absl::optional<SecurityDescriptor> SecurityDescriptor::FromHandle(
+    HANDLE handle,
+    SecurityObjectType object_type,
+    SECURITY_INFORMATION security_info) {
+  return GetSecurityDescriptor<HANDLE>(handle, object_type, security_info,
+                                       ::GetSecurityInfo);
+}
+
+absl::optional<SecurityDescriptor> SecurityDescriptor::FromSddl(
+    const std::wstring& sddl) {
+  PSECURITY_DESCRIPTOR sd;
+  if (!::ConvertStringSecurityDescriptorToSecurityDescriptor(
+          sddl.c_str(), SDDL_REVISION_1, &sd, nullptr)) {
+    return absl::nullopt;
+  }
+  auto sd_ptr = TakeLocalAlloc(sd);
+  return FromPointer(sd_ptr.get());
+}
+
+SecurityDescriptor::SecurityDescriptor() = default;
+SecurityDescriptor::SecurityDescriptor(SecurityDescriptor&&) = default;
+SecurityDescriptor& SecurityDescriptor::operator=(SecurityDescriptor&&) =
+    default;
+SecurityDescriptor::~SecurityDescriptor() = default;
+
+bool SecurityDescriptor::WriteToFile(const base::FilePath& path,
+                                     SECURITY_INFORMATION security_info) const {
+  return WriteToName(path.value().c_str(), SecurityObjectType::kFile,
+                     security_info);
+}
+
+bool SecurityDescriptor::WriteToName(const std::wstring& name,
+                                     SecurityObjectType object_type,
+                                     SECURITY_INFORMATION security_info) const {
+  return SetSecurityDescriptor<wchar_t*>(
+      *this, const_cast<wchar_t*>(name.c_str()), object_type, security_info,
+      ::SetNamedSecurityInfo);
+}
+
+bool SecurityDescriptor::WriteToHandle(
+    HANDLE handle,
+    SecurityObjectType object_type,
+    SECURITY_INFORMATION security_info) const {
+  return SetSecurityDescriptor<HANDLE>(*this, handle, object_type,
+                                       security_info, ::SetSecurityInfo);
+}
+
+absl::optional<std::wstring> SecurityDescriptor::ToSddl(
+    SECURITY_INFORMATION security_info) const {
+  SECURITY_DESCRIPTOR sd = {};
+  ToAbsolute(sd);
+  LPWSTR sddl;
+  if (!::ConvertSecurityDescriptorToStringSecurityDescriptor(
+          &sd, SDDL_REVISION_1, security_info, &sddl, nullptr)) {
+    return absl::nullopt;
+  }
+  auto sddl_ptr = TakeLocalAlloc(sddl);
+  return sddl_ptr.get();
+}
+
+void SecurityDescriptor::ToAbsolute(SECURITY_DESCRIPTOR& sd) const {
+  memset(&sd, 0, sizeof(sd));
+  sd.Revision = SECURITY_DESCRIPTOR_REVISION;
+  sd.Owner = owner_ ? owner_->GetPSID() : nullptr;
+  sd.Group = group_ ? group_->GetPSID() : nullptr;
+  if (dacl_) {
+    sd.Dacl = dacl_->get();
+    sd.Control |= SE_DACL_PRESENT;
+    if (dacl_protected_) {
+      sd.Control |= SE_DACL_PROTECTED;
+    }
+  }
+  if (sacl_) {
+    sd.Sacl = sacl_->get();
+    sd.Control |= SE_SACL_PRESENT;
+    if (sacl_protected_) {
+      sd.Control |= SE_SACL_PROTECTED;
+    }
+  }
+  DCHECK(::IsValidSecurityDescriptor(&sd));
+}
+
+absl::optional<SecurityDescriptor::SelfRelative>
+SecurityDescriptor::ToSelfRelative() const {
+  SECURITY_DESCRIPTOR sd = {};
+  ToAbsolute(sd);
+  DWORD size = sizeof(SECURITY_DESCRIPTOR_MIN_LENGTH);
+  std::vector<uint8_t> buffer(SECURITY_DESCRIPTOR_MIN_LENGTH);
+  if (::MakeSelfRelativeSD(&sd, buffer.data(), &size)) {
+    return SelfRelative(std::move(buffer));
+  }
+
+  if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+    return absl::nullopt;
+  }
+
+  buffer.resize(size);
+  if (!::MakeSelfRelativeSD(&sd, buffer.data(), &size)) {
+    return absl::nullopt;
+  }
+  return SelfRelative(std::move(buffer));
+}
+
+SecurityDescriptor SecurityDescriptor::Clone() const {
+  return SecurityDescriptor{CloneValue(owner_), CloneValue(group_),
+                            CloneValue(dacl_),  dacl_protected_,
+                            CloneValue(sacl_),  sacl_protected_};
+}
+
+bool SecurityDescriptor::SetMandatoryLabel(DWORD integrity_level,
+                                           DWORD inheritance,
+                                           DWORD mandatory_policy) {
+  absl::optional<AccessControlList> sacl =
+      AccessControlList::FromMandatoryLabel(integrity_level, inheritance,
+                                            mandatory_policy);
+  if (!sacl) {
+    return false;
+  }
+  sacl_ = std::move(*sacl);
+  return true;
+}
+
+bool SecurityDescriptor::SetDaclEntries(
+    const std::vector<ExplicitAccessEntry>& entries) {
+  if (!dacl_) {
+    dacl_ = AccessControlList{};
+  }
+  return dacl_->SetEntries(entries);
+}
+
+bool SecurityDescriptor::SetDaclEntry(const Sid& sid,
+                                      SecurityAccessMode mode,
+                                      DWORD access_mask,
+                                      DWORD inheritance) {
+  if (!dacl_) {
+    dacl_ = AccessControlList{};
+  }
+  return dacl_->SetEntry(sid, mode, access_mask, inheritance);
+}
+
+SecurityDescriptor::SecurityDescriptor(absl::optional<Sid>&& owner,
+                                       absl::optional<Sid>&& group,
+                                       absl::optional<AccessControlList>&& dacl,
+                                       bool dacl_protected,
+                                       absl::optional<AccessControlList>&& sacl,
+                                       bool sacl_protected) {
+  owner_.swap(owner);
+  group_.swap(group);
+  dacl_.swap(dacl);
+  dacl_protected_ = dacl_protected;
+  sacl_.swap(sacl);
+  sacl_protected_ = sacl_protected;
+}
+
+}  // namespace base::win
diff --git a/base/win/security_descriptor.h b/base/win/security_descriptor.h
new file mode 100644
index 0000000..2a7ab210e
--- /dev/null
+++ b/base/win/security_descriptor.h
@@ -0,0 +1,207 @@
+// 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 BASE_WIN_SECURITY_DESCRIPTOR_H_
+#define BASE_WIN_SECURITY_DESCRIPTOR_H_
+
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include "base/base_export.h"
+#include "base/files/file_path.h"
+#include "base/win/access_control_list.h"
+#include "base/win/sid.h"
+#include "base/win/windows_types.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace base::win {
+
+// Represents the type of Windows kernel object for reading/writing the security
+// descriptor.
+enum class SecurityObjectType { kFile, kRegistry, kWindow, kKernel };
+
+// This class is used to hold and modify a Windows security descriptor.
+class BASE_EXPORT SecurityDescriptor {
+ public:
+  class BASE_EXPORT SelfRelative {
+   public:
+    friend SecurityDescriptor;
+
+    SelfRelative(const SelfRelative&);
+    ~SelfRelative();
+
+    size_t size() const { return sd_.size(); }
+    PSECURITY_DESCRIPTOR get() const {
+      return const_cast<uint8_t*>(sd_.data());
+    }
+
+   private:
+    explicit SelfRelative(std::vector<uint8_t>&& sd);
+
+    std::vector<uint8_t> sd_;
+  };
+
+  // Create from an existing security descriptor pointer.
+  // |security_descriptor| The pointer to a self-relative or absolute security
+  // descriptor. This method will copy all security descriptor data.
+  static absl::optional<SecurityDescriptor> FromPointer(
+      PSECURITY_DESCRIPTOR security_descriptor);
+
+  // Create from the security descriptor of an existing file.
+  // |path| the path to the file.
+  // |security_info| indicates what parts to read.
+  static absl::optional<SecurityDescriptor> FromFile(
+      const base::FilePath& path,
+      SECURITY_INFORMATION security_info);
+
+  // Create from the security descriptor of a named Windows object.
+  // |name| the name of the object using the format specified for the
+  // GetNamedSecurityInfo API.
+  // |object_type| specifies the type of object the name represents.
+  // |security_info| indicates what parts to read.
+  static absl::optional<SecurityDescriptor> FromName(
+      const std::wstring& name,
+      SecurityObjectType object_type,
+      SECURITY_INFORMATION security_info);
+
+  // Create from the security descriptor of a kernel object.
+  // |handle| the object handle. It must have READ_CONTROL access.
+  // |object_type| specifies the type of object the handle represents.
+  // |security_info| indicates what parts to read.
+  static absl::optional<SecurityDescriptor> FromHandle(
+      HANDLE handle,
+      SecurityObjectType object_type,
+      SECURITY_INFORMATION security_info);
+
+  // Create from a string representation of a security descriptor.
+  // |sddl| the security descriptor in SDDL format.
+  static absl::optional<SecurityDescriptor> FromSddl(const std::wstring& sddl);
+
+  SecurityDescriptor();
+  SecurityDescriptor(const SecurityDescriptor&) = delete;
+  SecurityDescriptor& operator=(const SecurityDescriptor&) = delete;
+  SecurityDescriptor(SecurityDescriptor&&);
+  SecurityDescriptor& operator=(SecurityDescriptor&&);
+  ~SecurityDescriptor();
+
+  // Write the security descriptor to a file.
+  // |path| specifies the path to the file.
+  // |security_info| indicates what parts to write.
+  bool WriteToFile(const base::FilePath& path,
+                   SECURITY_INFORMATION security_info) const;
+
+  // Write the security descriptor to a named kernel object.
+  // |name| the name of the object using the format specified for the
+  // SetNamedSecurityInfo API.
+  // |object_type| specifies the type of object name represents.
+  // |security_info| indicates what parts to write.
+  bool WriteToName(const std::wstring& name,
+                   SecurityObjectType object_type,
+                   SECURITY_INFORMATION security_info) const;
+
+  // Write the SecurityDescriptor to a kernel object.
+  // |handle| the handle to the object. Must have WRITE_DAC and/or WRITE_OWNER
+  // access depending of the parts specified with |security_info|. |object_type|
+  // specifies the type of object the handle represents. Use kKernel for
+  // undefined types. |security_info| indicates what parts to write.
+  bool WriteToHandle(HANDLE handle,
+                     SecurityObjectType object_type,
+                     SECURITY_INFORMATION security_info) const;
+
+  // Convert the SecurityDescriptor to an SDDL string.
+  // |security_info| determines what parts are included in the string.
+  absl::optional<std::wstring> ToSddl(SECURITY_INFORMATION security_info) const;
+
+  // Create an reference to the absolute security descriptor of this instance.
+  // |sd| the SECURITY_DESCRIPTOR structure to populate. This is is only valid
+  // as long as this object is in scope and not modified.
+  void ToAbsolute(SECURITY_DESCRIPTOR& sd) const;
+
+  // Create a self-relative security descriptor in a single buffer.
+  absl::optional<SelfRelative> ToSelfRelative() const;
+
+  // Make a clone of the current security descriptor object.
+  SecurityDescriptor Clone() const;
+
+  // Set the mandatory label in the security descriptor. Note that calling
+  // this will completely replace the SACL.
+  // |integrity_level| is the integrity level for the label.
+  // |inheritance| specify the flags for inheritance.
+  // |mandatory_policy| is the policy, e.g. SYSTEM_MANDATORY_LABEL_NO_WRITE_UP.
+  bool SetMandatoryLabel(DWORD integrity_level,
+                         DWORD inheritance,
+                         DWORD mandatory_policy);
+
+  // Set one or more entry in the DACL.
+  // |entries| the list of entries to set in the ACL.
+  // Returns true if successful, false on error, with the Win32 last error set.
+  // If DACL is not present a NULL ACL will be added first.
+  bool SetDaclEntries(const std::vector<ExplicitAccessEntry>& entries);
+
+  // Set one entry in the DACL.
+  // |sid| the SID for the entry.
+  // |mode| the operation to perform on the ACL, e.g. grant access.
+  // |access_mask| the entries access mask.
+  // |inheritance| inheritance flags.
+  // Returns true if successful, false on
+  // error, with the Win32 last error set.
+  // If DACL is not present a NULL ACL will be added first.
+  bool SetDaclEntry(const Sid& sid,
+                    SecurityAccessMode mode,
+                    DWORD access_mask,
+                    DWORD inheritance);
+
+  // Get, set and clear owner member.
+  const absl::optional<Sid>& owner() const { return owner_; }
+  void set_owner(const Sid& owner) { owner_ = owner.Clone(); }
+  void clear_owner() { owner_ = absl::nullopt; }
+
+  // Get, set and clear group member.
+  const absl::optional<Sid>& group() const { return group_; }
+  void set_group(const Sid& group) { group_ = group.Clone(); }
+  void clear_group() { group_ = absl::nullopt; }
+
+  // Get, set and clear dacl member.
+  const absl::optional<AccessControlList>& dacl() const { return dacl_; }
+  void set_dacl(const AccessControlList& dacl) { dacl_ = dacl.Clone(); }
+  void clear_dacl() { dacl_ = absl::nullopt; }
+
+  // Get and set dacl_protected member.
+  bool dacl_protected() const { return dacl_protected_; }
+  void set_dacl_protected(bool dacl_protected) {
+    dacl_protected_ = dacl_protected;
+  }
+
+  // Get, set and clear sacl member.
+  const absl::optional<AccessControlList>& sacl() const { return sacl_; }
+  void set_sacl(const AccessControlList& sacl) { sacl_ = sacl.Clone(); }
+  void clear_sacl() { sacl_ = absl::nullopt; }
+
+  // Get and set sacl_protected member.
+  bool sacl_protected() const { return sacl_protected_; }
+  void set_sacl_protected(bool sacl_protected) {
+    sacl_protected_ = sacl_protected;
+  }
+
+ private:
+  SecurityDescriptor(absl::optional<Sid>&& owner,
+                     absl::optional<Sid>&& group,
+                     absl::optional<AccessControlList>&& dacl,
+                     bool dacl_protected,
+                     absl::optional<AccessControlList>&& sacl,
+                     bool sacl_protected);
+
+  absl::optional<Sid> owner_;
+  absl::optional<Sid> group_;
+  absl::optional<AccessControlList> dacl_;
+  bool dacl_protected_ = false;
+  absl::optional<AccessControlList> sacl_;
+  bool sacl_protected_ = false;
+};
+
+}  // namespace base::win
+
+#endif  // BASE_WIN_SECURITY_DESCRIPTOR_H_
diff --git a/base/win/security_descriptor_unittest.cc b/base/win/security_descriptor_unittest.cc
new file mode 100644
index 0000000..7316eb8
--- /dev/null
+++ b/base/win/security_descriptor_unittest.cc
@@ -0,0 +1,479 @@
+// 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 "base/win/security_descriptor.h"
+
+#include <aclapi.h>
+#include <sddl.h>
+#include <windows.h>
+
+#include <string>
+#include <vector>
+
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/unguessable_token.h"
+#include "base/win/scoped_handle.h"
+#include "base/win/scoped_localalloc.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace base::win {
+
+namespace {
+
+constexpr wchar_t kOwnerOnly[] = L"O:BU";
+constexpr wchar_t kGroupOnly[] = L"G:SY";
+constexpr wchar_t kDaclOnly[] = L"D:(A;;GA;;;WD)";
+constexpr wchar_t kProtectedDaclOnly[] = L"D:P(A;;GA;;;WD)";
+constexpr wchar_t kSaclOnly[] = L"S:(ML;;;;;SI)";
+constexpr wchar_t kProtectedSaclOnly[] = L"S:P(ML;;;;;SI)";
+constexpr wchar_t kSaclProtected[] = L"S:P";
+constexpr wchar_t kFullSd[] = L"O:BUG:SYD:P(A;;GA;;;WD)S:P(ML;;;;;SI)";
+constexpr wchar_t kFileProtected[] = L"D:P(A;;FA;;;WD)";
+constexpr wchar_t kFileIntegrity[] = L"S:(ML;;NW;;;ME)";
+constexpr wchar_t kFileIntegrityInherit[] = L"S:(ML;OICI;NW;;;ME)";
+constexpr wchar_t kFileProtectedIntegrity[] = L"D:P(A;;FA;;;WD)S:(ML;;NW;;;ME)";
+constexpr wchar_t kNewDirectory[] = L"D:P(A;OICI;FA;;;WD)";
+constexpr wchar_t kInheritedFile[] = L"D:(A;ID;FA;;;WD)";
+constexpr wchar_t kProtectedUsers[] = L"D:P(A;;FA;;;BU)";
+constexpr wchar_t kEvent[] = L"D:(A;;0x1f0003;;;WD)";
+constexpr wchar_t kEventWithSystem[] = L"D:(D;;DC;;;SY)(A;;0x1f0003;;;WD)";
+constexpr wchar_t kEventSystemOnly[] = L"D:(D;;DC;;;SY)";
+constexpr wchar_t kEventProtectedWithLabel[] =
+    L"D:P(A;;0x1f0003;;;WD)S:(ML;;NW;;;ME)";
+constexpr wchar_t kEventReadControl[] = L"D:(A;;RC;;;WD)";
+constexpr wchar_t kEventReadControlModify[] = L"D:(A;;DCRC;;;WD)";
+constexpr wchar_t kNullDacl[] = L"D:NO_ACCESS_CONTROL";
+constexpr wchar_t kEmptyDacl[] = L"D:";
+constexpr SECURITY_INFORMATION kAllSecurityInfo =
+    OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
+    DACL_SECURITY_INFORMATION | LABEL_SECURITY_INFORMATION;
+constexpr SECURITY_INFORMATION kDaclLabelSecurityInfo =
+    DACL_SECURITY_INFORMATION | LABEL_SECURITY_INFORMATION;
+
+base::win::ScopedLocalAllocTyped<void> ConvertSddlToSd(const wchar_t* sddl) {
+  PSECURITY_DESCRIPTOR sd = nullptr;
+  CHECK(ConvertStringSecurityDescriptorToSecurityDescriptor(
+      sddl, SDDL_REVISION_1, &sd, nullptr));
+  return TakeLocalAlloc(sd);
+}
+
+bool CreateFileWithSd(const FilePath& path, void* sd, bool directory) {
+  SECURITY_ATTRIBUTES security_attr = {};
+  security_attr.nLength = sizeof(security_attr);
+  security_attr.lpSecurityDescriptor = sd;
+  if (directory)
+    return !!::CreateDirectory(path.value().c_str(), &security_attr);
+
+  return ScopedHandle(::CreateFile(path.value().c_str(), GENERIC_ALL, 0,
+                                   &security_attr, CREATE_ALWAYS, 0, nullptr))
+      .is_valid();
+}
+
+bool CreateFileWithDacl(const FilePath& path,
+                        const wchar_t* sddl,
+                        bool directory) {
+  auto sd_ptr = ConvertSddlToSd(sddl);
+  CHECK(sd_ptr);
+  return CreateFileWithSd(path, sd_ptr.get(), directory);
+}
+
+base::win::ScopedHandle CreateEventWithDacl(const wchar_t* name,
+                                            const wchar_t* sddl) {
+  auto sd_ptr = ConvertSddlToSd(sddl);
+  CHECK(sd_ptr);
+  SECURITY_ATTRIBUTES security_attr = {};
+  security_attr.nLength = sizeof(security_attr);
+  security_attr.lpSecurityDescriptor = sd_ptr.get();
+  return base::win::ScopedHandle(
+      ::CreateEvent(&security_attr, FALSE, FALSE, name));
+}
+
+base::win::ScopedHandle DuplicateHandle(const base::win::ScopedHandle& handle,
+                                        DWORD access_mask) {
+  HANDLE dup_handle;
+  CHECK(::DuplicateHandle(::GetCurrentProcess(), handle.get(),
+                          ::GetCurrentProcess(), &dup_handle, access_mask,
+                          FALSE, 0));
+  return base::win::ScopedHandle(dup_handle);
+}
+
+void ExpectSid(const absl::optional<Sid>& sid, WellKnownSid known_sid) {
+  ASSERT_TRUE(sid);
+  auto compare_sid = Sid::FromKnownSid(known_sid);
+  ASSERT_TRUE(compare_sid);
+  EXPECT_EQ(*sid, *compare_sid);
+}
+
+}  // namespace
+
+TEST(SecurityDescriptorTest, Initialize) {
+  SecurityDescriptor sd;
+  EXPECT_FALSE(sd.owner());
+  EXPECT_FALSE(sd.group());
+  EXPECT_FALSE(sd.dacl());
+  EXPECT_FALSE(sd.dacl_protected());
+  EXPECT_FALSE(sd.sacl());
+  EXPECT_FALSE(sd.sacl_protected());
+
+  sd.set_owner(*Sid::FromKnownSid(WellKnownSid::kBuiltinUsers));
+  ExpectSid(sd.owner(), WellKnownSid::kBuiltinUsers);
+  sd.clear_owner();
+  EXPECT_FALSE(sd.owner());
+  sd.set_group(*Sid::FromKnownSid(WellKnownSid::kLocalSystem));
+  ExpectSid(sd.group(), WellKnownSid::kLocalSystem);
+  sd.clear_group();
+  EXPECT_FALSE(sd.group());
+  sd.set_dacl(AccessControlList());
+  EXPECT_TRUE(sd.dacl());
+  EXPECT_FALSE(sd.dacl()->is_null());
+  sd.clear_dacl();
+  EXPECT_FALSE(sd.dacl());
+  sd.set_sacl(AccessControlList());
+  EXPECT_TRUE(sd.sacl());
+  EXPECT_FALSE(sd.sacl()->is_null());
+  sd.clear_sacl();
+  EXPECT_FALSE(sd.sacl());
+}
+
+TEST(SecurityDescriptorTest, FromPointer) {
+  auto sd = SecurityDescriptor::FromPointer(nullptr);
+  EXPECT_FALSE(sd);
+  SECURITY_DESCRIPTOR sd_abs = {};
+  sd = SecurityDescriptor::FromPointer(&sd_abs);
+  EXPECT_FALSE(sd);
+  sd = SecurityDescriptor::FromPointer(ConvertSddlToSd(kOwnerOnly).get());
+  ASSERT_TRUE(sd);
+  ExpectSid(sd->owner(), WellKnownSid::kBuiltinUsers);
+  sd = SecurityDescriptor::FromPointer(ConvertSddlToSd(kGroupOnly).get());
+  ASSERT_TRUE(sd);
+  ExpectSid(sd->group(), WellKnownSid::kLocalSystem);
+  sd = SecurityDescriptor::FromPointer(ConvertSddlToSd(kDaclOnly).get());
+  ASSERT_TRUE(sd);
+  EXPECT_TRUE(sd->dacl());
+  EXPECT_FALSE(sd->dacl_protected());
+  sd = SecurityDescriptor::FromPointer(
+      ConvertSddlToSd(kProtectedDaclOnly).get());
+  ASSERT_TRUE(sd);
+  EXPECT_TRUE(sd->dacl());
+  EXPECT_TRUE(sd->dacl_protected());
+  sd = SecurityDescriptor::FromPointer(ConvertSddlToSd(kSaclOnly).get());
+  ASSERT_TRUE(sd);
+  EXPECT_TRUE(sd->sacl());
+  EXPECT_FALSE(sd->sacl_protected());
+  sd = SecurityDescriptor::FromPointer(
+      ConvertSddlToSd(kProtectedSaclOnly).get());
+  ASSERT_TRUE(sd);
+  EXPECT_TRUE(sd->sacl());
+  EXPECT_TRUE(sd->sacl_protected());
+  sd = SecurityDescriptor::FromPointer(ConvertSddlToSd(kFullSd).get());
+  ASSERT_TRUE(sd);
+  ExpectSid(sd->owner(), WellKnownSid::kBuiltinUsers);
+  ExpectSid(sd->group(), WellKnownSid::kLocalSystem);
+  EXPECT_TRUE(sd->dacl());
+  EXPECT_TRUE(sd->dacl_protected());
+  EXPECT_TRUE(sd->sacl());
+  EXPECT_TRUE(sd->sacl_protected());
+}
+
+TEST(SecurityDescriptorTest, ToSddl) {
+  auto sd = SecurityDescriptor::FromPointer(ConvertSddlToSd(kFullSd).get());
+  ASSERT_TRUE(sd);
+  EXPECT_EQ(sd->ToSddl(0), L"");
+  EXPECT_EQ(sd->ToSddl(OWNER_SECURITY_INFORMATION), kOwnerOnly);
+  EXPECT_EQ(sd->ToSddl(GROUP_SECURITY_INFORMATION), kGroupOnly);
+  EXPECT_EQ(sd->ToSddl(DACL_SECURITY_INFORMATION), kProtectedDaclOnly);
+  EXPECT_EQ(sd->ToSddl(LABEL_SECURITY_INFORMATION), kProtectedSaclOnly);
+  EXPECT_EQ(sd->ToSddl(SACL_SECURITY_INFORMATION), kSaclProtected);
+  EXPECT_EQ(sd->ToSddl(kAllSecurityInfo), kFullSd);
+  SecurityDescriptor empty_sd;
+  empty_sd.set_dacl(AccessControlList());
+  EXPECT_EQ(empty_sd.ToSddl(DACL_SECURITY_INFORMATION), kEmptyDacl);
+}
+
+TEST(SecurityDescriptorTest, FromSddl) {
+  auto sd = SecurityDescriptor::FromSddl(L"");
+  EXPECT_TRUE(sd);
+  EXPECT_FALSE(sd->owner());
+  EXPECT_FALSE(sd->group());
+  EXPECT_FALSE(sd->dacl());
+  EXPECT_FALSE(sd->sacl());
+  sd = SecurityDescriptor::FromSddl(kOwnerOnly);
+  ASSERT_TRUE(sd);
+  ExpectSid(sd->owner(), WellKnownSid::kBuiltinUsers);
+  sd = SecurityDescriptor::FromSddl(kGroupOnly);
+  ASSERT_TRUE(sd);
+  ExpectSid(sd->group(), WellKnownSid::kLocalSystem);
+  sd = SecurityDescriptor::FromSddl(kDaclOnly);
+  ASSERT_TRUE(sd);
+  EXPECT_TRUE(sd->dacl());
+  EXPECT_FALSE(sd->dacl_protected());
+  sd = SecurityDescriptor::FromSddl(kProtectedDaclOnly);
+  ASSERT_TRUE(sd);
+  EXPECT_TRUE(sd->dacl());
+  EXPECT_TRUE(sd->dacl_protected());
+  sd = SecurityDescriptor::FromSddl(kSaclOnly);
+  ASSERT_TRUE(sd);
+  EXPECT_TRUE(sd->sacl());
+  EXPECT_FALSE(sd->sacl_protected());
+  sd = SecurityDescriptor::FromSddl(kProtectedSaclOnly);
+  ASSERT_TRUE(sd);
+  EXPECT_TRUE(sd->sacl());
+  EXPECT_TRUE(sd->sacl_protected());
+  sd = SecurityDescriptor::FromSddl(kFullSd);
+  ASSERT_TRUE(sd);
+  ExpectSid(sd->owner(), WellKnownSid::kBuiltinUsers);
+  ExpectSid(sd->group(), WellKnownSid::kLocalSystem);
+  EXPECT_TRUE(sd->dacl());
+  EXPECT_TRUE(sd->dacl_protected());
+  EXPECT_TRUE(sd->sacl());
+  EXPECT_TRUE(sd->sacl_protected());
+  sd = SecurityDescriptor::FromSddl(kNullDacl);
+  ASSERT_TRUE(sd);
+  ASSERT_TRUE(sd->dacl());
+  EXPECT_TRUE(sd->dacl()->is_null());
+}
+
+TEST(SecurityDescriptorTest, Clone) {
+  SecurityDescriptor cloned = SecurityDescriptor().Clone();
+  EXPECT_FALSE(cloned.owner());
+  EXPECT_FALSE(cloned.group());
+  EXPECT_FALSE(cloned.dacl());
+  EXPECT_FALSE(cloned.dacl_protected());
+  EXPECT_FALSE(cloned.sacl());
+  EXPECT_FALSE(cloned.sacl_protected());
+  auto sd = SecurityDescriptor::FromSddl(kFullSd);
+  ASSERT_TRUE(sd);
+  cloned = sd->Clone();
+  EXPECT_EQ(sd->owner(), cloned.owner());
+  EXPECT_NE(sd->owner()->GetPSID(), cloned.owner()->GetPSID());
+  EXPECT_EQ(sd->group(), cloned.group());
+  EXPECT_NE(sd->group()->GetPSID(), cloned.group()->GetPSID());
+  EXPECT_NE(sd->dacl()->get(), cloned.dacl()->get());
+  EXPECT_EQ(sd->dacl_protected(), cloned.dacl_protected());
+  EXPECT_NE(sd->sacl()->get(), cloned.sacl()->get());
+  EXPECT_EQ(sd->sacl_protected(), cloned.sacl_protected());
+}
+
+TEST(SecurityDescriptorTest, ToAbsolute) {
+  auto sd = SecurityDescriptor::FromPointer(ConvertSddlToSd(kFullSd).get());
+  ASSERT_TRUE(sd);
+  SECURITY_DESCRIPTOR sd_abs;
+  sd->ToAbsolute(sd_abs);
+  EXPECT_EQ(sd_abs.Revision, SECURITY_DESCRIPTOR_REVISION);
+  EXPECT_EQ(sd_abs.Control, SE_DACL_PRESENT | SE_DACL_PROTECTED |
+                                SE_SACL_PRESENT | SE_SACL_PROTECTED);
+  EXPECT_EQ(sd_abs.Owner, sd->owner()->GetPSID());
+  EXPECT_EQ(sd_abs.Group, sd->group()->GetPSID());
+  EXPECT_EQ(sd_abs.Dacl, sd->dacl()->get());
+  EXPECT_EQ(sd_abs.Sacl, sd->sacl()->get());
+}
+
+TEST(SecurityDescriptorTest, ToSelfRelative) {
+  auto sd = SecurityDescriptor::FromPointer(ConvertSddlToSd(kFullSd).get());
+  ASSERT_TRUE(sd);
+  auto sd_rel = sd->ToSelfRelative();
+  ASSERT_TRUE(sd_rel);
+  EXPECT_TRUE(sd_rel->get());
+  EXPECT_EQ(sd_rel->size(), ::GetSecurityDescriptorLength(sd_rel->get()));
+  sd = SecurityDescriptor::FromPointer(sd_rel->get());
+  ASSERT_TRUE(sd);
+  EXPECT_EQ(sd->ToSddl(kAllSecurityInfo), kFullSd);
+}
+
+TEST(SecurityDescriptorTest, SetMandatoryLabel) {
+  SecurityDescriptor sd;
+  EXPECT_FALSE(sd.sacl());
+  sd.SetMandatoryLabel(SECURITY_MANDATORY_SYSTEM_RID, 0, 0);
+  EXPECT_TRUE(sd.sacl());
+  EXPECT_EQ(sd.ToSddl(LABEL_SECURITY_INFORMATION), kSaclOnly);
+  sd.SetMandatoryLabel(SECURITY_MANDATORY_MEDIUM_RID,
+                       OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE,
+                       SYSTEM_MANDATORY_LABEL_NO_WRITE_UP);
+  EXPECT_TRUE(sd.sacl());
+  EXPECT_EQ(sd.ToSddl(LABEL_SECURITY_INFORMATION), kFileIntegrityInherit);
+}
+
+TEST(SecurityDescriptorTest, SetDaclEntries) {
+  SecurityDescriptor sd;
+  EXPECT_FALSE(sd.dacl());
+  std::vector<ExplicitAccessEntry> ace_list;
+  EXPECT_TRUE(sd.SetDaclEntries(ace_list));
+  EXPECT_EQ(sd.ToSddl(DACL_SECURITY_INFORMATION), kEmptyDacl);
+  ace_list.emplace_back(*Sid::FromKnownSid(WellKnownSid::kWorld),
+                        SecurityAccessMode::kGrant, EVENT_ALL_ACCESS, 0);
+  EXPECT_TRUE(sd.SetDaclEntries(ace_list));
+  EXPECT_EQ(sd.ToSddl(DACL_SECURITY_INFORMATION), kEvent);
+  ace_list.emplace_back(*Sid::FromKnownSid(WellKnownSid::kLocalSystem),
+                        SecurityAccessMode::kDeny, EVENT_MODIFY_STATE, 0);
+  EXPECT_TRUE(sd.SetDaclEntries(ace_list));
+  EXPECT_EQ(sd.ToSddl(DACL_SECURITY_INFORMATION), kEventWithSystem);
+  ace_list.emplace_back(*Sid::FromKnownSid(WellKnownSid::kWorld),
+                        SecurityAccessMode::kRevoke, EVENT_MODIFY_STATE, 0);
+  EXPECT_TRUE(sd.SetDaclEntries(ace_list));
+  EXPECT_EQ(sd.ToSddl(DACL_SECURITY_INFORMATION), kEventSystemOnly);
+}
+
+TEST(SecurityDescriptorTest, SetDaclEntry) {
+  SecurityDescriptor sd;
+  EXPECT_TRUE(sd.SetDaclEntry(*Sid::FromKnownSid(WellKnownSid::kWorld),
+                              SecurityAccessMode::kGrant, READ_CONTROL, 0));
+  EXPECT_EQ(sd.ToSddl(DACL_SECURITY_INFORMATION), kEventReadControl);
+  EXPECT_TRUE(sd.SetDaclEntry(*Sid::FromKnownSid(WellKnownSid::kWorld),
+                              SecurityAccessMode::kGrant, EVENT_MODIFY_STATE,
+                              0));
+  EXPECT_EQ(sd.ToSddl(DACL_SECURITY_INFORMATION), kEventReadControlModify);
+  EXPECT_TRUE(sd.SetDaclEntry(*Sid::FromKnownSid(WellKnownSid::kWorld),
+                              SecurityAccessMode::kSet, EVENT_ALL_ACCESS, 0));
+  EXPECT_EQ(sd.ToSddl(DACL_SECURITY_INFORMATION), kEvent);
+  EXPECT_TRUE(sd.SetDaclEntry(*Sid::FromKnownSid(WellKnownSid::kLocalSystem),
+                              SecurityAccessMode::kDeny, EVENT_MODIFY_STATE,
+                              0));
+  EXPECT_EQ(sd.ToSddl(DACL_SECURITY_INFORMATION), kEventWithSystem);
+  EXPECT_TRUE(sd.SetDaclEntry(*Sid::FromKnownSid(WellKnownSid::kWorld),
+                              SecurityAccessMode::kRevoke, EVENT_ALL_ACCESS,
+                              0));
+  EXPECT_EQ(sd.ToSddl(DACL_SECURITY_INFORMATION), kEventSystemOnly);
+}
+
+TEST(SecurityDescriptorTest, FromFile) {
+  ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  FilePath path = temp_dir.GetPath().Append(L"test");
+  EXPECT_FALSE(SecurityDescriptor::FromFile(path, kAllSecurityInfo));
+  ASSERT_TRUE(CreateFileWithDacl(path, kFileProtectedIntegrity, false));
+  auto sd = SecurityDescriptor::FromFile(path, kAllSecurityInfo);
+  ASSERT_TRUE(sd);
+  EXPECT_EQ(sd->ToSddl(DACL_SECURITY_INFORMATION), kFileProtected);
+  sd = SecurityDescriptor::FromFile(path, LABEL_SECURITY_INFORMATION);
+  ASSERT_TRUE(sd);
+  EXPECT_EQ(sd->ToSddl(LABEL_SECURITY_INFORMATION), kFileIntegrity);
+  sd = SecurityDescriptor::FromFile(path, kAllSecurityInfo);
+  ASSERT_TRUE(sd);
+  EXPECT_EQ(sd->ToSddl(kDaclLabelSecurityInfo), kFileProtectedIntegrity);
+}
+
+TEST(SecurityDescriptorTest, WriteToFile) {
+  ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  FilePath dir_path = temp_dir.GetPath().Append(L"test");
+  ASSERT_TRUE(CreateFileWithDacl(dir_path, kNewDirectory, true));
+  FilePath path = dir_path.Append(L"test");
+  ASSERT_TRUE(CreateFileWithSd(path, nullptr, false));
+
+  auto curr_sd = SecurityDescriptor::FromFile(path, DACL_SECURITY_INFORMATION);
+  ASSERT_TRUE(curr_sd);
+  EXPECT_EQ(curr_sd->ToSddl(DACL_SECURITY_INFORMATION), kInheritedFile);
+
+  AccessControlList new_acl;
+  EXPECT_TRUE(new_acl.SetEntry(*Sid::FromKnownSid(WellKnownSid::kBuiltinUsers),
+                               SecurityAccessMode::kGrant, FILE_ALL_ACCESS, 0));
+  SecurityDescriptor new_sd;
+  new_sd.set_dacl(new_acl);
+  new_sd.set_dacl_protected(true);
+  EXPECT_TRUE(new_sd.WriteToFile(path, DACL_SECURITY_INFORMATION));
+  curr_sd = SecurityDescriptor::FromFile(path, DACL_SECURITY_INFORMATION);
+  ASSERT_TRUE(curr_sd);
+  EXPECT_EQ(curr_sd->ToSddl(DACL_SECURITY_INFORMATION), kProtectedUsers);
+
+  SecurityDescriptor empty_sd;
+  empty_sd.set_dacl(AccessControlList{});
+  EXPECT_TRUE(empty_sd.WriteToFile(path, DACL_SECURITY_INFORMATION));
+  curr_sd = SecurityDescriptor::FromFile(path, DACL_SECURITY_INFORMATION);
+  ASSERT_TRUE(curr_sd);
+  EXPECT_EQ(curr_sd->ToSddl(DACL_SECURITY_INFORMATION), kInheritedFile);
+
+  auto label_acl = AccessControlList::FromMandatoryLabel(
+      SECURITY_MANDATORY_MEDIUM_RID, 0, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP);
+  ASSERT_TRUE(label_acl);
+  SecurityDescriptor label_sd;
+  label_sd.set_sacl(*label_acl);
+  EXPECT_TRUE(label_sd.WriteToFile(path, LABEL_SECURITY_INFORMATION));
+  curr_sd = SecurityDescriptor::FromFile(path, LABEL_SECURITY_INFORMATION);
+  ASSERT_TRUE(curr_sd);
+  EXPECT_EQ(curr_sd->ToSddl(LABEL_SECURITY_INFORMATION), kFileIntegrity);
+}
+
+TEST(SecurityDescriptorTest, FromName) {
+  std::wstring name =
+      base::ASCIIToWide(base::UnguessableToken::Create().ToString());
+  EXPECT_FALSE(SecurityDescriptor::FromName(
+      name.c_str(), SecurityObjectType::kKernel, kAllSecurityInfo));
+  base::win::ScopedHandle handle = CreateEventWithDacl(name.c_str(), kEvent);
+  ASSERT_TRUE(handle.is_valid());
+  auto curr_sd = SecurityDescriptor::FromName(
+      name.c_str(), SecurityObjectType::kKernel, kAllSecurityInfo);
+  ASSERT_TRUE(curr_sd);
+  EXPECT_EQ(curr_sd->ToSddl(DACL_SECURITY_INFORMATION), kEvent);
+  EXPECT_TRUE(SecurityDescriptor::FromName(
+      L"MACHINE\\SOFTWARE", SecurityObjectType::kRegistry, kAllSecurityInfo));
+  EXPECT_TRUE(SecurityDescriptor::FromName(L".", SecurityObjectType::kFile,
+                                           kAllSecurityInfo));
+  EXPECT_FALSE(SecurityDescriptor::FromName(
+      L"Default", SecurityObjectType::kWindow, kAllSecurityInfo));
+}
+
+TEST(SecurityDescriptorTest, WriteToName) {
+  std::wstring name =
+      base::ASCIIToWide(base::UnguessableToken::Create().ToString());
+  EXPECT_FALSE(SecurityDescriptor().WriteToName(
+      name.c_str(), SecurityObjectType::kKernel, kAllSecurityInfo));
+  base::win::ScopedHandle handle = CreateEventWithDacl(name.c_str(), kEvent);
+  ASSERT_TRUE(handle.is_valid());
+  auto curr_sd = SecurityDescriptor::FromName(
+      name.c_str(), SecurityObjectType::kKernel, kAllSecurityInfo);
+  ASSERT_TRUE(curr_sd);
+  curr_sd->set_dacl_protected(true);
+  curr_sd->SetMandatoryLabel(SECURITY_MANDATORY_MEDIUM_RID, 0,
+                             SYSTEM_MANDATORY_LABEL_NO_WRITE_UP);
+
+  EXPECT_TRUE(curr_sd->WriteToName(name.c_str(), SecurityObjectType::kKernel,
+                                   kDaclLabelSecurityInfo));
+
+  curr_sd = SecurityDescriptor::FromName(
+      name.c_str(), SecurityObjectType::kKernel, kAllSecurityInfo);
+  ASSERT_TRUE(curr_sd);
+  EXPECT_EQ(curr_sd->ToSddl(kDaclLabelSecurityInfo), kEventProtectedWithLabel);
+}
+
+TEST(SecurityDescriptorTest, FromHandle) {
+  EXPECT_FALSE(SecurityDescriptor::FromHandle(
+      nullptr, SecurityObjectType::kKernel, kAllSecurityInfo));
+  auto handle = CreateEventWithDacl(nullptr, kEvent);
+  ASSERT_TRUE(handle.is_valid());
+  auto curr_sd = SecurityDescriptor::FromHandle(
+      handle.get(), SecurityObjectType::kKernel, kAllSecurityInfo);
+  ASSERT_TRUE(curr_sd);
+  EXPECT_EQ(curr_sd->ToSddl(DACL_SECURITY_INFORMATION), kEvent);
+  auto dup_handle = DuplicateHandle(handle, EVENT_MODIFY_STATE);
+  EXPECT_FALSE(SecurityDescriptor::FromHandle(
+      dup_handle.get(), SecurityObjectType::kKernel, kAllSecurityInfo));
+}
+
+TEST(SecurityDescriptorTest, WriteToHandle) {
+  EXPECT_FALSE(SecurityDescriptor().WriteToHandle(
+      nullptr, SecurityObjectType::kKernel, kAllSecurityInfo));
+  base::win::ScopedHandle handle = CreateEventWithDacl(nullptr, kEvent);
+  ASSERT_TRUE(handle.is_valid());
+  auto curr_sd = SecurityDescriptor::FromHandle(
+      handle.get(), SecurityObjectType::kKernel, kAllSecurityInfo);
+  EXPECT_EQ(curr_sd->ToSddl(DACL_SECURITY_INFORMATION), kEvent);
+  ASSERT_TRUE(curr_sd);
+  curr_sd->set_dacl_protected(true);
+  curr_sd->SetMandatoryLabel(SECURITY_MANDATORY_MEDIUM_RID, 0,
+                             SYSTEM_MANDATORY_LABEL_NO_WRITE_UP);
+
+  EXPECT_TRUE(curr_sd->WriteToHandle(handle.get(), SecurityObjectType::kKernel,
+                                     kDaclLabelSecurityInfo));
+
+  curr_sd = SecurityDescriptor::FromHandle(
+      handle.get(), SecurityObjectType::kKernel, kAllSecurityInfo);
+  ASSERT_TRUE(curr_sd);
+  EXPECT_EQ(curr_sd->ToSddl(kDaclLabelSecurityInfo), kEventProtectedWithLabel);
+}
+
+}  // namespace base::win
diff --git a/base/win/windows_types.h b/base/win/windows_types.h
index 542d343..380d6729 100644
--- a/base/win/windows_types.h
+++ b/base/win/windows_types.h
@@ -111,6 +111,8 @@
 typedef struct _SP_DEVINFO_DATA SP_DEVINFO_DATA;
 
 typedef PVOID PSID;
+typedef PVOID PSECURITY_DESCRIPTOR;
+typedef DWORD SECURITY_INFORMATION;
 
 typedef HANDLE HLOCAL;
 
@@ -129,6 +131,7 @@
 typedef struct _PROCESS_INFORMATION PROCESS_INFORMATION;
 typedef struct _SECURITY_CAPABILITIES SECURITY_CAPABILITIES;
 typedef struct _ACL ACL;
+typedef struct _SECURITY_DESCRIPTOR SECURITY_DESCRIPTOR;
 
 // Declare Chrome versions of some Windows structures. These are needed for
 // when we need a concrete type but don't want to pull in Windows.h. We can't
diff --git a/build/fuchsia/cipd/BUILD.gn b/build/fuchsia/cipd/BUILD.gn
index 5ed25961..f8c7e8a1 100644
--- a/build/fuchsia/cipd/BUILD.gn
+++ b/build/fuchsia/cipd/BUILD.gn
@@ -151,6 +151,7 @@
     sources = []
   }
   sources += get_target_outputs(":${target_name}_license")
+  sources += get_target_outputs(":${target_name}_license_spdx")
 
   fuchsia_cipd_package("${target_name}${_archive_suffix}") {
     package = "${package_base_path}/${package_subdirectory}/${targetarch}/${invoker.target_name}"
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1
index 82eb83b0..939bfed 100644
--- a/build/fuchsia/linux_internal.sdk.sha1
+++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@
-10.20221207.2.1
+10.20221207.3.1
diff --git a/buildtools/deps_revisions.gni b/buildtools/deps_revisions.gni
index d4f03c7..1048aa3 100644
--- a/buildtools/deps_revisions.gni
+++ b/buildtools/deps_revisions.gni
@@ -5,5 +5,5 @@
 declare_args() {
   # Used to cause full rebuilds on libc++ rolls. This should be kept in sync
   # with the libcxx_revision vars in //DEPS.
-  libcxx_revision = "a9779c11d2349375be0c29f7c42d9c42633297b5"
+  libcxx_revision = "e4e39cee1f5e89a9f9949084ba26a6efc3cd4141"
 }
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index f0690ee..bd059f3d 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -350,8 +350,6 @@
     "trees/compositor_mode.h",
     "trees/damage_tracker.cc",
     "trees/damage_tracker.h",
-    "trees/de_jelly_state.cc",
-    "trees/de_jelly_state.h",
     "trees/debug_rect_history.cc",
     "trees/debug_rect_history.h",
     "trees/draw_property_utils.cc",
diff --git a/cc/layers/render_surface_impl.cc b/cc/layers/render_surface_impl.cc
index adc750f..6158196 100644
--- a/cc/layers/render_surface_impl.cc
+++ b/cc/layers/render_surface_impl.cc
@@ -19,7 +19,6 @@
 #include "cc/trees/layer_tree_impl.h"
 #include "cc/trees/occlusion.h"
 #include "cc/trees/transform_node.h"
-#include "components/viz/common/display/de_jelly.h"
 #include "components/viz/common/quads/compositor_render_pass.h"
 #include "components/viz/common/quads/compositor_render_pass_draw_quad.h"
 #include "components/viz/common/quads/content_draw_quad_base.h"
@@ -261,10 +260,6 @@
   } else {
     clipped_accumulated_rect_in_target_space = clip_rect();
   }
-  if (layer_tree_impl_->settings().allow_de_jelly_effect) {
-    clipped_accumulated_rect_in_target_space.Inset(
-        gfx::Insets::VH(-viz::MaxDeJellyHeight(), 0));
-  }
   clipped_accumulated_rect_in_target_space.Intersect(
       accumulated_rect_in_target_space);
 
diff --git a/cc/trees/de_jelly_state.cc b/cc/trees/de_jelly_state.cc
deleted file mode 100644
index b9fe894..0000000
--- a/cc/trees/de_jelly_state.cc
+++ /dev/null
@@ -1,187 +0,0 @@
-// Copyright 2019 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/trees/de_jelly_state.h"
-
-#include <algorithm>
-#include <utility>
-
-#include "cc/trees/layer_tree_impl.h"
-#include "cc/trees/scroll_node.h"
-#include "cc/trees/transform_node.h"
-#include "components/viz/common/display/de_jelly.h"
-
-namespace cc {
-
-DeJellyState::DeJellyState() = default;
-DeJellyState::~DeJellyState() = default;
-
-void DeJellyState::AdvanceFrame(LayerTreeImpl* layer_tree_impl) {
-  if (!layer_tree_impl->settings().allow_de_jelly_effect)
-    return;
-
-  should_de_jelly_ = false;
-
-  // Move the |new_transforms_| from the previous draw into
-  // |previous_transforms_|.
-  std::swap(previous_transforms_, new_transforms_);
-  new_transforms_.clear();
-
-  // Make sure we have an active scroll node. Otherwise we won't perform any
-  // de-jelly.
-  const ScrollNode* current_scroll =
-      layer_tree_impl->property_trees()->scroll_tree().Node(
-          layer_tree_impl->property_trees()
-              ->scroll_tree()
-              .currently_scrolling_node());
-  if (!current_scroll) {
-    new_scroll_node_transform_.reset();
-    return;
-  }
-
-  scroll_transform_node_ = current_scroll->transform_id;
-
-  // Check to make sure the ToScreen transform of our scroll node is not a
-  // complex transform (doesn't work well with de-jelly). Also make sure the
-  // scale is not changing.
-  absl::optional<gfx::Transform> previous_scroll_transform =
-      new_scroll_node_transform_;
-  new_scroll_node_transform_ =
-      layer_tree_impl->property_trees()->transform_tree().ToScreen(
-          current_scroll->transform_id);
-  if (!previous_scroll_transform ||
-      !previous_scroll_transform->IsScaleOrTranslation() ||
-      !new_scroll_node_transform_->IsScaleOrTranslation() ||
-      new_scroll_node_transform_->To2dScale() !=
-          previous_scroll_transform->To2dScale()) {
-    return;
-  }
-
-  // Compute the fallback movement of a scrolling element based purely on the
-  // scroll offset of the currently scrolling node.
-  float previous_scroll_offset = scroll_offset_;
-  scroll_offset_ = layer_tree_impl->property_trees()
-                       ->transform_tree()
-                       .Node(scroll_transform_node_)
-                       ->scroll_offset.y();
-  float scroll_delta = scroll_offset_ - previous_scroll_offset;
-  fallback_delta_y_ =
-      new_scroll_node_transform_->MapVector(gfx::Vector3dF(0, scroll_delta, 0))
-          .y();
-
-  // Don't attempt de-jelly while the omnibox is transitioning in or out. There
-  // is no correct way to handle this.
-  float top_controls_shown_ratio =
-      layer_tree_impl->top_controls_shown_ratio()->Current(
-          true /* is_active_tree */);
-  if (top_controls_shown_ratio != 0.0f && top_controls_shown_ratio != 1.0f)
-    return;
-
-  // We've passed our initial checks, allow de-jelly in UpdateSharedQuadState.
-  should_de_jelly_ = true;
-}
-
-void DeJellyState::UpdateSharedQuadState(
-    LayerTreeImpl* layer_tree_impl,
-    int transform_id,
-    viz::CompositorRenderPass* target_render_pass) {
-  if (!should_de_jelly_)
-    return;
-  DCHECK(layer_tree_impl->settings().allow_de_jelly_effect);
-
-  viz::SharedQuadState* state =
-      target_render_pass->shared_quad_state_list.back();
-  state->de_jelly_delta_y = 0.0f;
-
-  // Check if |transform_id| is a child of our |scroll_transform_node_|
-  // and if it scrolls (is not sticky or fixed).
-  bool does_not_scroll = false;
-  auto node_id = transform_id;
-  while (node_id != scroll_transform_node_ && node_id != kInvalidNodeId) {
-    const auto* current_node =
-        layer_tree_impl->property_trees()->transform_tree().Node(node_id);
-
-    // Position fixed.
-    if (current_node->moved_by_outer_viewport_bounds_delta_y) {
-      does_not_scroll = true;
-      break;
-    }
-    // Position sticky.
-    if (current_node->sticky_position_constraint_id > -1) {
-      const StickyPositionNodeData* sticky_data =
-          layer_tree_impl->property_trees()
-              ->transform_tree()
-              .GetStickyPositionData(node_id);
-      if (sticky_data &&
-          sticky_data->total_containing_block_sticky_offset.y() > 0.0f) {
-        does_not_scroll = true;
-        break;
-      }
-    }
-
-    node_id = current_node->parent_id;
-  }
-  does_not_scroll |= node_id == kInvalidNodeId;
-  if (does_not_scroll)
-    return;
-
-  // Get the current node's ToScreen transform.
-  gfx::Transform transform =
-      layer_tree_impl->property_trees()->transform_tree().ToScreen(
-          transform_id);
-  new_transforms_[transform_id] = transform;
-
-  // Get the previous transform (if any).
-  const auto& found = previous_transforms_.find(transform_id);
-
-  float delta_y = 0.0f;
-  if (found == previous_transforms_.end()) {
-    delta_y = fallback_delta_y_;
-  } else {
-    // Calculate the delta of point (0, 0) from the previous frame.
-    gfx::Transform previous_transform = found->second;
-    gfx::PointF new_point = transform.MapPoint(gfx::PointF(0, 0));
-    gfx::PointF old_point = previous_transform.MapPoint(gfx::PointF(0, 0));
-    delta_y = old_point.y() - new_point.y();
-  }
-
-  if (delta_y == 0.0f) {
-    return;
-  }
-
-  // To minimize jarring visible effects, we de-jelly differently at
-  // different magnitudes of |delta_y|. This is controlled by three variables:
-  // kLinearDeJellyStart, kFixedDeJellyStart, kZeroDeJellyStart.
-  //                              _____________
-  //                  |     |    _/|           |
-  // de_jelly_delta_y |     |  _/  |           |
-  //                  |_____|_/    |           |_______________
-  //                  +----------------------------------------
-  //                        kLinear   kFixed          kZero
-  //
-  const float kLinearDeJellyStart = 2.0f;
-  const float kFixedDeJellyStart =
-      viz::MaxDeJellyHeight() + kLinearDeJellyStart;
-  const float kZeroDeJellyStart = 100.0f + kLinearDeJellyStart;
-  float sign = std::abs(delta_y) / delta_y;
-  float de_jelly_delta_y = std::abs(delta_y);
-  if (de_jelly_delta_y > kZeroDeJellyStart) {
-    de_jelly_delta_y = 0.0f;
-  } else if (de_jelly_delta_y > kFixedDeJellyStart) {
-    de_jelly_delta_y = kFixedDeJellyStart - kLinearDeJellyStart;
-  } else if (de_jelly_delta_y > kLinearDeJellyStart) {
-    de_jelly_delta_y = std::max(0.0f, de_jelly_delta_y - kLinearDeJellyStart);
-  } else {
-    de_jelly_delta_y = 0.0f;
-  }
-  // Re-apply the sign.
-  de_jelly_delta_y *= sign;
-  if (de_jelly_delta_y == 0.0f) {
-    return;
-  }
-
-  state->de_jelly_delta_y = de_jelly_delta_y;
-}
-
-}  // namespace cc
diff --git a/cc/trees/de_jelly_state.h b/cc/trees/de_jelly_state.h
deleted file mode 100644
index 934b019..0000000
--- a/cc/trees/de_jelly_state.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2019 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CC_TREES_DE_JELLY_STATE_H_
-#define CC_TREES_DE_JELLY_STATE_H_
-
-#include <map>
-
-#include "cc/cc_export.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "ui/gfx/geometry/transform.h"
-
-namespace viz {
-class SharedQuadState;
-class CompositorRenderPass;
-}  // namespace viz
-
-namespace cc {
-class LayerTreeImpl;
-
-// Helper class which tracks the movement of layers and renderpasses
-// and computes the |de_jelly_delta_y| for their SharedQuadState.
-class CC_EXPORT DeJellyState {
- public:
-  DeJellyState();
-  ~DeJellyState();
-
-  // Called once per frame to move tracking structure to the next frame and
-  // determine if we should apply de-jelly at all.
-  void AdvanceFrame(LayerTreeImpl* layer_tree_impl);
-
-  // Populates |de_jelly_delta_y| for the most recent SharedQuadState on
-  // |target_render_pass|.
-  void UpdateSharedQuadState(LayerTreeImpl* layer_tree_impl,
-                             int transform_id,
-                             viz::CompositorRenderPass* target_render_pass);
-
- private:
-  bool should_de_jelly_ = false;
-  int scroll_transform_node_ = 0;
-  float scroll_offset_ = 0;
-  float fallback_delta_y_ = 0;
-
-  absl::optional<gfx::Transform> new_scroll_node_transform_;
-  std::map<int, gfx::Transform> previous_transforms_;
-  std::map<int, gfx::Transform> new_transforms_;
-};
-
-}  // namespace cc
-
-#endif  // CC_TREES_DE_JELLY_STATE_H_
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc
index 56fefaa..332e826 100644
--- a/cc/trees/draw_property_utils.cc
+++ b/cc/trees/draw_property_utils.cc
@@ -32,7 +32,6 @@
 #include "cc/trees/scroll_node.h"
 #include "cc/trees/transform_node.h"
 #include "cc/trees/viewport_property_ids.h"
-#include "components/viz/common/display/de_jelly.h"
 #include "components/viz/common/view_transition_element_resource_id.h"
 #include "ui/gfx/geometry/rect_conversions.h"
 
@@ -711,13 +710,6 @@
   clip_in_layer_space.Offset(-layer->offset_to_transform_parent());
 
   gfx::Rect visible_rect = ToEnclosingClipRect(clip_in_layer_space);
-  if (layer->layer_tree_impl()->settings().allow_de_jelly_effect) {
-    float padding_amount = viz::MaxDeJellyHeight();
-    if (layer->IsAffectedByPageScale()) {
-      padding_amount /= layer->layer_tree_impl()->current_page_scale_factor();
-    }
-    visible_rect.Inset(gfx::Insets::VH(-padding_amount, 0.0f));
-  }
   visible_rect.Intersect(layer_content_rect);
   return visible_rect;
 }
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 8ec9af18..66b2943 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -1379,9 +1379,6 @@
   bool have_missing_animated_tiles = false;
   int num_of_layers_with_videos = 0;
 
-  // Advance our de-jelly state. This is a no-op if de-jelly is not active.
-  de_jelly_state_.AdvanceFrame(active_tree_.get());
-
   if (settings_.enable_compositing_based_throttling)
     throttle_decider_.Prepare();
   for (EffectTreeLayerListIterator it(active_tree());
@@ -1410,11 +1407,6 @@
       if (render_surface->contributes_to_drawn_surface()) {
         render_surface->AppendQuads(draw_mode, target_render_pass,
                                     &append_quads_data);
-        if (settings_.allow_de_jelly_effect) {
-          de_jelly_state_.UpdateSharedQuadState(
-              active_tree_.get(), render_surface->TransformTreeIndex(),
-              target_render_pass);
-        }
       }
     } else if (it.state() == EffectTreeLayerListIterator::State::LAYER) {
       LayerImpl* layer = it.current_layer();
@@ -1428,11 +1420,6 @@
         }
         layer->NotifyKnownResourceIdsBeforeAppendQuads(known_resource_ids);
         layer->AppendQuads(target_render_pass, &append_quads_data);
-        if (settings_.allow_de_jelly_effect) {
-          de_jelly_state_.UpdateSharedQuadState(active_tree_.get(),
-                                                layer->transform_tree_index(),
-                                                target_render_pass);
-        }
       } else {
         if (settings_.enable_compositing_based_throttling)
           throttle_decider_.ProcessLayerNotToDraw(layer);
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index fd3c731..568c240 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -45,7 +45,6 @@
 #include "cc/scheduler/video_frame_controller.h"
 #include "cc/tiles/tile_manager.h"
 #include "cc/trees/animated_paint_worklet_tracker.h"
-#include "cc/trees/de_jelly_state.h"
 #include "cc/trees/frame_rate_estimator.h"
 #include "cc/trees/layer_tree_frame_sink_client.h"
 #include "cc/trees/layer_tree_host.h"
@@ -1304,9 +1303,6 @@
 
   AverageLagTrackingManager lag_tracking_manager_;
 
-  // Helper for de-jelly logic.
-  DeJellyState de_jelly_state_;
-
   EventsMetricsManager events_metrics_manager_;
 
   std::unique_ptr<LCDTextMetricsReporter> lcd_text_metrics_reporter_;
diff --git a/cc/trees/layer_tree_settings.h b/cc/trees/layer_tree_settings.h
index 0df77c20..e4901842 100644
--- a/cc/trees/layer_tree_settings.h
+++ b/cc/trees/layer_tree_settings.h
@@ -181,9 +181,6 @@
   // Defaults to true.
   bool enable_occlusion = true;
 
-  // Whether experimental de-jelly effect is allowed.
-  bool allow_de_jelly_effect = false;
-
   // Whether the compositor should attempt to sync with the scroll handlers
   // before submitting a frame.
   bool enable_synchronized_scrolling = true;
diff --git a/chrome/VERSION b/chrome/VERSION
index 4cd556c..1530c7df 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=110
 MINOR=0
-BUILD=5465
+BUILD=5466
 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 3766812..793012b7 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -638,7 +638,6 @@
       "//components/variations:variations_java",
       "//components/variations/android:variations_java",
       "//components/version_info/android:version_constants_java",
-      "//components/viz/common:common_java",
       "//components/viz/service:service_java",
       "//components/webapk/android/libs/client:java",
       "//components/webapk/android/libs/common:java",
@@ -2666,7 +2665,6 @@
 
       # Deps needed for child processes.
       "//components/version_info/android:version_constants_java",
-      "//components/viz/common:common_java",
       "//components/viz/service:service_java",
       "//content/public/android:content_main_dex_java",
       "//media/base/android:media_java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/creator/CreatorActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/creator/CreatorActivity.java
index 5052c55..4f26754b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/app/creator/CreatorActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/app/creator/CreatorActivity.java
@@ -10,12 +10,19 @@
 
 import androidx.appcompat.widget.Toolbar;
 
+import org.chromium.base.supplier.ObservableSupplierImpl;
+import org.chromium.base.supplier.UnownedUserDataSupplier;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.ActivityTabProvider;
 import org.chromium.chrome.browser.SnackbarActivity;
 import org.chromium.chrome.browser.compositor.bottombar.ephemeraltab.EphemeralTabCoordinator;
 import org.chromium.chrome.browser.creator.CreatorCoordinator;
 import org.chromium.chrome.browser.feedback.HelpAndFeedbackLauncherImpl;
+import org.chromium.chrome.browser.init.ActivityLifecycleDispatcherImpl;
 import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.share.ShareDelegate;
+import org.chromium.chrome.browser.share.ShareDelegateImpl;
+import org.chromium.chrome.browser.share.ShareDelegateSupplier;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
 import org.chromium.components.browser_ui.widget.scrim.ScrimCoordinator;
 import org.chromium.ui.base.ActivityWindowAndroid;
@@ -29,29 +36,47 @@
     public static final String CREATOR_WEB_FEED_ID = "CREATOR_WEB_FEED_ID";
     public static final String CREATOR_TITLE = "CREATOR_TITLE";
     public static final String CREATOR_URL = "CREATOR_URL";
+
     private ActivityWindowAndroid mWindowAndroid;
     private BottomSheetController mBottomSheetController;
     private ViewGroup mBottomSheetContainer;
     private CreatorActionDelegateImpl mCreatorActionDelegate;
     private ScrimCoordinator mScrim;
     private EphemeralTabCoordinator mEphemeralTabCoordinator;
+    private ActivityTabProvider mActivityTabProvider;
+    private ActivityLifecycleDispatcherImpl mLifecycleDispatcher;
+    private UnownedUserDataSupplier<ShareDelegate> mShareDelegateSupplier;
+    private ObservableSupplierImpl<Profile> mProfileSupplier;
+    private Profile mProfile;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
         byte[] mWebFeedId = getIntent().getByteArrayExtra(CREATOR_WEB_FEED_ID);
         String mTitle = getIntent().getStringExtra(CREATOR_TITLE);
         String mUrl = getIntent().getStringExtra(CREATOR_URL);
+        mActivityTabProvider = new ActivityTabProvider();
+        mLifecycleDispatcher = new ActivityLifecycleDispatcherImpl(this);
+        mShareDelegateSupplier = new ShareDelegateSupplier();
+        mProfileSupplier = new ObservableSupplierImpl<>();
+        mProfile = Profile.getLastUsedRegularProfile();
+        mProfileSupplier.set(mProfile);
 
         super.onCreate(savedInstanceState);
         IntentRequestTracker intentRequestTracker = IntentRequestTracker.createFromActivity(this);
         mWindowAndroid = new ActivityWindowAndroid(this, false, intentRequestTracker);
-        CreatorCoordinator coordinator =
-                new CreatorCoordinator(this, mWebFeedId, getSnackbarManager(), mWindowAndroid,
-                        Profile.getLastUsedRegularProfile(), mTitle, mUrl);
+        CreatorCoordinator coordinator = new CreatorCoordinator(
+                this, mWebFeedId, getSnackbarManager(), mWindowAndroid, mProfile, mTitle, mUrl);
 
+        mBottomSheetController = coordinator.getBottomSheetController();
+        ShareDelegate shareDelegate = new ShareDelegateImpl(mBottomSheetController,
+                mLifecycleDispatcher, mActivityTabProvider,
+                /* tabModelSelectProvider */ new ObservableSupplierImpl<>(), mProfileSupplier,
+                new ShareDelegateImpl.ShareSheetDelegate(),
+                /* isCustomTab */ false);
+        mShareDelegateSupplier.set(shareDelegate);
         mCreatorActionDelegate = new CreatorActionDelegateImpl();
-        coordinator.initFeedStream(
-                mCreatorActionDelegate, HelpAndFeedbackLauncherImpl.getInstance());
+        coordinator.initFeedStream(mCreatorActionDelegate,
+                HelpAndFeedbackLauncherImpl.getInstance(), mShareDelegateSupplier);
 
         setContentView(coordinator.getView());
         Toolbar actionBar = findViewById(R.id.action_bar);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java
index 8b13667..a83385a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java
@@ -103,8 +103,6 @@
 import org.chromium.components.version_info.Channel;
 import org.chromium.components.version_info.VersionConstants;
 import org.chromium.components.version_info.VersionInfo;
-import org.chromium.components.viz.common.VizSwitches;
-import org.chromium.components.viz.common.display.DeJellyUtils;
 import org.chromium.components.webapps.AppBannerManager;
 import org.chromium.content_public.browser.BrowserTaskExecutor;
 import org.chromium.content_public.browser.ChildProcessLauncherHelper;
@@ -187,12 +185,6 @@
                 new AccountManagerFacadeImpl(AppHooks.get().createAccountManagerDelegate()));
 
         setProcessStateSummaryForAnrs(false);
-
-        // De-jelly can also be controlled by a system property. As sandboxed processes can't
-        // read this property directly, convert it to the equivalent command line flag.
-        if (DeJellyUtils.externallyEnableDeJelly()) {
-            CommandLine.getInstance().appendSwitch(VizSwitches.ENABLE_DE_JELLY);
-        }
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/RequestDesktopUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/RequestDesktopUtils.java
index fb625a3..36e4964 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/RequestDesktopUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/RequestDesktopUtils.java
@@ -86,6 +86,9 @@
             "opt_in_display_size_max_threshold_inches";
     static final double DEFAULT_GLOBAL_SETTING_OPT_IN_DISPLAY_SIZE_MAX_THRESHOLD_INCHES =
             Double.MAX_VALUE;
+    static final String PARAM_GLOBAL_SETTING_OPT_IN_SMALLEST_SCREEN_WIDTH =
+            "opt_in_smallest_screen_width";
+    static final int DEFAULT_GLOBAL_SETTING_OPT_IN_SMALLEST_SCREEN_WIDTH_THRESHOLD_DP = 600;
     static final String PARAM_GLOBAL_SETTING_OPT_IN_MEMORY_LIMIT = "opt_in_memory_limit";
     static final int DEFAULT_GLOBAL_SETTING_OPT_IN_MEMORY_LIMIT_THRESHOLD_MB = 0;
 
@@ -536,10 +539,11 @@
      * crbug.com/1362914 for details.
      * @param displaySizeInInches The device primary display size, in inches.
      * @param profile The current {@link Profile}.
+     * @param context The current context.
      * @return Whether the message to opt-in to the desktop site global setting should be shown.
      */
     static boolean shouldShowGlobalSettingOptInMessage(
-            double displaySizeInInches, Profile profile) {
+            double displaySizeInInches, Profile profile, Context context) {
         if (!ChromeFeatureList.isEnabled(ChromeFeatureList.REQUEST_DESKTOP_SITE_DEFAULTS)
                 && !ChromeFeatureList.isEnabled(
                         ChromeFeatureList.REQUEST_DESKTOP_SITE_DEFAULTS_CONTROL)) {
@@ -570,6 +574,14 @@
             return false;
         }
 
+        // If the smallest screen size in dp is below threshold, avoid presenting the message.
+        if (context.getResources().getConfiguration().smallestScreenWidthDp
+                < ChromeFeatureList.getFieldTrialParamByFeatureAsInt(feature,
+                        PARAM_GLOBAL_SETTING_OPT_IN_SMALLEST_SCREEN_WIDTH,
+                        DEFAULT_GLOBAL_SETTING_OPT_IN_SMALLEST_SCREEN_WIDTH_THRESHOLD_DP)) {
+            return false;
+        }
+
         // Present the message only if the desktop site global setting is off.
         if (WebsitePreferenceBridge.isCategoryEnabled(
                     profile, ContentSettingsType.REQUEST_DESKTOP_SITE)) {
@@ -626,7 +638,7 @@
             ObservableSupplier<Tab> currentTabSupplier) {
         if (messageDispatcher == null) return false;
 
-        if (!shouldShowGlobalSettingOptInMessage(displaySizeInInches, profile)) {
+        if (!shouldShowGlobalSettingOptInMessage(displaySizeInInches, profile, context)) {
             return false;
         }
 
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tab/RequestDesktopUtilsUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tab/RequestDesktopUtilsUnitTest.java
index acb8e0e..36ee7684 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/tab/RequestDesktopUtilsUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/tab/RequestDesktopUtilsUnitTest.java
@@ -674,7 +674,7 @@
 
         boolean shouldShowOptIn = RequestDesktopUtils.shouldShowGlobalSettingOptInMessage(
                 RequestDesktopUtils.DEFAULT_GLOBAL_SETTING_OPT_IN_DISPLAY_SIZE_MIN_THRESHOLD_INCHES,
-                mProfile);
+                mProfile, mActivity);
         Assert.assertFalse(
                 "Opt-in message for desktop site global setting should not be shown in the control experiment group.",
                 shouldShowOptIn);
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 683cb4e..94cb8422 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -12323,6 +12323,9 @@
       <message name="IDS_DEVICE_LOG_TYPE_CAMERA" desc="Checkbox to enable showing events of type Camera">
         Camera
       </message>
+      <message name="IDS_DEVICE_LOG_TYPE_GEOLOCATION" desc="Checkbox to enable showing events of type Geolocation">
+        Geolocation
+      </message>
       <message name="IDS_DEVICE_LOG_FILEINFO" desc="File info checkbox in device event log">
         File Info
       </message>
diff --git a/chrome/app/generated_resources_grd/IDS_DEVICE_LOG_TYPE_GEOLOCATION.png.sha1 b/chrome/app/generated_resources_grd/IDS_DEVICE_LOG_TYPE_GEOLOCATION.png.sha1
new file mode 100644
index 0000000..1b76500
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_DEVICE_LOG_TYPE_GEOLOCATION.png.sha1
@@ -0,0 +1 @@
+7684d0be772da65d6a0aeb98df6029bcc94ea7a4
\ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 7f022dd..65c1ee9 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -585,8 +585,6 @@
     "history/top_sites_factory.h",
     "history/web_history_service_factory.cc",
     "history/web_history_service_factory.h",
-    "history_clusters/entity_image_service.cc",
-    "history_clusters/entity_image_service.h",
     "history_clusters/history_clusters_metrics_logger.cc",
     "history_clusters/history_clusters_metrics_logger.h",
     "history_clusters/history_clusters_service_factory.cc",
@@ -2140,6 +2138,7 @@
     "//components/history/metrics",
     "//components/history_clusters/core",
     "//components/history_clusters/history_clusters_internals/webui",
+    "//components/image_service",
     "//components/infobars/content",
     "//components/infobars/core",
     "//components/invalidation/impl",
@@ -4091,8 +4090,6 @@
       "resource_coordinator/lifecycle_unit_source_base.cc",
       "resource_coordinator/lifecycle_unit_source_base.h",
       "resource_coordinator/lifecycle_unit_source_observer.h",
-      "resource_coordinator/tab_activity_watcher.cc",
-      "resource_coordinator/tab_activity_watcher.h",
       "resource_coordinator/tab_lifecycle_observer.h",
       "resource_coordinator/tab_lifecycle_unit.cc",
       "resource_coordinator/tab_lifecycle_unit.h",
@@ -8290,8 +8287,18 @@
     sources += [
       "apps/app_service/webapk/webapk_test_server.cc",
       "apps/app_service/webapk/webapk_test_server.h",
+      "ash/accessibility/caret_bounds_changed_waiter.cc",
+      "ash/accessibility/caret_bounds_changed_waiter.h",
+      "ash/accessibility/html_test_utils.cc",
+      "ash/accessibility/html_test_utils.h",
       "ash/accessibility/service/fake_accessibility_service.cc",
       "ash/accessibility/service/fake_accessibility_service.h",
+      "ash/app_list/test/chrome_app_list_test_support.cc",
+      "ash/app_list/test/chrome_app_list_test_support.h",
+      "ash/app_list/test/test_app_list_controller.cc",
+      "ash/app_list/test/test_app_list_controller.h",
+      "ash/app_list/test/test_app_list_controller_delegate.cc",
+      "ash/app_list/test/test_app_list_controller_delegate.h",
       "ash/app_mode/fake_cws.cc",
       "ash/app_mode/fake_cws.h",
       "ash/arc/extensions/fake_arc_support.cc",
@@ -8340,12 +8347,6 @@
       "sharesheet/sharesheet_test_util.h",
       "speech/speech_recognition_test_helper.cc",
       "speech/speech_recognition_test_helper.h",
-      "ui/app_list/test/chrome_app_list_test_support.cc",
-      "ui/app_list/test/chrome_app_list_test_support.h",
-      "ui/app_list/test/test_app_list_controller.cc",
-      "ui/app_list/test/test_app_list_controller.h",
-      "ui/app_list/test/test_app_list_controller_delegate.cc",
-      "ui/app_list/test/test_app_list_controller_delegate.h",
     ]
     configs += [ "//build/config/linux/dbus" ]
     deps += [
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index 42874b2..cf1310e 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -167,6 +167,7 @@
   "+components/history/core/test",
   "+components/history/metrics",
   "+components/image_fetcher/core",
+  "+components/image_service",
   "+components/infobars/android",
   "+components/infobars/content",
   "+components/infobars/core",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 3e1b3a61..f188f6a9 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -34,6 +34,7 @@
 #include "cc/base/features.h"
 #include "cc/base/switches.h"
 #include "chrome/browser/ash/android_sms/android_sms_switches.h"
+#include "chrome/browser/ash/app_list/search/files/item_suggest_cache.h"
 #include "chrome/browser/browser_features.h"
 #include "chrome/browser/fast_checkout/fast_checkout_features.h"
 #include "chrome/browser/feature_guide/notifications/feature_notification_guide_service.h"
@@ -59,7 +60,6 @@
 #include "chrome/browser/sharing_hub/sharing_hub_features.h"
 #include "chrome/browser/signin/signin_features.h"
 #include "chrome/browser/site_isolation/about_flags.h"
-#include "chrome/browser/ui/app_list/search/files/item_suggest_cache.h"
 #include "chrome/browser/ui/app_list/search/search_features.h"
 #include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/ui_features.h"
@@ -8526,6 +8526,10 @@
      flag_descriptions::kHttpsOnlyModeDescription, kOsDesktop | kOsAndroid,
      FEATURE_VALUE_TYPE(features::kHttpsOnlyMode)},
 
+    {"https-upgrades", flag_descriptions::kHttpsUpgradesName,
+     flag_descriptions::kHttpsUpgradesDescription, kOsDesktop | kOsAndroid,
+     FEATURE_VALUE_TYPE(features::kHttpsUpgrades)},
+
 #if BUILDFLAG(IS_WIN)
     {"win-10-tab-search-caption-button",
      flag_descriptions::kWin10TabSearchCaptionButtonName,
diff --git a/chrome/browser/accessibility/ax_screen_ai_annotator.cc b/chrome/browser/accessibility/ax_screen_ai_annotator.cc
index 807d7b8a..9b7c94d 100644
--- a/chrome/browser/accessibility/ax_screen_ai_annotator.cc
+++ b/chrome/browser/accessibility/ax_screen_ai_annotator.cc
@@ -124,13 +124,13 @@
 
   base::UmaHistogramTimes(
       "Accessibility.ScreenAI.AnnotateScreenshotTime.Success", elapsed_time);
-  screen_ai_annotator_->Annotate(
+  screen_ai_annotator_->ExtractSemanticLayout(
       snapshot.AsBitmap(), ax_tree_id,
-      base::BindOnce(&AXScreenAIAnnotator::OnAnnotationPerformed,
+      base::BindOnce(&AXScreenAIAnnotator::OnSemanticLayoutExtractionPerformed,
                      weak_ptr_factory_.GetWeakPtr(), ax_tree_id));
 }
 
-void AXScreenAIAnnotator::OnAnnotationPerformed(
+void AXScreenAIAnnotator::OnSemanticLayoutExtractionPerformed(
     const ui::AXTreeID& parent_tree_id,
     const ui::AXTreeID& screen_ai_tree_id) {
   VLOG(2) << base::StrCat({"AXScreenAIAnnotator received tree ids: parent: ",
diff --git a/chrome/browser/accessibility/ax_screen_ai_annotator.h b/chrome/browser/accessibility/ax_screen_ai_annotator.h
index 0ba34a3b..7aee868 100644
--- a/chrome/browser/accessibility/ax_screen_ai_annotator.h
+++ b/chrome/browser/accessibility/ax_screen_ai_annotator.h
@@ -65,12 +65,13 @@
                                     gfx::Image snapshot);
 
   // Informs this instance that the Screen AI Service has finished creating the
-  // visual annotations. `parent_tree_id` is the ID of the accessibility tree
+  // semantic layout. `parent_tree_id` is the ID of the accessibility tree
   // associated with the screenshot that was sent to the Screen AI Service, and
   // `screen_ai_tree_id` is the ID of the accessibility tree that has been
   // created by the Service, containing the visual annotations.
-  void OnAnnotationPerformed(const ui::AXTreeID& parent_tree_id,
-                             const ui::AXTreeID& screen_ai_tree_id);
+  void OnSemanticLayoutExtractionPerformed(
+      const ui::AXTreeID& parent_tree_id,
+      const ui::AXTreeID& screen_ai_tree_id);
 
   // mojom::ScreenAIAnnotatorClient:
   void HandleAXTreeUpdate(const ui::AXTreeUpdate& update) override;
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 1a02baa..e994e40b 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
@@ -10,6 +10,7 @@
 #include "services/data_decoder/public/cpp/data_decoder.h"
 #include "ui/base/layout.h"
 #include "ui/gfx/codec/png_codec.h"
+#include "ui/gfx/image/image_skia_rep.h"
 
 namespace {
 
diff --git a/chrome/browser/apps/app_service/app_icon/app_icon_factory.cc b/chrome/browser/apps/app_service/app_icon/app_icon_factory.cc
index 76565aed..acfd4c1 100644
--- a/chrome/browser/apps/app_service/app_icon/app_icon_factory.cc
+++ b/chrome/browser/apps/app_service/app_icon/app_icon_factory.cc
@@ -37,6 +37,7 @@
 #include "ui/gfx/image/image.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/image/image_skia_operations.h"
+#include "ui/gfx/image/image_skia_rep.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/grit/app_icon_resources.h"
@@ -510,6 +511,24 @@
   icon_loader->GetWebAppCompressedIconData(web_app_id, scale_factor,
                                            web_app_provider->icon_manager());
 }
+
+void GetChromeAppCompressedIconData(content::BrowserContext* context,
+                                    const std::string& extension_id,
+                                    IconType icon_type,
+                                    int size_in_dip,
+                                    ui::ResourceScaleFactor scale_factor,
+                                    LoadIconCallback callback) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  scoped_refptr<AppIconLoader> icon_loader =
+      base::MakeRefCounted<AppIconLoader>(
+          icon_type, size_in_dip, /*is_placeholder_icon=*/false,
+          IconEffects::kNone, kInvalidIconResource, std::move(callback));
+  icon_loader->GetChromeAppCompressedIconData(
+      extensions::ExtensionRegistry::Get(context)->GetInstalledExtension(
+          extension_id),
+      context, scale_factor);
+}
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 void LoadIconFromFileWithFallback(
diff --git a/chrome/browser/apps/app_service/app_icon/app_icon_factory.h b/chrome/browser/apps/app_service/app_icon/app_icon_factory.h
index 8eb4cf9..1b2ce3d 100644
--- a/chrome/browser/apps/app_service/app_icon/app_icon_factory.h
+++ b/chrome/browser/apps/app_service/app_icon/app_icon_factory.h
@@ -107,13 +107,22 @@
                         LoadIconCallback callback);
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-// Requests a compressed icon data for an web app identified by `app_id`.
+// Requests a compressed icon data for an web app identified by `web_app_id`.
 void GetWebAppCompressedIconData(content::BrowserContext* context,
                                  const std::string& web_app_id,
                                  IconType icon_type,
                                  int size_in_dip,
                                  ui::ResourceScaleFactor scale_factor,
                                  LoadIconCallback callback);
+
+// Requests a compressed icon data for a chrome app identified by
+// `extension_id`.
+void GetChromeAppCompressedIconData(content::BrowserContext* context,
+                                    const std::string& extension_id,
+                                    IconType icon_type,
+                                    int size_in_dip,
+                                    ui::ResourceScaleFactor scale_factor,
+                                    LoadIconCallback callback);
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 // Loads an icon from a FilePath. If that fails, it calls the fallback.
diff --git a/chrome/browser/apps/app_service/app_icon/app_icon_factory_unittest.cc b/chrome/browser/apps/app_service/app_icon/app_icon_factory_unittest.cc
index 989835c..e628c1e 100644
--- a/chrome/browser/apps/app_service/app_icon/app_icon_factory_unittest.cc
+++ b/chrome/browser/apps/app_service/app_icon/app_icon_factory_unittest.cc
@@ -29,6 +29,7 @@
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/codec/png_codec.h"
 #include "ui/gfx/image/image_skia_operations.h"
+#include "ui/gfx/image/image_skia_rep.h"
 #include "ui/gfx/image/image_unittest_util.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/apps/app_service/app_icon/app_icon_loader.cc b/chrome/browser/apps/app_service/app_icon/app_icon_loader.cc
index 4fddcef..c57bee9 100644
--- a/chrome/browser/apps/app_service/app_icon/app_icon_loader.cc
+++ b/chrome/browser/apps/app_service/app_icon/app_icon_loader.cc
@@ -45,6 +45,7 @@
 #include "ui/gfx/image/image.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/image/image_skia_operations.h"
+#include "ui/gfx/image/image_skia_rep.h"
 #include "url/gurl.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
@@ -603,6 +604,26 @@
                      base::WrapRefCounted(this)));
 }
 
+void AppIconLoader::GetChromeAppCompressedIconData(
+    const extensions::Extension* extension,
+    content::BrowserContext* context,
+    ui::ResourceScaleFactor scale_factor) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+  if (!extension || icon_type_ == IconType::kUnknown) {
+    MaybeLoadFallbackOrCompleteEmpty();
+    return;
+  }
+
+  icon_scale_ = ui::GetScaleForResourceScaleFactor(scale_factor);
+  profile_ = Profile::FromBrowserContext(context);
+  extensions::ImageLoader::Get(context)->LoadImageAtEveryScaleFactorAsync(
+      extension, gfx::Size(size_hint_in_dip_, size_hint_in_dip_),
+      ImageToImageSkia(
+          base::BindOnce(&AppIconLoader::OnReadChromeAppForCompressedIconData,
+                         base::WrapRefCounted(this))));
+}
+
 std::unique_ptr<arc::IconDecodeRequest>
 AppIconLoader::CreateArcIconDecodeRequest(
     base::OnceCallback<void(const gfx::ImageSkia& icon)> callback,
@@ -799,6 +820,20 @@
                      base::WrapRefCounted(this)));
 }
 
+void AppIconLoader::OnReadChromeAppForCompressedIconData(gfx::ImageSkia image) {
+  if (image.isNull()) {
+    MaybeLoadFallbackOrCompleteEmpty();
+    return;
+  }
+
+  image.MakeThreadSafe();
+  base::ThreadPool::PostTaskAndReplyWithResult(
+      FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+      base::BindOnce(&apps::EncodeImageToPngBytes, image, icon_scale_),
+      base::BindOnce(&AppIconLoader::CompleteWithCompressed,
+                     base::WrapRefCounted(this)));
+}
+
 void AppIconLoader::MaybeLoadFallbackOrCompleteEmpty() {
   if (fallback_favicon_url_.is_valid() &&
       icon_size_in_px_ == kFaviconFallbackImagePx) {
diff --git a/chrome/browser/apps/app_service/app_icon/app_icon_loader.h b/chrome/browser/apps/app_service/app_icon/app_icon_loader.h
index 5491fe1..faf87b8 100644
--- a/chrome/browser/apps/app_service/app_icon/app_icon_loader.h
+++ b/chrome/browser/apps/app_service/app_icon/app_icon_loader.h
@@ -114,10 +114,16 @@
       const std::vector<arc::mojom::ActivityIconPtr>& icons);
 
   // Requests a compressed icon data with `scale_factor` for an web app
-  // identified by `app_id`.
+  // identified by `web_app_id`.
   void GetWebAppCompressedIconData(const std::string& web_app_id,
                                    ui::ResourceScaleFactor scale_factor,
                                    web_app::WebAppIconManager& icon_manager);
+
+  // Requests a compressed icon data with `scale_factor` for a chrome app
+  // identified by `extension`.
+  void GetChromeAppCompressedIconData(const extensions::Extension* extension,
+                                      content::BrowserContext* context,
+                                      ui::ResourceScaleFactor scale_factor);
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
  private:
@@ -151,6 +157,8 @@
 
   void OnReadWebAppForCompressedIconData(std::map<int, SkBitmap> icon_bitmaps);
 
+  void OnReadChromeAppForCompressedIconData(gfx::ImageSkia image);
+
   void MaybeLoadFallbackOrCompleteEmpty();
 
   const IconType icon_type_ = IconType::kUnknown;
diff --git a/chrome/browser/apps/app_service/app_icon/app_icon_source.cc b/chrome/browser/apps/app_service/app_icon/app_icon_source.cc
index adcdfca..11bddda 100644
--- a/chrome/browser/apps/app_service/app_icon/app_icon_source.cc
+++ b/chrome/browser/apps/app_service/app_icon/app_icon_source.cc
@@ -8,6 +8,7 @@
 
 #include "base/bind.h"
 #include "base/callback.h"
+#include "base/memory/ref_counted_memory.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
diff --git a/chrome/browser/apps/app_service/app_icon/app_icon_test_util.cc b/chrome/browser/apps/app_service/app_icon/app_icon_test_util.cc
index de4059d..bda689a 100644
--- a/chrome/browser/apps/app_service/app_icon/app_icon_test_util.cc
+++ b/chrome/browser/apps/app_service/app_icon/app_icon_test_util.cc
@@ -11,6 +11,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/layout.h"
 #include "ui/gfx/image/image_skia.h"
+#include "ui/gfx/image/image_skia_rep.h"
 #include "ui/gfx/image/image_unittest_util.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/apps/app_service/app_icon/chrome_apps_icon_unittest.cc b/chrome/browser/apps/app_service/app_icon/chrome_apps_icon_unittest.cc
index cc74867..ed9af07 100644
--- a/chrome/browser/apps/app_service/app_icon/chrome_apps_icon_unittest.cc
+++ b/chrome/browser/apps/app_service/app_icon/chrome_apps_icon_unittest.cc
@@ -85,12 +85,12 @@
   }
 
   void GenerateExtensionAppCompressedIcon(const std::string app_id,
+                                          float scale,
                                           std::vector<uint8_t>& result,
                                           bool skip_effects = false) {
     gfx::ImageSkia image_skia;
     GenerateExtensionAppIcon(app_id, image_skia, skip_effects);
 
-    const float scale = 1.0;
     const gfx::ImageSkiaRep& image_skia_rep =
         image_skia.GetRepresentation(scale);
     ASSERT_EQ(image_skia_rep.scale(), scale);
@@ -109,6 +109,19 @@
                                 icon_effects, result.GetCallback());
     return result.Take();
   }
+
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  apps::IconValuePtr GetCompressedIconData(
+      const std::string& app_id,
+      IconType icon_type,
+      ui::ResourceScaleFactor scale_factor) {
+    base::test::TestFuture<apps::IconValuePtr> result;
+    apps::GetChromeAppCompressedIconData(profile(), app_id, icon_type,
+                                         kSizeInDip, scale_factor,
+                                         result.GetCallback());
+    return result.Take();
+  }
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 };
 
 TEST_F(ChromeAppsIconFactoryTest, LoadUncompressedIcon) {
@@ -138,7 +151,7 @@
 TEST_F(ChromeAppsIconFactoryTest, LoadCompressedIcon) {
   // Generate the source compressed icon for comparing.
   std::vector<uint8_t> src_data;
-  GenerateExtensionAppCompressedIcon(kPackagedApp1Id, src_data);
+  GenerateExtensionAppCompressedIcon(kPackagedApp1Id, /*scale=*/1.0, src_data);
 
   IconValuePtr iv = LoadIconFromExtension(
       kPackagedApp1Id, IconType::kCompressed, IconEffects::kCrOsStandardIcon);
@@ -150,7 +163,7 @@
 TEST_F(ChromeAppsIconFactoryTest, LoadCompressedIconWithoutEffect) {
   // Generate the source compressed icon for comparing.
   std::vector<uint8_t> src_data;
-  GenerateExtensionAppCompressedIcon(kPackagedApp1Id, src_data,
+  GenerateExtensionAppCompressedIcon(kPackagedApp1Id, /*scale=*/1.0, src_data,
                                      /*skip_effects=*/true);
 
   IconValuePtr iv = LoadIconFromExtension(
@@ -160,4 +173,56 @@
   VerifyCompressedIcon(src_data, *iv);
 }
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+TEST_F(ChromeAppsIconFactoryTest, GetCompressedIconDataForUncompressedIcon) {
+  // Generate the source uncompressed icon for comparing.
+  std::vector<uint8_t> src_data1;
+  std::vector<uint8_t> src_data2;
+  GenerateExtensionAppCompressedIcon(kPackagedApp1Id, /*scale=*/1.0, src_data1,
+                                     /*skip_effects=*/true);
+  GenerateExtensionAppCompressedIcon(kPackagedApp1Id, /*scale=*/2.0, src_data2,
+                                     /*skip_effects=*/true);
+
+  IconValuePtr icon1 =
+      GetCompressedIconData(kPackagedApp1Id, IconType::kUncompressed,
+                            ui::ResourceScaleFactor::k100Percent);
+  IconValuePtr icon2 =
+      GetCompressedIconData(kPackagedApp1Id, IconType::kUncompressed,
+                            ui::ResourceScaleFactor::k200Percent);
+  VerifyCompressedIcon(src_data1, *icon1);
+  VerifyCompressedIcon(src_data2, *icon2);
+}
+
+TEST_F(ChromeAppsIconFactoryTest, GetCompressedIconDataForStandardIcon) {
+  // Generate the source uncompressed icon for comparing.
+  std::vector<uint8_t> src_data1;
+  std::vector<uint8_t> src_data2;
+  GenerateExtensionAppCompressedIcon(kPackagedApp1Id, /*scale=*/1.0, src_data1,
+                                     /*skip_effects=*/true);
+  GenerateExtensionAppCompressedIcon(kPackagedApp1Id, /*scale=*/2.0, src_data2,
+                                     /*skip_effects=*/true);
+
+  IconValuePtr icon1 =
+      GetCompressedIconData(kPackagedApp1Id, IconType::kStandard,
+                            ui::ResourceScaleFactor::k100Percent);
+  IconValuePtr icon2 =
+      GetCompressedIconData(kPackagedApp1Id, IconType::kStandard,
+                            ui::ResourceScaleFactor::k200Percent);
+  VerifyCompressedIcon(src_data1, *icon1);
+  VerifyCompressedIcon(src_data2, *icon2);
+}
+
+TEST_F(ChromeAppsIconFactoryTest, GetCompressedIconDataForCompressedIcon) {
+  // Generate the source compressed icon for comparing.
+  std::vector<uint8_t> src_data;
+  GenerateExtensionAppCompressedIcon(kPackagedApp1Id, /*scale=*/1.0, src_data,
+                                     /*skip_effects=*/true);
+
+  IconValuePtr icon =
+      GetCompressedIconData(kPackagedApp1Id, IconType::kCompressed,
+                            ui::ResourceScaleFactor::k100Percent);
+  VerifyCompressedIcon(src_data, *icon);
+}
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+
 }  // namespace apps
diff --git a/chrome/browser/apps/app_service/app_icon/web_app_icon_unittest.cc b/chrome/browser/apps/app_service/app_icon/web_app_icon_unittest.cc
index a5646a70..405b8f4 100644
--- a/chrome/browser/apps/app_service/app_icon/web_app_icon_unittest.cc
+++ b/chrome/browser/apps/app_service/app_icon/web_app_icon_unittest.cc
@@ -47,6 +47,7 @@
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/codec/png_codec.h"
 #include "ui/gfx/image/image_skia_operations.h"
+#include "ui/gfx/image/image_skia_rep.h"
 #include "ui/gfx/image/image_unittest_util.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/apps/app_service/app_service_test.cc b/chrome/browser/apps/app_service/app_service_test.cc
index 9dd50ad..0bb27b8 100644
--- a/chrome/browser/apps/app_service/app_service_test.cc
+++ b/chrome/browser/apps/app_service/app_service_test.cc
@@ -8,6 +8,7 @@
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "components/services/app_service/public/cpp/icon_types.h"
+#include "ui/gfx/image/image_skia_rep.h"
 #include "ui/gfx/image/image_unittest_util.h"
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/apps/app_service/metrics/app_platform_metrics.h b/chrome/browser/apps/app_service/metrics/app_platform_metrics.h
index 3445a07..34f5c3b1 100644
--- a/chrome/browser/apps/app_service/metrics/app_platform_metrics.h
+++ b/chrome/browser/apps/app_service/metrics/app_platform_metrics.h
@@ -13,6 +13,7 @@
 #include "base/observer_list_types.h"
 #include "base/time/time.h"
 #include "base/unguessable_token.h"
+#include "base/values.h"
 #include "chrome/browser/apps/app_service/metrics/app_platform_metrics_utils.h"
 #include "chrome/browser/apps/app_service/metrics/browser_to_tab_list.h"
 #include "components/services/app_service/public/cpp/app_launch_util.h"
diff --git a/chrome/browser/apps/app_service/metrics/website_metrics.cc b/chrome/browser/apps/app_service/metrics/website_metrics.cc
index 7594e53..b83d71a 100644
--- a/chrome/browser/apps/app_service/metrics/website_metrics.cc
+++ b/chrome/browser/apps/app_service/metrics/website_metrics.cc
@@ -273,7 +273,8 @@
 
   std::map<GURL, UrlInfo> url_infos;
   for (const auto& it : webcontents_to_ukm_key_) {
-    if (!base::Contains(url_infos, it.second)) {
+    if (!base::Contains(url_infos, it.second) && !it.second.is_empty() &&
+        it.second.SchemeIsHTTPOrHTTPS()) {
       url_infos[it.second] = std::move(url_infos_[it.second]);
     }
   }
@@ -430,9 +431,10 @@
   // When the primary page of `web_contents` is changed called by
   // contents::WebContentsObserver::PrimaryPageChanged(), set the visible url as
   // default value for the ukm key url.
-  webcontents_to_ukm_key_[web_contents] = web_contents->GetVisibleURL();
+  auto url = web_contents->GetVisibleURL();
+  webcontents_to_ukm_key_[web_contents] = url;
 
-  if (web_contents->GetVisibleURL().is_empty()) {
+  if (url.is_empty() || !url.SchemeIsHTTPOrHTTPS()) {
     return;
   }
 
@@ -513,6 +515,10 @@
     url_infos_.erase(old_url);
   }
 
+  if (new_url.is_empty() || !new_url.SchemeIsHTTPOrHTTPS()) {
+    return;
+  }
+
   AddUrlInfo(new_url, start_time, url_content, is_activated, promotable);
   url_infos_[new_url].running_time_in_five_minutes =
       running_time_in_five_minutes;
@@ -613,13 +619,17 @@
   const base::Value::Dict& usage_time =
       profile_->GetPrefs()->GetDict(kWebsiteUsageTime);
 
-  for (const auto [url, url_info_value] : usage_time) {
-    if (url.empty()) {
+  for (const auto [urlstr, url_info_value] : usage_time) {
+    if (urlstr.empty()) {
+      continue;
+    }
+    auto url = GURL(urlstr);
+    if (!url.SchemeIsHTTPOrHTTPS()) {
       continue;
     }
     auto url_info = std::make_unique<UrlInfo>(url_info_value);
     if (!url_info->running_time_in_two_hours.is_zero()) {
-      EmitUkm(GURL(url), url_info->running_time_in_two_hours.InMilliseconds(),
+      EmitUkm(url, url_info->running_time_in_two_hours.InMilliseconds(),
               url_info->url_content, url_info->promotable,
               /*is_from_last_login=*/true);
     }
@@ -633,8 +643,9 @@
                              bool is_from_last_login) {
   auto source_id = ukm::UkmRecorder::GetSourceIdForWebsiteUrl(
       base::PassKey<WebsiteMetrics>(), url);
-  if (url.is_empty() || ukm::SourceIdObj::FromInt64(source_id).GetType() !=
-                            ukm::SourceIdType::DESKTOP_WEB_APP_ID) {
+  if (url.is_empty() || !url.SchemeIsHTTPOrHTTPS() ||
+      ukm::SourceIdObj::FromInt64(source_id).GetType() !=
+          ukm::SourceIdType::DESKTOP_WEB_APP_ID) {
     LOG(ERROR) << "WebsiteMetrics::EmitUkm url is " << url.spec()
                << ", source id type is "
                << (int)ukm::SourceIdObj::FromInt64(source_id).GetType();
diff --git a/chrome/browser/apps/app_service/publishers/built_in_chromeos_apps.cc b/chrome/browser/apps/app_service/publishers/built_in_chromeos_apps.cc
index be712e2c..b1a4eeca 100644
--- a/chrome/browser/apps/app_service/publishers/built_in_chromeos_apps.cc
+++ b/chrome/browser/apps/app_service/publishers/built_in_chromeos_apps.cc
@@ -17,8 +17,8 @@
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/menu_util.h"
 #include "chrome/browser/apps/app_service/metrics/app_service_metrics.h"
+#include "chrome/browser/ash/app_list/internal_app/internal_app_metadata.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/app_list/internal_app/internal_app_metadata.h"
 #include "chrome/browser/ui/settings_window_manager_chromeos.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/services/app_service/public/cpp/app_types.h"
diff --git a/chrome/browser/apps/app_service/publishers/publisher_unittest.cc b/chrome/browser/apps/app_service/publishers/publisher_unittest.cc
index 9a393879..061a877 100644
--- a/chrome/browser/apps/app_service/publishers/publisher_unittest.cc
+++ b/chrome/browser/apps/app_service/publishers/publisher_unittest.cc
@@ -47,11 +47,11 @@
 #include "chrome/browser/apps/app_service/publishers/web_apps_crosapi.h"
 #include "chrome/browser/apps/app_service/publishers/web_apps_crosapi_factory.h"
 #include "chrome/browser/ash/app_list/arc/arc_app_test.h"
+#include "chrome/browser/ash/app_list/internal_app/internal_app_metadata.h"
 #include "chrome/browser/ash/borealis/borealis_util.h"
 #include "chrome/browser/ash/crosapi/browser_util.h"
 #include "chrome/browser/ash/crosapi/fake_browser_manager.h"
 #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
-#include "chrome/browser/ui/app_list/internal_app/internal_app_metadata.h"
 #include "chrome/common/chrome_features.h"
 #include "chromeos/ash/components/login/login_state/login_state.h"
 #include "components/services/app_service/public/cpp/app_capability_access_cache.h"
@@ -72,12 +72,12 @@
     const std::string& url,
     const std::string& id) {
   std::string err;
-  base::DictionaryValue value;
-  value.SetStringKey("name", name);
-  value.SetStringKey("version", version);
+  base::Value::Dict value;
+  value.Set("name", name);
+  value.Set("version", version);
   base::ListValue scripts;
   scripts.Append("script.js");
-  value.SetPath("app.background.scripts", std::move(scripts));
+  value.SetByDottedPath("app.background.scripts", std::move(scripts));
   scoped_refptr<extensions::Extension> app = extensions::Extension::Create(
       base::FilePath(), extensions::mojom::ManifestLocation::kInternal, value,
       extensions::Extension::WAS_INSTALLED_BY_DEFAULT, id, &err);
@@ -95,10 +95,10 @@
     const std::string& url,
     const std::string& id) {
   std::string err;
-  base::DictionaryValue value;
-  value.SetStringKey("name", name);
-  value.SetStringKey("version", version);
-  value.SetStringPath("app.launch.local_path", "index.html");
+  base::Value::Dict value;
+  value.Set("name", name);
+  value.Set("version", version);
+  value.SetByDottedPath("app.launch.local_path", "index.html");
   scoped_refptr<extensions::Extension> app = extensions::Extension::Create(
       base::FilePath(), extensions::mojom::ManifestLocation::kInternal, value,
       extensions::Extension::WAS_INSTALLED_BY_DEFAULT, id, &err);
diff --git a/chrome/browser/apps/app_service/webapk/webapk_install_task.cc b/chrome/browser/apps/app_service/webapk/webapk_install_task.cc
index 6959c92..ae4e319 100644
--- a/chrome/browser/apps/app_service/webapk/webapk_install_task.cc
+++ b/chrome/browser/apps/app_service/webapk/webapk_install_task.cc
@@ -266,7 +266,7 @@
     return;
   }
 
-  auto& registrar = web_app_provider_->registrar();
+  auto& registrar = web_app_provider_->registrar_unsafe();
 
   // Installation & share target are already checked in WebApkManager, check
   // again in case anything changed while the install request was queued.
@@ -366,7 +366,7 @@
   // sending has been resized and so doesn't exactly match any of the images in
   // the manifest. Since we can't be perfect, it's okay to be roughly correct
   // and just send any URL of the correct purpose.
-  auto& registrar = web_app_provider_->registrar();
+  auto& registrar = web_app_provider_->registrar_unsafe();
   const auto& manifest_icons = registrar.GetAppIconInfos(app_id_);
   auto it = base::ranges::find_if(
       manifest_icons, [&icon_size_and_purpose](const apps::IconInfo& info) {
diff --git a/chrome/browser/apps/app_service/webapk/webapk_utils.cc b/chrome/browser/apps/app_service/webapk/webapk_utils.cc
index dc4e22c..c882f7ed 100644
--- a/chrome/browser/apps/app_service/webapk/webapk_utils.cc
+++ b/chrome/browser/apps/app_service/webapk/webapk_utils.cc
@@ -79,7 +79,7 @@
                             const std::string& app_id,
                             webapk::WebAppManifest* web_app_manifest) {
   auto* provider = web_app::WebAppProvider::GetForWebApps(profile);
-  auto& registrar = provider->registrar();
+  auto& registrar = provider->registrar_unsafe();
 
   // TODO(crbug.com/1254199): Call WebAppRegistrar::GetAppById(const AppId&
   // app_id) instead of performing repeated app_id lookups.
@@ -133,7 +133,7 @@
     return;
   }
 
-  auto& registrar = provider->registrar();
+  auto& registrar = provider->registrar_unsafe();
 
   // TODO(crbug.com/1254199): Call WebAppRegistrar::GetAppById(const AppId&
   // app_id) instead of performing repeated app_id lookups.
diff --git a/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.cc b/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.cc
index fc306c9..9316e5b 100644
--- a/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.cc
+++ b/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.cc
@@ -126,15 +126,14 @@
                      file_launches, profile, allowed);
 
   if (remember_user_choice) {
+    WebAppProvider* provider = WebAppProvider::GetForWebApps(profile);
     if (protocol_url) {
-      PersistProtocolHandlersUserChoice(profile, app_id, *protocol_url, allowed,
-                                        std::move(persist_done));
+      provider->scheduler().UpdateProtocolHandlerUserApproval(
+          app_id, protocol_url->scheme(), allowed, std::move(persist_done));
     } else {
       DCHECK(is_file_launch);
-      WebAppProvider::GetForWebApps(profile)
-          ->scheduler()
-          .PersistFileHandlersUserChoice(app_id, allowed,
-                                         std::move(persist_done));
+      provider->scheduler().PersistFileHandlersUserChoice(
+          app_id, allowed, std::move(persist_done));
     }
   } else {
     std::move(persist_done).Run();
diff --git a/chrome/browser/apps/digital_goods/digital_goods_lacros.cc b/chrome/browser/apps/digital_goods/digital_goods_lacros.cc
index 6bf9c3a..b7459921 100644
--- a/chrome/browser/apps/digital_goods/digital_goods_lacros.cc
+++ b/chrome/browser/apps/digital_goods/digital_goods_lacros.cc
@@ -28,7 +28,7 @@
     return absl::nullopt;
   }
 
-  const web_app::WebAppRegistrar& registrar = provider->registrar();
+  const web_app::WebAppRegistrar& registrar = provider->registrar_unsafe();
   absl::optional<web_app::AppId> app_id = registrar.FindAppWithUrlInScope(
       render_frame_host.GetMainFrame()->GetLastCommittedURL());
   if (!app_id) {
diff --git a/chrome/browser/apps/digital_goods/util.cc b/chrome/browser/apps/digital_goods/util.cc
index cb69950..ac4870b 100644
--- a/chrome/browser/apps/digital_goods/util.cc
+++ b/chrome/browser/apps/digital_goods/util.cc
@@ -52,7 +52,7 @@
     return std::string();
   }
 
-  const web_app::WebAppRegistrar& registrar = provider->registrar();
+  const web_app::WebAppRegistrar& registrar = provider->registrar_unsafe();
   absl::optional<web_app::AppId> app_id = registrar.FindAppWithUrlInScope(
       render_frame_host->GetMainFrame()->GetLastCommittedURL());
   if (!app_id) {
diff --git a/chrome/browser/ash/accessibility/autoclick_browsertest.cc b/chrome/browser/ash/accessibility/autoclick_browsertest.cc
new file mode 100644
index 0000000..41bf4851
--- /dev/null
+++ b/chrome/browser/ash/accessibility/autoclick_browsertest.cc
@@ -0,0 +1,368 @@
+// 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 "ash/accessibility/autoclick/autoclick_controller.h"
+#include "ash/accessibility/ui/accessibility_focus_ring_controller_impl.h"
+#include "ash/accessibility/ui/accessibility_focus_ring_layer.h"
+#include "ash/constants/ash_pref_names.h"
+#include "ash/public/cpp/accessibility_controller_enums.h"
+#include "ash/shell.h"
+#include "ash/system/accessibility/autoclick_menu_bubble_controller.h"
+#include "ash/system/accessibility/autoclick_menu_view.h"
+#include "base/test/bind.h"
+#include "build/branding_buildflags.h"
+#include "build/build_config.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/ash/accessibility/accessibility_manager.h"
+#include "chrome/browser/ash/accessibility/accessibility_test_utils.h"
+#include "chrome/browser/ash/accessibility/caret_bounds_changed_waiter.h"
+#include "chrome/browser/ash/accessibility/html_test_utils.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/renderer_context_menu/render_view_context_menu_browsertest_util.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/common/extensions/extension_constants.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "components/prefs/pref_service.h"
+#include "content/public/test/accessibility_notification_waiter.h"
+#include "content/public/test/browser_test.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_utils.h"
+#include "extensions/browser/browsertest_util.h"
+#include "extensions/browser/extension_host.h"
+#include "extensions/browser/extension_host_test_helper.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/events/test/event_generator.h"
+#include "url/url_constants.h"
+
+namespace ash {
+
+class AutoclickBrowserTest : public InProcessBrowserTest {
+ public:
+  AutoclickBrowserTest(const AutoclickBrowserTest&) = delete;
+  AutoclickBrowserTest& operator=(const AutoclickBrowserTest&) = delete;
+
+ protected:
+  AutoclickBrowserTest() = default;
+  ~AutoclickBrowserTest() override = default;
+
+  // InProcessBrowserTest:
+  void SetUpOnMainThread() override {
+    ASSERT_FALSE(AccessibilityManager::Get()->IsAutoclickEnabled());
+    console_observer_ = std::make_unique<ExtensionConsoleErrorObserver>(
+        browser()->profile(), extension_misc::kAccessibilityCommonExtensionId);
+
+    aura::Window* root_window = Shell::Get()->GetPrimaryRootWindow();
+    generator_ = std::make_unique<ui::test::EventGenerator>(root_window);
+
+    SetAutoclickDelayMs(5);
+
+    pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>();
+    pref_change_registrar_->Init(browser()->profile()->GetPrefs());
+    pref_change_registrar_->Add(
+        prefs::kAccessibilityAutoclickEventType,
+        base::BindRepeating(&AutoclickBrowserTest::OnEventTypePrefChanged,
+                            GetWeakPtr()));
+
+    ASSERT_TRUE(
+        ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)));
+  }
+
+  void TearDownOnMainThread() override { pref_change_registrar_.reset(); }
+
+  content::WebContents* GetWebContents() {
+    return browser()->tab_strip_model()->GetActiveWebContents();
+  }
+
+  // Loads a page with the given URL and then starts up Autoclick.
+  void LoadURLAndAutoclick(const std::string& url) {
+    content::AccessibilityNotificationWaiter waiter(
+        GetWebContents(), ui::kAXModeComplete, ax::mojom::Event::kLoadComplete);
+    ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL(url)));
+    ASSERT_TRUE(waiter.WaitForNotification());
+
+    extensions::ExtensionHostTestHelper host_helper(
+        browser()->profile(), extension_misc::kAccessibilityCommonExtensionId);
+    AccessibilityManager::Get()->EnableAutoclick(true);
+    Shell::Get()
+        ->autoclick_controller()
+        ->GetMenuBubbleControllerForTesting()
+        ->SetAnimateForTesting(false);
+    host_helper.WaitForHostCompletedFirstLoad();
+    WaitForAutoclickReady();
+  }
+
+  void WaitForAutoclickReady() {
+    base::ScopedAllowBlockingForTesting allow_blocking;
+    std::string script = base::StringPrintf(R"JS(
+      (async function() {
+        window.accessibilityCommon.setAutoclickLoadCallbackForTest(() => {
+            window.domAutomationController.send('ready');
+          });
+      })();
+    )JS");
+    std::string result =
+        extensions::browsertest_util::ExecuteScriptInBackgroundPage(
+            browser()->profile(),
+            extension_misc::kAccessibilityCommonExtensionId, script);
+    ASSERT_EQ("ready", result);
+  }
+
+  void SetAutoclickDelayMs(int ms) {
+    PrefService* prefs = browser()->profile()->GetPrefs();
+    prefs->SetInteger(prefs::kAccessibilityAutoclickDelayMs, ms);
+  }
+
+  void OnEventTypePrefChanged() {
+    if (pref_change_waiter_)
+      std::move(pref_change_waiter_).Run();
+  }
+
+  // Performs a hover over the autoclick menu to change the event type.
+  void SetAutoclickEventType(AutoclickEventType type) {
+    // Check if we already have the right type selected.
+    PrefService* prefs = browser()->profile()->GetPrefs();
+    if (prefs->GetInteger(prefs::kAccessibilityAutoclickEventType) ==
+        static_cast<int>(type)) {
+      return;
+    }
+
+    // Find the menu button.
+    AutoclickMenuView::ButtonId button_id;
+    switch (type) {
+      case AutoclickEventType::kLeftClick:
+        button_id = AutoclickMenuView::ButtonId::kLeftClick;
+        break;
+      case AutoclickEventType::kRightClick:
+        button_id = AutoclickMenuView::ButtonId::kRightClick;
+        break;
+      case AutoclickEventType::kDoubleClick:
+        button_id = AutoclickMenuView::ButtonId::kDoubleClick;
+        break;
+      case AutoclickEventType::kDragAndDrop:
+        button_id = AutoclickMenuView::ButtonId::kDragAndDrop;
+        break;
+      case AutoclickEventType::kScroll:
+        button_id = AutoclickMenuView::ButtonId::kScroll;
+        break;
+      case AutoclickEventType::kNoAction:
+        button_id = AutoclickMenuView::ButtonId::kPause;
+        break;
+    }
+    AutoclickMenuView* menu_view = Shell::Get()
+                                       ->autoclick_controller()
+                                       ->GetMenuBubbleControllerForTesting()
+                                       ->menu_view_;
+    ASSERT_NE(nullptr, menu_view);
+    auto* button_view = menu_view->GetViewByID(static_cast<int>(button_id));
+    ASSERT_NE(nullptr, button_view);
+
+    // Hover over it.
+    const gfx::Rect bounds = button_view->GetBoundsInScreen();
+    generator_->MoveMouseTo(bounds.CenterPoint());
+
+    // Wait for the pref change, indicating the button was pressed.
+    base::RunLoop runner;
+    pref_change_waiter_ = runner.QuitClosure();
+    runner.Run();
+  }
+
+  void HoverOverHtmlElement(const std::string& element) {
+    const gfx::Rect bounds = GetControlBoundsInRoot(GetWebContents(), element);
+    generator_->MoveMouseTo(bounds.CenterPoint());
+  }
+
+  base::WeakPtr<AutoclickBrowserTest> GetWeakPtr() {
+    return weak_ptr_factory_.GetWeakPtr();
+  }
+
+  std::unique_ptr<ui::test::EventGenerator> generator_;
+
+ private:
+  std::unique_ptr<ExtensionConsoleErrorObserver> console_observer_;
+  std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_;
+  base::OnceClosure pref_change_waiter_;
+  base::WeakPtrFactory<AutoclickBrowserTest> weak_ptr_factory_{this};
+};
+
+IN_PROC_BROWSER_TEST_F(AutoclickBrowserTest, LeftClickButtonOnHover) {
+  LoadURLAndAutoclick(R"(
+        data:text/html;charset=utf-8,
+        <input type="button" id="test_button"
+               onclick="window.open();" value="click me">
+      )");
+  // No need to change click type: Default should be right-click.
+  ui_test_utils::TabAddedWaiter tab_waiter(browser());
+  HoverOverHtmlElement("test_button");
+  tab_waiter.Wait();
+}
+
+IN_PROC_BROWSER_TEST_F(AutoclickBrowserTest, DoubleClickHover) {
+  LoadURLAndAutoclick(R"(
+      data:text/html;charset=utf-8,
+      <input type="text" id="text_field"
+             value="peanutbuttersandwichmadewithjam">
+      )");
+  SetAutoclickEventType(AutoclickEventType::kDoubleClick);
+
+  content::AccessibilityNotificationWaiter selection_waiter(
+      browser()->tab_strip_model()->GetActiveWebContents(), ui::kAXModeComplete,
+      ui::AXEventGenerator::Event::TEXT_SELECTION_CHANGED);
+  content::BoundingBoxUpdateWaiter bounding_box_waiter(GetWebContents());
+
+  // Double-clicking over the text field should result in the text being
+  // selected.
+  HoverOverHtmlElement("text_field");
+
+  bounding_box_waiter.Wait();
+  ASSERT_TRUE(selection_waiter.WaitForNotification());
+}
+
+IN_PROC_BROWSER_TEST_F(AutoclickBrowserTest, ClickAndDrag) {
+  LoadURLAndAutoclick(R"(
+      data:text/html;charset=utf-8,
+      <input type="text" id="text_field"
+             value="peanutbuttersandwichmadewithjam">
+      )");
+  SetAutoclickEventType(AutoclickEventType::kDragAndDrop);
+
+  const gfx::Rect bounds =
+      GetControlBoundsInRoot(GetWebContents(), "text_field");
+
+  content::AccessibilityNotificationWaiter selection_waiter(
+      browser()->tab_strip_model()->GetActiveWebContents(), ui::kAXModeComplete,
+      ui::AXEventGenerator::Event::TEXT_SELECTION_CHANGED);
+
+  // First hover causes a down click even that changes the caret.
+  CaretBoundsChangedWaiter caret_waiter(
+      browser()->window()->GetNativeWindow()->GetHost()->GetInputMethod());
+  generator_->MoveMouseTo(
+      gfx::Point(bounds.left_center().y(), bounds.x() + 10));
+  caret_waiter.Wait();
+  ASSERT_TRUE(selection_waiter.WaitForNotification());
+
+  // Second hover causes a selection.
+  content::BoundingBoxUpdateWaiter bounding_box_waiter(GetWebContents());
+  generator_->MoveMouseTo(bounds.right_center());
+  bounding_box_waiter.Wait();
+  ASSERT_TRUE(selection_waiter.WaitForNotification());
+}
+
+IN_PROC_BROWSER_TEST_F(AutoclickBrowserTest,
+                       RightClickOnHoverOpensContextMenu) {
+  LoadURLAndAutoclick(R"(
+      data:text/html;charset=utf-8,
+      <input type="text" id="text_field" value="stop copying me">
+      )");
+  SetAutoclickEventType(AutoclickEventType::kRightClick);
+
+  ContextMenuWaiter context_menu_waiter;
+
+  // Right clicking over the text field should result in a context menu.
+  HoverOverHtmlElement("text_field");
+
+  context_menu_waiter.WaitForMenuOpenAndClose();
+
+  // Since we right-clicked on a context menu, the copy/paste commands were
+  // included.
+  EXPECT_THAT(context_menu_waiter.GetCapturedCommandIds(),
+              testing::IsSupersetOf(
+                  {IDC_CONTENT_CONTEXT_COPY, IDC_CONTENT_CONTEXT_PASTE}));
+}
+
+// TODO(b/261462562): Fix flaky crash and enable.
+IN_PROC_BROWSER_TEST_F(AutoclickBrowserTest,
+                       DISABLED_ScrollHoverHighlightsScrollableArea) {
+  // Create a callback for the focus ring observer.
+  base::RunLoop runner;
+  base::RepeatingCallback<void()> callback =
+      base::BindLambdaForTesting([&runner]() { runner.Quit(); });
+  AccessibilityManager::Get()->SetFocusRingObserverForTest(callback);
+
+  LoadURLAndAutoclick(R"(
+      data:text/html;charset=utf-8,
+      <textarea id="test_textarea" rows="2" cols="20">"Whatever you
+          choose to do, leave tracks. That means don't do it just for
+          yourself. You will want to leave the world a little better
+          for your havinglived."</textarea>
+      )");
+
+  AccessibilityFocusRingControllerImpl* controller =
+      Shell::Get()->accessibility_focus_ring_controller();
+  std::string focus_ring_id = AccessibilityManager::Get()->GetFocusRingId(
+      extension_misc::kAccessibilityCommonExtensionId, "");
+  const AccessibilityFocusRingGroup* focus_ring_group =
+      controller->GetFocusRingGroupForTesting(focus_ring_id);
+  // No focus rings to start.
+  EXPECT_EQ(nullptr, focus_ring_group);
+
+  SetAutoclickEventType(AutoclickEventType::kScroll);
+
+  HoverOverHtmlElement("test_textarea");
+  runner.Run();
+
+  focus_ring_group = controller->GetFocusRingGroupForTesting(focus_ring_id);
+  ASSERT_NE(nullptr, focus_ring_group);
+  std::vector<std::unique_ptr<AccessibilityFocusRingLayer>> const& focus_rings =
+      focus_ring_group->focus_layers_for_testing();
+  ASSERT_EQ(focus_rings.size(), 1u);
+}
+
+IN_PROC_BROWSER_TEST_F(AutoclickBrowserTest, LongDelay) {
+  SetAutoclickDelayMs(500);
+  LoadURLAndAutoclick(R"(
+        data:text/html;charset=utf-8,
+        <input type="button" id="test_button"
+               onclick="window.open();" value="click me">
+      )");
+
+  ui_test_utils::TabAddedWaiter tab_waiter(browser());
+  base::ElapsedTimer timer;
+  HoverOverHtmlElement("test_button");
+  tab_waiter.Wait();
+  EXPECT_GT(timer.Elapsed().InMilliseconds(), 500);
+}
+
+IN_PROC_BROWSER_TEST_F(AutoclickBrowserTest, ShortDelay) {
+  SetAutoclickDelayMs(5);
+  LoadURLAndAutoclick(R"(
+        data:text/html;charset=utf-8,
+        <input type="button" id="test_button"
+               onclick="window.open();" value="click me">
+      )");
+
+  ui_test_utils::TabAddedWaiter tab_waiter(browser());
+  base::ElapsedTimer timer;
+  HoverOverHtmlElement("test_button");
+  tab_waiter.Wait();
+  // Seems to take around 100 ms, so let's check 500 ms to be safe.
+  EXPECT_LT(timer.Elapsed().InMilliseconds(), 500);
+  EXPECT_EQ(2, browser()->tab_strip_model()->GetTabCount());
+}
+
+IN_PROC_BROWSER_TEST_F(AutoclickBrowserTest, PauseAutoclick) {
+  SetAutoclickDelayMs(5);
+  LoadURLAndAutoclick(R"(
+        data:text/html;charset=utf-8,
+        <input type="button" id="test_button"
+               onclick="window.open();" value="click me">
+      )");
+  SetAutoclickEventType(AutoclickEventType::kNoAction);
+
+  base::OneShotTimer timer;
+  base::RunLoop runner;
+  HoverOverHtmlElement("test_button");
+  timer.Start(FROM_HERE, base::Milliseconds(500),
+              base::BindLambdaForTesting([&runner, this]() {
+                runner.Quit();
+                // Because the test above passes, we know that this would have
+                // resulted in an action before 500 ms if autoclick was not
+                // paused.
+                EXPECT_EQ(1, browser()->tab_strip_model()->GetTabCount());
+              }));
+  runner.Run();
+}
+
+}  // namespace ash
diff --git a/chrome/browser/ash/accessibility/caret_bounds_changed_waiter.cc b/chrome/browser/ash/accessibility/caret_bounds_changed_waiter.cc
new file mode 100644
index 0000000..138fffb
--- /dev/null
+++ b/chrome/browser/ash/accessibility/caret_bounds_changed_waiter.cc
@@ -0,0 +1,27 @@
+// 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/accessibility/caret_bounds_changed_waiter.h"
+
+namespace ash {
+
+CaretBoundsChangedWaiter::CaretBoundsChangedWaiter(
+    ui::InputMethod* input_method)
+    : input_method_(input_method) {
+  input_method_->AddObserver(this);
+}
+CaretBoundsChangedWaiter::~CaretBoundsChangedWaiter() {
+  input_method_->RemoveObserver(this);
+}
+
+void CaretBoundsChangedWaiter::Wait() {
+  run_loop_.Run();
+}
+
+void CaretBoundsChangedWaiter::OnCaretBoundsChanged(
+    const ui::TextInputClient* client) {
+  run_loop_.Quit();
+}
+
+}  // namespace ash
diff --git a/chrome/browser/ash/accessibility/caret_bounds_changed_waiter.h b/chrome/browser/ash/accessibility/caret_bounds_changed_waiter.h
new file mode 100644
index 0000000..0583af2
--- /dev/null
+++ b/chrome/browser/ash/accessibility/caret_bounds_changed_waiter.h
@@ -0,0 +1,39 @@
+// 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_ACCESSIBILITY_CARET_BOUNDS_CHANGED_WAITER_H_
+#define CHROME_BROWSER_ASH_ACCESSIBILITY_CARET_BOUNDS_CHANGED_WAITER_H_
+
+#include "base/run_loop.h"
+#include "ui/base/ime/input_method_base.h"
+#include "ui/base/ime/input_method_observer.h"
+
+namespace ash {
+
+// A class that waits for caret bounds changed, used in tests.
+class CaretBoundsChangedWaiter : public ui::InputMethodObserver {
+ public:
+  explicit CaretBoundsChangedWaiter(ui::InputMethod* input_method);
+  CaretBoundsChangedWaiter(const CaretBoundsChangedWaiter&) = delete;
+  CaretBoundsChangedWaiter& operator=(const CaretBoundsChangedWaiter&) = delete;
+  ~CaretBoundsChangedWaiter() override;
+
+  // Waits for bounds changed within the input method.
+  void Wait();
+
+ private:
+  // ui::InputMethodObserver:
+  void OnFocus() override {}
+  void OnBlur() override {}
+  void OnTextInputStateChanged(const ui::TextInputClient* client) override {}
+  void OnInputMethodDestroyed(const ui::InputMethod* input_method) override {}
+  void OnCaretBoundsChanged(const ui::TextInputClient* client) override;
+
+  ui::InputMethod* input_method_;
+  base::RunLoop run_loop_;
+};
+
+}  // namespace ash
+
+#endif  // CHROME_BROWSER_ASH_ACCESSIBILITY_CARET_BOUNDS_CHANGED_WAITER_H_
diff --git a/chrome/browser/ash/accessibility/dictation_browsertest.cc b/chrome/browser/ash/accessibility/dictation_browsertest.cc
index 468e65d..77da76d 100644
--- a/chrome/browser/ash/accessibility/dictation_browsertest.cc
+++ b/chrome/browser/ash/accessibility/dictation_browsertest.cc
@@ -29,6 +29,7 @@
 #include "build/build_config.h"
 #include "chrome/browser/ash/accessibility/accessibility_manager.h"
 #include "chrome/browser/ash/accessibility/accessibility_test_utils.h"
+#include "chrome/browser/ash/accessibility/caret_bounds_changed_waiter.h"
 #include "chrome/browser/ash/accessibility/dictation_bubble_test_helper.h"
 #include "chrome/browser/ash/accessibility/speech_monitor.h"
 #include "chrome/browser/ash/base/locale_util.h"
@@ -262,32 +263,6 @@
   base::WeakPtrFactory<SuccessWaiter> weak_factory_{this};
 };
 
-class CaretBoundsChangedWaiter : public ui::InputMethodObserver {
- public:
-  explicit CaretBoundsChangedWaiter(ui::InputMethod* input_method)
-      : input_method_(input_method) {
-    input_method_->AddObserver(this);
-  }
-  CaretBoundsChangedWaiter(const CaretBoundsChangedWaiter&) = delete;
-  CaretBoundsChangedWaiter& operator=(const CaretBoundsChangedWaiter&) = delete;
-  ~CaretBoundsChangedWaiter() override { input_method_->RemoveObserver(this); }
-
-  void Wait() { run_loop_.Run(); }
-
- private:
-  // ui::InputMethodObserver:
-  void OnFocus() override {}
-  void OnBlur() override {}
-  void OnTextInputStateChanged(const ui::TextInputClient* client) override {}
-  void OnInputMethodDestroyed(const ui::InputMethod* input_method) override {}
-  void OnCaretBoundsChanged(const ui::TextInputClient* client) override {
-    run_loop_.Quit();
-  }
-
-  ui::InputMethod* input_method_;
-  base::RunLoop run_loop_;
-};
-
 // Listens for changes to the clipboard. This class only allows `Wait()` to be
 // called once. If you need to call `Wait()` multiple times, create multiple
 // instances of this class.
diff --git a/chrome/browser/ash/accessibility/html_test_utils.cc b/chrome/browser/ash/accessibility/html_test_utils.cc
new file mode 100644
index 0000000..4248f25
--- /dev/null
+++ b/chrome/browser/ash/accessibility/html_test_utils.cc
@@ -0,0 +1,55 @@
+// 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/accessibility/html_test_utils.h"
+
+#include "ash/shell.h"
+#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/test/browser_test_utils.h"
+#include "ui/wm/core/coordinate_conversion.h"
+
+namespace ash {
+
+void ExecuteScriptAndExtractInt(content::WebContents* web_contents,
+                                const std::string& script,
+                                int* result) {
+  ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
+      web_contents,
+      base::StringPrintf("window.domAutomationController.send(%s);",
+                         script.c_str()),
+      result));
+}
+
+void ExecuteScript(content::WebContents* web_contents,
+                   const std::string& script) {
+  ASSERT_TRUE(content::ExecuteScript(web_contents, script));
+}
+
+gfx::Rect GetControlBoundsInRoot(content::WebContents* web_contents,
+                                 const std::string& field_id) {
+  // Use var instead of const or let so that this can be executed many
+  // times within a context on different elements without Javascript
+  // variable redeclaration errors.
+  ExecuteScript(web_contents, base::StringPrintf(R"(
+      var element = document.getElementById('%s');
+      var bounds = element.getBoundingClientRect();
+    )",
+                                                 field_id.c_str()));
+  int top, left, width, height;
+  ExecuteScriptAndExtractInt(web_contents, "bounds.top", &top);
+  ExecuteScriptAndExtractInt(web_contents, "bounds.left", &left);
+  ExecuteScriptAndExtractInt(web_contents, "bounds.width", &width);
+  ExecuteScriptAndExtractInt(web_contents, "bounds.height", &height);
+  gfx::Rect rect(left, top, width, height);
+
+  content::RenderWidgetHostView* view = web_contents->GetRenderWidgetHostView();
+  gfx::Rect view_bounds_in_screen = view->GetViewBounds();
+  gfx::Point origin = rect.origin();
+  origin.Offset(view_bounds_in_screen.x(), view_bounds_in_screen.y());
+  gfx::Rect rect_in_screen(origin.x(), origin.y(), rect.width(), rect.height());
+  ::wm::ConvertRectFromScreen(Shell::GetPrimaryRootWindow(), &rect_in_screen);
+  return rect_in_screen;
+}
+
+}  // namespace ash
diff --git a/chrome/browser/ash/accessibility/html_test_utils.h b/chrome/browser/ash/accessibility/html_test_utils.h
new file mode 100644
index 0000000..d3b5d7d
--- /dev/null
+++ b/chrome/browser/ash/accessibility/html_test_utils.h
@@ -0,0 +1,33 @@
+// 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_ACCESSIBILITY_HTML_TEST_UTILS_H_
+#define CHROME_BROWSER_ASH_ACCESSIBILITY_HTML_TEST_UTILS_H_
+
+#include <string>
+
+#include "ui/gfx/geometry/rect.h"
+
+namespace content {
+class WebContents;
+}
+
+namespace ash {
+
+// Helper methods for browser tests that need to get HTML element bounds
+// and execute Javascript.
+
+void ExecuteScriptAndExtractInt(content::WebContents* web_contents,
+                                const std::string& script,
+                                int* result);
+
+void ExecuteScript(content::WebContents* web_contents,
+                   const std::string& script);
+
+gfx::Rect GetControlBoundsInRoot(content::WebContents* web_contents,
+                                 const std::string& field_id);
+
+}  // namespace ash
+
+#endif  // CHROME_BROWSER_ASH_ACCESSIBILITY_HTML_TEST_UTILS_H_
diff --git a/chrome/browser/ash/accessibility/magnification_controller_browsertest.cc b/chrome/browser/ash/accessibility/magnification_controller_browsertest.cc
index 94c12c0..74600fa 100644
--- a/chrome/browser/ash/accessibility/magnification_controller_browsertest.cc
+++ b/chrome/browser/ash/accessibility/magnification_controller_browsertest.cc
@@ -8,22 +8,15 @@
 #include "ash/shell.h"
 #include "base/command_line.h"
 #include "base/run_loop.h"
-#include "base/timer/timer.h"
 #include "build/build_config.h"
+#include "chrome/browser/ash/accessibility/html_test_utils.h"
 #include "chrome/browser/ash/accessibility/magnification_manager.h"
 #include "chrome/browser/ash/accessibility/magnifier_animation_waiter.h"
-#include "chrome/browser/browser_process.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
-#include "content/public/browser/render_widget_host_view.h"
-#include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test.h"
-#include "content/public/test/browser_test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "ui/wm/core/coordinate_conversion.h"
 
 namespace ash {
 
@@ -37,10 +30,6 @@
     "Big Button 1</button>"
     "</body>";
 
-aura::Window* GetRootWindow() {
-  return Shell::GetPrimaryRootWindow();
-}
-
 FullscreenMagnifierController* GetFullscreenMagnifierController() {
   return Shell::Get()->fullscreen_magnifier_controller();
 }
@@ -99,40 +88,9 @@
     return browser()->tab_strip_model()->GetActiveWebContents();
   }
 
-  void ExecuteScriptAndExtractInt(const std::string& script, int* result) {
-    ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
-        GetWebContents(),
-        "window.domAutomationController.send(" + script + ");", result));
-  }
-
-  void ExecuteScript(const std::string& script) {
-    ASSERT_TRUE(content::ExecuteScript(GetWebContents(), script));
-  }
-
-  gfx::Rect GetControlBoundsInRoot(const std::string& field_id) {
-    ExecuteScript("var element = document.getElementById('" + field_id +
-                  "');"
-                  "var bounds = element.getBoundingClientRect();");
-    int top, left, width, height;
-    ExecuteScriptAndExtractInt("bounds.top", &top);
-    ExecuteScriptAndExtractInt("bounds.left", &left);
-    ExecuteScriptAndExtractInt("bounds.width", &width);
-    ExecuteScriptAndExtractInt("bounds.height", &height);
-    gfx::Rect rect(top, left, width, height);
-
-    content::RenderWidgetHostView* view =
-        GetWebContents()->GetRenderWidgetHostView();
-    gfx::Rect view_bounds_in_screen = view->GetViewBounds();
-    gfx::Point origin = rect.origin();
-    origin.Offset(view_bounds_in_screen.x(), view_bounds_in_screen.y());
-    gfx::Rect rect_in_screen(origin.x(), origin.y(), rect.width(),
-                             rect.height());
-    ::wm::ConvertRectFromScreen(GetRootWindow(), &rect_in_screen);
-    return rect_in_screen;
-  }
-
   void SetFocusOnElement(const std::string& element_id) {
-    ExecuteScript("document.getElementById('" + element_id + "').focus();");
+    ExecuteScript(GetWebContents(),
+                  "document.getElementById('" + element_id + "').focus();");
   }
 };
 
@@ -144,7 +102,8 @@
       browser(), GURL(std::string(kDataURIPrefix) + kTestHtmlContent))));
 
   // Move magnifier window to contain the button.
-  const gfx::Rect button_bounds = GetControlBoundsInRoot("test_button");
+  const gfx::Rect button_bounds =
+      GetControlBoundsInRoot(GetWebContents(), "test_button");
   MoveMagnifierWindow(button_bounds.x() - 100, button_bounds.y() - 100);
   const gfx::Rect view_port_before_focus = GetViewPort();
   EXPECT_TRUE(view_port_before_focus.Contains(button_bounds));
diff --git a/chrome/browser/ash/accessibility/spoken_feedback_app_list_browsertest.cc b/chrome/browser/ash/accessibility/spoken_feedback_app_list_browsertest.cc
index 0d8ba842..7be2ffc 100644
--- a/chrome/browser/ash/accessibility/spoken_feedback_app_list_browsertest.cc
+++ b/chrome/browser/ash/accessibility/spoken_feedback_app_list_browsertest.cc
@@ -16,13 +16,13 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "chrome/browser/ash/accessibility/spoken_feedback_browsertest.h"
+#include "chrome/browser/ash/app_list/test/chrome_app_list_test_support.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/app_list_client_impl.h"
 #include "chrome/browser/ui/app_list/chrome_app_list_model_updater.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
 #include "chrome/browser/ui/app_list/search/search_controller_impl.h"
 #include "chrome/browser/ui/app_list/search/search_provider.h"
-#include "chrome/browser/ui/app_list/test/chrome_app_list_test_support.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/common/chrome_switches.h"
diff --git a/chrome/browser/ash/app_list/app_service/app_service_app_model_builder_unittest.cc b/chrome/browser/ash/app_list/app_service/app_service_app_model_builder_unittest.cc
index 4fb6391..d7213ee 100644
--- a/chrome/browser/ash/app_list/app_service/app_service_app_model_builder_unittest.cc
+++ b/chrome/browser/ash/app_list/app_service/app_service_app_model_builder_unittest.cc
@@ -21,6 +21,9 @@
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "chrome/browser/apps/app_service/app_service_test.h"
 #include "chrome/browser/apps/icon_standardizer.h"
+#include "chrome/browser/ash/app_list/internal_app/internal_app_metadata.h"
+#include "chrome/browser/ash/app_list/test/fake_app_list_model_updater.h"
+#include "chrome/browser/ash/app_list/test/test_app_list_controller_delegate.h"
 #include "chrome/browser/ash/borealis/borealis_features.h"
 #include "chrome/browser/ash/borealis/borealis_service.h"
 #include "chrome/browser/ash/borealis/borealis_util.h"
@@ -40,10 +43,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/app_list_test_util.h"
 #include "chrome/browser/ui/app_list/chrome_app_list_item.h"
-#include "chrome/browser/ui/app_list/internal_app/internal_app_metadata.h"
 #include "chrome/browser/ui/app_list/md_icon_normalizer.h"
-#include "chrome/browser/ui/app_list/test/fake_app_list_model_updater.h"
-#include "chrome/browser/ui/app_list/test/test_app_list_controller_delegate.h"
 #include "chrome/browser/web_applications/test/fake_web_app_provider.h"
 #include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
 #include "chrome/browser/web_applications/user_display_mode.h"
@@ -131,10 +131,10 @@
                                              const std::string& url,
                                              const std::string& id) {
   std::string err;
-  base::DictionaryValue value;
-  value.SetStringKey("name", name);
-  value.SetStringKey("version", version);
-  value.SetStringPath("app.launch.web_url", url);
+  base::Value::Dict value;
+  value.Set("name", name);
+  value.Set("version", version);
+  value.SetByDottedPath("app.launch.web_url", url);
   scoped_refptr<extensions::Extension> app = extensions::Extension::Create(
       base::FilePath(), extensions::mojom::ManifestLocation::kInternal, value,
       extensions::Extension::WAS_INSTALLED_BY_DEFAULT, id, &err);
diff --git a/chrome/browser/ash/app_list/app_service/app_service_context_menu_browsertest.cc b/chrome/browser/ash/app_list/app_service/app_service_context_menu_browsertest.cc
index f36aae6..80af735 100644
--- a/chrome/browser/ash/app_list/app_service/app_service_context_menu_browsertest.cc
+++ b/chrome/browser/ash/app_list/app_service/app_service_context_menu_browsertest.cc
@@ -8,10 +8,10 @@
 #include "ash/public/cpp/app_menu_constants.h"
 #include "base/run_loop.h"
 #include "base/test/bind.h"
+#include "chrome/browser/ash/app_list/test/chrome_app_list_test_support.h"
 #include "chrome/browser/ui/app_list/app_list_client_impl.h"
 #include "chrome/browser/ui/app_list/app_list_model_updater.h"
 #include "chrome/browser/ui/app_list/chrome_app_list_item.h"
-#include "chrome/browser/ui/app_list/test/chrome_app_list_test_support.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
 #include "chrome/browser/web_applications/web_app_command_manager.h"
diff --git a/chrome/browser/ash/app_list/arc/arc_app_icon.cc b/chrome/browser/ash/app_list/arc/arc_app_icon.cc
index df403a9..5a3264ef 100644
--- a/chrome/browser/ash/app_list/arc/arc_app_icon.cc
+++ b/chrome/browser/ash/app_list/arc/arc_app_icon.cc
@@ -31,6 +31,7 @@
 #include "ui/gfx/codec/png_codec.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/image/image_skia_operations.h"
+#include "ui/gfx/image/image_skia_rep.h"
 #include "ui/gfx/image/image_skia_source.h"
 
 namespace {
diff --git a/chrome/browser/ash/app_list/arc/arc_app_unittest.cc b/chrome/browser/ash/app_list/arc/arc_app_unittest.cc
index f755c610..7bb7680 100644
--- a/chrome/browser/ash/app_list/arc/arc_app_unittest.cc
+++ b/chrome/browser/ash/app_list/arc/arc_app_unittest.cc
@@ -58,6 +58,8 @@
 #include "chrome/browser/ash/app_list/arc/arc_pai_starter.h"
 #include "chrome/browser/ash/app_list/arc/intent.h"
 #include "chrome/browser/ash/app_list/arc/mock_arc_app_list_prefs_observer.h"
+#include "chrome/browser/ash/app_list/test/fake_app_list_model_updater.h"
+#include "chrome/browser/ash/app_list/test/test_app_list_controller_delegate.h"
 #include "chrome/browser/ash/arc/arc_optin_uma.h"
 #include "chrome/browser/ash/arc/arc_support_host.h"
 #include "chrome/browser/ash/arc/arc_util.h"
@@ -67,8 +69,6 @@
 #include "chrome/browser/policy/profile_policy_connector.h"
 #include "chrome/browser/sync/sync_service_factory.h"
 #include "chrome/browser/ui/app_list/chrome_app_list_item.h"
-#include "chrome/browser/ui/app_list/test/fake_app_list_model_updater.h"
-#include "chrome/browser/ui/app_list/test/test_app_list_controller_delegate.h"
 #include "chrome/browser/ui/ash/shelf/arc_app_shelf_id.h"
 #include "chrome/browser/ui/ash/shelf/chrome_shelf_controller.h"
 #include "chrome/browser/ui/ash/shelf/shelf_controller_helper.h"
@@ -1352,12 +1352,12 @@
   void OnBeforeArcTestSetup() override {
     ArcDefaultAppTest::OnBeforeArcTestSetup();
 
-    base::DictionaryValue manifest;
-    manifest.SetStringPath(extensions::manifest_keys::kName, "Play Store");
-    manifest.SetStringPath(extensions::manifest_keys::kVersion, "1");
-    manifest.SetIntPath(extensions::manifest_keys::kManifestVersion, 2);
-    manifest.SetStringPath(extensions::manifest_keys::kDescription,
-                           "Play Store for testing");
+    base::Value::Dict manifest;
+    manifest.Set(extensions::manifest_keys::kName, "Play Store");
+    manifest.Set(extensions::manifest_keys::kVersion, "1");
+    manifest.Set(extensions::manifest_keys::kManifestVersion, 2);
+    manifest.Set(extensions::manifest_keys::kDescription,
+                 "Play Store for testing");
 
     std::string error;
     arc_support_host_ = extensions::Extension::Create(
diff --git a/chrome/browser/ash/app_list/arc/arc_app_utils.cc b/chrome/browser/ash/app_list/arc/arc_app_utils.cc
index 14c7ec22..79a2176b 100644
--- a/chrome/browser/ash/app_list/arc/arc_app_utils.cc
+++ b/chrome/browser/ash/app_list/arc/arc_app_utils.cc
@@ -29,6 +29,7 @@
 #include "base/values.h"
 #include "chrome/browser/apps/app_service/intent_util.h"
 #include "chrome/browser/ash/app_list/arc/intent.h"
+#include "chrome/browser/ash/app_list/search/ranking/launch_data.h"
 #include "chrome/browser/ash/arc/arc_migration_guide_notification.h"
 #include "chrome/browser/ash/arc/arc_util.h"
 #include "chrome/browser/ash/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge.h"
@@ -42,7 +43,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_observer.h"
 #include "chrome/browser/ui/app_list/app_list_client_impl.h"
-#include "chrome/browser/ui/app_list/search/ranking/launch_data.h"
 #include "chrome/browser/ui/app_list/search/search_controller.h"
 #include "chrome/browser/ui/ash/shelf/arc_app_shelf_id.h"
 #include "chrome/browser/ui/ash/shelf/arc_shelf_spinner_item_controller.h"
diff --git a/chrome/browser/ui/app_list/internal_app/internal_app_metadata.cc b/chrome/browser/ash/app_list/internal_app/internal_app_metadata.cc
similarity index 98%
rename from chrome/browser/ui/app_list/internal_app/internal_app_metadata.cc
rename to chrome/browser/ash/app_list/internal_app/internal_app_metadata.cc
index fdc8d2fb..abaa8cad 100644
--- a/chrome/browser/ui/app_list/internal_app/internal_app_metadata.cc
+++ b/chrome/browser/ash/app_list/internal_app/internal_app_metadata.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/ui/app_list/internal_app/internal_app_metadata.h"
+#include "chrome/browser/ash/app_list/internal_app/internal_app_metadata.h"
 
 #include <memory>
 #include <string>
diff --git a/chrome/browser/ui/app_list/internal_app/internal_app_metadata.h b/chrome/browser/ash/app_list/internal_app/internal_app_metadata.h
similarity index 91%
rename from chrome/browser/ui/app_list/internal_app/internal_app_metadata.h
rename to chrome/browser/ash/app_list/internal_app/internal_app_metadata.h
index 0b4792a..e2236af 100644
--- a/chrome/browser/ui/app_list/internal_app/internal_app_metadata.h
+++ b/chrome/browser/ash/app_list/internal_app/internal_app_metadata.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 CHROME_BROWSER_UI_APP_LIST_INTERNAL_APP_INTERNAL_APP_METADATA_H_
-#define CHROME_BROWSER_UI_APP_LIST_INTERNAL_APP_INTERNAL_APP_METADATA_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_INTERNAL_APP_INTERNAL_APP_METADATA_H_
+#define CHROME_BROWSER_ASH_APP_LIST_INTERNAL_APP_INTERNAL_APP_METADATA_H_
 
 #include <string>
 #include <vector>
@@ -83,4 +83,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_INTERNAL_APP_INTERNAL_APP_METADATA_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_INTERNAL_APP_INTERNAL_APP_METADATA_H_
diff --git a/chrome/browser/ui/app_list/reorder/app_list_reorder_core.cc b/chrome/browser/ash/app_list/reorder/app_list_reorder_core.cc
similarity index 99%
rename from chrome/browser/ui/app_list/reorder/app_list_reorder_core.cc
rename to chrome/browser/ash/app_list/reorder/app_list_reorder_core.cc
index 0cebdb2..519cfd8 100644
--- a/chrome/browser/ui/app_list/reorder/app_list_reorder_core.cc
+++ b/chrome/browser/ash/app_list/reorder/app_list_reorder_core.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/ui/app_list/reorder/app_list_reorder_core.h"
+#include "chrome/browser/ash/app_list/reorder/app_list_reorder_core.h"
 
 #include <stack>
 
diff --git a/chrome/browser/ui/app_list/reorder/app_list_reorder_core.h b/chrome/browser/ash/app_list/reorder/app_list_reorder_core.h
similarity index 90%
rename from chrome/browser/ui/app_list/reorder/app_list_reorder_core.h
rename to chrome/browser/ash/app_list/reorder/app_list_reorder_core.h
index 10339e8..f5eb31e 100644
--- a/chrome/browser/ui/app_list/reorder/app_list_reorder_core.h
+++ b/chrome/browser/ash/app_list/reorder/app_list_reorder_core.h
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_REORDER_APP_LIST_REORDER_CORE_H_
-#define CHROME_BROWSER_UI_APP_LIST_REORDER_APP_LIST_REORDER_CORE_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_REORDER_APP_LIST_REORDER_CORE_H_
+#define CHROME_BROWSER_ASH_APP_LIST_REORDER_APP_LIST_REORDER_CORE_H_
 
 #include <vector>
 
-#include "chrome/browser/ui/app_list/reorder/app_list_reorder_util.h"
+#include "chrome/browser/ash/app_list/reorder/app_list_reorder_util.h"
 
 namespace app_list {
 namespace reorder {
@@ -58,4 +58,4 @@
 }  // namespace reorder
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_REORDER_APP_LIST_REORDER_CORE_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_REORDER_APP_LIST_REORDER_CORE_H_
diff --git a/chrome/browser/ui/app_list/reorder/app_list_reorder_core_unittest.cc b/chrome/browser/ash/app_list/reorder/app_list_reorder_core_unittest.cc
similarity index 98%
rename from chrome/browser/ui/app_list/reorder/app_list_reorder_core_unittest.cc
rename to chrome/browser/ash/app_list/reorder/app_list_reorder_core_unittest.cc
index 713a8211..f755a0a 100644
--- a/chrome/browser/ui/app_list/reorder/app_list_reorder_core_unittest.cc
+++ b/chrome/browser/ash/app_list/reorder/app_list_reorder_core_unittest.cc
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/reorder/app_list_reorder_core.h"
+#include "chrome/browser/ash/app_list/reorder/app_list_reorder_core.h"
+
 #include "ash/public/cpp/app_list/app_list_types.h"
 #include "chrome/browser/ui/app_list/chrome_app_list_item.h"
 #include "components/crx_file/id_util.h"
diff --git a/chrome/browser/ui/app_list/reorder/app_list_reorder_delegate.h b/chrome/browser/ash/app_list/reorder/app_list_reorder_delegate.h
similarity index 88%
rename from chrome/browser/ui/app_list/reorder/app_list_reorder_delegate.h
rename to chrome/browser/ash/app_list/reorder/app_list_reorder_delegate.h
index c1d8ff2..45dd616 100644
--- a/chrome/browser/ui/app_list/reorder/app_list_reorder_delegate.h
+++ b/chrome/browser/ash/app_list/reorder/app_list_reorder_delegate.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 CHROME_BROWSER_UI_APP_LIST_REORDER_APP_LIST_REORDER_DELEGATE_H_
-#define CHROME_BROWSER_UI_APP_LIST_REORDER_APP_LIST_REORDER_DELEGATE_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_REORDER_APP_LIST_REORDER_DELEGATE_H_
+#define CHROME_BROWSER_ASH_APP_LIST_REORDER_APP_LIST_REORDER_DELEGATE_H_
 
 #include "components/sync/model/string_ordinal.h"
 
@@ -47,4 +47,4 @@
 }  // namespace reorder
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_REORDER_APP_LIST_REORDER_DELEGATE_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_REORDER_APP_LIST_REORDER_DELEGATE_H_
diff --git a/chrome/browser/ui/app_list/reorder/app_list_reorder_util.cc b/chrome/browser/ash/app_list/reorder/app_list_reorder_util.cc
similarity index 99%
rename from chrome/browser/ui/app_list/reorder/app_list_reorder_util.cc
rename to chrome/browser/ash/app_list/reorder/app_list_reorder_util.cc
index 4951e4a..c135aad 100644
--- a/chrome/browser/ui/app_list/reorder/app_list_reorder_util.cc
+++ b/chrome/browser/ash/app_list/reorder/app_list_reorder_util.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/ui/app_list/reorder/app_list_reorder_util.h"
+#include "chrome/browser/ash/app_list/reorder/app_list_reorder_util.h"
 
 #include "ash/public/cpp/app_list/app_list_types.h"
 #include "ash/strings/grit/ash_strings.h"
diff --git a/chrome/browser/ui/app_list/reorder/app_list_reorder_util.h b/chrome/browser/ash/app_list/reorder/app_list_reorder_util.h
similarity index 96%
rename from chrome/browser/ui/app_list/reorder/app_list_reorder_util.h
rename to chrome/browser/ash/app_list/reorder/app_list_reorder_util.h
index b03c67f..d52c51b 100644
--- a/chrome/browser/ui/app_list/reorder/app_list_reorder_util.h
+++ b/chrome/browser/ash/app_list/reorder/app_list_reorder_util.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 CHROME_BROWSER_UI_APP_LIST_REORDER_APP_LIST_REORDER_UTIL_H_
-#define CHROME_BROWSER_UI_APP_LIST_REORDER_APP_LIST_REORDER_UTIL_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_REORDER_APP_LIST_REORDER_UTIL_H_
+#define CHROME_BROWSER_ASH_APP_LIST_REORDER_APP_LIST_REORDER_UTIL_H_
 
 #include <string>
 #include <vector>
@@ -182,4 +182,4 @@
 }  // namespace reorder
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_REORDER_APP_LIST_REORDER_UTIL_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_REORDER_APP_LIST_REORDER_UTIL_H_
diff --git a/chrome/browser/ui/app_list/reorder/app_list_reorder_util_unittest.cc b/chrome/browser/ash/app_list/reorder/app_list_reorder_util_unittest.cc
similarity index 97%
rename from chrome/browser/ui/app_list/reorder/app_list_reorder_util_unittest.cc
rename to chrome/browser/ash/app_list/reorder/app_list_reorder_util_unittest.cc
index 58a1b9c..f7534e2 100644
--- a/chrome/browser/ui/app_list/reorder/app_list_reorder_util_unittest.cc
+++ b/chrome/browser/ash/app_list/reorder/app_list_reorder_util_unittest.cc
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/reorder/app_list_reorder_util.h"
+#include "chrome/browser/ash/app_list/reorder/app_list_reorder_util.h"
+
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/gfx/image/image_skia.h"
diff --git a/chrome/browser/ash/app_list/search/DEPS b/chrome/browser/ash/app_list/search/DEPS
new file mode 100644
index 0000000..ce5e7b9
--- /dev/null
+++ b/chrome/browser/ash/app_list/search/DEPS
@@ -0,0 +1,11 @@
+# TODO(https://crbug.com/1164001): When this file is edited, same file in
+# //chrome/browser/ui/app_list/search should be updated as well. We need
+# to sync both files until the migration is done.
+include_rules = [
+  "+ash/accelerators",
+  "+ash/assistant/model",
+  "+ash/assistant/util",
+  "+ash/shortcut_viewer",
+  "+ash/strings/grit",
+  "+chromeos/ui/vector_icons",
+]
diff --git a/chrome/browser/ash/app_list/search/OWNERS b/chrome/browser/ash/app_list/search/OWNERS
new file mode 100644
index 0000000..eb3513f
--- /dev/null
+++ b/chrome/browser/ash/app_list/search/OWNERS
@@ -0,0 +1,5 @@
+amandadeacon@chromium.org
+chenjih@google.com
+tby@chromium.org
+thanhdng@chromium.org
+wrong@chromium.org
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.cc b/chrome/browser/ash/app_list/search/arc/arc_app_shortcut_search_result.cc
similarity index 96%
rename from chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.cc
rename to chrome/browser/ash/app_list/search/arc/arc_app_shortcut_search_result.cc
index 94f846d..87db59f8 100644
--- a/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.cc
+++ b/chrome/browser/ash/app_list/search/arc/arc_app_shortcut_search_result.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/ui/app_list/search/arc/arc_app_shortcut_search_result.h"
+#include "chrome/browser/ash/app_list/search/arc/arc_app_shortcut_search_result.h"
 
 #include <string>
 #include <utility>
@@ -15,10 +15,10 @@
 #include "chrome/browser/ash/app_list/app_service/app_service_app_icon_loader.h"
 #include "chrome/browser/ash/app_list/arc/arc_app_list_prefs.h"
 #include "chrome/browser/ash/app_list/arc/arc_app_utils.h"
+#include "chrome/browser/ash/app_list/search/common/icon_constants.h"
 #include "chrome/browser/chromeos/arc/icon_decode_request.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
-#include "chrome/browser/ui/app_list/search/common/icon_constants.h"
 #include "chrome/grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/models/image_model.h"
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.h b/chrome/browser/ash/app_list/search/arc/arc_app_shortcut_search_result.h
similarity index 90%
rename from chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.h
rename to chrome/browser/ash/app_list/search/arc/arc_app_shortcut_search_result.h
index 0b660de..ebb26df 100644
--- a/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.h
+++ b/chrome/browser/ash/app_list/search/arc/arc_app_shortcut_search_result.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_ARC_APP_SHORTCUT_SEARCH_RESULT_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_ARC_APP_SHORTCUT_SEARCH_RESULT_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_ARC_ARC_APP_SHORTCUT_SEARCH_RESULT_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_ARC_ARC_APP_SHORTCUT_SEARCH_RESULT_H_
 
 #include <memory>
 #include <string>
@@ -73,4 +73,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_ARC_APP_SHORTCUT_SEARCH_RESULT_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_ARC_ARC_APP_SHORTCUT_SEARCH_RESULT_H_
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.cc b/chrome/browser/ash/app_list/search/arc/arc_app_shortcuts_search_provider.cc
similarity index 94%
rename from chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.cc
rename to chrome/browser/ash/app_list/search/arc/arc_app_shortcuts_search_provider.cc
index 0526b06..3e0c23f8 100644
--- a/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.cc
+++ b/chrome/browser/ash/app_list/search/arc/arc_app_shortcuts_search_provider.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/ui/app_list/search/arc/arc_app_shortcuts_search_provider.h"
+#include "chrome/browser/ash/app_list/search/arc/arc_app_shortcuts_search_provider.h"
 
 #include <memory>
 #include <string>
@@ -12,8 +12,8 @@
 #include "ash/components/arc/session/arc_service_manager.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ash/app_list/arc/arc_app_list_prefs.h"
+#include "chrome/browser/ash/app_list/search/arc/arc_app_shortcut_search_result.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.h"
 
 namespace app_list {
 
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.h b/chrome/browser/ash/app_list/search/arc/arc_app_shortcuts_search_provider.h
similarity index 85%
rename from chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.h
rename to chrome/browser/ash/app_list/search/arc/arc_app_shortcuts_search_provider.h
index 2bd5fc3e..4750538 100644
--- a/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.h
+++ b/chrome/browser/ash/app_list/search/arc/arc_app_shortcuts_search_provider.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_ARC_APP_SHORTCUTS_SEARCH_PROVIDER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_ARC_APP_SHORTCUTS_SEARCH_PROVIDER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_ARC_ARC_APP_SHORTCUTS_SEARCH_PROVIDER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_ARC_ARC_APP_SHORTCUTS_SEARCH_PROVIDER_H_
 
 #include <string>
 #include <vector>
@@ -48,4 +48,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_ARC_APP_SHORTCUTS_SEARCH_PROVIDER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_ARC_ARC_APP_SHORTCUTS_SEARCH_PROVIDER_H_
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider_unittest.cc b/chrome/browser/ash/app_list/search/arc/arc_app_shortcuts_search_provider_unittest.cc
similarity index 94%
rename from chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider_unittest.cc
rename to chrome/browser/ash/app_list/search/arc/arc_app_shortcuts_search_provider_unittest.cc
index ed6b2429..d055cae 100644
--- a/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider_unittest.cc
+++ b/chrome/browser/ash/app_list/search/arc/arc_app_shortcuts_search_provider_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/ui/app_list/search/arc/arc_app_shortcuts_search_provider.h"
+#include "chrome/browser/ash/app_list/search/arc/arc_app_shortcuts_search_provider.h"
 
 #include <memory>
 #include <string>
@@ -14,11 +14,11 @@
 #include "base/test/scoped_feature_list.h"
 #include "chrome/browser/ash/app_list/arc/arc_app_list_prefs.h"
 #include "chrome/browser/ash/app_list/arc/arc_app_test.h"
+#include "chrome/browser/ash/app_list/search/test/test_search_controller.h"
+#include "chrome/browser/ash/app_list/test/test_app_list_controller_delegate.h"
 #include "chrome/browser/chromeos/arc/icon_decode_request.h"
 #include "chrome/browser/ui/app_list/app_list_test_util.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
-#include "chrome/browser/ui/app_list/search/test/test_search_controller.h"
-#include "chrome/browser/ui/app_list/test/test_app_list_controller_delegate.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace app_list::test {
diff --git a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider.cc b/chrome/browser/ash/app_list/search/arc/arc_playstore_search_provider.cc
similarity index 97%
rename from chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider.cc
rename to chrome/browser/ash/app_list/search/arc/arc_playstore_search_provider.cc
index d49559b..1e106ae 100644
--- a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider.cc
+++ b/chrome/browser/ash/app_list/search/arc/arc_playstore_search_provider.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/ui/app_list/search/arc/arc_playstore_search_provider.h"
+#include "chrome/browser/ash/app_list/search/arc/arc_playstore_search_provider.h"
 
 #include <memory>
 #include <string>
@@ -16,9 +16,9 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "chrome/browser/ash/app_list/arc/arc_app_list_prefs.h"
+#include "chrome/browser/ash/app_list/search/arc/arc_playstore_search_result.h"
 #include "chrome/browser/ash/extensions/gfx_utils.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.h"
 
 namespace {
 constexpr int kHistogramBuckets = 13;
diff --git a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider.h b/chrome/browser/ash/app_list/search/arc/arc_playstore_search_provider.h
similarity index 87%
rename from chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider.h
rename to chrome/browser/ash/app_list/search/arc/arc_playstore_search_provider.h
index 9f5ae9c..5fdd89d 100644
--- a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider.h
+++ b/chrome/browser/ash/app_list/search/arc/arc_playstore_search_provider.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_ARC_PLAYSTORE_SEARCH_PROVIDER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_ARC_PLAYSTORE_SEARCH_PROVIDER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_ARC_ARC_PLAYSTORE_SEARCH_PROVIDER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_ARC_ARC_PLAYSTORE_SEARCH_PROVIDER_H_
 
 #include <vector>
 
@@ -56,4 +56,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_ARC_PLAYSTORE_SEARCH_PROVIDER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_ARC_ARC_PLAYSTORE_SEARCH_PROVIDER_H_
diff --git a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider_unittest.cc b/chrome/browser/ash/app_list/search/arc/arc_playstore_search_provider_unittest.cc
similarity index 97%
rename from chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider_unittest.cc
rename to chrome/browser/ash/app_list/search/arc/arc_playstore_search_provider_unittest.cc
index 8c3ad55..9376fd2 100644
--- a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider_unittest.cc
+++ b/chrome/browser/ash/app_list/search/arc/arc_playstore_search_provider_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/ui/app_list/search/arc/arc_playstore_search_provider.h"
+#include "chrome/browser/ash/app_list/search/arc/arc_playstore_search_provider.h"
 
 #include <memory>
 #include <string>
@@ -14,12 +14,12 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ash/app_list/arc/arc_app_test.h"
+#include "chrome/browser/ash/app_list/search/test/test_search_controller.h"
+#include "chrome/browser/ash/app_list/test/test_app_list_controller_delegate.h"
 #include "chrome/browser/chromeos/arc/icon_decode_request.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/ui/app_list/app_list_test_util.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
-#include "chrome/browser/ui/app_list/search/test/test_search_controller.h"
-#include "chrome/browser/ui/app_list/test/test_app_list_controller_delegate.h"
 #include "chrome/test/base/testing_profile.h"
 #include "extensions/common/extension_builder.h"
 
diff --git a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.cc b/chrome/browser/ash/app_list/search/arc/arc_playstore_search_result.cc
similarity index 97%
rename from chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.cc
rename to chrome/browser/ash/app_list/search/arc/arc_playstore_search_result.cc
index 147b335..6ea7c96 100644
--- a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.cc
+++ b/chrome/browser/ash/app_list/search/arc/arc_playstore_search_result.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/ui/app_list/search/arc/arc_playstore_search_result.h"
+#include "chrome/browser/ash/app_list/search/arc/arc_playstore_search_result.h"
 
 #include <utility>
 
@@ -14,10 +14,10 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/apps/app_service/app_icon/app_icon_factory.h"
 #include "chrome/browser/ash/app_list/arc/arc_playstore_app_context_menu.h"
+#include "chrome/browser/ash/app_list/search/common/icon_constants.h"
 #include "chrome/browser/chromeos/arc/icon_decode_request.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
-#include "chrome/browser/ui/app_list/search/common/icon_constants.h"
 #include "components/crx_file/id_util.h"
 #include "ui/base/models/image_model.h"
 #include "ui/gfx/canvas.h"
diff --git a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.h b/chrome/browser/ash/app_list/search/arc/arc_playstore_search_result.h
similarity index 91%
rename from chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.h
rename to chrome/browser/ash/app_list/search/arc/arc_playstore_search_result.h
index fa5de235..ace56f2 100644
--- a/chrome/browser/ui/app_list/search/arc/arc_playstore_search_result.h
+++ b/chrome/browser/ash/app_list/search/arc/arc_playstore_search_result.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_ARC_PLAYSTORE_SEARCH_RESULT_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_ARC_PLAYSTORE_SEARCH_RESULT_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_ARC_ARC_PLAYSTORE_SEARCH_RESULT_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_ARC_ARC_PLAYSTORE_SEARCH_RESULT_H_
 
 #include <memory>
 #include <string>
@@ -79,4 +79,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_ARC_PLAYSTORE_SEARCH_RESULT_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_ARC_ARC_PLAYSTORE_SEARCH_RESULT_H_
diff --git a/chrome/browser/ui/app_list/search/arc/fake_recommend_apps_fetcher_delegate.cc b/chrome/browser/ash/app_list/search/arc/fake_recommend_apps_fetcher_delegate.cc
similarity index 92%
rename from chrome/browser/ui/app_list/search/arc/fake_recommend_apps_fetcher_delegate.cc
rename to chrome/browser/ash/app_list/search/arc/fake_recommend_apps_fetcher_delegate.cc
index 9856eab6..36c0187 100644
--- a/chrome/browser/ui/app_list/search/arc/fake_recommend_apps_fetcher_delegate.cc
+++ b/chrome/browser/ash/app_list/search/arc/fake_recommend_apps_fetcher_delegate.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/ui/app_list/search/arc/fake_recommend_apps_fetcher_delegate.h"
+#include "chrome/browser/ash/app_list/search/arc/fake_recommend_apps_fetcher_delegate.h"
 
 #include <utility>
 
diff --git a/chrome/browser/ui/app_list/search/arc/fake_recommend_apps_fetcher_delegate.h b/chrome/browser/ash/app_list/search/arc/fake_recommend_apps_fetcher_delegate.h
similarity index 84%
rename from chrome/browser/ui/app_list/search/arc/fake_recommend_apps_fetcher_delegate.h
rename to chrome/browser/ash/app_list/search/arc/fake_recommend_apps_fetcher_delegate.h
index 8d5667c0..66566ffdc 100644
--- a/chrome/browser/ui/app_list/search/arc/fake_recommend_apps_fetcher_delegate.h
+++ b/chrome/browser/ash/app_list/search/arc/fake_recommend_apps_fetcher_delegate.h
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_FAKE_RECOMMEND_APPS_FETCHER_DELEGATE_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_FAKE_RECOMMEND_APPS_FETCHER_DELEGATE_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_ARC_FAKE_RECOMMEND_APPS_FETCHER_DELEGATE_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_ARC_FAKE_RECOMMEND_APPS_FETCHER_DELEGATE_H_
 
-#include "chrome/browser/ui/app_list/search/arc/recommend_apps_fetcher_delegate.h"
+#include "chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher_delegate.h"
 
 #include "base/callback.h"
 #include "base/values.h"
@@ -63,4 +63,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_FAKE_RECOMMEND_APPS_FETCHER_DELEGATE_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_ARC_FAKE_RECOMMEND_APPS_FETCHER_DELEGATE_H_
diff --git a/chrome/browser/ui/app_list/search/arc/recommend_apps_fetcher.cc b/chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher.cc
similarity index 82%
rename from chrome/browser/ui/app_list/search/arc/recommend_apps_fetcher.cc
rename to chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher.cc
index c54645e..af6872a 100644
--- a/chrome/browser/ui/app_list/search/arc/recommend_apps_fetcher.cc
+++ b/chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/arc/recommend_apps_fetcher.h"
+#include "chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher.h"
 
+#include "chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher_impl.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/ui/app_list/search/arc/recommend_apps_fetcher_impl.h"
 #include "content/public/browser/storage_partition.h"
 
 namespace app_list {
diff --git a/chrome/browser/ui/app_list/search/arc/recommend_apps_fetcher.h b/chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher.h
similarity index 68%
rename from chrome/browser/ui/app_list/search/arc/recommend_apps_fetcher.h
rename to chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher.h
index e3bc9071..ef66878c 100644
--- a/chrome/browser/ui/app_list/search/arc/recommend_apps_fetcher.h
+++ b/chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_RECOMMEND_APPS_FETCHER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_RECOMMEND_APPS_FETCHER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_ARC_RECOMMEND_APPS_FETCHER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_ARC_RECOMMEND_APPS_FETCHER_H_
 
 #include <memory>
 
@@ -23,4 +23,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_RECOMMEND_APPS_FETCHER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_ARC_RECOMMEND_APPS_FETCHER_H_
diff --git a/chrome/browser/ui/app_list/search/arc/recommend_apps_fetcher_delegate.h b/chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher_delegate.h
similarity index 75%
rename from chrome/browser/ui/app_list/search/arc/recommend_apps_fetcher_delegate.h
rename to chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher_delegate.h
index c68caa5c..1d6b3757 100644
--- a/chrome/browser/ui/app_list/search/arc/recommend_apps_fetcher_delegate.h
+++ b/chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher_delegate.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_RECOMMEND_APPS_FETCHER_DELEGATE_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_RECOMMEND_APPS_FETCHER_DELEGATE_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_ARC_RECOMMEND_APPS_FETCHER_DELEGATE_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_ARC_RECOMMEND_APPS_FETCHER_DELEGATE_H_
 
 namespace base {
 class Value;
@@ -28,4 +28,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_RECOMMEND_APPS_FETCHER_DELEGATE_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_ARC_RECOMMEND_APPS_FETCHER_DELEGATE_H_
diff --git a/chrome/browser/ui/app_list/search/arc/recommend_apps_fetcher_impl.cc b/chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher_impl.cc
similarity index 98%
rename from chrome/browser/ui/app_list/search/arc/recommend_apps_fetcher_impl.cc
rename to chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher_impl.cc
index 2bdb7bf..2b10a1de 100644
--- a/chrome/browser/ui/app_list/search/arc/recommend_apps_fetcher_impl.cc
+++ b/chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher_impl.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/ui/app_list/search/arc/recommend_apps_fetcher_impl.h"
+#include "chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher_impl.h"
 
 #include <cstdint>
 #include <iomanip>
@@ -15,7 +15,7 @@
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "chrome/browser/ash/app_list/arc/arc_app_utils.h"
-#include "chrome/browser/ui/app_list/search/arc/recommend_apps_fetcher_delegate.h"
+#include "chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher_delegate.h"
 #include "net/base/load_flags.h"
 #include "net/http/http_status_code.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
@@ -66,8 +66,7 @@
 RecommendAppsFetcherImpl::RecommendAppsFetcherImpl(
     RecommendAppsFetcherDelegate* delegate,
     network::mojom::URLLoaderFactory* url_loader_factory)
-    : delegate_(delegate), url_loader_factory_(url_loader_factory) {
-}
+    : delegate_(delegate), url_loader_factory_(url_loader_factory) {}
 
 RecommendAppsFetcherImpl::~RecommendAppsFetcherImpl() = default;
 
diff --git a/chrome/browser/ui/app_list/search/arc/recommend_apps_fetcher_impl.h b/chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher_impl.h
similarity index 90%
rename from chrome/browser/ui/app_list/search/arc/recommend_apps_fetcher_impl.h
rename to chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher_impl.h
index ded0def..7353095 100644
--- a/chrome/browser/ui/app_list/search/arc/recommend_apps_fetcher_impl.h
+++ b/chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher_impl.h
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_RECOMMEND_APPS_FETCHER_IMPL_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_RECOMMEND_APPS_FETCHER_IMPL_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_ARC_RECOMMEND_APPS_FETCHER_IMPL_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_ARC_RECOMMEND_APPS_FETCHER_IMPL_H_
 
 #include "base/memory/weak_ptr.h"
 #include "base/strings/string_piece_forward.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
-#include "chrome/browser/ui/app_list/search/arc/recommend_apps_fetcher.h"
+#include "chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace base {
@@ -103,4 +103,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_RECOMMEND_APPS_FETCHER_IMPL_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_ARC_RECOMMEND_APPS_FETCHER_IMPL_H_
diff --git a/chrome/browser/ui/app_list/search/arc/recommend_apps_fetcher_impl_unittest.cc b/chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher_impl_unittest.cc
similarity index 97%
rename from chrome/browser/ui/app_list/search/arc/recommend_apps_fetcher_impl_unittest.cc
rename to chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher_impl_unittest.cc
index 07b6b01..5b97c03 100644
--- a/chrome/browser/ui/app_list/search/arc/recommend_apps_fetcher_impl_unittest.cc
+++ b/chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher_impl_unittest.cc
@@ -2,12 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/arc/recommend_apps_fetcher_impl.h"
+#include "chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher_impl.h"
+
 #include <memory>
 
 #include "base/run_loop.h"
 #include "base/values.h"
-#include "chrome/browser/ui/app_list/search/arc/fake_recommend_apps_fetcher_delegate.h"
+#include "chrome/browser/ash/app_list/search/arc/fake_recommend_apps_fetcher_delegate.h"
 #include "content/public/test/browser_task_environment.h"
 #include "services/network/test/test_url_loader_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ui/app_list/search/common/icon_constants.cc b/chrome/browser/ash/app_list/search/common/icon_constants.cc
similarity index 90%
rename from chrome/browser/ui/app_list/search/common/icon_constants.cc
rename to chrome/browser/ash/app_list/search/common/icon_constants.cc
index 268944f..71227c6 100644
--- a/chrome/browser/ui/app_list/search/common/icon_constants.cc
+++ b/chrome/browser/ash/app_list/search/common/icon_constants.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/ui/app_list/search/common/icon_constants.h"
+#include "chrome/browser/ash/app_list/search/common/icon_constants.h"
 
 #include "ash/public/cpp/style/color_provider.h"
 
diff --git a/chrome/browser/ui/app_list/search/common/icon_constants.h b/chrome/browser/ash/app_list/search/common/icon_constants.h
similarity index 72%
rename from chrome/browser/ui/app_list/search/common/icon_constants.h
rename to chrome/browser/ash/app_list/search/common/icon_constants.h
index f2fdde61..60721b4f 100644
--- a/chrome/browser/ui/app_list/search/common/icon_constants.h
+++ b/chrome/browser/ash/app_list/search/common/icon_constants.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_COMMON_ICON_CONSTANTS_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_COMMON_ICON_CONSTANTS_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_COMMON_ICON_CONSTANTS_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_COMMON_ICON_CONSTANTS_H_
 
 #include "ui/gfx/color_palette.h"
 
@@ -21,4 +21,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_COMMON_ICON_CONSTANTS_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_COMMON_ICON_CONSTANTS_H_
diff --git a/chrome/browser/ui/app_list/search/common/search_result_util.cc b/chrome/browser/ash/app_list/search/common/search_result_util.cc
similarity index 94%
rename from chrome/browser/ui/app_list/search/common/search_result_util.cc
rename to chrome/browser/ash/app_list/search/common/search_result_util.cc
index 8f3313e..ca20332 100644
--- a/chrome/browser/ui/app_list/search/common/search_result_util.cc
+++ b/chrome/browser/ash/app_list/search/common/search_result_util.cc
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/common/search_result_util.h"
+#include "chrome/browser/ash/app_list/search/common/search_result_util.h"
+
 #include "base/strings/strcat.h"
 #include "ui/base/l10n/l10n_util.h"
 
diff --git a/chrome/browser/ui/app_list/search/common/search_result_util.h b/chrome/browser/ash/app_list/search/common/search_result_util.h
similarity index 84%
rename from chrome/browser/ui/app_list/search/common/search_result_util.h
rename to chrome/browser/ash/app_list/search/common/search_result_util.h
index 77cc7a2c..7701cca 100644
--- a/chrome/browser/ui/app_list/search/common/search_result_util.h
+++ b/chrome/browser/ash/app_list/search/common/search_result_util.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_SEARCH_RESULT_UTIL_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_SEARCH_RESULT_UTIL_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_COMMON_SEARCH_RESULT_UTIL_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_COMMON_SEARCH_RESULT_UTIL_H_
 
 #include <string>
 
@@ -35,4 +35,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_SEARCH_RESULT_UTIL_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_COMMON_SEARCH_RESULT_UTIL_H_
diff --git a/chrome/browser/ui/app_list/search/common/string_util.cc b/chrome/browser/ash/app_list/search/common/string_util.cc
similarity index 95%
rename from chrome/browser/ui/app_list/search/common/string_util.cc
rename to chrome/browser/ash/app_list/search/common/string_util.cc
index 3886c540..be6871d 100644
--- a/chrome/browser/ui/app_list/search/common/string_util.cc
+++ b/chrome/browser/ash/app_list/search/common/string_util.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/ui/app_list/search/common/string_util.h"
+#include "chrome/browser/ash/app_list/search/common/string_util.h"
 
 namespace app_list {
 
diff --git a/chrome/browser/ui/app_list/search/common/string_util.h b/chrome/browser/ash/app_list/search/common/string_util.h
similarity index 80%
rename from chrome/browser/ui/app_list/search/common/string_util.h
rename to chrome/browser/ash/app_list/search/common/string_util.h
index 4028761..43d8556 100644
--- a/chrome/browser/ui/app_list/search/common/string_util.h
+++ b/chrome/browser/ash/app_list/search/common/string_util.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_COMMON_STRING_UTIL_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_COMMON_STRING_UTIL_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_COMMON_STRING_UTIL_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_COMMON_STRING_UTIL_H_
 
 #include <string>
 
@@ -26,4 +26,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_COMMON_STRING_UTIL_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_COMMON_STRING_UTIL_H_
diff --git a/chrome/browser/ui/app_list/search/common/string_util_unittest.cc b/chrome/browser/ash/app_list/search/common/string_util_unittest.cc
similarity index 96%
rename from chrome/browser/ui/app_list/search/common/string_util_unittest.cc
rename to chrome/browser/ash/app_list/search/common/string_util_unittest.cc
index 9e73c81..cf7044a 100644
--- a/chrome/browser/ui/app_list/search/common/string_util_unittest.cc
+++ b/chrome/browser/ash/app_list/search/common/string_util_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/ui/app_list/search/common/string_util.h"
+#include "chrome/browser/ash/app_list/search/common/string_util.h"
 
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ui/app_list/search/common/types_util.cc b/chrome/browser/ash/app_list/search/common/types_util.cc
similarity index 98%
rename from chrome/browser/ui/app_list/search/common/types_util.cc
rename to chrome/browser/ash/app_list/search/common/types_util.cc
index 21dcebce..f0e5f93 100644
--- a/chrome/browser/ui/app_list/search/common/types_util.cc
+++ b/chrome/browser/ash/app_list/search/common/types_util.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/ui/app_list/search/common/types_util.h"
+#include "chrome/browser/ash/app_list/search/common/types_util.h"
 
 #include "ash/public/cpp/app_list/app_list_types.h"
 
diff --git a/chrome/browser/ui/app_list/search/common/types_util.h b/chrome/browser/ash/app_list/search/common/types_util.h
similarity index 77%
rename from chrome/browser/ui/app_list/search/common/types_util.h
rename to chrome/browser/ash/app_list/search/common/types_util.h
index ee166755..cafafb5 100644
--- a/chrome/browser/ui/app_list/search/common/types_util.h
+++ b/chrome/browser/ash/app_list/search/common/types_util.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_COMMON_TYPES_UTIL_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_COMMON_TYPES_UTIL_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_COMMON_TYPES_UTIL_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_COMMON_TYPES_UTIL_H_
 
 #include "ash/public/cpp/app_list/app_list_metrics.h"
 #include "ash/public/cpp/app_list/app_list_types.h"
@@ -22,4 +22,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_COMMON_TYPES_UTIL_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_COMMON_TYPES_UTIL_H_
diff --git a/chrome/browser/ui/app_list/search/cros_action_history/BUILD.gn b/chrome/browser/ash/app_list/search/cros_action_history/BUILD.gn
similarity index 78%
rename from chrome/browser/ui/app_list/search/cros_action_history/BUILD.gn
rename to chrome/browser/ash/app_list/search/cros_action_history/BUILD.gn
index 21eecb1..5600dfb2 100644
--- a/chrome/browser/ui/app_list/search/cros_action_history/BUILD.gn
+++ b/chrome/browser/ash/app_list/search/cros_action_history/BUILD.gn
@@ -2,8 +2,11 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//third_party/protobuf/proto_library.gni")
 
+assert(is_chromeos_ash)
+
 proto_library("cros_action_proto") {
   sources = [ "cros_action.proto" ]
 }
diff --git a/chrome/browser/ui/app_list/search/cros_action_history/OWNERS b/chrome/browser/ash/app_list/search/cros_action_history/OWNERS
similarity index 100%
rename from chrome/browser/ui/app_list/search/cros_action_history/OWNERS
rename to chrome/browser/ash/app_list/search/cros_action_history/OWNERS
diff --git a/chrome/browser/ui/app_list/search/cros_action_history/cros_action.proto b/chrome/browser/ash/app_list/search/cros_action_history/cros_action.proto
similarity index 100%
rename from chrome/browser/ui/app_list/search/cros_action_history/cros_action.proto
rename to chrome/browser/ash/app_list/search/cros_action_history/cros_action.proto
diff --git a/chrome/browser/ui/app_list/search/cros_action_history/cros_action_recorder.cc b/chrome/browser/ash/app_list/search/cros_action_history/cros_action_recorder.cc
similarity index 98%
rename from chrome/browser/ui/app_list/search/cros_action_history/cros_action_recorder.cc
rename to chrome/browser/ash/app_list/search/cros_action_history/cros_action_recorder.cc
index af933ee..093776a 100644
--- a/chrome/browser/ui/app_list/search/cros_action_history/cros_action_recorder.cc
+++ b/chrome/browser/ash/app_list/search/cros_action_history/cros_action_recorder.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/ui/app_list/search/cros_action_history/cros_action_recorder.h"
+#include "chrome/browser/ash/app_list/search/cros_action_history/cros_action_recorder.h"
 
 #include <utility>
 
@@ -20,10 +20,10 @@
 #include "base/strings/string_util.h"
 #include "base/task/thread_pool.h"
 #include "base/threading/scoped_blocking_call.h"
+#include "chrome/browser/ash/app_list/search/cros_action_history/cros_action.pb.h"
 #include "chrome/browser/download/download_prefs.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/ui/app_list/search/cros_action_history/cros_action.pb.h"
 #include "components/metrics/structured/structured_events.h"
 
 namespace app_list {
diff --git a/chrome/browser/ui/app_list/search/cros_action_history/cros_action_recorder.h b/chrome/browser/ash/app_list/search/cros_action_history/cros_action_recorder.h
similarity index 91%
rename from chrome/browser/ui/app_list/search/cros_action_history/cros_action_recorder.h
rename to chrome/browser/ash/app_list/search/cros_action_history/cros_action_recorder.h
index c78eff3..7a7dfd9 100644
--- a/chrome/browser/ui/app_list/search/cros_action_history/cros_action_recorder.h
+++ b/chrome/browser/ash/app_list/search/cros_action_history/cros_action_recorder.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_CROS_ACTION_HISTORY_CROS_ACTION_RECORDER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_CROS_ACTION_HISTORY_CROS_ACTION_RECORDER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_CROS_ACTION_HISTORY_CROS_ACTION_RECORDER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_CROS_ACTION_HISTORY_CROS_ACTION_RECORDER_H_
 
 #include <cstdint>
 #include <map>
@@ -15,7 +15,7 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/task/sequenced_task_runner.h"
 #include "base/time/time.h"
-#include "chrome/browser/ui/app_list/search/cros_action_history/cros_action.pb.h"
+#include "chrome/browser/ash/app_list/search/cros_action_history/cros_action.pb.h"
 
 class Profile;
 
@@ -122,4 +122,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_CROS_ACTION_HISTORY_CROS_ACTION_RECORDER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_CROS_ACTION_HISTORY_CROS_ACTION_RECORDER_H_
diff --git a/chrome/browser/ui/app_list/search/cros_action_history/cros_action_recorder_tab_tracker.cc b/chrome/browser/ash/app_list/search/cros_action_history/cros_action_recorder_tab_tracker.cc
similarity index 93%
rename from chrome/browser/ui/app_list/search/cros_action_history/cros_action_recorder_tab_tracker.cc
rename to chrome/browser/ash/app_list/search/cros_action_history/cros_action_recorder_tab_tracker.cc
index e4b3f76..bc9f860 100644
--- a/chrome/browser/ui/app_list/search/cros_action_history/cros_action_recorder_tab_tracker.cc
+++ b/chrome/browser/ash/app_list/search/cros_action_history/cros_action_recorder_tab_tracker.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/cros_action_history/cros_action_recorder_tab_tracker.h"
+#include "chrome/browser/ash/app_list/search/cros_action_history/cros_action_recorder_tab_tracker.h"
 
 #include "base/strings/strcat.h"
 #include "base/strings/string_util.h"
-#include "chrome/browser/ui/app_list/search/cros_action_history/cros_action_recorder.h"
+#include "chrome/browser/ash/app_list/search/cros_action_history/cros_action_recorder.h"
 
 namespace app_list {
 
diff --git a/chrome/browser/ui/app_list/search/cros_action_history/cros_action_recorder_tab_tracker.h b/chrome/browser/ash/app_list/search/cros_action_history/cros_action_recorder_tab_tracker.h
similarity index 87%
rename from chrome/browser/ui/app_list/search/cros_action_history/cros_action_recorder_tab_tracker.h
rename to chrome/browser/ash/app_list/search/cros_action_history/cros_action_recorder_tab_tracker.h
index 3e1a4d3..3bb52fe 100644
--- a/chrome/browser/ui/app_list/search/cros_action_history/cros_action_recorder_tab_tracker.h
+++ b/chrome/browser/ash/app_list/search/cros_action_history/cros_action_recorder_tab_tracker.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_CROS_ACTION_HISTORY_CROS_ACTION_RECORDER_TAB_TRACKER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_CROS_ACTION_HISTORY_CROS_ACTION_RECORDER_TAB_TRACKER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_CROS_ACTION_HISTORY_CROS_ACTION_RECORDER_TAB_TRACKER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_CROS_ACTION_HISTORY_CROS_ACTION_RECORDER_TAB_TRACKER_H_
 
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/render_frame_host.h"
@@ -57,4 +57,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_CROS_ACTION_HISTORY_CROS_ACTION_RECORDER_TAB_TRACKER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_CROS_ACTION_HISTORY_CROS_ACTION_RECORDER_TAB_TRACKER_H_
diff --git a/chrome/browser/ui/app_list/search/cros_action_history/cros_action_recorder_tab_tracker_unittest.cc b/chrome/browser/ash/app_list/search/cros_action_history/cros_action_recorder_tab_tracker_unittest.cc
similarity index 98%
rename from chrome/browser/ui/app_list/search/cros_action_history/cros_action_recorder_tab_tracker_unittest.cc
rename to chrome/browser/ash/app_list/search/cros_action_history/cros_action_recorder_tab_tracker_unittest.cc
index c689af4..91b1e318 100644
--- a/chrome/browser/ui/app_list/search/cros_action_history/cros_action_recorder_tab_tracker_unittest.cc
+++ b/chrome/browser/ash/app_list/search/cros_action_history/cros_action_recorder_tab_tracker_unittest.cc
@@ -5,8 +5,8 @@
 #include "ash/public/cpp/app_list/app_list_switches.h"
 #include "base/command_line.h"
 #include "base/no_destructor.h"
+#include "chrome/browser/ash/app_list/search/cros_action_history/cros_action_recorder.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/app_list/search/cros_action_history/cros_action_recorder.h"
 #include "content/public/test/navigation_simulator.h"
 #include "content/public/test/prerender_test_util.h"
 #include "content/public/test/web_contents_tester.h"
diff --git a/chrome/browser/ui/app_list/search/cros_action_history/cros_action_recorder_unittest.cc b/chrome/browser/ash/app_list/search/cros_action_history/cros_action_recorder_unittest.cc
similarity index 98%
rename from chrome/browser/ui/app_list/search/cros_action_history/cros_action_recorder_unittest.cc
rename to chrome/browser/ash/app_list/search/cros_action_history/cros_action_recorder_unittest.cc
index 25f14ac..568922f 100644
--- a/chrome/browser/ui/app_list/search/cros_action_history/cros_action_recorder_unittest.cc
+++ b/chrome/browser/ash/app_list/search/cros_action_history/cros_action_recorder_unittest.cc
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/cros_action_history/cros_action_recorder.h"
+#include "chrome/browser/ash/app_list/search/cros_action_history/cros_action_recorder.h"
+
 #include "ash/public/cpp/app_list/app_list_switches.h"
 #include "base/command_line.h"
 #include "base/files/file_util.h"
diff --git a/chrome/browser/ui/app_list/search/files/drive_file_suggestion_provider.cc b/chrome/browser/ash/app_list/search/files/drive_file_suggestion_provider.cc
similarity index 98%
rename from chrome/browser/ui/app_list/search/files/drive_file_suggestion_provider.cc
rename to chrome/browser/ash/app_list/search/files/drive_file_suggestion_provider.cc
index 78a0a8bf..ef42066 100644
--- a/chrome/browser/ui/app_list/search/files/drive_file_suggestion_provider.cc
+++ b/chrome/browser/ash/app_list/search/files/drive_file_suggestion_provider.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/ui/app_list/search/files/drive_file_suggestion_provider.h"
+#include "chrome/browser/ash/app_list/search/files/drive_file_suggestion_provider.h"
 
 #include "ash/constants/ash_pref_names.h"
 #include "base/files/file_util.h"
@@ -12,9 +12,9 @@
 #include "base/task/thread_pool.h"
 #include "base/threading/scoped_blocking_call.h"
 #include "base/time/time.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_util.h"
 #include "chrome/browser/ash/drive/drive_integration_service.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_util.h"
 #include "components/drive/drive_pref_names.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/storage_partition.h"
diff --git a/chrome/browser/ui/app_list/search/files/drive_file_suggestion_provider.h b/chrome/browser/ash/app_list/search/files/drive_file_suggestion_provider.h
similarity index 89%
rename from chrome/browser/ui/app_list/search/files/drive_file_suggestion_provider.h
rename to chrome/browser/ash/app_list/search/files/drive_file_suggestion_provider.h
index 1cce902..8b0897fc 100644
--- a/chrome/browser/ui/app_list/search/files/drive_file_suggestion_provider.h
+++ b/chrome/browser/ash/app_list/search/files/drive_file_suggestion_provider.h
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_DRIVE_FILE_SUGGESTION_PROVIDER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_DRIVE_FILE_SUGGESTION_PROVIDER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_DRIVE_FILE_SUGGESTION_PROVIDER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_DRIVE_FILE_SUGGESTION_PROVIDER_H_
 
-#include "chrome/browser/ui/app_list/search/files/file_suggestion_provider.h"
-#include "chrome/browser/ui/app_list/search/files/item_suggest_cache.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggestion_provider.h"
+#include "chrome/browser/ash/app_list/search/files/item_suggest_cache.h"
 #include "chromeos/ash/components/drivefs/mojom/drivefs.mojom.h"
 
 namespace drive {
@@ -93,4 +93,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_DRIVE_FILE_SUGGESTION_PROVIDER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_DRIVE_FILE_SUGGESTION_PROVIDER_H_
diff --git a/chrome/browser/ui/app_list/search/files/drive_search_browsertest.cc b/chrome/browser/ash/app_list/search/files/drive_search_browsertest.cc
similarity index 98%
rename from chrome/browser/ui/app_list/search/files/drive_search_browsertest.cc
rename to chrome/browser/ash/app_list/search/files/drive_search_browsertest.cc
index c47d87f..df2e6cc 100644
--- a/chrome/browser/ui/app_list/search/files/drive_search_browsertest.cc
+++ b/chrome/browser/ash/app_list/search/files/drive_search_browsertest.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 "chrome/browser/ash/app_list/search/test/app_list_search_test_helper.h"
 #include "chrome/browser/ash/drive/drive_integration_service.h"
 #include "chrome/browser/ash/drive/drivefs_test_support.h"
-#include "chrome/browser/ui/app_list/search/test/app_list_search_test_helper.h"
 
 namespace app_list::test {
 
diff --git a/chrome/browser/ui/app_list/search/files/drive_search_provider.cc b/chrome/browser/ash/app_list/search/files/drive_search_provider.cc
similarity index 96%
rename from chrome/browser/ui/app_list/search/files/drive_search_provider.cc
rename to chrome/browser/ash/app_list/search/files/drive_search_provider.cc
index c73e53f27..c0e26e47 100644
--- a/chrome/browser/ui/app_list/search/files/drive_search_provider.cc
+++ b/chrome/browser/ash/app_list/search/files/drive_search_provider.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/ui/app_list/search/files/drive_search_provider.h"
+#include "chrome/browser/ash/app_list/search/files/drive_search_provider.h"
 
 #include <cmath>
 
@@ -14,10 +14,10 @@
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool.h"
 #include "base/threading/scoped_blocking_call.h"
+#include "chrome/browser/ash/app_list/search/common/string_util.h"
+#include "chrome/browser/ash/app_list/search/files/file_result.h"
 #include "chrome/browser/ash/drive/drive_integration_service.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/app_list/search/common/string_util.h"
-#include "chrome/browser/ui/app_list/search/files/file_result.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/chromeos/strings/grit/ui_chromeos_strings.h"
diff --git a/chrome/browser/ui/app_list/search/files/drive_search_provider.h b/chrome/browser/ash/app_list/search/files/drive_search_provider.h
similarity index 88%
rename from chrome/browser/ui/app_list/search/files/drive_search_provider.h
rename to chrome/browser/ash/app_list/search/files/drive_search_provider.h
index e22c88d..a30b5fb 100644
--- a/chrome/browser/ui/app_list/search/files/drive_search_provider.h
+++ b/chrome/browser/ash/app_list/search/files/drive_search_provider.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_DRIVE_SEARCH_PROVIDER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_DRIVE_SEARCH_PROVIDER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_DRIVE_SEARCH_PROVIDER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_DRIVE_SEARCH_PROVIDER_H_
 
 #include <vector>
 
@@ -11,7 +11,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/sequence_checker.h"
 #include "base/time/time.h"
-#include "chrome/browser/ui/app_list/search/files/file_result.h"
+#include "chrome/browser/ash/app_list/search/files/file_result.h"
 #include "chrome/browser/ui/app_list/search/search_provider.h"
 #include "chromeos/ash/components/drivefs/mojom/drivefs.mojom.h"
 #include "chromeos/ash/components/string_matching/tokenized_string.h"
@@ -76,4 +76,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_DRIVE_SEARCH_PROVIDER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_DRIVE_SEARCH_PROVIDER_H_
diff --git a/chrome/browser/ui/app_list/search/files/file_result.cc b/chrome/browser/ash/app_list/search/files/file_result.cc
similarity index 98%
rename from chrome/browser/ui/app_list/search/files/file_result.cc
rename to chrome/browser/ash/app_list/search/files/file_result.cc
index 021fb73..927fca6 100644
--- a/chrome/browser/ui/app_list/search/files/file_result.cc
+++ b/chrome/browser/ash/app_list/search/files/file_result.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/ui/app_list/search/files/file_result.h"
+#include "chrome/browser/ash/app_list/search/files/file_result.h"
 
 #include <string>
 #include <utility>
@@ -18,8 +18,8 @@
 #include "base/no_destructor.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/ash/app_list/search/common/icon_constants.h"
 #include "chrome/browser/platform_util.h"
-#include "chrome/browser/ui/app_list/search/common/icon_constants.h"
 #include "chrome/browser/ui/ash/thumbnail_loader.h"
 #include "chromeos/ash/components/string_matching/tokenized_string.h"
 #include "chromeos/ash/components/string_matching/tokenized_string_match.h"
diff --git a/chrome/browser/ui/app_list/search/files/file_result.h b/chrome/browser/ash/app_list/search/files/file_result.h
similarity index 93%
rename from chrome/browser/ui/app_list/search/files/file_result.h
rename to chrome/browser/ash/app_list/search/files/file_result.h
index 84cb217a..1b212cc 100644
--- a/chrome/browser/ui/app_list/search/files/file_result.h
+++ b/chrome/browser/ash/app_list/search/files/file_result.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_FILE_RESULT_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_FILE_RESULT_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_FILE_RESULT_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_FILE_RESULT_H_
 
 #include <iosfwd>
 
@@ -87,4 +87,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_FILE_RESULT_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_FILE_RESULT_H_
diff --git a/chrome/browser/ui/app_list/search/files/file_result_unittest.cc b/chrome/browser/ash/app_list/search/files/file_result_unittest.cc
similarity index 97%
rename from chrome/browser/ui/app_list/search/files/file_result_unittest.cc
rename to chrome/browser/ash/app_list/search/files/file_result_unittest.cc
index 77dfcd21..32805d10 100644
--- a/chrome/browser/ui/app_list/search/files/file_result_unittest.cc
+++ b/chrome/browser/ash/app_list/search/files/file_result_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/ui/app_list/search/files/file_result.h"
+#include "chrome/browser/ash/app_list/search/files/file_result.h"
 
 #include "ash/public/cpp/app_list/app_list_types.h"
 #include "ash/public/cpp/test/test_app_list_color_provider.h"
@@ -10,8 +10,8 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
+#include "chrome/browser/ash/app_list/search/common/icon_constants.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/app_list/search/common/icon_constants.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/ash/components/string_matching/tokenized_string.h"
 #include "chromeos/ui/base/file_icon_util.h"
diff --git a/chrome/browser/ui/app_list/search/files/file_search_provider.cc b/chrome/browser/ash/app_list/search/files/file_search_provider.cc
similarity index 98%
rename from chrome/browser/ui/app_list/search/files/file_search_provider.cc
rename to chrome/browser/ash/app_list/search/files/file_search_provider.cc
index 6d26940..9c50464c0 100644
--- a/chrome/browser/ui/app_list/search/files/file_search_provider.cc
+++ b/chrome/browser/ash/app_list/search/files/file_search_provider.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/ui/app_list/search/files/file_search_provider.h"
+#include "chrome/browser/ash/app_list/search/files/file_search_provider.h"
 
 #include <cctype>
 #include <cmath>
@@ -19,11 +19,11 @@
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool.h"
 #include "base/time/time.h"
+#include "chrome/browser/ash/app_list/search/files/file_result.h"
 #include "chrome/browser/ash/file_manager/path_util.h"
 #include "chrome/browser/ash/file_manager/trash_common_util.h"
 #include "chrome/browser/ash/input_method/diacritics_checker.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/app_list/search/files/file_result.h"
 
 namespace app_list {
 
diff --git a/chrome/browser/ui/app_list/search/files/file_search_provider.h b/chrome/browser/ash/app_list/search/files/file_search_provider.h
similarity index 90%
rename from chrome/browser/ui/app_list/search/files/file_search_provider.h
rename to chrome/browser/ash/app_list/search/files/file_search_provider.h
index 837cba7..5d6f50f 100644
--- a/chrome/browser/ui/app_list/search/files/file_search_provider.h
+++ b/chrome/browser/ash/app_list/search/files/file_search_provider.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_FILE_SEARCH_PROVIDER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_FILE_SEARCH_PROVIDER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_FILE_SEARCH_PROVIDER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_FILE_SEARCH_PROVIDER_H_
 
 #include <utility>
 #include <vector>
@@ -75,4 +75,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_FILE_SEARCH_PROVIDER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_FILE_SEARCH_PROVIDER_H_
diff --git a/chrome/browser/ui/app_list/search/files/file_search_provider_unittest.cc b/chrome/browser/ash/app_list/search/files/file_search_provider_unittest.cc
similarity index 97%
rename from chrome/browser/ui/app_list/search/files/file_search_provider_unittest.cc
rename to chrome/browser/ash/app_list/search/files/file_search_provider_unittest.cc
index f438065..7cec0cb 100644
--- a/chrome/browser/ui/app_list/search/files/file_search_provider_unittest.cc
+++ b/chrome/browser/ash/app_list/search/files/file_search_provider_unittest.cc
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/files/file_search_provider.h"
+#include "chrome/browser/ash/app_list/search/files/file_search_provider.h"
+
 #include <cctype>
 
 #include "ash/constants/ash_features.h"
@@ -14,11 +15,11 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
+#include "chrome/browser/ash/app_list/search/files/file_result.h"
+#include "chrome/browser/ash/app_list/search/test/test_search_controller.h"
 #include "chrome/browser/ash/file_manager/path_util.h"
 #include "chrome/browser/ash/file_manager/trash_common_util.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/app_list/search/files/file_result.h"
-#include "chrome/browser/ui/app_list/search/test/test_search_controller.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.cc b/chrome/browser/ash/app_list/search/files/file_suggest_keyed_service.cc
similarity index 95%
rename from chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.cc
rename to chrome/browser/ash/app_list/search/files/file_suggest_keyed_service.cc
index 36a51af..b91973d2 100644
--- a/chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.cc
+++ b/chrome/browser/ash/app_list/search/files/file_suggest_keyed_service.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_keyed_service.h"
 
 #include "ash/public/cpp/app_list/app_list_types.h"
+#include "chrome/browser/ash/app_list/search/files/drive_file_suggestion_provider.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_util.h"
+#include "chrome/browser/ash/app_list/search/files/local_file_suggestion_provider.h"
 #include "chrome/browser/ash/file_manager/fileapi_util.h"
-#include "chrome/browser/ui/app_list/search/files/drive_file_suggestion_provider.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_util.h"
-#include "chrome/browser/ui/app_list/search/files/local_file_suggestion_provider.h"
 #include "storage/browser/file_system/file_system_context.h"
 
 namespace app_list {
diff --git a/chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.h b/chrome/browser/ash/app_list/search/files/file_suggest_keyed_service.h
similarity index 92%
rename from chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.h
rename to chrome/browser/ash/app_list/search/files/file_suggest_keyed_service.h
index 669732b8..fcef387b 100644
--- a/chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.h
+++ b/chrome/browser/ash/app_list/search/files/file_suggest_keyed_service.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_FILE_SUGGEST_KEYED_SERVICE_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_FILE_SUGGEST_KEYED_SERVICE_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_FILE_SUGGEST_KEYED_SERVICE_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_FILE_SUGGEST_KEYED_SERVICE_H_
 
 #include <utility>
 #include <vector>
@@ -12,9 +12,9 @@
 #include "base/observer_list.h"
 #include "base/observer_list_types.h"
 #include "base/types/pass_key.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_util.h"
-#include "chrome/browser/ui/app_list/search/ranking/removed_results.pb.h"
-#include "chrome/browser/ui/app_list/search/util/persistent_proto.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_util.h"
+#include "chrome/browser/ash/app_list/search/ranking/removed_results.pb.h"
+#include "chrome/browser/ash/app_list/search/util/persistent_proto.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
@@ -146,4 +146,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_FILE_SUGGEST_KEYED_SERVICE_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_FILE_SUGGEST_KEYED_SERVICE_H_
diff --git a/chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_browsertest.cc b/chrome/browser/ash/app_list/search/files/file_suggest_keyed_service_browsertest.cc
similarity index 94%
rename from chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_browsertest.cc
rename to chrome/browser/ash/app_list/search/files/file_suggest_keyed_service_browsertest.cc
index aa1a567..4b6b7a87 100644
--- a/chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_browsertest.cc
+++ b/chrome/browser/ash/app_list/search/files/file_suggest_keyed_service_browsertest.cc
@@ -1,15 +1,15 @@
-// Copyright 2022 The Chromium Authors. All rights reserved.
+// Copyright 2022 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "base/files/file_util.h"
+#include "chrome/browser/ash/app_list/search/files/drive_file_suggestion_provider.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_keyed_service.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_keyed_service_factory.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_test_util.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_util.h"
 #include "chrome/browser/ash/drive/drive_integration_service_browser_test_base.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/app_list/search/files/drive_file_suggestion_provider.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_factory.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_test_util.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_util.h"
 #include "chrome/browser/ui/browser.h"
 #include "content/public/test/browser_test.h"
 
diff --git a/chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_factory.cc b/chrome/browser/ash/app_list/search/files/file_suggest_keyed_service_factory.cc
similarity index 89%
rename from chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_factory.cc
rename to chrome/browser/ash/app_list/search/files/file_suggest_keyed_service_factory.cc
index 2a54201..46dc03b 100644
--- a/chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_factory.cc
+++ b/chrome/browser/ash/app_list/search/files/file_suggest_keyed_service_factory.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_factory.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_keyed_service_factory.h"
 
+#include "chrome/browser/ash/app_list/search/files/file_suggest_keyed_service.h"
+#include "chrome/browser/ash/app_list/search/ranking/util.h"
 #include "chrome/browser/ash/drive/drive_integration_service.h"
 #include "chrome/browser/ash/file_manager/file_tasks_notifier_factory.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.h"
-#include "chrome/browser/ui/app_list/search/ranking/util.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 
 namespace app_list {
diff --git a/chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_factory.h b/chrome/browser/ash/app_list/search/files/file_suggest_keyed_service_factory.h
similarity index 81%
rename from chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_factory.h
rename to chrome/browser/ash/app_list/search/files/file_suggest_keyed_service_factory.h
index aaff669..802a5af0 100644
--- a/chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_factory.h
+++ b/chrome/browser/ash/app_list/search/files/file_suggest_keyed_service_factory.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_FILE_SUGGEST_KEYED_SERVICE_FACTORY_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_FILE_SUGGEST_KEYED_SERVICE_FACTORY_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_FILE_SUGGEST_KEYED_SERVICE_FACTORY_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_FILE_SUGGEST_KEYED_SERVICE_FACTORY_H_
 
 #include "base/no_destructor.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
@@ -38,4 +38,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_FILE_SUGGEST_KEYED_SERVICE_FACTORY_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_FILE_SUGGEST_KEYED_SERVICE_FACTORY_H_
diff --git a/chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_unittest.cc b/chrome/browser/ash/app_list/search/files/file_suggest_keyed_service_unittest.cc
similarity index 96%
rename from chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_unittest.cc
rename to chrome/browser/ash/app_list/search/files/file_suggest_keyed_service_unittest.cc
index ae13fd7..116865bb 100644
--- a/chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_unittest.cc
+++ b/chrome/browser/ash/app_list/search/files/file_suggest_keyed_service_unittest.cc
@@ -7,11 +7,11 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/scoped_observation.h"
 #include "base/test/metrics/histogram_tester.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_factory.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_test_util.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_util.h"
-#include "chrome/browser/ui/app_list/search/files/mock_file_suggest_keyed_service.h"
-#include "chrome/browser/ui/app_list/search/files/mock_file_suggest_keyed_service_observer.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_keyed_service_factory.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_test_util.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_util.h"
+#include "chrome/browser/ash/app_list/search/files/mock_file_suggest_keyed_service.h"
+#include "chrome/browser/ash/app_list/search/files/mock_file_suggest_keyed_service_observer.h"
 #include "chrome/browser/ui/ash/holding_space/scoped_test_mount_point.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
diff --git a/chrome/browser/ui/app_list/search/files/file_suggest_test_util.cc b/chrome/browser/ash/app_list/search/files/file_suggest_test_util.cc
similarity index 90%
rename from chrome/browser/ui/app_list/search/files/file_suggest_test_util.cc
rename to chrome/browser/ash/app_list/search/files/file_suggest_test_util.cc
index 6dfdc38d..94d95541 100644
--- a/chrome/browser/ui/app_list/search/files/file_suggest_test_util.cc
+++ b/chrome/browser/ash/app_list/search/files/file_suggest_test_util.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/files/file_suggest_test_util.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_test_util.h"
 
 #include "base/json/json_writer.h"
 #include "base/run_loop.h"
 #include "base/scoped_observation.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_util.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_keyed_service.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_util.h"
 
 namespace app_list {
 
diff --git a/chrome/browser/ui/app_list/search/files/file_suggest_test_util.h b/chrome/browser/ash/app_list/search/files/file_suggest_test_util.h
similarity index 79%
rename from chrome/browser/ui/app_list/search/files/file_suggest_test_util.h
rename to chrome/browser/ash/app_list/search/files/file_suggest_test_util.h
index b4ec6507..367529a 100644
--- a/chrome/browser/ui/app_list/search/files/file_suggest_test_util.h
+++ b/chrome/browser/ash/app_list/search/files/file_suggest_test_util.h
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_FILE_SUGGEST_TEST_UTIL_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_FILE_SUGGEST_TEST_UTIL_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_FILE_SUGGEST_TEST_UTIL_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_FILE_SUGGEST_TEST_UTIL_H_
 
 #include <string>
 #include <vector>
 
-#include "chrome/browser/ui/app_list/search/files/mock_file_suggest_keyed_service_observer.h"
+#include "chrome/browser/ash/app_list/search/files/mock_file_suggest_keyed_service_observer.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 namespace app_list {
@@ -49,4 +49,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_FILE_SUGGEST_TEST_UTIL_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_FILE_SUGGEST_TEST_UTIL_H_
diff --git a/chrome/browser/ui/app_list/search/files/file_suggest_util.cc b/chrome/browser/ash/app_list/search/files/file_suggest_util.cc
similarity index 95%
rename from chrome/browser/ui/app_list/search/files/file_suggest_util.cc
rename to chrome/browser/ash/app_list/search/files/file_suggest_util.cc
index 65d6b7a1..543be0ad 100644
--- a/chrome/browser/ui/app_list/search/files/file_suggest_util.cc
+++ b/chrome/browser/ash/app_list/search/files/file_suggest_util.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/ui/app_list/search/files/file_suggest_util.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_util.h"
 
 namespace app_list {
 namespace {
diff --git a/chrome/browser/ui/app_list/search/files/file_suggest_util.h b/chrome/browser/ash/app_list/search/files/file_suggest_util.h
similarity index 90%
rename from chrome/browser/ui/app_list/search/files/file_suggest_util.h
rename to chrome/browser/ash/app_list/search/files/file_suggest_util.h
index 0a52b53..7a61ec498 100644
--- a/chrome/browser/ui/app_list/search/files/file_suggest_util.h
+++ b/chrome/browser/ash/app_list/search/files/file_suggest_util.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_FILE_SUGGEST_UTIL_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_FILE_SUGGEST_UTIL_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_FILE_SUGGEST_UTIL_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_FILE_SUGGEST_UTIL_H_
 
 #include "base/callback_forward.h"
 #include "base/files/file_path.h"
@@ -70,4 +70,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_FILE_SUGGEST_UTIL_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_FILE_SUGGEST_UTIL_H_
diff --git a/chrome/browser/ui/app_list/search/files/file_suggestion_provider.cc b/chrome/browser/ash/app_list/search/files/file_suggestion_provider.cc
similarity index 87%
rename from chrome/browser/ui/app_list/search/files/file_suggestion_provider.cc
rename to chrome/browser/ash/app_list/search/files/file_suggestion_provider.cc
index 7c6a0a1..2d8c3a9 100644
--- a/chrome/browser/ui/app_list/search/files/file_suggestion_provider.cc
+++ b/chrome/browser/ash/app_list/search/files/file_suggestion_provider.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/ui/app_list/search/files/file_suggestion_provider.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggestion_provider.h"
 
 namespace app_list {
 
diff --git a/chrome/browser/ui/app_list/search/files/file_suggestion_provider.h b/chrome/browser/ash/app_list/search/files/file_suggestion_provider.h
similarity index 83%
rename from chrome/browser/ui/app_list/search/files/file_suggestion_provider.h
rename to chrome/browser/ash/app_list/search/files/file_suggestion_provider.h
index c78fb26..b750f472 100644
--- a/chrome/browser/ui/app_list/search/files/file_suggestion_provider.h
+++ b/chrome/browser/ash/app_list/search/files/file_suggestion_provider.h
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_FILE_SUGGESTION_PROVIDER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_FILE_SUGGESTION_PROVIDER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_FILE_SUGGESTION_PROVIDER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_FILE_SUGGESTION_PROVIDER_H_
 
 #include "base/functional/callback.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_util.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_util.h"
 
 namespace app_list {
 
@@ -39,4 +39,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_FILE_SUGGESTION_PROVIDER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_FILE_SUGGESTION_PROVIDER_H_
diff --git a/chrome/browser/ui/app_list/search/files/item_suggest_cache.cc b/chrome/browser/ash/app_list/search/files/item_suggest_cache.cc
similarity index 99%
rename from chrome/browser/ui/app_list/search/files/item_suggest_cache.cc
rename to chrome/browser/ash/app_list/search/files/item_suggest_cache.cc
index 0860760..03435a8 100644
--- a/chrome/browser/ui/app_list/search/files/item_suggest_cache.cc
+++ b/chrome/browser/ash/app_list/search/files/item_suggest_cache.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/ui/app_list/search/files/item_suggest_cache.h"
+#include "chrome/browser/ash/app_list/search/files/item_suggest_cache.h"
 
 #include <algorithm>
 #include <string>
diff --git a/chrome/browser/ui/app_list/search/files/item_suggest_cache.h b/chrome/browser/ash/app_list/search/files/item_suggest_cache.h
similarity index 96%
rename from chrome/browser/ui/app_list/search/files/item_suggest_cache.h
rename to chrome/browser/ash/app_list/search/files/item_suggest_cache.h
index e2d68fd..8f1e7a01 100644
--- a/chrome/browser/ui/app_list/search/files/item_suggest_cache.h
+++ b/chrome/browser/ash/app_list/search/files/item_suggest_cache.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_ITEM_SUGGEST_CACHE_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_ITEM_SUGGEST_CACHE_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_ITEM_SUGGEST_CACHE_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_ITEM_SUGGEST_CACHE_H_
 
 #include "base/callback_list.h"
 #include "base/feature_list.h"
@@ -180,4 +180,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_ITEM_SUGGEST_CACHE_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_ITEM_SUGGEST_CACHE_H_
diff --git a/chrome/browser/ui/app_list/search/files/item_suggest_cache_unittest.cc b/chrome/browser/ash/app_list/search/files/item_suggest_cache_unittest.cc
similarity index 99%
rename from chrome/browser/ui/app_list/search/files/item_suggest_cache_unittest.cc
rename to chrome/browser/ash/app_list/search/files/item_suggest_cache_unittest.cc
index b2629453..de9b7e5 100644
--- a/chrome/browser/ui/app_list/search/files/item_suggest_cache_unittest.cc
+++ b/chrome/browser/ash/app_list/search/files/item_suggest_cache_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/ui/app_list/search/files/item_suggest_cache.h"
+#include "chrome/browser/ash/app_list/search/files/item_suggest_cache.h"
 
 #include <vector>
 
diff --git a/chrome/browser/ui/app_list/search/files/justifications.cc b/chrome/browser/ash/app_list/search/files/justifications.cc
similarity index 97%
rename from chrome/browser/ui/app_list/search/files/justifications.cc
rename to chrome/browser/ash/app_list/search/files/justifications.cc
index ed8d93dd..c40b441 100644
--- a/chrome/browser/ui/app_list/search/files/justifications.cc
+++ b/chrome/browser/ash/app_list/search/files/justifications.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/ui/app_list/search/files/justifications.h"
+#include "chrome/browser/ash/app_list/search/files/justifications.h"
 
 #include "ash/strings/grit/ash_strings.h"
 #include "base/files/file.h"
diff --git a/chrome/browser/ui/app_list/search/files/justifications.h b/chrome/browser/ash/app_list/search/files/justifications.h
similarity index 77%
rename from chrome/browser/ui/app_list/search/files/justifications.h
rename to chrome/browser/ash/app_list/search/files/justifications.h
index 85ac229..b485b298 100644
--- a/chrome/browser/ui/app_list/search/files/justifications.h
+++ b/chrome/browser/ash/app_list/search/files/justifications.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_JUSTIFICATIONS_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_JUSTIFICATIONS_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_JUSTIFICATIONS_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_JUSTIFICATIONS_H_
 
 #include <string>
 
@@ -22,4 +22,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_JUSTIFICATIONS_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_JUSTIFICATIONS_H_
diff --git a/chrome/browser/ui/app_list/search/files/justifications_unittest.cc b/chrome/browser/ash/app_list/search/files/justifications_unittest.cc
similarity index 97%
rename from chrome/browser/ui/app_list/search/files/justifications_unittest.cc
rename to chrome/browser/ash/app_list/search/files/justifications_unittest.cc
index 2d01160..b93cc9d 100644
--- a/chrome/browser/ui/app_list/search/files/justifications_unittest.cc
+++ b/chrome/browser/ash/app_list/search/files/justifications_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/ui/app_list/search/files/justifications.h"
+#include "chrome/browser/ash/app_list/search/files/justifications.h"
 
 #include "ash/strings/grit/ash_strings.h"
 #include "base/time/time.h"
diff --git a/chrome/browser/ui/app_list/search/files/local_file_suggestion_provider.cc b/chrome/browser/ash/app_list/search/files/local_file_suggestion_provider.cc
similarity index 94%
rename from chrome/browser/ui/app_list/search/files/local_file_suggestion_provider.cc
rename to chrome/browser/ash/app_list/search/files/local_file_suggestion_provider.cc
index ce753c2..e346864 100644
--- a/chrome/browser/ui/app_list/search/files/local_file_suggestion_provider.cc
+++ b/chrome/browser/ash/app_list/search/files/local_file_suggestion_provider.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/ui/app_list/search/files/local_file_suggestion_provider.h"
+#include "chrome/browser/ash/app_list/search/files/local_file_suggestion_provider.h"
 
 #include <vector>
 
@@ -12,13 +12,13 @@
 #include "base/functional/bind.h"
 #include "base/ranges/algorithm.h"
 #include "base/time/time.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_util.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggestion_provider.h"
+#include "chrome/browser/ash/app_list/search/files/justifications.h"
+#include "chrome/browser/ash/app_list/search/ranking/util.h"
+#include "chrome/browser/ash/app_list/search/util/mrfu_cache.h"
 #include "chrome/browser/ash/file_manager/trash_common_util.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_util.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggestion_provider.h"
-#include "chrome/browser/ui/app_list/search/files/justifications.h"
-#include "chrome/browser/ui/app_list/search/ranking/util.h"
-#include "chrome/browser/ui/app_list/search/util/mrfu_cache.h"
 
 namespace app_list {
 
diff --git a/chrome/browser/ui/app_list/search/files/local_file_suggestion_provider.h b/chrome/browser/ash/app_list/search/files/local_file_suggestion_provider.h
similarity index 87%
rename from chrome/browser/ui/app_list/search/files/local_file_suggestion_provider.h
rename to chrome/browser/ash/app_list/search/files/local_file_suggestion_provider.h
index 1750432e..3b6ca9b 100644
--- a/chrome/browser/ui/app_list/search/files/local_file_suggestion_provider.h
+++ b/chrome/browser/ash/app_list/search/files/local_file_suggestion_provider.h
@@ -2,19 +2,19 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_LOCAL_FILE_SUGGESTION_PROVIDER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_LOCAL_FILE_SUGGESTION_PROVIDER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_LOCAL_FILE_SUGGESTION_PROVIDER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_LOCAL_FILE_SUGGESTION_PROVIDER_H_
 
 #include "base/callback_list.h"
 #include "base/files/file_path.h"
 #include "base/memory/weak_ptr.h"
 #include "base/scoped_observation.h"
 #include "base/time/time.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_util.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggestion_provider.h"
+#include "chrome/browser/ash/app_list/search/util/mrfu_cache.h"
 #include "chrome/browser/ash/file_manager/file_tasks_notifier.h"
 #include "chrome/browser/ash/file_manager/file_tasks_observer.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_util.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggestion_provider.h"
-#include "chrome/browser/ui/app_list/search/util/mrfu_cache.h"
 
 class Profile;
 
@@ -94,4 +94,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_LOCAL_FILE_SUGGESTION_PROVIDER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_LOCAL_FILE_SUGGESTION_PROVIDER_H_
diff --git a/chrome/browser/ui/app_list/search/files/local_file_suggestion_provider_unittest.cc b/chrome/browser/ash/app_list/search/files/local_file_suggestion_provider_unittest.cc
similarity index 97%
rename from chrome/browser/ui/app_list/search/files/local_file_suggestion_provider_unittest.cc
rename to chrome/browser/ash/app_list/search/files/local_file_suggestion_provider_unittest.cc
index e7a917a..05a42800 100644
--- a/chrome/browser/ui/app_list/search/files/local_file_suggestion_provider_unittest.cc
+++ b/chrome/browser/ash/app_list/search/files/local_file_suggestion_provider_unittest.cc
@@ -1,18 +1,18 @@
-// Copyright 2022 The Chromium Authors. All rights reserved.
+// Copyright 2022 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/files/local_file_suggestion_provider.h"
+#include "chrome/browser/ash/app_list/search/files/local_file_suggestion_provider.h"
 
 #include "ash/constants/ash_features.h"
 #include "ash/constants/ash_pref_names.h"
 #include "base/functional/bind.h"
 #include "base/test/bind.h"
 #include "base/time/time.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_util.h"
 #include "chrome/browser/ash/file_manager/file_tasks_observer.h"
 #include "chrome/browser/ash/file_manager/path_util.h"
 #include "chrome/browser/ash/file_manager/trash_common_util.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_util.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile_manager.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ui/app_list/search/files/mock_file_suggest_keyed_service.cc b/chrome/browser/ash/app_list/search/files/mock_file_suggest_keyed_service.cc
similarity index 90%
rename from chrome/browser/ui/app_list/search/files/mock_file_suggest_keyed_service.cc
rename to chrome/browser/ash/app_list/search/files/mock_file_suggest_keyed_service.cc
index 92c56260..8f8aa34 100644
--- a/chrome/browser/ui/app_list/search/files/mock_file_suggest_keyed_service.cc
+++ b/chrome/browser/ash/app_list/search/files/mock_file_suggest_keyed_service.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/files/mock_file_suggest_keyed_service.h"
+#include "chrome/browser/ash/app_list/search/files/mock_file_suggest_keyed_service.h"
 
 #include "base/functional/callback.h"
 #include "base/task/sequenced_task_runner.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_keyed_service.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_util.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_util.h"
 
 namespace app_list {
 
diff --git a/chrome/browser/ui/app_list/search/files/mock_file_suggest_keyed_service.h b/chrome/browser/ash/app_list/search/files/mock_file_suggest_keyed_service.h
similarity index 83%
rename from chrome/browser/ui/app_list/search/files/mock_file_suggest_keyed_service.h
rename to chrome/browser/ash/app_list/search/files/mock_file_suggest_keyed_service.h
index 8e8447e..71d59d0 100644
--- a/chrome/browser/ui/app_list/search/files/mock_file_suggest_keyed_service.h
+++ b/chrome/browser/ash/app_list/search/files/mock_file_suggest_keyed_service.h
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_MOCK_FILE_SUGGEST_KEYED_SERVICE_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_MOCK_FILE_SUGGEST_KEYED_SERVICE_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_MOCK_FILE_SUGGEST_KEYED_SERVICE_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_MOCK_FILE_SUGGEST_KEYED_SERVICE_H_
 
 #include <map>
 
-#include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_util.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_keyed_service.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_util.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 namespace content {
@@ -67,4 +67,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_MOCK_FILE_SUGGEST_KEYED_SERVICE_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_MOCK_FILE_SUGGEST_KEYED_SERVICE_H_
diff --git a/chrome/browser/ui/app_list/search/files/mock_file_suggest_keyed_service_observer.cc b/chrome/browser/ash/app_list/search/files/mock_file_suggest_keyed_service_observer.cc
similarity index 79%
rename from chrome/browser/ui/app_list/search/files/mock_file_suggest_keyed_service_observer.cc
rename to chrome/browser/ash/app_list/search/files/mock_file_suggest_keyed_service_observer.cc
index 847b6c34..a0fbdb5d 100644
--- a/chrome/browser/ui/app_list/search/files/mock_file_suggest_keyed_service_observer.cc
+++ b/chrome/browser/ash/app_list/search/files/mock_file_suggest_keyed_service_observer.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/ui/app_list/search/files/mock_file_suggest_keyed_service_observer.h"
+#include "chrome/browser/ash/app_list/search/files/mock_file_suggest_keyed_service_observer.h"
 
 namespace app_list {
 
diff --git a/chrome/browser/ui/app_list/search/files/mock_file_suggest_keyed_service_observer.h b/chrome/browser/ash/app_list/search/files/mock_file_suggest_keyed_service_observer.h
similarity index 71%
rename from chrome/browser/ui/app_list/search/files/mock_file_suggest_keyed_service_observer.h
rename to chrome/browser/ash/app_list/search/files/mock_file_suggest_keyed_service_observer.h
index 261791e..c915064e 100644
--- a/chrome/browser/ui/app_list/search/files/mock_file_suggest_keyed_service_observer.h
+++ b/chrome/browser/ash/app_list/search/files/mock_file_suggest_keyed_service_observer.h
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_MOCK_FILE_SUGGEST_KEYED_SERVICE_OBSERVER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_MOCK_FILE_SUGGEST_KEYED_SERVICE_OBSERVER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_MOCK_FILE_SUGGEST_KEYED_SERVICE_OBSERVER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_MOCK_FILE_SUGGEST_KEYED_SERVICE_OBSERVER_H_
 
-#include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_keyed_service.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 namespace app_list {
@@ -30,4 +30,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_MOCK_FILE_SUGGEST_KEYED_SERVICE_OBSERVER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_MOCK_FILE_SUGGEST_KEYED_SERVICE_OBSERVER_H_
diff --git a/chrome/browser/ui/app_list/search/files/zero_state_drive_provider.cc b/chrome/browser/ash/app_list/search/files/zero_state_drive_provider.cc
similarity index 95%
rename from chrome/browser/ui/app_list/search/files/zero_state_drive_provider.cc
rename to chrome/browser/ash/app_list/search/files/zero_state_drive_provider.cc
index 4de8aae..e57391d 100644
--- a/chrome/browser/ui/app_list/search/files/zero_state_drive_provider.cc
+++ b/chrome/browser/ash/app_list/search/files/zero_state_drive_provider.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/ui/app_list/search/files/zero_state_drive_provider.h"
+#include "chrome/browser/ash/app_list/search/files/zero_state_drive_provider.h"
 
 #include <algorithm>
 #include <memory>
@@ -11,11 +11,11 @@
 #include "ash/public/cpp/app_list/app_list_types.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/time/time.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_keyed_service.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_keyed_service_factory.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_util.h"
 #include "chrome/browser/ash/drive/drive_integration_service.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_factory.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_util.h"
 #include "chrome/browser/ui/app_list/search/search_controller.h"
 #include "chromeos/dbus/power_manager/idle.pb.h"
 #include "content/public/browser/browser_context.h"
diff --git a/chrome/browser/ui/app_list/search/files/zero_state_drive_provider.h b/chrome/browser/ash/app_list/search/files/zero_state_drive_provider.h
similarity index 90%
rename from chrome/browser/ui/app_list/search/files/zero_state_drive_provider.h
rename to chrome/browser/ash/app_list/search/files/zero_state_drive_provider.h
index d80c7e3..1d5eebf 100644
--- a/chrome/browser/ui/app_list/search/files/zero_state_drive_provider.h
+++ b/chrome/browser/ash/app_list/search/files/zero_state_drive_provider.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_ZERO_STATE_DRIVE_PROVIDER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_ZERO_STATE_DRIVE_PROVIDER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_ZERO_STATE_DRIVE_PROVIDER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_ZERO_STATE_DRIVE_PROVIDER_H_
 
 #include <string>
 #include <vector>
@@ -13,10 +13,10 @@
 #include "base/sequence_checker.h"
 #include "base/task/sequenced_task_runner.h"
 #include "base/time/time.h"
+#include "chrome/browser/ash/app_list/search/files/file_result.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_keyed_service.h"
+#include "chrome/browser/ash/app_list/search/files/item_suggest_cache.h"
 #include "chrome/browser/ash/drive/drive_integration_service.h"
-#include "chrome/browser/ui/app_list/search/files/file_result.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.h"
-#include "chrome/browser/ui/app_list/search/files/item_suggest_cache.h"
 #include "chrome/browser/ui/app_list/search/search_provider.h"
 #include "chromeos/ash/components/drivefs/mojom/drivefs.mojom-forward.h"
 #include "chromeos/dbus/power/power_manager_client.h"
@@ -122,4 +122,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_ZERO_STATE_DRIVE_PROVIDER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_ZERO_STATE_DRIVE_PROVIDER_H_
diff --git a/chrome/browser/ui/app_list/search/files/zero_state_drive_provider_unittest.cc b/chrome/browser/ash/app_list/search/files/zero_state_drive_provider_unittest.cc
similarity index 95%
rename from chrome/browser/ui/app_list/search/files/zero_state_drive_provider_unittest.cc
rename to chrome/browser/ash/app_list/search/files/zero_state_drive_provider_unittest.cc
index 146c755..2cb96a91 100644
--- a/chrome/browser/ui/app_list/search/files/zero_state_drive_provider_unittest.cc
+++ b/chrome/browser/ash/app_list/search/files/zero_state_drive_provider_unittest.cc
@@ -2,18 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/files/zero_state_drive_provider.h"
+#include "chrome/browser/ash/app_list/search/files/zero_state_drive_provider.h"
 
 #include "base/files/file_path.h"
 #include "base/test/bind.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_factory.h"
-#include "chrome/browser/ui/app_list/search/ranking/removed_results.pb.h"
-#include "chrome/browser/ui/app_list/search/test/test_search_controller.h"
-#include "chrome/browser/ui/app_list/search/util/persistent_proto.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_keyed_service.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_keyed_service_factory.h"
+#include "chrome/browser/ash/app_list/search/ranking/removed_results.pb.h"
+#include "chrome/browser/ash/app_list/search/test/test_search_controller.h"
+#include "chrome/browser/ash/app_list/search/util/persistent_proto.h"
 #include "chrome/browser/ui/ash/holding_space/scoped_test_mount_point.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
diff --git a/chrome/browser/ui/app_list/search/files/zero_state_file_provider.cc b/chrome/browser/ash/app_list/search/files/zero_state_file_provider.cc
similarity index 92%
rename from chrome/browser/ui/app_list/search/files/zero_state_file_provider.cc
rename to chrome/browser/ash/app_list/search/files/zero_state_file_provider.cc
index 56d377d..59b1cc8b 100644
--- a/chrome/browser/ui/app_list/search/files/zero_state_file_provider.cc
+++ b/chrome/browser/ash/app_list/search/files/zero_state_file_provider.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/ui/app_list/search/files/zero_state_file_provider.h"
+#include "chrome/browser/ash/app_list/search/files/zero_state_file_provider.h"
 
 #include <string>
 
@@ -21,12 +21,12 @@
 #include "base/task/thread_pool.h"
 #include "base/threading/scoped_blocking_call.h"
 #include "base/time/time.h"
+#include "chrome/browser/ash/app_list/search/files/file_result.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_keyed_service_factory.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_util.h"
+#include "chrome/browser/ash/app_list/search/files/justifications.h"
 #include "chrome/browser/ash/file_manager/path_util.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/app_list/search/files/file_result.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_factory.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_util.h"
-#include "chrome/browser/ui/app_list/search/files/justifications.h"
 #include "components/drive/drive_pref_names.h"
 #include "components/prefs/pref_service.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
diff --git a/chrome/browser/ui/app_list/search/files/zero_state_file_provider.h b/chrome/browser/ash/app_list/search/files/zero_state_file_provider.h
similarity index 88%
rename from chrome/browser/ui/app_list/search/files/zero_state_file_provider.h
rename to chrome/browser/ash/app_list/search/files/zero_state_file_provider.h
index 2fc2ba2..072bba52 100644
--- a/chrome/browser/ui/app_list/search/files/zero_state_file_provider.h
+++ b/chrome/browser/ash/app_list/search/files/zero_state_file_provider.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_ZERO_STATE_FILE_PROVIDER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_ZERO_STATE_FILE_PROVIDER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_ZERO_STATE_FILE_PROVIDER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_ZERO_STATE_FILE_PROVIDER_H_
 
 #include <memory>
 #include <string>
@@ -16,9 +16,9 @@
 #include "base/scoped_observation.h"
 #include "base/task/sequenced_task_runner.h"
 #include "base/time/time.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_keyed_service.h"
 #include "chrome/browser/ash/file_manager/file_tasks_notifier.h"
 #include "chrome/browser/ash/file_manager/file_tasks_observer.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.h"
 #include "chrome/browser/ui/app_list/search/search_provider.h"
 #include "chrome/browser/ui/ash/thumbnail_loader.h"
 
@@ -79,4 +79,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_ZERO_STATE_FILE_PROVIDER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_FILES_ZERO_STATE_FILE_PROVIDER_H_
diff --git a/chrome/browser/ui/app_list/search/files/zero_state_file_provider_unittest.cc b/chrome/browser/ash/app_list/search/files/zero_state_file_provider_unittest.cc
similarity index 93%
rename from chrome/browser/ui/app_list/search/files/zero_state_file_provider_unittest.cc
rename to chrome/browser/ash/app_list/search/files/zero_state_file_provider_unittest.cc
index 2f851ac..b7958f2 100644
--- a/chrome/browser/ui/app_list/search/files/zero_state_file_provider_unittest.cc
+++ b/chrome/browser/ash/app_list/search/files/zero_state_file_provider_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/ui/app_list/search/files/zero_state_file_provider.h"
+#include "chrome/browser/ash/app_list/search/files/zero_state_file_provider.h"
 
 #include <string>
 
@@ -12,11 +12,11 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/test/scoped_running_on_chromeos.h"
 #include "base/test/task_environment.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_keyed_service_factory.h"
+#include "chrome/browser/ash/app_list/search/files/local_file_suggestion_provider.h"
+#include "chrome/browser/ash/app_list/search/test/test_search_controller.h"
 #include "chrome/browser/ash/file_manager/path_util.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_factory.h"
-#include "chrome/browser/ui/app_list/search/files/local_file_suggestion_provider.h"
-#include "chrome/browser/ui/app_list/search/test/test_search_controller.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
diff --git a/chrome/browser/ui/app_list/search/games/game_provider.cc b/chrome/browser/ash/app_list/search/games/game_provider.cc
similarity index 98%
rename from chrome/browser/ui/app_list/search/games/game_provider.cc
rename to chrome/browser/ash/app_list/search/games/game_provider.cc
index a6d9100..620273f 100644
--- a/chrome/browser/ui/app_list/search/games/game_provider.cc
+++ b/chrome/browser/ash/app_list/search/games/game_provider.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/ui/app_list/search/games/game_provider.h"
+#include "chrome/browser/ash/app_list/search/games/game_provider.h"
 
 #include <algorithm>
 #include <utility>
@@ -19,9 +19,9 @@
 #include "chrome/browser/apps/app_discovery_service/app_discovery_util.h"
 #include "chrome/browser/apps/app_discovery_service/game_extras.h"
 #include "chrome/browser/apps/app_discovery_service/result.h"
+#include "chrome/browser/ash/app_list/search/games/game_result.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
-#include "chrome/browser/ui/app_list/search/games/game_result.h"
 #include "chrome/browser/ui/app_list/search/search_features.h"
 #include "chromeos/ash/components/string_matching/fuzzy_tokenized_string_match.h"
 #include "chromeos/ash/components/string_matching/tokenized_string.h"
diff --git a/chrome/browser/ui/app_list/search/games/game_provider.h b/chrome/browser/ash/app_list/search/games/game_provider.h
similarity index 90%
rename from chrome/browser/ui/app_list/search/games/game_provider.h
rename to chrome/browser/ash/app_list/search/games/game_provider.h
index 44ca088b..6671128 100644
--- a/chrome/browser/ui/app_list/search/games/game_provider.h
+++ b/chrome/browser/ash/app_list/search/games/game_provider.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_GAMES_GAME_PROVIDER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_GAMES_GAME_PROVIDER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_GAMES_GAME_PROVIDER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_GAMES_GAME_PROVIDER_H_
 
 #include <utility>
 #include <vector>
@@ -68,4 +68,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_GAMES_GAME_PROVIDER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_GAMES_GAME_PROVIDER_H_
diff --git a/chrome/browser/ui/app_list/search/games/game_provider_unittest.cc b/chrome/browser/ash/app_list/search/games/game_provider_unittest.cc
similarity index 97%
rename from chrome/browser/ui/app_list/search/games/game_provider_unittest.cc
rename to chrome/browser/ash/app_list/search/games/game_provider_unittest.cc
index 73694d9a..a85b594 100644
--- a/chrome/browser/ui/app_list/search/games/game_provider_unittest.cc
+++ b/chrome/browser/ash/app_list/search/games/game_provider_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/ui/app_list/search/games/game_provider.h"
+#include "chrome/browser/ash/app_list/search/games/game_provider.h"
 
 #include "ash/constants/ash_pref_names.h"
 #include "base/files/file_path.h"
@@ -11,9 +11,9 @@
 #include "chrome/browser/apps/app_discovery_service/app_discovery_util.h"
 #include "chrome/browser/apps/app_discovery_service/game_extras.h"
 #include "chrome/browser/apps/app_discovery_service/result.h"
+#include "chrome/browser/ash/app_list/search/test/test_search_controller.h"
+#include "chrome/browser/ash/app_list/test/test_app_list_controller_delegate.h"
 #include "chrome/browser/ui/app_list/search/search_features.h"
-#include "chrome/browser/ui/app_list/search/test/test_search_controller.h"
-#include "chrome/browser/ui/app_list/test/test_app_list_controller_delegate.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ui/app_list/search/games/game_result.cc b/chrome/browser/ash/app_list/search/games/game_result.cc
similarity index 96%
rename from chrome/browser/ui/app_list/search/games/game_result.cc
rename to chrome/browser/ash/app_list/search/games/game_result.cc
index 2b047e25..1df2273 100644
--- a/chrome/browser/ui/app_list/search/games/game_result.cc
+++ b/chrome/browser/ash/app_list/search/games/game_result.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/ui/app_list/search/games/game_result.h"
+#include "chrome/browser/ash/app_list/search/games/game_result.h"
 
 #include <cmath>
 #include <string>
@@ -17,9 +17,9 @@
 #include "chrome/browser/apps/app_discovery_service/game_extras.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
+#include "chrome/browser/ash/app_list/search/common/icon_constants.h"
+#include "chrome/browser/ash/app_list/search/common/search_result_util.h"
 #include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
-#include "chrome/browser/ui/app_list/search/common/icon_constants.h"
-#include "chrome/browser/ui/app_list/search/common/search_result_util.h"
 #include "ui/base/page_transition_types.h"
 #include "ui/base/window_open_disposition_utils.h"
 #include "ui/gfx/image/image_skia.h"
diff --git a/chrome/browser/ui/app_list/search/games/game_result.h b/chrome/browser/ash/app_list/search/games/game_result.h
similarity index 88%
rename from chrome/browser/ui/app_list/search/games/game_result.h
rename to chrome/browser/ash/app_list/search/games/game_result.h
index 45ffd381..3ee304ee 100644
--- a/chrome/browser/ui/app_list/search/games/game_result.h
+++ b/chrome/browser/ash/app_list/search/games/game_result.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_GAMES_GAME_RESULT_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_GAMES_GAME_RESULT_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_GAMES_GAME_RESULT_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_GAMES_GAME_RESULT_H_
 
 #include "ash/public/cpp/style/color_mode_observer.h"
 #include "base/memory/weak_ptr.h"
@@ -58,4 +58,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_GAMES_GAME_RESULT_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_GAMES_GAME_RESULT_H_
diff --git a/chrome/browser/ui/app_list/search/games/game_result_unittest.cc b/chrome/browser/ash/app_list/search/games/game_result_unittest.cc
similarity index 94%
rename from chrome/browser/ui/app_list/search/games/game_result_unittest.cc
rename to chrome/browser/ash/app_list/search/games/game_result_unittest.cc
index b761b23..4a9146f 100644
--- a/chrome/browser/ui/app_list/search/games/game_result_unittest.cc
+++ b/chrome/browser/ash/app_list/search/games/game_result_unittest.cc
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/games/game_result.h"
+#include "chrome/browser/ash/app_list/search/games/game_result.h"
 
 #include "chrome/browser/apps/app_discovery_service/app_discovery_service.h"
 #include "chrome/browser/apps/app_discovery_service/game_extras.h"
 #include "chrome/browser/apps/app_discovery_service/result.h"
+#include "chrome/browser/ash/app_list/search/common/icon_constants.h"
+#include "chrome/browser/ash/app_list/search/common/search_result_util.h"
+#include "chrome/browser/ash/app_list/test/test_app_list_controller_delegate.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/app_list/search/common/icon_constants.h"
-#include "chrome/browser/ui/app_list/search/common/search_result_util.h"
-#include "chrome/browser/ui/app_list/test/test_app_list_controller_delegate.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/browser/ui/app_list/search/omnibox/omnibox_answer_result.cc b/chrome/browser/ash/app_list/search/omnibox/omnibox_answer_result.cc
similarity index 96%
rename from chrome/browser/ui/app_list/search/omnibox/omnibox_answer_result.cc
rename to chrome/browser/ash/app_list/search/omnibox/omnibox_answer_result.cc
index 5a42453..3fd9cf3 100644
--- a/chrome/browser/ui/app_list/search/omnibox/omnibox_answer_result.cc
+++ b/chrome/browser/ash/app_list/search/omnibox/omnibox_answer_result.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/ui/app_list/search/omnibox/omnibox_answer_result.h"
+#include "chrome/browser/ash/app_list/search/omnibox/omnibox_answer_result.h"
 
 #include <string>
 #include <utility>
@@ -10,13 +10,13 @@
 #include "ash/public/cpp/app_list/vector_icons/vector_icons.h"
 #include "ash/public/cpp/style/dark_light_mode_controller.h"
 #include "base/strings/string_util.h"
+#include "chrome/browser/ash/app_list/search/common/icon_constants.h"
+#include "chrome/browser/ash/app_list/search/common/search_result_util.h"
+#include "chrome/browser/ash/app_list/search/omnibox/omnibox_util.h"
 #include "chrome/browser/bitmap_fetcher/bitmap_fetcher.h"
 #include "chrome/browser/chromeos/launcher_search/search_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
-#include "chrome/browser/ui/app_list/search/common/icon_constants.h"
-#include "chrome/browser/ui/app_list/search/common/search_result_util.h"
-#include "chrome/browser/ui/app_list/search/omnibox/omnibox_util.h"
 #include "chromeos/crosapi/mojom/launcher_search.mojom.h"
 #include "components/omnibox/browser/vector_icons.h"
 #include "extensions/common/image_util.h"
diff --git a/chrome/browser/ui/app_list/search/omnibox/omnibox_answer_result.h b/chrome/browser/ash/app_list/search/omnibox/omnibox_answer_result.h
similarity index 90%
rename from chrome/browser/ui/app_list/search/omnibox/omnibox_answer_result.h
rename to chrome/browser/ash/app_list/search/omnibox/omnibox_answer_result.h
index 9aa2501e..5bf2373e 100644
--- a/chrome/browser/ui/app_list/search/omnibox/omnibox_answer_result.h
+++ b/chrome/browser/ash/app_list/search/omnibox/omnibox_answer_result.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_OMNIBOX_OMNIBOX_ANSWER_RESULT_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_OMNIBOX_OMNIBOX_ANSWER_RESULT_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_OMNIBOX_OMNIBOX_ANSWER_RESULT_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_OMNIBOX_OMNIBOX_ANSWER_RESULT_H_
 
 #include "ash/public/cpp/style/color_mode_observer.h"
 #include "base/memory/weak_ptr.h"
@@ -69,4 +69,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_OMNIBOX_OMNIBOX_ANSWER_RESULT_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_OMNIBOX_OMNIBOX_ANSWER_RESULT_H_
diff --git a/chrome/browser/ui/app_list/search/omnibox/omnibox_answer_result_unittest.cc b/chrome/browser/ash/app_list/search/omnibox/omnibox_answer_result_unittest.cc
similarity index 99%
rename from chrome/browser/ui/app_list/search/omnibox/omnibox_answer_result_unittest.cc
rename to chrome/browser/ash/app_list/search/omnibox/omnibox_answer_result_unittest.cc
index 12426eab5..ce1941ba 100644
--- a/chrome/browser/ui/app_list/search/omnibox/omnibox_answer_result_unittest.cc
+++ b/chrome/browser/ash/app_list/search/omnibox/omnibox_answer_result_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/ui/app_list/search/omnibox/omnibox_answer_result.h"
+#include "chrome/browser/ash/app_list/search/omnibox/omnibox_answer_result.h"
 
 #include "ash/public/cpp/app_list/app_list_metrics.h"
 #include "ash/public/cpp/app_list/app_list_types.h"
diff --git a/chrome/browser/ui/app_list/search/omnibox/omnibox_lacros_provider.cc b/chrome/browser/ash/app_list/search/omnibox/omnibox_lacros_provider.cc
similarity index 92%
rename from chrome/browser/ui/app_list/search/omnibox/omnibox_lacros_provider.cc
rename to chrome/browser/ash/app_list/search/omnibox/omnibox_lacros_provider.cc
index 000381b..0c7f0b4f 100644
--- a/chrome/browser/ui/app_list/search/omnibox/omnibox_lacros_provider.cc
+++ b/chrome/browser/ash/app_list/search/omnibox/omnibox_lacros_provider.cc
@@ -2,8 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/omnibox/omnibox_lacros_provider.h"
+#include "chrome/browser/ash/app_list/search/omnibox/omnibox_lacros_provider.h"
 
+#include "chrome/browser/ash/app_list/search/omnibox/omnibox_answer_result.h"
+#include "chrome/browser/ash/app_list/search/omnibox/omnibox_result.h"
+#include "chrome/browser/ash/app_list/search/omnibox/omnibox_util.h"
+#include "chrome/browser/ash/app_list/search/omnibox/open_tab_result.h"
 #include "chrome/browser/ash/crosapi/crosapi_ash.h"
 #include "chrome/browser/ash/crosapi/crosapi_manager.h"
 #include "chrome/browser/ash/crosapi/search_provider_ash.h"
@@ -11,10 +15,6 @@
 #include "chrome/browser/chromeos/launcher_search/search_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
-#include "chrome/browser/ui/app_list/search/omnibox/omnibox_answer_result.h"
-#include "chrome/browser/ui/app_list/search/omnibox/omnibox_result.h"
-#include "chrome/browser/ui/app_list/search/omnibox/omnibox_util.h"
-#include "chrome/browser/ui/app_list/search/omnibox/open_tab_result.h"
 #include "chromeos/ash/components/string_matching/tokenized_string.h"
 #include "chromeos/crosapi/mojom/crosapi.mojom.h"
 #include "chromeos/crosapi/mojom/launcher_search.mojom.h"
diff --git a/chrome/browser/ui/app_list/search/omnibox/omnibox_lacros_provider.h b/chrome/browser/ash/app_list/search/omnibox/omnibox_lacros_provider.h
similarity index 86%
rename from chrome/browser/ui/app_list/search/omnibox/omnibox_lacros_provider.h
rename to chrome/browser/ash/app_list/search/omnibox/omnibox_lacros_provider.h
index fcaebd3..8d5d49d0 100644
--- a/chrome/browser/ui/app_list/search/omnibox/omnibox_lacros_provider.h
+++ b/chrome/browser/ash/app_list/search/omnibox/omnibox_lacros_provider.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_OMNIBOX_OMNIBOX_LACROS_PROVIDER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_OMNIBOX_OMNIBOX_LACROS_PROVIDER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_OMNIBOX_OMNIBOX_LACROS_PROVIDER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_OMNIBOX_OMNIBOX_LACROS_PROVIDER_H_
 
 #include "ash/public/cpp/app_list/app_list_types.h"
 #include "base/memory/weak_ptr.h"
@@ -52,4 +52,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_OMNIBOX_OMNIBOX_LACROS_PROVIDER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_OMNIBOX_OMNIBOX_LACROS_PROVIDER_H_
diff --git a/chrome/browser/ui/app_list/search/omnibox/omnibox_lacros_provider_unittest.cc b/chrome/browser/ash/app_list/search/omnibox/omnibox_lacros_provider_unittest.cc
similarity index 97%
rename from chrome/browser/ui/app_list/search/omnibox/omnibox_lacros_provider_unittest.cc
rename to chrome/browser/ash/app_list/search/omnibox/omnibox_lacros_provider_unittest.cc
index 9819a97e..333a040 100644
--- a/chrome/browser/ui/app_list/search/omnibox/omnibox_lacros_provider_unittest.cc
+++ b/chrome/browser/ash/app_list/search/omnibox/omnibox_lacros_provider_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/ui/app_list/search/omnibox/omnibox_lacros_provider.h"
+#include "chrome/browser/ash/app_list/search/omnibox/omnibox_lacros_provider.h"
 
 #include <memory>
 #include <string>
@@ -10,15 +10,15 @@
 
 #include "ash/constants/ash_features.h"
 #include "base/run_loop.h"
+#include "chrome/browser/ash/app_list/search/omnibox/omnibox_util.h"
+#include "chrome/browser/ash/app_list/search/test/test_search_controller.h"
+#include "chrome/browser/ash/app_list/test/test_app_list_controller_delegate.h"
 #include "chrome/browser/ash/crosapi/crosapi_ash.h"
 #include "chrome/browser/ash/crosapi/crosapi_manager.h"
 #include "chrome/browser/ash/crosapi/idle_service_ash.h"
 #include "chrome/browser/ash/crosapi/search_provider_ash.h"
 #include "chrome/browser/ash/crosapi/test_crosapi_dependency_registry.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
-#include "chrome/browser/ui/app_list/search/omnibox/omnibox_util.h"
-#include "chrome/browser/ui/app_list/search/test/test_search_controller.h"
-#include "chrome/browser/ui/app_list/test/test_app_list_controller_delegate.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile_manager.h"
diff --git a/chrome/browser/ui/app_list/search/omnibox/omnibox_provider.cc b/chrome/browser/ash/app_list/search/omnibox/omnibox_provider.cc
similarity index 94%
rename from chrome/browser/ui/app_list/search/omnibox/omnibox_provider.cc
rename to chrome/browser/ash/app_list/search/omnibox/omnibox_provider.cc
index ae3f355..a60bc8d 100644
--- a/chrome/browser/ui/app_list/search/omnibox/omnibox_provider.cc
+++ b/chrome/browser/ash/app_list/search/omnibox/omnibox_provider.cc
@@ -2,13 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/omnibox/omnibox_provider.h"
+#include "chrome/browser/ash/app_list/search/omnibox/omnibox_provider.h"
 
 #include <iterator>
 #include <string>
 #include <utility>
 
 #include "base/metrics/histogram_macros.h"
+#include "chrome/browser/ash/app_list/search/omnibox/omnibox_answer_result.h"
+#include "chrome/browser/ash/app_list/search/omnibox/omnibox_result.h"
+#include "chrome/browser/ash/app_list/search/omnibox/omnibox_util.h"
+#include "chrome/browser/ash/app_list/search/omnibox/open_tab_result.h"
 #include "chrome/browser/autocomplete/chrome_autocomplete_provider_client.h"
 #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
@@ -17,10 +21,6 @@
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
-#include "chrome/browser/ui/app_list/search/omnibox/omnibox_answer_result.h"
-#include "chrome/browser/ui/app_list/search/omnibox/omnibox_result.h"
-#include "chrome/browser/ui/app_list/search/omnibox/omnibox_util.h"
-#include "chrome/browser/ui/app_list/search/omnibox/open_tab_result.h"
 #include "components/favicon/core/favicon_service.h"
 #include "components/omnibox/browser/autocomplete_classifier.h"
 #include "components/omnibox/browser/autocomplete_input.h"
diff --git a/chrome/browser/ui/app_list/search/omnibox/omnibox_provider.h b/chrome/browser/ash/app_list/search/omnibox/omnibox_provider.h
similarity index 91%
rename from chrome/browser/ui/app_list/search/omnibox/omnibox_provider.h
rename to chrome/browser/ash/app_list/search/omnibox/omnibox_provider.h
index 4e2a93e..5ed467b8 100644
--- a/chrome/browser/ui/app_list/search/omnibox/omnibox_provider.h
+++ b/chrome/browser/ash/app_list/search/omnibox/omnibox_provider.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_OMNIBOX_OMNIBOX_PROVIDER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_OMNIBOX_OMNIBOX_PROVIDER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_OMNIBOX_OMNIBOX_PROVIDER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_OMNIBOX_OMNIBOX_PROVIDER_H_
 
 #include <algorithm>
 #include <memory>
@@ -75,4 +75,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_OMNIBOX_OMNIBOX_PROVIDER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_OMNIBOX_OMNIBOX_PROVIDER_H_
diff --git a/chrome/browser/ui/app_list/search/omnibox/omnibox_provider_unittest.cc b/chrome/browser/ash/app_list/search/omnibox/omnibox_provider_unittest.cc
similarity index 97%
rename from chrome/browser/ui/app_list/search/omnibox/omnibox_provider_unittest.cc
rename to chrome/browser/ash/app_list/search/omnibox/omnibox_provider_unittest.cc
index c04253b..1caa90b1 100644
--- a/chrome/browser/ui/app_list/search/omnibox/omnibox_provider_unittest.cc
+++ b/chrome/browser/ash/app_list/search/omnibox/omnibox_provider_unittest.cc
@@ -2,17 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/omnibox/omnibox_provider.h"
+#include "chrome/browser/ash/app_list/search/omnibox/omnibox_provider.h"
 
 #include <cstddef>
 #include <string>
 #include <vector>
 
 #include "base/run_loop.h"
+#include "chrome/browser/ash/app_list/search/test/test_search_controller.h"
+#include "chrome/browser/ash/app_list/test/test_app_list_controller_delegate.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/ui/app_list/search/search_controller.h"
-#include "chrome/browser/ui/app_list/search/test/test_search_controller.h"
-#include "chrome/browser/ui/app_list/test/test_app_list_controller_delegate.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile_manager.h"
diff --git a/chrome/browser/ui/app_list/search/omnibox/omnibox_result.cc b/chrome/browser/ash/app_list/search/omnibox/omnibox_result.cc
similarity index 97%
rename from chrome/browser/ui/app_list/search/omnibox/omnibox_result.cc
rename to chrome/browser/ash/app_list/search/omnibox/omnibox_result.cc
index f8451d7..d4ee7bc 100644
--- a/chrome/browser/ui/app_list/search/omnibox/omnibox_result.cc
+++ b/chrome/browser/ash/app_list/search/omnibox/omnibox_result.cc
@@ -2,18 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/omnibox/omnibox_result.h"
+#include "chrome/browser/ash/app_list/search/omnibox/omnibox_result.h"
 
 #include "ash/public/cpp/app_list/vector_icons/vector_icons.h"
 #include "ash/public/cpp/style/dark_light_mode_controller.h"
 #include "base/strings/strcat.h"
+#include "chrome/browser/ash/app_list/search/common/icon_constants.h"
+#include "chrome/browser/ash/app_list/search/omnibox/omnibox_util.h"
 #include "chrome/browser/bitmap_fetcher/bitmap_fetcher.h"
 #include "chrome/browser/chromeos/launcher_search/search_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
-#include "chrome/browser/ui/app_list/search/common/icon_constants.h"
-#include "chrome/browser/ui/app_list/search/omnibox/omnibox_util.h"
 #include "chrome/grit/generated_resources.h"
 #include "chromeos/crosapi/mojom/launcher_search.mojom.h"
 #include "components/omnibox/browser/vector_icons.h"
diff --git a/chrome/browser/ui/app_list/search/omnibox/omnibox_result.h b/chrome/browser/ash/app_list/search/omnibox/omnibox_result.h
similarity index 93%
rename from chrome/browser/ui/app_list/search/omnibox/omnibox_result.h
rename to chrome/browser/ash/app_list/search/omnibox/omnibox_result.h
index 934841f1..fe49506e 100644
--- a/chrome/browser/ui/app_list/search/omnibox/omnibox_result.h
+++ b/chrome/browser/ash/app_list/search/omnibox/omnibox_result.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_OMNIBOX_OMNIBOX_RESULT_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_OMNIBOX_OMNIBOX_RESULT_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_OMNIBOX_OMNIBOX_RESULT_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_OMNIBOX_OMNIBOX_RESULT_H_
 
 #include <memory>
 #include <string>
@@ -96,4 +96,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_OMNIBOX_OMNIBOX_RESULT_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_OMNIBOX_OMNIBOX_RESULT_H_
diff --git a/chrome/browser/ui/app_list/search/omnibox/omnibox_result_unittest.cc b/chrome/browser/ash/app_list/search/omnibox/omnibox_result_unittest.cc
similarity index 98%
rename from chrome/browser/ui/app_list/search/omnibox/omnibox_result_unittest.cc
rename to chrome/browser/ash/app_list/search/omnibox/omnibox_result_unittest.cc
index 432072d..bc786d0 100644
--- a/chrome/browser/ui/app_list/search/omnibox/omnibox_result_unittest.cc
+++ b/chrome/browser/ash/app_list/search/omnibox/omnibox_result_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/ui/app_list/search/omnibox/omnibox_result.h"
+#include "chrome/browser/ash/app_list/search/omnibox/omnibox_result.h"
 
 #include <memory>
 #include <string>
@@ -16,12 +16,12 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/run_loop.h"
 #include "base/task/cancelable_task_tracker.h"
+#include "chrome/browser/ash/app_list/search/common/icon_constants.h"
+#include "chrome/browser/ash/app_list/test/test_app_list_controller_delegate.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/chromeos/launcher_search/search_util.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
-#include "chrome/browser/ui/app_list/search/common/icon_constants.h"
-#include "chrome/browser/ui/app_list/test/test_app_list_controller_delegate.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/bookmarks/browser/bookmark_model.h"
 #include "components/bookmarks/test/bookmark_test_helpers.h"
diff --git a/chrome/browser/ui/app_list/search/omnibox/omnibox_util.cc b/chrome/browser/ash/app_list/search/omnibox/omnibox_util.cc
similarity index 93%
rename from chrome/browser/ui/app_list/search/omnibox/omnibox_util.cc
rename to chrome/browser/ash/app_list/search/omnibox/omnibox_util.cc
index b67ff976..d786d64 100644
--- a/chrome/browser/ui/app_list/search/omnibox/omnibox_util.cc
+++ b/chrome/browser/ash/app_list/search/omnibox/omnibox_util.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/omnibox/omnibox_util.h"
+#include "chrome/browser/ash/app_list/search/omnibox/omnibox_util.h"
 
 #include <algorithm>
 #include <string>
 
 #include "base/containers/flat_set.h"
-#include "chrome/browser/ui/app_list/search/omnibox/omnibox_result.h"
+#include "chrome/browser/ash/app_list/search/omnibox/omnibox_result.h"
 #include "url/gurl.h"
 
 namespace app_list {
diff --git a/chrome/browser/ui/app_list/search/omnibox/omnibox_util.h b/chrome/browser/ash/app_list/search/omnibox/omnibox_util.h
similarity index 92%
rename from chrome/browser/ui/app_list/search/omnibox/omnibox_util.h
rename to chrome/browser/ash/app_list/search/omnibox/omnibox_util.h
index 5a3c70b..5057f61 100644
--- a/chrome/browser/ui/app_list/search/omnibox/omnibox_util.h
+++ b/chrome/browser/ash/app_list/search/omnibox/omnibox_util.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_OMNIBOX_OMNIBOX_UTIL_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_OMNIBOX_OMNIBOX_UTIL_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_OMNIBOX_OMNIBOX_UTIL_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_OMNIBOX_OMNIBOX_UTIL_H_
 
 #include <memory>
 #include <string>
@@ -69,4 +69,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_OMNIBOX_OMNIBOX_UTIL_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_OMNIBOX_OMNIBOX_UTIL_H_
diff --git a/chrome/browser/ui/app_list/search/omnibox/open_tab_result.cc b/chrome/browser/ash/app_list/search/omnibox/open_tab_result.cc
similarity index 93%
rename from chrome/browser/ui/app_list/search/omnibox/open_tab_result.cc
rename to chrome/browser/ash/app_list/search/omnibox/open_tab_result.cc
index e337f54b1..8401752 100644
--- a/chrome/browser/ui/app_list/search/omnibox/open_tab_result.cc
+++ b/chrome/browser/ash/app_list/search/omnibox/open_tab_result.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/ui/app_list/search/omnibox/open_tab_result.h"
+#include "chrome/browser/ash/app_list/search/omnibox/open_tab_result.h"
 
 #include "ash/public/cpp/app_list/vector_icons/vector_icons.h"
 #include "ash/public/cpp/style/dark_light_mode_controller.h"
@@ -10,12 +10,12 @@
 #include "base/strings/strcat.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/ash/app_list/search/common/icon_constants.h"
+#include "chrome/browser/ash/app_list/search/common/search_result_util.h"
+#include "chrome/browser/ash/app_list/search/common/string_util.h"
+#include "chrome/browser/ash/app_list/search/omnibox/omnibox_util.h"
 #include "chrome/browser/chromeos/launcher_search/search_util.h"
 #include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
-#include "chrome/browser/ui/app_list/search/common/icon_constants.h"
-#include "chrome/browser/ui/app_list/search/common/search_result_util.h"
-#include "chrome/browser/ui/app_list/search/common/string_util.h"
-#include "chrome/browser/ui/app_list/search/omnibox/omnibox_util.h"
 #include "chromeos/ash/components/string_matching/tokenized_string.h"
 #include "chromeos/ash/components/string_matching/tokenized_string_match.h"
 #include "chromeos/crosapi/mojom/launcher_search.mojom.h"
diff --git a/chrome/browser/ui/app_list/search/omnibox/open_tab_result.h b/chrome/browser/ash/app_list/search/omnibox/open_tab_result.h
similarity index 91%
rename from chrome/browser/ui/app_list/search/omnibox/open_tab_result.h
rename to chrome/browser/ash/app_list/search/omnibox/open_tab_result.h
index 0d4aa474..ab40c9a4e 100644
--- a/chrome/browser/ui/app_list/search/omnibox/open_tab_result.h
+++ b/chrome/browser/ash/app_list/search/omnibox/open_tab_result.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_OMNIBOX_OPEN_TAB_RESULT_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_OMNIBOX_OPEN_TAB_RESULT_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_OMNIBOX_OPEN_TAB_RESULT_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_OMNIBOX_OPEN_TAB_RESULT_H_
 
 #include <string>
 
@@ -69,4 +69,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_OMNIBOX_OPEN_TAB_RESULT_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_OMNIBOX_OPEN_TAB_RESULT_H_
diff --git a/chrome/browser/ui/app_list/search/omnibox/open_tab_result_unittest.cc b/chrome/browser/ash/app_list/search/omnibox/open_tab_result_unittest.cc
similarity index 95%
rename from chrome/browser/ui/app_list/search/omnibox/open_tab_result_unittest.cc
rename to chrome/browser/ash/app_list/search/omnibox/open_tab_result_unittest.cc
index 2cb17a8c..23e4860 100644
--- a/chrome/browser/ui/app_list/search/omnibox/open_tab_result_unittest.cc
+++ b/chrome/browser/ash/app_list/search/omnibox/open_tab_result_unittest.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/omnibox/open_tab_result.h"
+#include "chrome/browser/ash/app_list/search/omnibox/open_tab_result.h"
 
 #include "ash/strings/grit/ash_strings.h"
 #include "base/strings/strcat.h"
+#include "chrome/browser/ash/app_list/search/common/search_result_util.h"
+#include "chrome/browser/ash/app_list/test/test_app_list_controller_delegate.h"
 #include "chrome/browser/chromeos/launcher_search/search_util.h"
-#include "chrome/browser/ui/app_list/search/common/search_result_util.h"
-#include "chrome/browser/ui/app_list/test/test_app_list_controller_delegate.h"
 #include "chromeos/ash/components/string_matching/tokenized_string.h"
 #include "components/bookmarks/browser/bookmark_model.h"
 #include "components/favicon/core/test/mock_favicon_service.h"
diff --git a/chrome/browser/ui/app_list/search/ranking/BUILD.gn b/chrome/browser/ash/app_list/search/ranking/BUILD.gn
similarity index 78%
rename from chrome/browser/ui/app_list/search/ranking/BUILD.gn
rename to chrome/browser/ash/app_list/search/ranking/BUILD.gn
index a9fbcb00..48a6d76 100644
--- a/chrome/browser/ui/app_list/search/ranking/BUILD.gn
+++ b/chrome/browser/ash/app_list/search/ranking/BUILD.gn
@@ -2,8 +2,11 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//third_party/protobuf/proto_library.gni")
 
+assert(is_chromeos_ash)
+
 proto_library("proto") {
   sources = [ "removed_results.proto" ]
 }
diff --git a/chrome/browser/ui/app_list/search/ranking/answer_ranker.cc b/chrome/browser/ash/app_list/search/ranking/answer_ranker.cc
similarity index 96%
rename from chrome/browser/ui/app_list/search/ranking/answer_ranker.cc
rename to chrome/browser/ash/app_list/search/ranking/answer_ranker.cc
index e31b915..a014485d 100644
--- a/chrome/browser/ui/app_list/search/ranking/answer_ranker.cc
+++ b/chrome/browser/ash/app_list/search/ranking/answer_ranker.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/ranking/answer_ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/answer_ranker.h"
 
 #include "ash/public/cpp/app_list/app_list_types.h"
+#include "chrome/browser/ash/app_list/search/common/icon_constants.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
-#include "chrome/browser/ui/app_list/search/common/icon_constants.h"
 
 namespace app_list {
 namespace {
diff --git a/chrome/browser/ui/app_list/search/ranking/answer_ranker.h b/chrome/browser/ash/app_list/search/ranking/answer_ranker.h
similarity index 81%
rename from chrome/browser/ui/app_list/search/ranking/answer_ranker.h
rename to chrome/browser/ash/app_list/search/ranking/answer_ranker.h
index 6edbed9e..d0c3339 100644
--- a/chrome/browser/ui/app_list/search/ranking/answer_ranker.h
+++ b/chrome/browser/ash/app_list/search/ranking/answer_ranker.h
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_ANSWER_RANKER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_ANSWER_RANKER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_ANSWER_RANKER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_ANSWER_RANKER_H_
 
 #include "base/memory/weak_ptr.h"
-#include "chrome/browser/ui/app_list/search/ranking/ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/ranker.h"
 #include "chrome/browser/ui/app_list/search/types.h"
 
 namespace app_list {
@@ -41,4 +41,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_ANSWER_RANKER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_ANSWER_RANKER_H_
diff --git a/chrome/browser/ui/app_list/search/ranking/answer_ranker_unittest.cc b/chrome/browser/ash/app_list/search/ranking/answer_ranker_unittest.cc
similarity index 96%
rename from chrome/browser/ui/app_list/search/ranking/answer_ranker_unittest.cc
rename to chrome/browser/ash/app_list/search/ranking/answer_ranker_unittest.cc
index 8585cef..806c208 100644
--- a/chrome/browser/ui/app_list/search/ranking/answer_ranker_unittest.cc
+++ b/chrome/browser/ash/app_list/search/ranking/answer_ranker_unittest.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/ranking/answer_ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/answer_ranker.h"
 
+#include "chrome/browser/ash/app_list/search/common/icon_constants.h"
+#include "chrome/browser/ash/app_list/search/test/test_result.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
-#include "chrome/browser/ui/app_list/search/common/icon_constants.h"
-#include "chrome/browser/ui/app_list/search/test/test_result.h"
 #include "chrome/browser/ui/app_list/search/types.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ui/app_list/search/ranking/best_match_ranker.cc b/chrome/browser/ash/app_list/search/ranking/best_match_ranker.cc
similarity index 97%
rename from chrome/browser/ui/app_list/search/ranking/best_match_ranker.cc
rename to chrome/browser/ash/app_list/search/ranking/best_match_ranker.cc
index 1b2d41a..afa6168 100644
--- a/chrome/browser/ui/app_list/search/ranking/best_match_ranker.cc
+++ b/chrome/browser/ash/app_list/search/ranking/best_match_ranker.cc
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/ranking/best_match_ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/best_match_ranker.h"
 
 #include <cmath>
 #include <vector>
 
 #include "base/containers/flat_set.h"
+#include "chrome/browser/ash/app_list/search/ranking/constants.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
-#include "chrome/browser/ui/app_list/search/ranking/constants.h"
 #include "chrome/browser/ui/app_list/search/types.h"
 
 namespace app_list {
diff --git a/chrome/browser/ui/app_list/search/ranking/best_match_ranker.h b/chrome/browser/ash/app_list/search/ranking/best_match_ranker.h
similarity index 87%
rename from chrome/browser/ui/app_list/search/ranking/best_match_ranker.h
rename to chrome/browser/ash/app_list/search/ranking/best_match_ranker.h
index 4bf16897..3a65212 100644
--- a/chrome/browser/ui/app_list/search/ranking/best_match_ranker.h
+++ b/chrome/browser/ash/app_list/search/ranking/best_match_ranker.h
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_BEST_MATCH_RANKER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_BEST_MATCH_RANKER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_BEST_MATCH_RANKER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_BEST_MATCH_RANKER_H_
 
-#include "chrome/browser/ui/app_list/search/ranking/ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/ranker.h"
 
 namespace app_list {
 
@@ -57,4 +57,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_BEST_MATCH_RANKER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_BEST_MATCH_RANKER_H_
diff --git a/chrome/browser/ui/app_list/search/ranking/best_match_ranker_unittest.cc b/chrome/browser/ash/app_list/search/ranking/best_match_ranker_unittest.cc
similarity index 98%
rename from chrome/browser/ui/app_list/search/ranking/best_match_ranker_unittest.cc
rename to chrome/browser/ash/app_list/search/ranking/best_match_ranker_unittest.cc
index 16a96a6..e3495cc 100644
--- a/chrome/browser/ui/app_list/search/ranking/best_match_ranker_unittest.cc
+++ b/chrome/browser/ash/app_list/search/ranking/best_match_ranker_unittest.cc
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/ranking/best_match_ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/best_match_ranker.h"
 
+#include "chrome/browser/ash/app_list/search/test/test_result.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
-#include "chrome/browser/ui/app_list/search/test/test_result.h"
 #include "chrome/browser/ui/app_list/search/types.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ui/app_list/search/ranking/constants.h b/chrome/browser/ash/app_list/search/ranking/constants.h
similarity index 79%
rename from chrome/browser/ui/app_list/search/ranking/constants.h
rename to chrome/browser/ash/app_list/search/ranking/constants.h
index 6afa8b7a..51905cb 100644
--- a/chrome/browser/ui/app_list/search/ranking/constants.h
+++ b/chrome/browser/ash/app_list/search/ranking/constants.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_CONSTANTS_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_CONSTANTS_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_CONSTANTS_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_CONSTANTS_H_
 
 namespace app_list {
 
@@ -24,4 +24,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_CONSTANTS_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_CONSTANTS_H_
diff --git a/chrome/browser/ui/app_list/search/ranking/continue_ranker.cc b/chrome/browser/ash/app_list/search/ranking/continue_ranker.cc
similarity index 93%
rename from chrome/browser/ui/app_list/search/ranking/continue_ranker.cc
rename to chrome/browser/ash/app_list/search/ranking/continue_ranker.cc
index 711bfacf..401bbf54 100644
--- a/chrome/browser/ui/app_list/search/ranking/continue_ranker.cc
+++ b/chrome/browser/ash/app_list/search/ranking/continue_ranker.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/ui/app_list/search/ranking/continue_ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/continue_ranker.h"
 
 #include "ash/public/cpp/app_list/app_list_types.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
diff --git a/chrome/browser/ui/app_list/search/ranking/continue_ranker.h b/chrome/browser/ash/app_list/search/ranking/continue_ranker.h
similarity index 69%
rename from chrome/browser/ui/app_list/search/ranking/continue_ranker.h
rename to chrome/browser/ash/app_list/search/ranking/continue_ranker.h
index d6e159c..bc36c71a 100644
--- a/chrome/browser/ui/app_list/search/ranking/continue_ranker.h
+++ b/chrome/browser/ash/app_list/search/ranking/continue_ranker.h
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_CONTINUE_RANKER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_CONTINUE_RANKER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_CONTINUE_RANKER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_CONTINUE_RANKER_H_
 
-#include "chrome/browser/ui/app_list/search/ranking/ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/ranker.h"
 #include "chrome/browser/ui/app_list/search/types.h"
 
 namespace app_list {
@@ -25,4 +25,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_CONTINUE_RANKER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_CONTINUE_RANKER_H_
diff --git a/chrome/browser/ui/app_list/search/ranking/filtering_ranker.cc b/chrome/browser/ash/app_list/search/ranking/filtering_ranker.cc
similarity index 95%
rename from chrome/browser/ui/app_list/search/ranking/filtering_ranker.cc
rename to chrome/browser/ash/app_list/search/ranking/filtering_ranker.cc
index 534ff350..5cd29df 100644
--- a/chrome/browser/ui/app_list/search/ranking/filtering_ranker.cc
+++ b/chrome/browser/ash/app_list/search/ranking/filtering_ranker.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/ranking/filtering_ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/filtering_ranker.h"
 
 #include "ash/public/cpp/app_list/app_list_config.h"
 #include "base/containers/flat_set.h"
+#include "chrome/browser/ash/app_list/search/omnibox/omnibox_util.h"
+#include "chrome/browser/ash/app_list/search/ranking/constants.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
-#include "chrome/browser/ui/app_list/search/omnibox/omnibox_util.h"
-#include "chrome/browser/ui/app_list/search/ranking/constants.h"
 #include "chromeos/crosapi/mojom/launcher_search.mojom.h"
 
 namespace app_list {
diff --git a/chrome/browser/ui/app_list/search/ranking/filtering_ranker.h b/chrome/browser/ash/app_list/search/ranking/filtering_ranker.h
similarity index 75%
rename from chrome/browser/ui/app_list/search/ranking/filtering_ranker.h
rename to chrome/browser/ash/app_list/search/ranking/filtering_ranker.h
index 7b6dbee..43d3100 100644
--- a/chrome/browser/ui/app_list/search/ranking/filtering_ranker.h
+++ b/chrome/browser/ash/app_list/search/ranking/filtering_ranker.h
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_FILTERING_RANKER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_FILTERING_RANKER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_FILTERING_RANKER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_FILTERING_RANKER_H_
 
-#include "chrome/browser/ui/app_list/search/ranking/ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/ranker.h"
 
 namespace app_list {
 
@@ -32,4 +32,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_FILTERING_RANKER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_FILTERING_RANKER_H_
diff --git a/chrome/browser/ui/app_list/search/ranking/filtering_ranker_unittest.cc b/chrome/browser/ash/app_list/search/ranking/filtering_ranker_unittest.cc
similarity index 95%
rename from chrome/browser/ui/app_list/search/ranking/filtering_ranker_unittest.cc
rename to chrome/browser/ash/app_list/search/ranking/filtering_ranker_unittest.cc
index 1b3d25b..50105fd 100644
--- a/chrome/browser/ui/app_list/search/ranking/filtering_ranker_unittest.cc
+++ b/chrome/browser/ash/app_list/search/ranking/filtering_ranker_unittest.cc
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/ranking/filtering_ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/filtering_ranker.h"
 
+#include "chrome/browser/ash/app_list/search/omnibox/omnibox_util.h"
+#include "chrome/browser/ash/app_list/search/test/test_result.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
-#include "chrome/browser/ui/app_list/search/omnibox/omnibox_util.h"
 #include "chrome/browser/ui/app_list/search/search_controller.h"
-#include "chrome/browser/ui/app_list/search/test/test_result.h"
 #include "chrome/browser/ui/app_list/search/types.h"
 #include "chromeos/crosapi/mojom/launcher_search.mojom-forward.h"
 #include "chromeos/crosapi/mojom/launcher_search.mojom.h"
diff --git a/chrome/browser/ui/app_list/search/ranking/ftrl_ranker.cc b/chrome/browser/ash/app_list/search/ranking/ftrl_ranker.cc
similarity index 96%
rename from chrome/browser/ui/app_list/search/ranking/ftrl_ranker.cc
rename to chrome/browser/ash/app_list/search/ranking/ftrl_ranker.cc
index c4990e3..d77c0b4 100644
--- a/chrome/browser/ui/app_list/search/ranking/ftrl_ranker.cc
+++ b/chrome/browser/ash/app_list/search/ranking/ftrl_ranker.cc
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/ranking/ftrl_ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/ftrl_ranker.h"
 
 #include "base/strings/string_number_conversions.h"
+#include "chrome/browser/ash/app_list/search/ranking/util.h"
+#include "chrome/browser/ash/app_list/search/util/ftrl_optimizer.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
-#include "chrome/browser/ui/app_list/search/ranking/util.h"
-#include "chrome/browser/ui/app_list/search/util/ftrl_optimizer.h"
 
 namespace app_list {
 
diff --git a/chrome/browser/ui/app_list/search/ranking/ftrl_ranker.h b/chrome/browser/ash/app_list/search/ranking/ftrl_ranker.h
similarity index 87%
rename from chrome/browser/ui/app_list/search/ranking/ftrl_ranker.h
rename to chrome/browser/ash/app_list/search/ranking/ftrl_ranker.h
index 51f0044e..931018b 100644
--- a/chrome/browser/ui/app_list/search/ranking/ftrl_ranker.h
+++ b/chrome/browser/ash/app_list/search/ranking/ftrl_ranker.h
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_FTRL_RANKER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_FTRL_RANKER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_FTRL_RANKER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_FTRL_RANKER_H_
 
-#include "chrome/browser/ui/app_list/search/ranking/ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/ranker.h"
+#include "chrome/browser/ash/app_list/search/util/ftrl_optimizer.h"
+#include "chrome/browser/ash/app_list/search/util/mrfu_cache.h"
 #include "chrome/browser/ui/app_list/search/types.h"
-#include "chrome/browser/ui/app_list/search/util/ftrl_optimizer.h"
-#include "chrome/browser/ui/app_list/search/util/mrfu_cache.h"
 
 namespace app_list {
 
@@ -94,4 +94,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_FTRL_RANKER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_FTRL_RANKER_H_
diff --git a/chrome/browser/ui/app_list/search/ranking/ftrl_ranker_unittest.cc b/chrome/browser/ash/app_list/search/ranking/ftrl_ranker_unittest.cc
similarity index 97%
rename from chrome/browser/ui/app_list/search/ranking/ftrl_ranker_unittest.cc
rename to chrome/browser/ash/app_list/search/ranking/ftrl_ranker_unittest.cc
index ecfc3fc..e9f127b 100644
--- a/chrome/browser/ui/app_list/search/ranking/ftrl_ranker_unittest.cc
+++ b/chrome/browser/ash/app_list/search/ranking/ftrl_ranker_unittest.cc
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/ranking/ftrl_ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/ftrl_ranker.h"
 
+#include "chrome/browser/ash/app_list/search/ranking/ranker.h"
+#include "chrome/browser/ash/app_list/search/test/ranking_test_util.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
-#include "chrome/browser/ui/app_list/search/ranking/ranker.h"
 #include "chrome/browser/ui/app_list/search/search_controller.h"
-#include "chrome/browser/ui/app_list/search/test/ranking_test_util.h"
 #include "chrome/browser/ui/app_list/search/types.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ui/app_list/search/ranking/launch_data.cc b/chrome/browser/ash/app_list/search/ranking/launch_data.cc
similarity index 82%
rename from chrome/browser/ui/app_list/search/ranking/launch_data.cc
rename to chrome/browser/ash/app_list/search/ranking/launch_data.cc
index cb1c6d86..6244a6074 100644
--- a/chrome/browser/ui/app_list/search/ranking/launch_data.cc
+++ b/chrome/browser/ash/app_list/search/ranking/launch_data.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/ui/app_list/search/ranking/launch_data.h"
+#include "chrome/browser/ash/app_list/search/ranking/launch_data.h"
 
 namespace app_list {
 
diff --git a/chrome/browser/ui/app_list/search/ranking/launch_data.h b/chrome/browser/ash/app_list/search/ranking/launch_data.h
similarity index 83%
rename from chrome/browser/ui/app_list/search/ranking/launch_data.h
rename to chrome/browser/ash/app_list/search/ranking/launch_data.h
index 32df0e8..f375c73b 100644
--- a/chrome/browser/ui/app_list/search/ranking/launch_data.h
+++ b/chrome/browser/ash/app_list/search/ranking/launch_data.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_LAUNCH_DATA_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_LAUNCH_DATA_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_LAUNCH_DATA_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_LAUNCH_DATA_H_
 
 #include <string>
 
@@ -36,4 +36,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_LAUNCH_DATA_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_LAUNCH_DATA_H_
diff --git a/chrome/browser/ui/app_list/search/ranking/mrfu_ranker.cc b/chrome/browser/ash/app_list/search/ranking/mrfu_ranker.cc
similarity index 95%
rename from chrome/browser/ui/app_list/search/ranking/mrfu_ranker.cc
rename to chrome/browser/ash/app_list/search/ranking/mrfu_ranker.cc
index 690abb1..32b9f04 100644
--- a/chrome/browser/ui/app_list/search/ranking/mrfu_ranker.cc
+++ b/chrome/browser/ash/app_list/search/ranking/mrfu_ranker.cc
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/ranking/mrfu_ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/mrfu_ranker.h"
 
+#include "chrome/browser/ash/app_list/search/ranking/util.h"
+#include "chrome/browser/ash/app_list/search/util/ftrl_optimizer.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
-#include "chrome/browser/ui/app_list/search/ranking/util.h"
 #include "chrome/browser/ui/app_list/search/types.h"
-#include "chrome/browser/ui/app_list/search/util/ftrl_optimizer.h"
 
 namespace app_list {
 
diff --git a/chrome/browser/ui/app_list/search/ranking/mrfu_ranker.h b/chrome/browser/ash/app_list/search/ranking/mrfu_ranker.h
similarity index 84%
rename from chrome/browser/ui/app_list/search/ranking/mrfu_ranker.h
rename to chrome/browser/ash/app_list/search/ranking/mrfu_ranker.h
index bec31fe9..2846318 100644
--- a/chrome/browser/ui/app_list/search/ranking/mrfu_ranker.h
+++ b/chrome/browser/ash/app_list/search/ranking/mrfu_ranker.h
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_MRFU_RANKER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_MRFU_RANKER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_MRFU_RANKER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_MRFU_RANKER_H_
 
-#include "chrome/browser/ui/app_list/search/ranking/ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/ranker.h"
+#include "chrome/browser/ash/app_list/search/util/ftrl_optimizer.h"
+#include "chrome/browser/ash/app_list/search/util/mrfu_cache.h"
 #include "chrome/browser/ui/app_list/search/types.h"
-#include "chrome/browser/ui/app_list/search/util/ftrl_optimizer.h"
-#include "chrome/browser/ui/app_list/search/util/mrfu_cache.h"
 
 namespace app_list {
 
@@ -68,4 +68,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_MRFU_RANKER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_MRFU_RANKER_H_
diff --git a/chrome/browser/ui/app_list/search/ranking/mrfu_ranker_unittest.cc b/chrome/browser/ash/app_list/search/ranking/mrfu_ranker_unittest.cc
similarity index 96%
rename from chrome/browser/ui/app_list/search/ranking/mrfu_ranker_unittest.cc
rename to chrome/browser/ash/app_list/search/ranking/mrfu_ranker_unittest.cc
index 3b36a11..224b761 100644
--- a/chrome/browser/ui/app_list/search/ranking/mrfu_ranker_unittest.cc
+++ b/chrome/browser/ash/app_list/search/ranking/mrfu_ranker_unittest.cc
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/ranking/mrfu_ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/mrfu_ranker.h"
 
+#include "chrome/browser/ash/app_list/search/ranking/ranker.h"
+#include "chrome/browser/ash/app_list/search/test/ranking_test_util.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
-#include "chrome/browser/ui/app_list/search/ranking/ranker.h"
 #include "chrome/browser/ui/app_list/search/search_controller.h"
-#include "chrome/browser/ui/app_list/search/test/ranking_test_util.h"
 #include "chrome/browser/ui/app_list/search/types.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ui/app_list/search/ranking/query_highlighter.cc b/chrome/browser/ash/app_list/search/ranking/query_highlighter.cc
similarity index 97%
rename from chrome/browser/ui/app_list/search/ranking/query_highlighter.cc
rename to chrome/browser/ash/app_list/search/ranking/query_highlighter.cc
index e0d7e3f5..d794a7c 100644
--- a/chrome/browser/ui/app_list/search/ranking/query_highlighter.cc
+++ b/chrome/browser/ash/app_list/search/ranking/query_highlighter.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/ui/app_list/search/ranking/query_highlighter.h"
+#include "chrome/browser/ash/app_list/search/ranking/query_highlighter.h"
 
 #include "ash/public/cpp/app_list/app_list_types.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
diff --git a/chrome/browser/ui/app_list/search/ranking/query_highlighter.h b/chrome/browser/ash/app_list/search/ranking/query_highlighter.h
similarity index 74%
rename from chrome/browser/ui/app_list/search/ranking/query_highlighter.h
rename to chrome/browser/ash/app_list/search/ranking/query_highlighter.h
index 74c8113..fa279f7 100644
--- a/chrome/browser/ui/app_list/search/ranking/query_highlighter.h
+++ b/chrome/browser/ash/app_list/search/ranking/query_highlighter.h
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_QUERY_HIGHLIGHTER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_QUERY_HIGHLIGHTER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_QUERY_HIGHLIGHTER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_QUERY_HIGHLIGHTER_H_
 
-#include "chrome/browser/ui/app_list/search/ranking/ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/ranker.h"
 #include "chrome/browser/ui/app_list/search/types.h"
 
 namespace app_list {
@@ -32,4 +32,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_QUERY_HIGHLIGHTER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_QUERY_HIGHLIGHTER_H_
diff --git a/chrome/browser/ui/app_list/search/ranking/query_highlighter_unittest.cc b/chrome/browser/ash/app_list/search/ranking/query_highlighter_unittest.cc
similarity index 95%
rename from chrome/browser/ui/app_list/search/ranking/query_highlighter_unittest.cc
rename to chrome/browser/ash/app_list/search/ranking/query_highlighter_unittest.cc
index 48ff359..9df7b6b 100644
--- a/chrome/browser/ui/app_list/search/ranking/query_highlighter_unittest.cc
+++ b/chrome/browser/ash/app_list/search/ranking/query_highlighter_unittest.cc
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/ranking/query_highlighter.h"
+#include "chrome/browser/ash/app_list/search/ranking/query_highlighter.h"
 
+#include "chrome/browser/ash/app_list/search/test/test_result.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
-#include "chrome/browser/ui/app_list/search/test/test_result.h"
 #include "chrome/browser/ui/app_list/search/types.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ui/app_list/search/ranking/ranker.cc b/chrome/browser/ash/app_list/search/ranking/ranker.cc
similarity index 96%
rename from chrome/browser/ui/app_list/search/ranking/ranker.cc
rename to chrome/browser/ash/app_list/search/ranking/ranker.cc
index dd4fab1..843a013 100644
--- a/chrome/browser/ui/app_list/search/ranking/ranker.cc
+++ b/chrome/browser/ash/app_list/search/ranking/ranker.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/ui/app_list/search/ranking/ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/ranker.h"
 
 #include "base/notreached.h"
 
diff --git a/chrome/browser/ui/app_list/search/ranking/ranker.h b/chrome/browser/ash/app_list/search/ranking/ranker.h
similarity index 90%
rename from chrome/browser/ui/app_list/search/ranking/ranker.h
rename to chrome/browser/ash/app_list/search/ranking/ranker.h
index d9c7d9ec..144dc466 100644
--- a/chrome/browser/ui/app_list/search/ranking/ranker.h
+++ b/chrome/browser/ash/app_list/search/ranking/ranker.h
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_RANKER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_RANKER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_RANKER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_RANKER_H_
 
-#include "chrome/browser/ui/app_list/search/ranking/launch_data.h"
+#include "chrome/browser/ash/app_list/search/ranking/launch_data.h"
 #include "chrome/browser/ui/app_list/search/search_controller.h"
 #include "chrome/browser/ui/app_list/search/types.h"
 
@@ -63,4 +63,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_RANKER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_RANKER_H_
diff --git a/chrome/browser/ui/app_list/search/ranking/ranker_manager.cc b/chrome/browser/ash/app_list/search/ranking/ranker_manager.cc
similarity index 83%
rename from chrome/browser/ui/app_list/search/ranking/ranker_manager.cc
rename to chrome/browser/ash/app_list/search/ranking/ranker_manager.cc
index 5a17ac29..3c32e3c 100644
--- a/chrome/browser/ui/app_list/search/ranking/ranker_manager.cc
+++ b/chrome/browser/ash/app_list/search/ranking/ranker_manager.cc
@@ -2,22 +2,22 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/ranking/ranker_manager.h"
+#include "chrome/browser/ash/app_list/search/ranking/ranker_manager.h"
 
+#include "chrome/browser/ash/app_list/search/ranking/answer_ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/best_match_ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/continue_ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/filtering_ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/ftrl_ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/mrfu_ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/query_highlighter.h"
+#include "chrome/browser/ash/app_list/search/ranking/removed_results.pb.h"
+#include "chrome/browser/ash/app_list/search/ranking/removed_results_ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/score_normalizing_ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/util.h"
+#include "chrome/browser/ash/app_list/search/util/score_normalizer.h"
+#include "chrome/browser/ash/app_list/search/util/score_normalizer.pb.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/app_list/search/ranking/answer_ranker.h"
-#include "chrome/browser/ui/app_list/search/ranking/best_match_ranker.h"
-#include "chrome/browser/ui/app_list/search/ranking/continue_ranker.h"
-#include "chrome/browser/ui/app_list/search/ranking/filtering_ranker.h"
-#include "chrome/browser/ui/app_list/search/ranking/ftrl_ranker.h"
-#include "chrome/browser/ui/app_list/search/ranking/mrfu_ranker.h"
-#include "chrome/browser/ui/app_list/search/ranking/query_highlighter.h"
-#include "chrome/browser/ui/app_list/search/ranking/removed_results.pb.h"
-#include "chrome/browser/ui/app_list/search/ranking/removed_results_ranker.h"
-#include "chrome/browser/ui/app_list/search/ranking/score_normalizing_ranker.h"
-#include "chrome/browser/ui/app_list/search/ranking/util.h"
-#include "chrome/browser/ui/app_list/search/util/score_normalizer.h"
-#include "chrome/browser/ui/app_list/search/util/score_normalizer.pb.h"
 
 namespace app_list {
 namespace {
diff --git a/chrome/browser/ui/app_list/search/ranking/ranker_manager.h b/chrome/browser/ash/app_list/search/ranking/ranker_manager.h
similarity index 83%
rename from chrome/browser/ui/app_list/search/ranking/ranker_manager.h
rename to chrome/browser/ash/app_list/search/ranking/ranker_manager.h
index 45b9ed6..a07c6cf 100644
--- a/chrome/browser/ui/app_list/search/ranking/ranker_manager.h
+++ b/chrome/browser/ash/app_list/search/ranking/ranker_manager.h
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_RANKER_MANAGER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_RANKER_MANAGER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_RANKER_MANAGER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_RANKER_MANAGER_H_
 
-#include "chrome/browser/ui/app_list/search/ranking/ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/ranker.h"
 
 class ChromeSearchResult;
 class Profile;
@@ -48,4 +48,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_RANKER_MANAGER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_RANKER_MANAGER_H_
diff --git a/chrome/browser/ui/app_list/search/ranking/removed_results.proto b/chrome/browser/ash/app_list/search/ranking/removed_results.proto
similarity index 100%
rename from chrome/browser/ui/app_list/search/ranking/removed_results.proto
rename to chrome/browser/ash/app_list/search/ranking/removed_results.proto
diff --git a/chrome/browser/ui/app_list/search/ranking/removed_results_proto_unittest.cc b/chrome/browser/ash/app_list/search/ranking/removed_results_proto_unittest.cc
similarity index 95%
rename from chrome/browser/ui/app_list/search/ranking/removed_results_proto_unittest.cc
rename to chrome/browser/ash/app_list/search/ranking/removed_results_proto_unittest.cc
index 505da1f5..b8a1054 100644
--- a/chrome/browser/ui/app_list/search/ranking/removed_results_proto_unittest.cc
+++ b/chrome/browser/ash/app_list/search/ranking/removed_results_proto_unittest.cc
@@ -5,8 +5,8 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
-#include "chrome/browser/ui/app_list/search/ranking/removed_results.pb.h"
-#include "chrome/browser/ui/app_list/search/util/persistent_proto.h"
+#include "chrome/browser/ash/app_list/search/ranking/removed_results.pb.h"
+#include "chrome/browser/ash/app_list/search/util/persistent_proto.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/browser/ui/app_list/search/ranking/removed_results_ranker.cc b/chrome/browser/ash/app_list/search/ranking/removed_results_ranker.cc
similarity index 90%
rename from chrome/browser/ui/app_list/search/ranking/removed_results_ranker.cc
rename to chrome/browser/ash/app_list/search/ranking/removed_results_ranker.cc
index 34f6256..551e122 100644
--- a/chrome/browser/ui/app_list/search/ranking/removed_results_ranker.cc
+++ b/chrome/browser/ash/app_list/search/ranking/removed_results_ranker.cc
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/ranking/removed_results_ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/removed_results_ranker.h"
 
+#include "chrome/browser/ash/app_list/search/files/file_suggest_keyed_service.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_keyed_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_factory.h"
 #include "chrome/browser/ui/app_list/search/types.h"
 
 namespace app_list {
diff --git a/chrome/browser/ui/app_list/search/ranking/removed_results_ranker.h b/chrome/browser/ash/app_list/search/ranking/removed_results_ranker.h
similarity index 78%
rename from chrome/browser/ui/app_list/search/ranking/removed_results_ranker.h
rename to chrome/browser/ash/app_list/search/ranking/removed_results_ranker.h
index 23bded9..3237f18 100644
--- a/chrome/browser/ui/app_list/search/ranking/removed_results_ranker.h
+++ b/chrome/browser/ash/app_list/search/ranking/removed_results_ranker.h
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_REMOVED_RESULTS_RANKER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_REMOVED_RESULTS_RANKER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_REMOVED_RESULTS_RANKER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_REMOVED_RESULTS_RANKER_H_
 
 #include "base/files/file_path.h"
 #include "base/time/time.h"
-#include "chrome/browser/ui/app_list/search/ranking/ranker.h"
-#include "chrome/browser/ui/app_list/search/ranking/removed_results.pb.h"
-#include "chrome/browser/ui/app_list/search/util/persistent_proto.h"
+#include "chrome/browser/ash/app_list/search/ranking/ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/removed_results.pb.h"
+#include "chrome/browser/ash/app_list/search/util/persistent_proto.h"
 
 class Profile;
 
@@ -55,4 +55,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_REMOVED_RESULTS_RANKER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_REMOVED_RESULTS_RANKER_H_
diff --git a/chrome/browser/ui/app_list/search/ranking/removed_results_ranker_unittest.cc b/chrome/browser/ash/app_list/search/ranking/removed_results_ranker_unittest.cc
similarity index 93%
rename from chrome/browser/ui/app_list/search/ranking/removed_results_ranker_unittest.cc
rename to chrome/browser/ash/app_list/search/ranking/removed_results_ranker_unittest.cc
index 4cad6d7..4e087b1 100644
--- a/chrome/browser/ui/app_list/search/ranking/removed_results_ranker_unittest.cc
+++ b/chrome/browser/ash/app_list/search/ranking/removed_results_ranker_unittest.cc
@@ -2,17 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/ranking/removed_results_ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/removed_results_ranker.h"
 
 #include "ash/public/cpp/app_list/app_list_types.h"
 #include "base/files/scoped_temp_dir.h"
+#include "chrome/browser/ash/app_list/search/files/file_result.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_keyed_service_factory.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_test_util.h"
+#include "chrome/browser/ash/app_list/search/files/mock_file_suggest_keyed_service.h"
+#include "chrome/browser/ash/app_list/search/test/test_result.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
-#include "chrome/browser/ui/app_list/search/files/file_result.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_factory.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_test_util.h"
-#include "chrome/browser/ui/app_list/search/files/mock_file_suggest_keyed_service.h"
 #include "chrome/browser/ui/app_list/search/search_controller.h"
-#include "chrome/browser/ui/app_list/search/test/test_result.h"
 #include "chrome/browser/ui/app_list/search/types.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile_manager.h"
diff --git a/chrome/browser/ui/app_list/search/ranking/score_normalizing_ranker.cc b/chrome/browser/ash/app_list/search/ranking/score_normalizing_ranker.cc
similarity index 92%
rename from chrome/browser/ui/app_list/search/ranking/score_normalizing_ranker.cc
rename to chrome/browser/ash/app_list/search/ranking/score_normalizing_ranker.cc
index 7520e5a6..1a8fe25b 100644
--- a/chrome/browser/ui/app_list/search/ranking/score_normalizing_ranker.cc
+++ b/chrome/browser/ash/app_list/search/ranking/score_normalizing_ranker.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/ranking/score_normalizing_ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/score_normalizing_ranker.h"
 
 #include "base/strings/strcat.h"
 #include "base/strings/string_number_conversions.h"
+#include "chrome/browser/ash/app_list/search/util/score_normalizer.pb.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
 #include "chrome/browser/ui/app_list/search/search_controller.h"
-#include "chrome/browser/ui/app_list/search/util/score_normalizer.pb.h"
 
 namespace app_list {
 namespace {
diff --git a/chrome/browser/ui/app_list/search/ranking/score_normalizing_ranker.h b/chrome/browser/ash/app_list/search/ranking/score_normalizing_ranker.h
similarity index 73%
rename from chrome/browser/ui/app_list/search/ranking/score_normalizing_ranker.h
rename to chrome/browser/ash/app_list/search/ranking/score_normalizing_ranker.h
index 577f456..f91b921a 100644
--- a/chrome/browser/ui/app_list/search/ranking/score_normalizing_ranker.h
+++ b/chrome/browser/ash/app_list/search/ranking/score_normalizing_ranker.h
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_SCORE_NORMALIZING_RANKER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_SCORE_NORMALIZING_RANKER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_SCORE_NORMALIZING_RANKER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_SCORE_NORMALIZING_RANKER_H_
 
-#include "chrome/browser/ui/app_list/search/ranking/ranker.h"
-#include "chrome/browser/ui/app_list/search/util/persistent_proto.h"
-#include "chrome/browser/ui/app_list/search/util/score_normalizer.h"
+#include "chrome/browser/ash/app_list/search/ranking/ranker.h"
+#include "chrome/browser/ash/app_list/search/util/persistent_proto.h"
+#include "chrome/browser/ash/app_list/search/util/score_normalizer.h"
 
 namespace app_list {
 
@@ -41,4 +41,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_SCORE_NORMALIZING_RANKER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_SCORE_NORMALIZING_RANKER_H_
diff --git a/chrome/browser/ui/app_list/search/ranking/score_normalizing_ranker_unittest.cc b/chrome/browser/ash/app_list/search/ranking/score_normalizing_ranker_unittest.cc
similarity index 95%
rename from chrome/browser/ui/app_list/search/ranking/score_normalizing_ranker_unittest.cc
rename to chrome/browser/ash/app_list/search/ranking/score_normalizing_ranker_unittest.cc
index b8d9c52..0bbf098a 100644
--- a/chrome/browser/ui/app_list/search/ranking/score_normalizing_ranker_unittest.cc
+++ b/chrome/browser/ash/app_list/search/ranking/score_normalizing_ranker_unittest.cc
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/ranking/score_normalizing_ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/score_normalizing_ranker.h"
 
 #include "base/files/scoped_temp_dir.h"
 #include "base/logging.h"
 #include "base/test/task_environment.h"
+#include "chrome/browser/ash/app_list/search/test/test_result.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
 #include "chrome/browser/ui/app_list/search/search_controller.h"
-#include "chrome/browser/ui/app_list/search/test/test_result.h"
 #include "chrome/browser/ui/app_list/search/types.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ui/app_list/search/ranking/scoring.cc b/chrome/browser/ash/app_list/search/ranking/scoring.cc
similarity index 98%
rename from chrome/browser/ui/app_list/search/ranking/scoring.cc
rename to chrome/browser/ash/app_list/search/ranking/scoring.cc
index 02f54550..b254805 100644
--- a/chrome/browser/ui/app_list/search/ranking/scoring.cc
+++ b/chrome/browser/ash/app_list/search/ranking/scoring.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/ui/app_list/search/ranking/scoring.h"
+#include "chrome/browser/ash/app_list/search/ranking/scoring.h"
 
 namespace app_list {
 
diff --git a/chrome/browser/ui/app_list/search/ranking/scoring.h b/chrome/browser/ash/app_list/search/ranking/scoring.h
similarity index 83%
rename from chrome/browser/ui/app_list/search/ranking/scoring.h
rename to chrome/browser/ash/app_list/search/ranking/scoring.h
index e3daee7..eebe11b 100644
--- a/chrome/browser/ui/app_list/search/ranking/scoring.h
+++ b/chrome/browser/ash/app_list/search/ranking/scoring.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_SCORING_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_SCORING_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_SCORING_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_SCORING_H_
 
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
 #include "chrome/browser/ui/app_list/search/types.h"
@@ -32,4 +32,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_SCORING_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_SCORING_H_
diff --git a/chrome/browser/ui/app_list/search/ranking/util.cc b/chrome/browser/ash/app_list/search/ranking/util.cc
similarity index 97%
rename from chrome/browser/ui/app_list/search/ranking/util.cc
rename to chrome/browser/ash/app_list/search/ranking/util.cc
index 7c4d4701..1c30ae6 100644
--- a/chrome/browser/ui/app_list/search/ranking/util.cc
+++ b/chrome/browser/ash/app_list/search/ranking/util.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/ui/app_list/search/ranking/util.h"
+#include "chrome/browser/ash/app_list/search/ranking/util.h"
 
 #include "base/strings/string_number_conversions.h"
 #include "chrome/browser/profiles/profile.h"
diff --git a/chrome/browser/ui/app_list/search/ranking/util.h b/chrome/browser/ash/app_list/search/ranking/util.h
similarity index 83%
rename from chrome/browser/ui/app_list/search/ranking/util.h
rename to chrome/browser/ash/app_list/search/ranking/util.h
index 8443233..7f7897e 100644
--- a/chrome/browser/ui/app_list/search/ranking/util.h
+++ b/chrome/browser/ash/app_list/search/ranking/util.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_UTIL_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_UTIL_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_UTIL_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_UTIL_H_
 
 #include <string>
 
@@ -31,4 +31,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_RANKING_UTIL_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_UTIL_H_
diff --git a/chrome/browser/ui/app_list/search/test/app_list_search_test_helper.cc b/chrome/browser/ash/app_list/search/test/app_list_search_test_helper.cc
similarity index 94%
rename from chrome/browser/ui/app_list/search/test/app_list_search_test_helper.cc
rename to chrome/browser/ash/app_list/search/test/app_list_search_test_helper.cc
index 992f7e6..8b2bf9f 100644
--- a/chrome/browser/ui/app_list/search/test/app_list_search_test_helper.cc
+++ b/chrome/browser/ash/app_list/search/test/app_list_search_test_helper.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/test/app_list_search_test_helper.h"
+#include "chrome/browser/ash/app_list/search/test/app_list_search_test_helper.h"
 
 #include "base/run_loop.h"
+#include "chrome/browser/ash/app_list/search/test/search_results_changed_waiter.h"
 #include "chrome/browser/ui/app_list/search/search_controller.h"
-#include "chrome/browser/ui/app_list/search/test/search_results_changed_waiter.h"
 #include "chrome/browser/ui/browser.h"
 
 namespace app_list {
diff --git a/chrome/browser/ui/app_list/search/test/app_list_search_test_helper.h b/chrome/browser/ash/app_list/search/test/app_list_search_test_helper.h
similarity index 91%
rename from chrome/browser/ui/app_list/search/test/app_list_search_test_helper.h
rename to chrome/browser/ash/app_list/search/test/app_list_search_test_helper.h
index ff7276df..ebf54d1b6 100644
--- a/chrome/browser/ui/app_list/search/test/app_list_search_test_helper.h
+++ b/chrome/browser/ash/app_list/search/test/app_list_search_test_helper.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_TEST_APP_LIST_SEARCH_TEST_HELPER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_TEST_APP_LIST_SEARCH_TEST_HELPER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_TEST_APP_LIST_SEARCH_TEST_HELPER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_TEST_APP_LIST_SEARCH_TEST_HELPER_H_
 
 #include <utility>
 #include <vector>
@@ -21,6 +21,7 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/threading/thread_restrictions.h"
+#include "chrome/browser/ash/app_list/test/chrome_app_list_test_support.h"
 #include "chrome/browser/ash/file_manager/path_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
@@ -28,7 +29,6 @@
 #include "chrome/browser/ui/app_list/app_list_model_updater.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
 #include "chrome/browser/ui/app_list/search/search_controller.h"
-#include "chrome/browser/ui/app_list/test/chrome_app_list_test_support.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/common/pref_names.h"
@@ -110,4 +110,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_TEST_APP_LIST_SEARCH_TEST_HELPER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_TEST_APP_LIST_SEARCH_TEST_HELPER_H_
diff --git a/chrome/browser/ui/app_list/search/test/ranking_test_util.cc b/chrome/browser/ash/app_list/search/test/ranking_test_util.cc
similarity index 92%
rename from chrome/browser/ui/app_list/search/test/ranking_test_util.cc
rename to chrome/browser/ash/app_list/search/test/ranking_test_util.cc
index a534aa0..1ff6fb7 100644
--- a/chrome/browser/ui/app_list/search/test/ranking_test_util.cc
+++ b/chrome/browser/ash/app_list/search/test/ranking_test_util.cc
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/test/ranking_test_util.h"
+#include "chrome/browser/ash/app_list/search/test/ranking_test_util.h"
 
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/ui/app_list/search/test/test_result.h"
+#include "chrome/browser/ash/app_list/search/test/test_result.h"
 
 namespace app_list {
 
diff --git a/chrome/browser/ui/app_list/search/test/ranking_test_util.h b/chrome/browser/ash/app_list/search/test/ranking_test_util.h
similarity index 87%
rename from chrome/browser/ui/app_list/search/test/ranking_test_util.h
rename to chrome/browser/ash/app_list/search/test/ranking_test_util.h
index d2274f6..993a9838 100644
--- a/chrome/browser/ui/app_list/search/test/ranking_test_util.h
+++ b/chrome/browser/ash/app_list/search/test/ranking_test_util.h
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_TEST_RANKING_TEST_UTIL_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_TEST_RANKING_TEST_UTIL_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_TEST_RANKING_TEST_UTIL_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_TEST_RANKING_TEST_UTIL_H_
 
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/test/task_environment.h"
-#include "chrome/browser/ui/app_list/search/ranking/ranker.h"
+#include "chrome/browser/ash/app_list/search/ranking/ranker.h"
 #include "chrome/browser/ui/app_list/search/types.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -57,4 +57,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_TEST_RANKING_TEST_UTIL_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_TEST_RANKING_TEST_UTIL_H_
diff --git a/chrome/browser/ui/app_list/search/test/search_controller_test_util.cc b/chrome/browser/ash/app_list/search/test/search_controller_test_util.cc
similarity index 92%
rename from chrome/browser/ui/app_list/search/test/search_controller_test_util.cc
rename to chrome/browser/ash/app_list/search/test/search_controller_test_util.cc
index 1bb15a5..711cfdb3 100644
--- a/chrome/browser/ui/app_list/search/test/search_controller_test_util.cc
+++ b/chrome/browser/ash/app_list/search/test/search_controller_test_util.cc
@@ -2,17 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/app_list/search/test/search_controller_test_util.h"
+#include "chrome/browser/ash/app_list/search/test/search_controller_test_util.h"
 
 #include <memory>
 #include <vector>
 
 #include "ash/public/cpp/app_list/app_list_types.h"
 #include "base/time/time.h"
+#include "chrome/browser/ash/app_list/search/test/test_result.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
 #include "chrome/browser/ui/app_list/search/search_controller.h"
 #include "chrome/browser/ui/app_list/search/search_provider.h"
-#include "chrome/browser/ui/app_list/search/test/test_result.h"
 #include "test_search_provider.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
diff --git a/chrome/browser/ui/app_list/search/test/search_controller_test_util.h b/chrome/browser/ash/app_list/search/test/search_controller_test_util.h
similarity index 84%
rename from chrome/browser/ui/app_list/search/test/search_controller_test_util.h
rename to chrome/browser/ash/app_list/search/test/search_controller_test_util.h
index 83efed2..ca8dd24 100644
--- a/chrome/browser/ui/app_list/search/test/search_controller_test_util.h
+++ b/chrome/browser/ash/app_list/search/test/search_controller_test_util.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_TEST_SEARCH_CONTROLLER_TEST_UTIL_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_TEST_SEARCH_CONTROLLER_TEST_UTIL_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_TEST_SEARCH_CONTROLLER_TEST_UTIL_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_TEST_SEARCH_CONTROLLER_TEST_UTIL_H_
 
 #include <memory>
 #include <vector>
@@ -36,4 +36,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_TEST_SEARCH_CONTROLLER_TEST_UTIL_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_TEST_SEARCH_CONTROLLER_TEST_UTIL_H_
diff --git a/chrome/browser/ui/app_list/search/test/search_results_changed_waiter.cc b/chrome/browser/ash/app_list/search/test/search_results_changed_waiter.cc
similarity index 93%
rename from chrome/browser/ui/app_list/search/test/search_results_changed_waiter.cc
rename to chrome/browser/ash/app_list/search/test/search_results_changed_waiter.cc
index 14a54fb..615a2a45 100644
--- a/chrome/browser/ui/app_list/search/test/search_results_changed_waiter.cc
+++ b/chrome/browser/ash/app_list/search/test/search_results_changed_waiter.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/ui/app_list/search/test/search_results_changed_waiter.h"
+#include "chrome/browser/ash/app_list/search/test/search_results_changed_waiter.h"
 
 #include "base/bind.h"
 #include "base/callback_helpers.h"
diff --git a/chrome/browser/ui/app_list/search/test/search_results_changed_waiter.h b/chrome/browser/ash/app_list/search/test/search_results_changed_waiter.h
similarity index 86%
rename from chrome/browser/ui/app_list/search/test/search_results_changed_waiter.h
rename to chrome/browser/ash/app_list/search/test/search_results_changed_waiter.h
index 1560d530..946b0f1 100644
--- a/chrome/browser/ui/app_list/search/test/search_results_changed_waiter.h
+++ b/chrome/browser/ash/app_list/search/test/search_results_changed_waiter.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_TEST_SEARCH_RESULTS_CHANGED_WAITER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_TEST_SEARCH_RESULTS_CHANGED_WAITER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_TEST_SEARCH_RESULTS_CHANGED_WAITER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_TEST_SEARCH_RESULTS_CHANGED_WAITER_H_
 
 #include <set>
 
@@ -53,4 +53,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_TEST_SEARCH_RESULTS_CHANGED_WAITER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_TEST_SEARCH_RESULTS_CHANGED_WAITER_H_
diff --git a/chrome/browser/ui/app_list/search/test/test_continue_files_search_provider.cc b/chrome/browser/ash/app_list/search/test/test_continue_files_search_provider.cc
similarity index 96%
rename from chrome/browser/ui/app_list/search/test/test_continue_files_search_provider.cc
rename to chrome/browser/ash/app_list/search/test/test_continue_files_search_provider.cc
index aa198bb2..2f63561b 100644
--- a/chrome/browser/ui/app_list/search/test/test_continue_files_search_provider.cc
+++ b/chrome/browser/ash/app_list/search/test/test_continue_files_search_provider.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/ui/app_list/search/test/test_continue_files_search_provider.h"
+#include "chrome/browser/ash/app_list/search/test/test_continue_files_search_provider.h"
 
 #include <memory>
 #include <string>
diff --git a/chrome/browser/ui/app_list/search/test/test_continue_files_search_provider.h b/chrome/browser/ash/app_list/search/test/test_continue_files_search_provider.h
similarity index 80%
rename from chrome/browser/ui/app_list/search/test/test_continue_files_search_provider.h
rename to chrome/browser/ash/app_list/search/test/test_continue_files_search_provider.h
index 7b3445d8..78b25f6 100644
--- a/chrome/browser/ui/app_list/search/test/test_continue_files_search_provider.h
+++ b/chrome/browser/ash/app_list/search/test/test_continue_files_search_provider.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_TEST_TEST_CONTINUE_FILES_SEARCH_PROVIDER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_TEST_TEST_CONTINUE_FILES_SEARCH_PROVIDER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_TEST_TEST_CONTINUE_FILES_SEARCH_PROVIDER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_TEST_TEST_CONTINUE_FILES_SEARCH_PROVIDER_H_
 
 #include "chrome/browser/ui/app_list/search/search_provider.h"
 
@@ -37,4 +37,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_TEST_TEST_CONTINUE_FILES_SEARCH_PROVIDER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_TEST_TEST_CONTINUE_FILES_SEARCH_PROVIDER_H_
diff --git a/chrome/browser/ui/app_list/search/test/test_ranker_manager.cc b/chrome/browser/ash/app_list/search/test/test_ranker_manager.cc
similarity index 94%
rename from chrome/browser/ui/app_list/search/test/test_ranker_manager.cc
rename to chrome/browser/ash/app_list/search/test/test_ranker_manager.cc
index 407b6aa8..dbe622da 100644
--- a/chrome/browser/ui/app_list/search/test/test_ranker_manager.cc
+++ b/chrome/browser/ash/app_list/search/test/test_ranker_manager.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/ui/app_list/search/test/test_ranker_manager.h"
+#include "chrome/browser/ash/app_list/search/test/test_ranker_manager.h"
 
 #include <memory>
 #include <vector>
diff --git a/chrome/browser/ui/app_list/search/test/test_ranker_manager.h b/chrome/browser/ash/app_list/search/test/test_ranker_manager.h
similarity index 84%
rename from chrome/browser/ui/app_list/search/test/test_ranker_manager.h
rename to chrome/browser/ash/app_list/search/test/test_ranker_manager.h
index 1bfeff7..5b5f060 100644
--- a/chrome/browser/ui/app_list/search/test/test_ranker_manager.h
+++ b/chrome/browser/ash/app_list/search/test/test_ranker_manager.h
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_TEST_TEST_RANKER_MANAGER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_TEST_TEST_RANKER_MANAGER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_TEST_TEST_RANKER_MANAGER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_TEST_TEST_RANKER_MANAGER_H_
 
 #include <memory>
 #include <vector>
 
+#include "chrome/browser/ash/app_list/search/ranking/ranker_manager.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
-#include "chrome/browser/ui/app_list/search/ranking/ranker_manager.h"
 #include "chrome/browser/ui/app_list/search/search_controller.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
@@ -53,4 +53,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_TEST_TEST_RANKER_MANAGER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_TEST_TEST_RANKER_MANAGER_H_
diff --git a/chrome/browser/ui/app_list/search/test/test_result.cc b/chrome/browser/ash/app_list/search/test/test_result.cc
similarity index 96%
rename from chrome/browser/ui/app_list/search/test/test_result.cc
rename to chrome/browser/ash/app_list/search/test/test_result.cc
index 933f3ca8..a7707760 100644
--- a/chrome/browser/ui/app_list/search/test/test_result.cc
+++ b/chrome/browser/ash/app_list/search/test/test_result.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/ui/app_list/search/test/test_result.h"
+#include "chrome/browser/ash/app_list/search/test/test_result.h"
 
 namespace app_list {
 
diff --git a/chrome/browser/ui/app_list/search/test/test_result.h b/chrome/browser/ash/app_list/search/test/test_result.h
similarity index 89%
rename from chrome/browser/ui/app_list/search/test/test_result.h
rename to chrome/browser/ash/app_list/search/test/test_result.h
index 7018134..265052a 100644
--- a/chrome/browser/ui/app_list/search/test/test_result.h
+++ b/chrome/browser/ash/app_list/search/test/test_result.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_TEST_TEST_RESULT_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_TEST_TEST_RESULT_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_TEST_TEST_RESULT_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_TEST_TEST_RESULT_H_
 
 #include "base/test/task_environment.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
@@ -51,4 +51,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_TEST_TEST_RESULT_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_TEST_TEST_RESULT_H_
diff --git a/chrome/browser/ui/app_list/search/test/test_search_controller.cc b/chrome/browser/ash/app_list/search/test/test_search_controller.cc
similarity index 97%
rename from chrome/browser/ui/app_list/search/test/test_search_controller.cc
rename to chrome/browser/ash/app_list/search/test/test_search_controller.cc
index c44a6e5f..4db89e10 100644
--- a/chrome/browser/ui/app_list/search/test/test_search_controller.cc
+++ b/chrome/browser/ash/app_list/search/test/test_search_controller.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/ui/app_list/search/test/test_search_controller.h"
+#include "chrome/browser/ash/app_list/search/test/test_search_controller.h"
 
 #include "ash/public/cpp/app_list/app_list_features.h"
 #include "ash/public/cpp/app_list/app_list_types.h"
diff --git a/chrome/browser/ui/app_list/search/test/test_search_controller.h b/chrome/browser/ash/app_list/search/test/test_search_controller.h
similarity index 90%
rename from chrome/browser/ui/app_list/search/test/test_search_controller.h
rename to chrome/browser/ash/app_list/search/test/test_search_controller.h
index 956c494..2a67dfc 100644
--- a/chrome/browser/ui/app_list/search/test/test_search_controller.h
+++ b/chrome/browser/ash/app_list/search/test/test_search_controller.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_TEST_TEST_SEARCH_CONTROLLER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_TEST_TEST_SEARCH_CONTROLLER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_TEST_TEST_SEARCH_CONTROLLER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_TEST_TEST_SEARCH_CONTROLLER_H_
 
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
 #include "chrome/browser/ui/app_list/search/search_controller.h"
@@ -63,4 +63,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_TEST_TEST_SEARCH_CONTROLLER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_TEST_TEST_SEARCH_CONTROLLER_H_
diff --git a/chrome/browser/ui/app_list/search/test/test_search_provider.cc b/chrome/browser/ash/app_list/search/test/test_search_provider.cc
similarity index 95%
rename from chrome/browser/ui/app_list/search/test/test_search_provider.cc
rename to chrome/browser/ash/app_list/search/test/test_search_provider.cc
index 0220f29..4272b7f0 100644
--- a/chrome/browser/ui/app_list/search/test/test_search_provider.cc
+++ b/chrome/browser/ash/app_list/search/test/test_search_provider.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/ui/app_list/search/test/test_search_provider.h"
+#include "chrome/browser/ash/app_list/search/test/test_search_provider.h"
 
 #include <memory>
 #include <vector>
diff --git a/chrome/browser/ui/app_list/search/test/test_search_provider.h b/chrome/browser/ash/app_list/search/test/test_search_provider.h
similarity index 85%
rename from chrome/browser/ui/app_list/search/test/test_search_provider.h
rename to chrome/browser/ash/app_list/search/test/test_search_provider.h
index b629efc7..f931dbf 100644
--- a/chrome/browser/ui/app_list/search/test/test_search_provider.h
+++ b/chrome/browser/ash/app_list/search/test/test_search_provider.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_TEST_TEST_SEARCH_PROVIDER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_TEST_TEST_SEARCH_PROVIDER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_TEST_TEST_SEARCH_PROVIDER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_TEST_TEST_SEARCH_PROVIDER_H_
 
 #include <memory>
 #include <vector>
@@ -45,4 +45,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_TEST_TEST_SEARCH_PROVIDER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_TEST_TEST_SEARCH_PROVIDER_H_
diff --git a/chrome/browser/ui/app_list/search/util/BUILD.gn b/chrome/browser/ash/app_list/search/util/BUILD.gn
similarity index 83%
rename from chrome/browser/ui/app_list/search/util/BUILD.gn
rename to chrome/browser/ash/app_list/search/util/BUILD.gn
index 3485a2f..7612cbd4 100644
--- a/chrome/browser/ui/app_list/search/util/BUILD.gn
+++ b/chrome/browser/ash/app_list/search/util/BUILD.gn
@@ -2,8 +2,11 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromeos/ui_mode.gni")
 import("//third_party/protobuf/proto_library.gni")
 
+assert(is_chromeos_ash)
+
 proto_library("proto") {
   sources = [
     "ftrl_optimizer.proto",
diff --git a/chrome/browser/ui/app_list/search/util/ftrl_optimizer.cc b/chrome/browser/ash/app_list/search/util/ftrl_optimizer.cc
similarity index 98%
rename from chrome/browser/ui/app_list/search/util/ftrl_optimizer.cc
rename to chrome/browser/ash/app_list/search/util/ftrl_optimizer.cc
index 4e881df..89a5689 100644
--- a/chrome/browser/ui/app_list/search/util/ftrl_optimizer.cc
+++ b/chrome/browser/ash/app_list/search/util/ftrl_optimizer.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/ui/app_list/search/util/ftrl_optimizer.h"
+#include "chrome/browser/ash/app_list/search/util/ftrl_optimizer.h"
 
 #include <cmath>
 
diff --git a/chrome/browser/ui/app_list/search/util/ftrl_optimizer.h b/chrome/browser/ash/app_list/search/util/ftrl_optimizer.h
similarity index 89%
rename from chrome/browser/ui/app_list/search/util/ftrl_optimizer.h
rename to chrome/browser/ash/app_list/search/util/ftrl_optimizer.h
index 35d2bfa6..0231954 100644
--- a/chrome/browser/ui/app_list/search/util/ftrl_optimizer.h
+++ b/chrome/browser/ash/app_list/search/util/ftrl_optimizer.h
@@ -2,16 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_UTIL_FTRL_OPTIMIZER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_UTIL_FTRL_OPTIMIZER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_UTIL_FTRL_OPTIMIZER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_UTIL_FTRL_OPTIMIZER_H_
 
 #include <string>
 #include <vector>
 
 #include "base/files/file_path.h"
 #include "base/memory/weak_ptr.h"
-#include "chrome/browser/ui/app_list/search/util/ftrl_optimizer.pb.h"
-#include "chrome/browser/ui/app_list/search/util/persistent_proto.h"
+#include "chrome/browser/ash/app_list/search/util/ftrl_optimizer.pb.h"
+#include "chrome/browser/ash/app_list/search/util/persistent_proto.h"
 
 namespace app_list {
 
@@ -98,4 +98,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_UTIL_FTRL_OPTIMIZER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_UTIL_FTRL_OPTIMIZER_H_
diff --git a/chrome/browser/ui/app_list/search/util/ftrl_optimizer.proto b/chrome/browser/ash/app_list/search/util/ftrl_optimizer.proto
similarity index 100%
rename from chrome/browser/ui/app_list/search/util/ftrl_optimizer.proto
rename to chrome/browser/ash/app_list/search/util/ftrl_optimizer.proto
diff --git a/chrome/browser/ui/app_list/search/util/ftrl_optimizer_unittest.cc b/chrome/browser/ash/app_list/search/util/ftrl_optimizer_unittest.cc
similarity index 98%
rename from chrome/browser/ui/app_list/search/util/ftrl_optimizer_unittest.cc
rename to chrome/browser/ash/app_list/search/util/ftrl_optimizer_unittest.cc
index 75a7f60c..2d777f4 100644
--- a/chrome/browser/ui/app_list/search/util/ftrl_optimizer_unittest.cc
+++ b/chrome/browser/ash/app_list/search/util/ftrl_optimizer_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/ui/app_list/search/util/ftrl_optimizer.h"
+#include "chrome/browser/ash/app_list/search/util/ftrl_optimizer.h"
 
 #include <memory>
 #include <string>
diff --git a/chrome/browser/ui/app_list/search/util/mrfu_cache.cc b/chrome/browser/ash/app_list/search/util/mrfu_cache.cc
similarity index 98%
rename from chrome/browser/ui/app_list/search/util/mrfu_cache.cc
rename to chrome/browser/ash/app_list/search/util/mrfu_cache.cc
index d58f1af..3b2006f8 100644
--- a/chrome/browser/ui/app_list/search/util/mrfu_cache.cc
+++ b/chrome/browser/ash/app_list/search/util/mrfu_cache.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/ui/app_list/search/util/mrfu_cache.h"
+#include "chrome/browser/ash/app_list/search/util/mrfu_cache.h"
 
 #include <cmath>
 
diff --git a/chrome/browser/ui/app_list/search/util/mrfu_cache.h b/chrome/browser/ash/app_list/search/util/mrfu_cache.h
similarity index 93%
rename from chrome/browser/ui/app_list/search/util/mrfu_cache.h
rename to chrome/browser/ash/app_list/search/util/mrfu_cache.h
index c4559561..e10f80a0 100644
--- a/chrome/browser/ui/app_list/search/util/mrfu_cache.h
+++ b/chrome/browser/ash/app_list/search/util/mrfu_cache.h
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_UTIL_MRFU_CACHE_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_UTIL_MRFU_CACHE_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_UTIL_MRFU_CACHE_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_UTIL_MRFU_CACHE_H_
 
 #include <map>
 #include <string>
 
 #include "base/memory/weak_ptr.h"
-#include "chrome/browser/ui/app_list/search/util/mrfu_cache.pb.h"
-#include "chrome/browser/ui/app_list/search/util/persistent_proto.h"
+#include "chrome/browser/ash/app_list/search/util/mrfu_cache.pb.h"
+#include "chrome/browser/ash/app_list/search/util/persistent_proto.h"
 
 namespace app_list {
 
@@ -157,4 +157,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_UTIL_MRFU_CACHE_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_UTIL_MRFU_CACHE_H_
diff --git a/chrome/browser/ui/app_list/search/util/mrfu_cache.proto b/chrome/browser/ash/app_list/search/util/mrfu_cache.proto
similarity index 100%
rename from chrome/browser/ui/app_list/search/util/mrfu_cache.proto
rename to chrome/browser/ash/app_list/search/util/mrfu_cache.proto
diff --git a/chrome/browser/ui/app_list/search/util/mrfu_cache_unittest.cc b/chrome/browser/ash/app_list/search/util/mrfu_cache_unittest.cc
similarity index 98%
rename from chrome/browser/ui/app_list/search/util/mrfu_cache_unittest.cc
rename to chrome/browser/ash/app_list/search/util/mrfu_cache_unittest.cc
index 1536ee8..9c26ffb 100644
--- a/chrome/browser/ui/app_list/search/util/mrfu_cache_unittest.cc
+++ b/chrome/browser/ash/app_list/search/util/mrfu_cache_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/ui/app_list/search/util/mrfu_cache.h"
+#include "chrome/browser/ash/app_list/search/util/mrfu_cache.h"
 
 #include <memory>
 #include <string>
@@ -11,7 +11,7 @@
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/test/task_environment.h"
-#include "chrome/browser/ui/app_list/search/util/mrfu_cache.pb.h"
+#include "chrome/browser/ash/app_list/search/util/mrfu_cache.pb.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/browser/ui/app_list/search/util/persistent_proto.h b/chrome/browser/ash/app_list/search/util/persistent_proto.h
similarity index 97%
rename from chrome/browser/ui/app_list/search/util/persistent_proto.h
rename to chrome/browser/ash/app_list/search/util/persistent_proto.h
index e9a657e..8c2437f 100644
--- a/chrome/browser/ui/app_list/search/util/persistent_proto.h
+++ b/chrome/browser/ash/app_list/search/util/persistent_proto.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 CHROME_BROWSER_UI_APP_LIST_SEARCH_UTIL_PERSISTENT_PROTO_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_UTIL_PERSISTENT_PROTO_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_UTIL_PERSISTENT_PROTO_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_UTIL_PERSISTENT_PROTO_H_
 
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
@@ -295,4 +295,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_UTIL_PERSISTENT_PROTO_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_UTIL_PERSISTENT_PROTO_H_
diff --git a/chrome/browser/ui/app_list/search/util/persistent_proto_test.proto b/chrome/browser/ash/app_list/search/util/persistent_proto_test.proto
similarity index 100%
rename from chrome/browser/ui/app_list/search/util/persistent_proto_test.proto
rename to chrome/browser/ash/app_list/search/util/persistent_proto_test.proto
diff --git a/chrome/browser/ui/app_list/search/util/persistent_proto_unittest.cc b/chrome/browser/ash/app_list/search/util/persistent_proto_unittest.cc
similarity index 97%
rename from chrome/browser/ui/app_list/search/util/persistent_proto_unittest.cc
rename to chrome/browser/ash/app_list/search/util/persistent_proto_unittest.cc
index 84b72e81..420ef42 100644
--- a/chrome/browser/ui/app_list/search/util/persistent_proto_unittest.cc
+++ b/chrome/browser/ash/app_list/search/util/persistent_proto_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/ui/app_list/search/util/persistent_proto.h"
+#include "chrome/browser/ash/app_list/search/util/persistent_proto.h"
 
 #include <memory>
 #include <string>
@@ -12,7 +12,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
-#include "chrome/browser/ui/app_list/search/util/persistent_proto_test.pb.h"
+#include "chrome/browser/ash/app_list/search/util/persistent_proto_test.pb.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace app_list::test {
diff --git a/chrome/browser/ui/app_list/search/util/score_normalizer.cc b/chrome/browser/ash/app_list/search/util/score_normalizer.cc
similarity index 98%
rename from chrome/browser/ui/app_list/search/util/score_normalizer.cc
rename to chrome/browser/ash/app_list/search/util/score_normalizer.cc
index 1aba53c5..a356247 100644
--- a/chrome/browser/ui/app_list/search/util/score_normalizer.cc
+++ b/chrome/browser/ash/app_list/search/util/score_normalizer.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/ui/app_list/search/util/score_normalizer.h"
+#include "chrome/browser/ash/app_list/search/util/score_normalizer.h"
 
 #include <algorithm>
 #include <cmath>
diff --git a/chrome/browser/ui/app_list/search/util/score_normalizer.h b/chrome/browser/ash/app_list/search/util/score_normalizer.h
similarity index 85%
rename from chrome/browser/ui/app_list/search/util/score_normalizer.h
rename to chrome/browser/ash/app_list/search/util/score_normalizer.h
index 00ea799..f6025358 100644
--- a/chrome/browser/ui/app_list/search/util/score_normalizer.h
+++ b/chrome/browser/ash/app_list/search/util/score_normalizer.h
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_UTIL_SCORE_NORMALIZER_H_
-#define CHROME_BROWSER_UI_APP_LIST_SEARCH_UTIL_SCORE_NORMALIZER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_SEARCH_UTIL_SCORE_NORMALIZER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_SEARCH_UTIL_SCORE_NORMALIZER_H_
 
 #include "base/memory/weak_ptr.h"
-#include "chrome/browser/ui/app_list/search/util/persistent_proto.h"
-#include "chrome/browser/ui/app_list/search/util/score_normalizer.pb.h"
+#include "chrome/browser/ash/app_list/search/util/persistent_proto.h"
+#include "chrome/browser/ash/app_list/search/util/score_normalizer.pb.h"
 
 namespace app_list {
 
@@ -66,4 +66,4 @@
 
 }  // namespace app_list
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_UTIL_SCORE_NORMALIZER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_SEARCH_UTIL_SCORE_NORMALIZER_H_
diff --git a/chrome/browser/ui/app_list/search/util/score_normalizer.md b/chrome/browser/ash/app_list/search/util/score_normalizer.md
similarity index 100%
rename from chrome/browser/ui/app_list/search/util/score_normalizer.md
rename to chrome/browser/ash/app_list/search/util/score_normalizer.md
diff --git a/chrome/browser/ui/app_list/search/util/score_normalizer.proto b/chrome/browser/ash/app_list/search/util/score_normalizer.proto
similarity index 100%
rename from chrome/browser/ui/app_list/search/util/score_normalizer.proto
rename to chrome/browser/ash/app_list/search/util/score_normalizer.proto
diff --git a/chrome/browser/ui/app_list/search/util/score_normalizer_unittest.cc b/chrome/browser/ash/app_list/search/util/score_normalizer_unittest.cc
similarity index 99%
rename from chrome/browser/ui/app_list/search/util/score_normalizer_unittest.cc
rename to chrome/browser/ash/app_list/search/util/score_normalizer_unittest.cc
index daac99e5..979264f 100644
--- a/chrome/browser/ui/app_list/search/util/score_normalizer_unittest.cc
+++ b/chrome/browser/ash/app_list/search/util/score_normalizer_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/ui/app_list/search/util/score_normalizer.h"
+#include "chrome/browser/ash/app_list/search/util/score_normalizer.h"
 
 #include "base/files/scoped_temp_dir.h"
 #include "base/test/task_environment.h"
diff --git a/chrome/browser/ui/app_list/test/app_list_syncable_service_test_base.cc b/chrome/browser/ash/app_list/test/app_list_syncable_service_test_base.cc
similarity index 98%
rename from chrome/browser/ui/app_list/test/app_list_syncable_service_test_base.cc
rename to chrome/browser/ash/app_list/test/app_list_syncable_service_test_base.cc
index 74e545d..c480708 100644
--- a/chrome/browser/ui/app_list/test/app_list_syncable_service_test_base.cc
+++ b/chrome/browser/ash/app_list/test/app_list_syncable_service_test_base.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/ui/app_list/test/app_list_syncable_service_test_base.h"
+#include "chrome/browser/ash/app_list/test/app_list_syncable_service_test_base.h"
 
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/profiles/profile_manager.h"
diff --git a/chrome/browser/ui/app_list/test/app_list_syncable_service_test_base.h b/chrome/browser/ash/app_list/test/app_list_syncable_service_test_base.h
similarity index 91%
rename from chrome/browser/ui/app_list/test/app_list_syncable_service_test_base.h
rename to chrome/browser/ash/app_list/test/app_list_syncable_service_test_base.h
index ee189f04c..26781cb 100644
--- a/chrome/browser/ui/app_list/test/app_list_syncable_service_test_base.h
+++ b/chrome/browser/ash/app_list/test/app_list_syncable_service_test_base.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 CHROME_BROWSER_UI_APP_LIST_TEST_APP_LIST_SYNCABLE_SERVICE_TEST_BASE_H_
-#define CHROME_BROWSER_UI_APP_LIST_TEST_APP_LIST_SYNCABLE_SERVICE_TEST_BASE_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_TEST_APP_LIST_SYNCABLE_SERVICE_TEST_BASE_H_
+#define CHROME_BROWSER_ASH_APP_LIST_TEST_APP_LIST_SYNCABLE_SERVICE_TEST_BASE_H_
 
 #include <string>
 
@@ -75,4 +75,4 @@
 
 }  // namespace test
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_TEST_APP_LIST_SYNCABLE_SERVICE_TEST_BASE_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_TEST_APP_LIST_SYNCABLE_SERVICE_TEST_BASE_H_
diff --git a/chrome/browser/ui/app_list/test/chrome_app_list_test_support.cc b/chrome/browser/ash/app_list/test/chrome_app_list_test_support.cc
similarity index 97%
rename from chrome/browser/ui/app_list/test/chrome_app_list_test_support.cc
rename to chrome/browser/ash/app_list/test/chrome_app_list_test_support.cc
index a7c02f7..b840ae4 100644
--- a/chrome/browser/ui/app_list/test/chrome_app_list_test_support.cc
+++ b/chrome/browser/ash/app_list/test/chrome_app_list_test_support.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/ui/app_list/test/chrome_app_list_test_support.h"
+#include "chrome/browser/ash/app_list/test/chrome_app_list_test_support.h"
 
 #include <memory>
 #include <string>
diff --git a/chrome/browser/ui/app_list/test/chrome_app_list_test_support.h b/chrome/browser/ash/app_list/test/chrome_app_list_test_support.h
similarity index 78%
rename from chrome/browser/ui/app_list/test/chrome_app_list_test_support.h
rename to chrome/browser/ash/app_list/test/chrome_app_list_test_support.h
index 78df945..678917850 100644
--- a/chrome/browser/ui/app_list/test/chrome_app_list_test_support.h
+++ b/chrome/browser/ash/app_list/test/chrome_app_list_test_support.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 CHROME_BROWSER_UI_APP_LIST_TEST_CHROME_APP_LIST_TEST_SUPPORT_H_
-#define CHROME_BROWSER_UI_APP_LIST_TEST_CHROME_APP_LIST_TEST_SUPPORT_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_TEST_CHROME_APP_LIST_TEST_SUPPORT_H_
+#define CHROME_BROWSER_ASH_APP_LIST_TEST_CHROME_APP_LIST_TEST_SUPPORT_H_
 
 class AppListClientImpl;
 class AppListModelUpdater;
@@ -27,4 +27,4 @@
 
 }  // namespace test
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_TEST_CHROME_APP_LIST_TEST_SUPPORT_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_TEST_CHROME_APP_LIST_TEST_SUPPORT_H_
diff --git a/chrome/browser/ui/app_list/test/fake_app_list_model_updater.cc b/chrome/browser/ash/app_list/test/fake_app_list_model_updater.cc
similarity index 98%
rename from chrome/browser/ui/app_list/test/fake_app_list_model_updater.cc
rename to chrome/browser/ash/app_list/test/fake_app_list_model_updater.cc
index f889b28d..f9b88d0b 100644
--- a/chrome/browser/ui/app_list/test/fake_app_list_model_updater.cc
+++ b/chrome/browser/ash/app_list/test/fake_app_list_model_updater.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/ui/app_list/test/fake_app_list_model_updater.h"
+#include "chrome/browser/ash/app_list/test/fake_app_list_model_updater.h"
 
 #include <utility>
 
diff --git a/chrome/browser/ui/app_list/test/fake_app_list_model_updater.h b/chrome/browser/ash/app_list/test/fake_app_list_model_updater.h
similarity index 94%
rename from chrome/browser/ui/app_list/test/fake_app_list_model_updater.h
rename to chrome/browser/ash/app_list/test/fake_app_list_model_updater.h
index bc877ecd..57d66a9 100644
--- a/chrome/browser/ui/app_list/test/fake_app_list_model_updater.h
+++ b/chrome/browser/ash/app_list/test/fake_app_list_model_updater.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 CHROME_BROWSER_UI_APP_LIST_TEST_FAKE_APP_LIST_MODEL_UPDATER_H_
-#define CHROME_BROWSER_UI_APP_LIST_TEST_FAKE_APP_LIST_MODEL_UPDATER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_TEST_FAKE_APP_LIST_MODEL_UPDATER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_TEST_FAKE_APP_LIST_MODEL_UPDATER_H_
 
 #include <memory>
 #include <string>
@@ -103,4 +103,4 @@
   syncer::StringOrdinal GetOemFolderPos();
 };
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_TEST_FAKE_APP_LIST_MODEL_UPDATER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_TEST_FAKE_APP_LIST_MODEL_UPDATER_H_
diff --git a/chrome/browser/ui/app_list/test/test_app_list_controller.cc b/chrome/browser/ash/app_list/test/test_app_list_controller.cc
similarity index 96%
rename from chrome/browser/ui/app_list/test/test_app_list_controller.cc
rename to chrome/browser/ash/app_list/test/test_app_list_controller.cc
index 0c4d619..ab6cb696 100644
--- a/chrome/browser/ui/app_list/test/test_app_list_controller.cc
+++ b/chrome/browser/ash/app_list/test/test_app_list_controller.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/ui/app_list/test/test_app_list_controller.h"
+#include "chrome/browser/ash/app_list/test/test_app_list_controller.h"
 
 #include "ash/public/cpp/app_list/app_list_controller_observer.h"
 #include "chrome/browser/ui/app_list/app_list_client_impl.h"
diff --git a/chrome/browser/ui/app_list/test/test_app_list_controller.h b/chrome/browser/ash/app_list/test/test_app_list_controller.h
similarity index 90%
rename from chrome/browser/ui/app_list/test/test_app_list_controller.h
rename to chrome/browser/ash/app_list/test/test_app_list_controller.h
index 05a5292..7dc414d 100644
--- a/chrome/browser/ui/app_list/test/test_app_list_controller.h
+++ b/chrome/browser/ash/app_list/test/test_app_list_controller.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 CHROME_BROWSER_UI_APP_LIST_TEST_TEST_APP_LIST_CONTROLLER_H_
-#define CHROME_BROWSER_UI_APP_LIST_TEST_TEST_APP_LIST_CONTROLLER_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_TEST_TEST_APP_LIST_CONTROLLER_H_
+#define CHROME_BROWSER_ASH_APP_LIST_TEST_TEST_APP_LIST_CONTROLLER_H_
 
 #include "ash/public/cpp/app_list/app_list_controller.h"
 
@@ -58,4 +58,4 @@
 
 }  // namespace test
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_TEST_TEST_APP_LIST_CONTROLLER_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_TEST_TEST_APP_LIST_CONTROLLER_H_
diff --git a/chrome/browser/ui/app_list/test/test_app_list_controller_delegate.cc b/chrome/browser/ash/app_list/test/test_app_list_controller_delegate.cc
similarity index 95%
rename from chrome/browser/ui/app_list/test/test_app_list_controller_delegate.cc
rename to chrome/browser/ash/app_list/test/test_app_list_controller_delegate.cc
index e36418a..71d86d7b 100644
--- a/chrome/browser/ui/app_list/test/test_app_list_controller_delegate.cc
+++ b/chrome/browser/ash/app_list/test/test_app_list_controller_delegate.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/ui/app_list/test/test_app_list_controller_delegate.h"
+#include "chrome/browser/ash/app_list/test/test_app_list_controller_delegate.h"
 
 #include <utility>
 
diff --git a/chrome/browser/ui/app_list/test/test_app_list_controller_delegate.h b/chrome/browser/ash/app_list/test/test_app_list_controller_delegate.h
similarity index 85%
rename from chrome/browser/ui/app_list/test/test_app_list_controller_delegate.h
rename to chrome/browser/ash/app_list/test/test_app_list_controller_delegate.h
index c16e63c..ccd7950 100644
--- a/chrome/browser/ui/app_list/test/test_app_list_controller_delegate.h
+++ b/chrome/browser/ash/app_list/test/test_app_list_controller_delegate.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 CHROME_BROWSER_UI_APP_LIST_TEST_TEST_APP_LIST_CONTROLLER_DELEGATE_H_
-#define CHROME_BROWSER_UI_APP_LIST_TEST_TEST_APP_LIST_CONTROLLER_DELEGATE_H_
+#ifndef CHROME_BROWSER_ASH_APP_LIST_TEST_TEST_APP_LIST_CONTROLLER_DELEGATE_H_
+#define CHROME_BROWSER_ASH_APP_LIST_TEST_TEST_APP_LIST_CONTROLLER_DELEGATE_H_
 
 #include <string>
 
@@ -45,4 +45,4 @@
 
 }  // namespace test
 
-#endif  // CHROME_BROWSER_UI_APP_LIST_TEST_TEST_APP_LIST_CONTROLLER_DELEGATE_H_
+#endif  // CHROME_BROWSER_ASH_APP_LIST_TEST_TEST_APP_LIST_CONTROLLER_DELEGATE_H_
diff --git a/chrome/browser/ash/apps/apk_web_app_installer_browsertest.cc b/chrome/browser/ash/apps/apk_web_app_installer_browsertest.cc
index 739444c..ebaf78d 100644
--- a/chrome/browser/ash/apps/apk_web_app_installer_browsertest.cc
+++ b/chrome/browser/ash/apps/apk_web_app_installer_browsertest.cc
@@ -254,7 +254,7 @@
   void OnWebAppInstalled(const web_app::AppId& web_app_id) override {
     installed_web_app_ids_.push_back(web_app_id);
     installed_web_app_names_.push_back(
-        provider_->registrar().GetAppShortName(web_app_id));
+        provider_->registrar_unsafe().GetAppShortName(web_app_id));
   }
 
   void OnWebAppWillBeUninstalled(const web_app::AppId& web_app_id) override {
@@ -676,7 +676,8 @@
 
   ASSERT_FALSE(service->IsWebAppInstalledFromArc(app_id));
 
-  const web_app::WebApp* web_app = provider_->registrar().GetAppById(app_id);
+  const web_app::WebApp* web_app =
+      provider_->registrar_unsafe().GetAppById(app_id);
   ASSERT_TRUE(web_app);
 
   EXPECT_TRUE(web_app->IsSynced());
@@ -704,7 +705,7 @@
 
   ASSERT_TRUE(service->IsWebAppInstalledFromArc(app_id));
 
-  EXPECT_EQ(web_app, provider_->registrar().GetAppById(app_id));
+  EXPECT_EQ(web_app, provider_->registrar_unsafe().GetAppById(app_id));
 
   EXPECT_TRUE(web_app->IsSynced());
   EXPECT_TRUE(web_app->IsWebAppStoreInstalledApp());
@@ -741,7 +742,8 @@
 
   ASSERT_TRUE(service->IsWebAppInstalledFromArc(app_id));
 
-  const web_app::WebApp* web_app = provider_->registrar().GetAppById(app_id);
+  const web_app::WebApp* web_app =
+      provider_->registrar_unsafe().GetAppById(app_id);
   ASSERT_TRUE(web_app);
 
   EXPECT_TRUE(web_app->IsWebAppStoreInstalledApp());
@@ -759,7 +761,7 @@
 
   EXPECT_TRUE(service->IsWebAppInstalledFromArc(app_id));
 
-  EXPECT_EQ(web_app, provider_->registrar().GetAppById(app_id));
+  EXPECT_EQ(web_app, provider_->registrar_unsafe().GetAppById(app_id));
 
   EXPECT_TRUE(web_app->IsWebAppStoreInstalledApp());
   EXPECT_TRUE(web_app->IsSynced());
diff --git a/chrome/browser/ash/apps/apk_web_app_service.cc b/chrome/browser/ash/apps/apk_web_app_service.cc
index 0d374181..1f2de08 100644
--- a/chrome/browser/ash/apps/apk_web_app_service.cc
+++ b/chrome/browser/ash/apps/apk_web_app_service.cc
@@ -235,7 +235,7 @@
     // ARC++.
     return WebAppToApks().FindDict(web_app_id) != nullptr;
   } else {
-    web_app::WebAppRegistrar& registrar = provider_->registrar();
+    web_app::WebAppRegistrar& registrar = provider_->registrar_unsafe();
     const web_app::WebApp* app = registrar.GetAppById(web_app_id);
     return app ? app->IsWebAppStoreInstalledApp() : false;
   }
@@ -263,7 +263,7 @@
   if (!web_app_provider)
     return absl::nullopt;
   absl::optional<web_app::AppId> app_id =
-      web_app_provider->registrar().FindAppWithUrlInScope(url);
+      web_app_provider->registrar_unsafe().FindAppWithUrlInScope(url);
   if (!app_id)
     return absl::nullopt;
 
diff --git a/chrome/browser/ash/arc/app_shortcuts/arc_app_shortcuts_menu_builder.cc b/chrome/browser/ash/arc/app_shortcuts/arc_app_shortcuts_menu_builder.cc
index 13e6ccc..1a1faec 100644
--- a/chrome/browser/ash/arc/app_shortcuts/arc_app_shortcuts_menu_builder.cc
+++ b/chrome/browser/ash/arc/app_shortcuts/arc_app_shortcuts_menu_builder.cc
@@ -11,10 +11,10 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ash/app_list/arc/arc_app_utils.h"
+#include "chrome/browser/ash/app_list/search/ranking/launch_data.h"
 #include "chrome/browser/ash/arc/app_shortcuts/arc_app_shortcuts_request.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/app_list_client_impl.h"
-#include "chrome/browser/ui/app_list/search/ranking/launch_data.h"
 #include "chrome/browser/ui/app_list/search/search_controller.h"
 #include "ui/base/models/image_model.h"
 #include "ui/base/models/simple_menu_model.h"
diff --git a/chrome/browser/ash/crosapi/test_controller_ash.cc b/chrome/browser/ash/crosapi/test_controller_ash.cc
index 81438b4..7de533ec 100644
--- a/chrome/browser/ash/crosapi/test_controller_ash.cc
+++ b/chrome/browser/ash/crosapi/test_controller_ash.cc
@@ -46,6 +46,7 @@
 #include "chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client.h"
 #include "chromeos/ash/components/network/network_handler_test_helper.h"
 #include "components/version_info/version_info.h"
+#include "content/public/browser/tts_utterance.h"
 #include "crypto/sha2.h"
 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
 #include "printing/buildflags/buildflags.h"
@@ -557,6 +558,48 @@
 
 #endif  // defined(USE_CUPS)
 
+// This class is set as UtteranceEventDelegate for the Ash TtsUtterance
+// created in TestControllerAsh::TtsSpeak(), which is called from lacros browser
+// test to simulate speaking an Ash utterance with a Lacros voice. It helps to
+// verify that Tts events sent from Tts Speech Engine (in Lacros) are forwarded
+// to its utterance event delegate in Ash.
+class TestControllerAsh::AshUtteranceEventDelegate
+    : public content::UtteranceEventDelegate {
+ public:
+  AshUtteranceEventDelegate(
+      TestControllerAsh* controller,
+      mojo::PendingRemote<crosapi::mojom::TtsUtteranceClient> client)
+      : controller_(controller), client_(std::move(client)) {}
+
+  AshUtteranceEventDelegate(const AshUtteranceEventDelegate&) = delete;
+  AshUtteranceEventDelegate& operator=(const AshUtteranceEventDelegate&) =
+      delete;
+  ~AshUtteranceEventDelegate() override = default;
+
+  // content::UtteranceEventDelegate:
+  void OnTtsEvent(content::TtsUtterance* utterance,
+                  content::TtsEventType event_type,
+                  int char_index,
+                  int char_length,
+                  const std::string& error_message) override {
+    // Forward the TtsEvent back to Lacros, so that Lacros browser test can
+    // be notified that TtsEvent has been received by its UtteranceEventDelegate
+    // in Ash.
+    client_->OnTtsEvent(tts_crosapi_util::ToMojo(event_type), char_index,
+                        char_length, error_message);
+
+    if (utterance->IsFinished()) {
+      controller_->OnAshUtteranceFinished(utterance->GetId());
+      // Note: |this| is deleted at this point.
+    }
+  }
+
+ private:
+  // |controller_| is guaranteed to be valid during the lifetime of this class.
+  const raw_ptr<TestControllerAsh> controller_;
+  mojo::Remote<crosapi::mojom::TtsUtteranceClient> client_;
+};
+
 void TestControllerAsh::CreateAndCancelPrintJob(
     const std::string& job_title,
     CreateAndCancelPrintJobCallback callback) {
@@ -630,6 +673,37 @@
       tts_crosapi_util::GetTtsUtteranceQueueSizeForTesting());
 }
 
+void TestControllerAsh::GetTtsVoices(GetTtsVoicesCallback callback) {
+  std::vector<content::VoiceData> voices;
+  tts_crosapi_util::GetAllVoicesForTesting(  // IN-TEST
+      ProfileManager::GetActiveUserProfile(), GURL(), &voices);
+
+  std::vector<crosapi::mojom::TtsVoicePtr> mojo_voices;
+  for (const auto& voice : voices)
+    mojo_voices.push_back(tts_crosapi_util::ToMojo(voice));
+
+  std::move(callback).Run(std::move(mojo_voices));
+}
+
+void TestControllerAsh::TtsSpeak(
+    crosapi::mojom::TtsUtterancePtr mojo_utterance,
+    mojo::PendingRemote<crosapi::mojom::TtsUtteranceClient> utterance_client) {
+  std::unique_ptr<content::TtsUtterance> ash_utterance =
+      tts_crosapi_util::CreateUtteranceFromMojo(
+          mojo_utterance, /*should_always_be_spoken=*/false);
+  auto event_delegate = std::make_unique<AshUtteranceEventDelegate>(
+      this, std::move(utterance_client));
+  ash_utterance->SetEventDelegate(event_delegate.get());
+  ash_utterance_event_delegates_.emplace(ash_utterance->GetId(),
+                                         std ::move(event_delegate));
+  tts_crosapi_util::SpeakForTesting(std::move(ash_utterance));
+}
+
+void TestControllerAsh::OnAshUtteranceFinished(int utterance_id) {
+  // Delete the utterace event delegate object when the utterance is finished.
+  ash_utterance_event_delegates_.erase(utterance_id);
+}
+
 // This class waits for overview mode to either enter or exit and fires a
 // callback. This class will fire the callback at most once.
 class TestControllerAsh::OverviewWaiter : public ash::OverviewObserver {
diff --git a/chrome/browser/ash/crosapi/test_controller_ash.h b/chrome/browser/ash/crosapi/test_controller_ash.h
index 7cd1cb8f..138d42df 100644
--- a/chrome/browser/ash/crosapi/test_controller_ash.h
+++ b/chrome/browser/ash/crosapi/test_controller_ash.h
@@ -109,6 +109,12 @@
   void GetTtsUtteranceQueueSize(
       GetTtsUtteranceQueueSizeCallback callback) override;
 
+  void GetTtsVoices(GetTtsVoicesCallback callback) override;
+
+  void TtsSpeak(crosapi::mojom::TtsUtterancePtr mojo_utterance,
+                mojo::PendingRemote<crosapi::mojom::TtsUtteranceClient>
+                    utterance_client) override;
+
   mojo::Remote<mojom::StandaloneBrowserTestController>&
   GetStandaloneBrowserTestController() {
     DCHECK(standalone_browser_test_controller_.is_bound());
@@ -123,6 +129,10 @@
 
  private:
   class OverviewWaiter;
+  class AshUtteranceEventDelegate;
+
+  // Called when a Tts utterance is finished.
+  void OnAshUtteranceFinished(int utterance_id);
 
   // Called when a waiter has finished waiting for its event.
   void WaiterFinished(OverviewWaiter* waiter);
@@ -157,6 +167,10 @@
       standalone_browser_test_controller_;
 
   base::OneShotEvent on_standalone_browser_test_controller_bound_;
+
+  // Ash utterance event delegates by utterance id.
+  std::map<int, std::unique_ptr<AshUtteranceEventDelegate>>
+      ash_utterance_event_delegates_;
 };
 
 class TestShillControllerAsh : public crosapi::mojom::TestShillController {
diff --git a/chrome/browser/ash/crostini/crostini_manager.cc b/chrome/browser/ash/crostini/crostini_manager.cc
index 6bbf2ec..8a22cf7 100644
--- a/chrome/browser/ash/crostini/crostini_manager.cc
+++ b/chrome/browser/ash/crostini/crostini_manager.cc
@@ -3011,8 +3011,10 @@
       LOG(ERROR) << "Failed to create container: "
                  << response->failure_reason();
       // Remove all create options and the existence of this container.
-      RemoveLxdContainerFromPrefs(profile_, container_id);
-      UnregisterContainer(container_id);
+      if (IsPendingCreation(container_id)) {
+        RemoveLxdContainerFromPrefs(profile_, container_id);
+        UnregisterContainer(container_id);
+      }
       std::move(callback).Run(CrostiniResult::CONTAINER_CREATE_FAILED);
   }
 }
@@ -3195,8 +3197,10 @@
   if (result != CrostiniResult::SUCCESS) {
     LOG(ERROR) << "Failed to create container. ID: " << container_id
                << " reason: " << signal.failure_reason();
-    RemoveLxdContainerFromPrefs(profile_, container_id);
-    UnregisterContainer(container_id);
+    if (IsPendingCreation(container_id)) {
+      RemoveLxdContainerFromPrefs(profile_, container_id);
+      UnregisterContainer(container_id);
+    }
   }
 
   InvokeAndErasePendingContainerCallbacks(&create_lxd_container_callbacks_,
@@ -4155,6 +4159,19 @@
   return true;
 }
 
+bool CrostiniManager::IsPendingCreation(const guest_os::GuestId& container_id) {
+  const base::Value* create_options = guest_os::GetContainerPrefValue(
+      profile_, container_id, guest_os::prefs::kContainerCreateOptions);
+  if (create_options == nullptr) {
+    // Will only reach here if it's a vmc-started container. Treat it as if the
+    // create options have already been used.
+    return false;
+  }
+
+  return !(*create_options->GetDict().FindBool(
+      prefs::kCrostiniCreateOptionsUsedKey));
+}
+
 void CrostiniManager::SetCreateOptionsUsed(
     const guest_os::GuestId& container_id) {
   const base::Value* create_options = guest_os::GetContainerPrefValue(
diff --git a/chrome/browser/ash/crostini/crostini_manager.h b/chrome/browser/ash/crostini/crostini_manager.h
index fc79a69..17f6108f 100644
--- a/chrome/browser/ash/crostini/crostini_manager.h
+++ b/chrome/browser/ash/crostini/crostini_manager.h
@@ -451,6 +451,9 @@
   bool FetchCreateOptions(const guest_os::GuestId& container_id,
                           RestartOptions* restart_options);
 
+  // Returns true if the container is currently pending creation.
+  bool IsPendingCreation(const guest_os::GuestId& container_id);
+
   // Sets an CreateOptions as booted, so it becomes a historical record and has
   // no effect on future starts.
   void SetCreateOptionsUsed(const guest_os::GuestId& container_id);
diff --git a/chrome/browser/ash/crostini/crostini_manager_unittest.cc b/chrome/browser/ash/crostini/crostini_manager_unittest.cc
index d991839..7e73117 100644
--- a/chrome/browser/ash/crostini/crostini_manager_unittest.cc
+++ b/chrome/browser/ash/crostini/crostini_manager_unittest.cc
@@ -1373,6 +1373,35 @@
   ExpectRestarterUmaCount(1);
 }
 
+TEST_F(CrostiniManagerRestartTest,
+       SuccessfulCreateCancelContainerCreatedKeepsPrefs) {
+  TestFuture<CrostiniResult> restart_future;
+  restart_id_ = crostini_manager()->RestartCrostini(
+      container_id(), restart_future.GetCallback());
+  EXPECT_EQ(restart_future.Get(), CrostiniResult::SUCCESS);
+  EXPECT_GE(
+      guest_os::GetContainers(profile_.get(), guest_os::VmType::TERMINA).size(),
+      1uL);
+
+  TestFuture<CrostiniResult> stop_future;
+  crostini_manager()->StopLxdContainer(container_id(),
+                                       stop_future.GetCallback());
+  EXPECT_EQ(stop_future.Get(), CrostiniResult::SUCCESS);
+
+  TestFuture<CrostiniResult> failed_restart_future;
+  cancel_on_container_setup_ = true;
+  fake_cicerone_client_->set_lxd_container_created_signal_status(
+      vm_tools::cicerone::LxdContainerCreatedSignal::UNKNOWN);
+  restart_id_ = crostini_manager()->RestartCrostini(
+      container_id(), failed_restart_future.GetCallback());
+  EXPECT_EQ(failed_restart_future.Get(), CrostiniResult::UNKNOWN_ERROR);
+
+  // Expect container wasn't removed from prefs.
+  EXPECT_GE(
+      guest_os::GetContainers(profile_.get(), guest_os::VmType::TERMINA).size(),
+      1uL);
+}
+
 TEST_F(CrostiniManagerRestartTest, TimeoutDuringContainerSetup) {
   fake_cicerone_client_->set_send_set_up_lxd_container_user_response_delay(
       base::TimeDelta::Max());
diff --git a/chrome/browser/ash/crostini/crostini_terminal_provider.cc b/chrome/browser/ash/crostini/crostini_terminal_provider.cc
index 3cc5b4b9..754c509 100644
--- a/chrome/browser/ash/crostini/crostini_terminal_provider.cc
+++ b/chrome/browser/ash/crostini/crostini_terminal_provider.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ash/crostini/crostini_terminal_provider.h"
 
 #include "base/no_destructor.h"
+#include "base/strings/stringprintf.h"
 #include "chrome/browser/ash/crostini/crostini_manager.h"
 #include "chrome/browser/ash/crostini/crostini_types.mojom-shared.h"
 #include "chrome/browser/ash/crostini/crostini_util.h"
diff --git a/chrome/browser/ash/extensions/autotest_private/autotest_private_apitest.cc b/chrome/browser/ash/extensions/autotest_private/autotest_private_apitest.cc
index 39b4dee..4eda1d7 100644
--- a/chrome/browser/ash/extensions/autotest_private/autotest_private_apitest.cc
+++ b/chrome/browser/ash/extensions/autotest_private/autotest_private_apitest.cc
@@ -29,6 +29,9 @@
 #include "base/values.h"
 #include "build/build_config.h"
 #include "chrome/browser/ash/app_list/arc/arc_app_list_prefs.h"
+#include "chrome/browser/ash/app_list/search/test/app_list_search_test_helper.h"
+#include "chrome/browser/ash/app_list/search/test/search_results_changed_waiter.h"
+#include "chrome/browser/ash/app_list/search/test/test_result.h"
 #include "chrome/browser/ash/arc/arc_util.h"
 #include "chrome/browser/ash/arc/session/arc_session_manager.h"
 #include "chrome/browser/ash/arc/tracing/arc_app_performance_tracing.h"
@@ -38,9 +41,6 @@
 #include "chrome/browser/ash/system_web_apps/test_support/test_system_web_app_installation.h"
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/ui/app_list/search/search_provider.h"
-#include "chrome/browser/ui/app_list/search/test/app_list_search_test_helper.h"
-#include "chrome/browser/ui/app_list/search/test/search_results_changed_waiter.h"
-#include "chrome/browser/ui/app_list/search/test/test_result.h"
 #include "chrome/browser/ui/ash/shelf/chrome_shelf_prefs.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "components/feature_engagement/public/feature_constants.h"
diff --git a/chrome/browser/ash/extensions/file_manager/drivefs_event_router_unittest.cc b/chrome/browser/ash/extensions/file_manager/drivefs_event_router_unittest.cc
index 30379a5..37f27a17 100644
--- a/chrome/browser/ash/extensions/file_manager/drivefs_event_router_unittest.cc
+++ b/chrome/browser/ash/extensions/file_manager/drivefs_event_router_unittest.cc
@@ -35,13 +35,13 @@
 
 namespace {
 
-using drivefs::mojom::ItemEvent::State::kCompleted;
-using drivefs::mojom::ItemEvent::State::kFailed;
-using drivefs::mojom::ItemEvent::State::kInProgress;
-using drivefs::mojom::ItemEvent::State::kQueued;
+constexpr auto kCompleted = drivefs::mojom::ItemEvent::State::kCompleted;
+constexpr auto kFailed = drivefs::mojom::ItemEvent::State::kFailed;
+constexpr auto kInProgress = drivefs::mojom::ItemEvent::State::kInProgress;
+constexpr auto kQueued = drivefs::mojom::ItemEvent::State::kQueued;
 
-using drivefs::mojom::ItemEventReason::kPin;
-using drivefs::mojom::ItemEventReason::kTransfer;
+constexpr auto kPin = drivefs::mojom::ItemEventReason::kPin;
+constexpr auto kTransfer = drivefs::mojom::ItemEventReason::kTransfer;
 
 constexpr auto QUEUED = file_manager_private::TRANSFER_STATE_QUEUED;
 constexpr auto IN_PROGRESS = file_manager_private::TRANSFER_STATE_IN_PROGRESS;
diff --git a/chrome/browser/ash/extensions/file_manager/private_api_misc.cc b/chrome/browser/ash/extensions/file_manager/private_api_misc.cc
index 4851f9b..a2af9761 100644
--- a/chrome/browser/ash/extensions/file_manager/private_api_misc.cc
+++ b/chrome/browser/ash/extensions/file_manager/private_api_misc.cc
@@ -979,8 +979,9 @@
       Profile::FromBrowserContext(browser_context())->GetOriginalProfile();
   auto* guest_os_share_path =
       guest_os::GuestOsSharePath::GetForProfile(profile);
-  bool first_for_session = params->observe_first_for_session &&
-                           guest_os_share_path->GetAndSetFirstForSession();
+  bool first_for_session =
+      params->observe_first_for_session &&
+      guest_os_share_path->GetAndSetFirstForSession(params->vm_name);
   auto shared_paths =
       guest_os_share_path->GetPersistedSharedPaths(params->vm_name);
   base::Value::List entries;
diff --git a/chrome/browser/ash/file_manager/file_manager_jstest.cc b/chrome/browser/ash/file_manager/file_manager_jstest.cc
index bd7864a..4b1dfbd 100644
--- a/chrome/browser/ash/file_manager/file_manager_jstest.cc
+++ b/chrome/browser/ash/file_manager/file_manager_jstest.cc
@@ -258,8 +258,8 @@
   RunTestURL("foreground/js/spinner_controller_unittest.js");
 }
 
-IN_PROC_BROWSER_TEST_F(FileManagerJsTest, StorageAdapter) {
-  RunTestURL("common/js/storage_adapter_unittest.js");
+IN_PROC_BROWSER_TEST_F(FileManagerJsTest, Storage) {
+  RunTestURL("common/js/storage_unittest.js");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, TaskController) {
diff --git a/chrome/browser/ash/guest_os/guest_os_share_path.cc b/chrome/browser/ash/guest_os/guest_os_share_path.cc
index cb967e3..04e0ba1 100644
--- a/chrome/browser/ash/guest_os/guest_os_share_path.cc
+++ b/chrome/browser/ash/guest_os/guest_os_share_path.cc
@@ -465,10 +465,9 @@
   }
 }
 
-bool GuestOsSharePath::GetAndSetFirstForSession() {
-  bool result = first_for_session_;
-  first_for_session_ = false;
-  return result;
+bool GuestOsSharePath::GetAndSetFirstForSession(const std::string& vm_name) {
+  auto result = first_for_session_.insert(vm_name);
+  return result.second;
 }
 
 std::vector<base::FilePath> GuestOsSharePath::GetPersistedSharedPaths(
diff --git a/chrome/browser/ash/guest_os/guest_os_share_path.h b/chrome/browser/ash/guest_os/guest_os_share_path.h
index 179ba9d9..a573d57 100644
--- a/chrome/browser/ash/guest_os/guest_os_share_path.h
+++ b/chrome/browser/ash/guest_os/guest_os_share_path.h
@@ -105,7 +105,7 @@
                    SuccessCallback callback);
 
   // Returns true the first time it is called on this service.
-  bool GetAndSetFirstForSession();
+  bool GetAndSetFirstForSession(const std::string& vm_name);
 
   // Get list of all shared paths for the specified VM.
   std::vector<base::FilePath> GetPersistedSharedPaths(
@@ -190,7 +190,9 @@
   Profile* profile_;
   // Task runner for FilePathWatchers to be created, run, and be destroyed on.
   scoped_refptr<base::SequencedTaskRunner> file_watcher_task_runner_;
-  bool first_for_session_ = true;
+
+  // List of VMs GetAndSetFirstForSession has been called on.
+  std::set<std::string> first_for_session_;
 
   // Allow seneschal callback to be overridden for testing.
   SeneschalCallback seneschal_callback_;
diff --git a/chrome/browser/ash/guest_os/guest_os_share_path_unittest.cc b/chrome/browser/ash/guest_os/guest_os_share_path_unittest.cc
index 699bc84..5b9b3a0 100644
--- a/chrome/browser/ash/guest_os/guest_os_share_path_unittest.cc
+++ b/chrome/browser/ash/guest_os/guest_os_share_path_unittest.cc
@@ -1016,4 +1016,10 @@
   }
 }
 
+TEST_F(GuestOsSharePathTest, GetAndSetFirstForSession) {
+  ASSERT_TRUE(guest_os_share_path_->GetAndSetFirstForSession("first"));
+  ASSERT_TRUE(guest_os_share_path_->GetAndSetFirstForSession("second"));
+  ASSERT_FALSE(guest_os_share_path_->GetAndSetFirstForSession("second"));
+}
+
 }  // namespace guest_os
diff --git a/chrome/browser/ash/guest_os/guest_os_terminal.h b/chrome/browser/ash/guest_os/guest_os_terminal.h
index 8cb448c..637169a1 100644
--- a/chrome/browser/ash/guest_os/guest_os_terminal.h
+++ b/chrome/browser/ash/guest_os/guest_os_terminal.h
@@ -13,7 +13,9 @@
 #include "components/services/app_service/public/cpp/intent.h"
 #include "components/services/app_service/public/mojom/app_service.mojom.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
+#include "third_party/skia/include/core/SkColor.h"
 #include "ui/display/types/display_constants.h"
+#include "ui/gfx/image/image_skia.h"
 
 namespace apps {
 struct MenuItems;
diff --git a/chrome/browser/ash/input_method/assistive_suggester.cc b/chrome/browser/ash/input_method/assistive_suggester.cc
index 7cf1bcf..b8e3083 100644
--- a/chrome/browser/ash/input_method/assistive_suggester.cc
+++ b/chrome/browser/ash/input_method/assistive_suggester.cc
@@ -665,6 +665,8 @@
 
 void AssistiveSuggester::OnActivate(const std::string& engine_id) {
   active_engine_id_ = engine_id;
+  longpress_diacritics_suggester_.SetEngineId(engine_id);
+
   if (features::IsAssistiveMultiWordEnabled()) {
     RecordAssistiveUserPrefForMultiWord(
         IsPredictiveWritingPrefEnabled(profile_->GetPrefs(), engine_id));
diff --git a/chrome/browser/ash/input_method/input_method_settings.cc b/chrome/browser/ash/input_method/input_method_settings.cc
index d8936dc..b1b15c7 100644
--- a/chrome/browser/ash/input_method/input_method_settings.cc
+++ b/chrome/browser/ash/input_method/input_method_settings.cc
@@ -10,13 +10,71 @@
 #include "chrome/browser/ash/input_method/autocorrect_enums.h"
 #include "chrome/browser/ash/input_method/autocorrect_prefs.h"
 #include "chrome/common/pref_names.h"
+#include "chromeos/ash/services/ime/public/mojom/japanese_settings.mojom-shared.h"
+#include "chromeos/ash/services/ime/public/mojom/japanese_settings.mojom.h"
 
 namespace ash {
 namespace input_method {
+
 namespace {
 
 namespace mojom = ::ash::ime::mojom;
 
+// The Japanese engine. This is the key for the settings object which lets us
+// know where to store the settings info.
+constexpr char kJapaneseEngineId[] = "nacl_mozc_jp";
+
+// This should be kept in sync with the values on the settings page's
+// InputMethodOptions. This should match
+// https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/resources/settings/chromeos/os_languages_page/input_method_util.js;l=71-88;drc=6c88edbfe6096489ccac66b3ef5c84d479892181.
+constexpr char kJapaneseAutomaticallySwitchToHalfwidth[] =
+    "AutomaticallySwitchToHalfwidth";
+constexpr char kJapaneseShiftKeyModeStyle[] = "ShiftKeyModeStyle";
+constexpr char kJapaneseUseInputHistory[] = "UseInputHistory";
+constexpr char kJapaneseUseSystemDictionary[] = "UseSystemDictionary";
+constexpr char kJapaneseNumberOfSuggestions[] = "numberOfSuggestions";
+constexpr char kJapaneseInputMode[] = "JapaneseInputMode";
+constexpr char kJapanesePunctuationStyle[] = "JapanesePunctuationStyle";
+constexpr char kJapaneseSymbolStyle[] = "JapaneseSymbolStyle";
+constexpr char kJapaneseSpaceInputStyle[] = "JapaneseSpaceInputStyle";
+constexpr char kJapaneseSelectionShortcut[] = "JapaneseSectionShortcut";
+constexpr char kJapaneseKeymapStyle[] = "JapaneseKeymapStyle";
+constexpr char kJapaneseDisablePersonalizedSuggestions[] =
+    "JapaneseDisableSuggestions";
+constexpr char kJapaneseAutomaticallySendStatisticsToGoogle[] =
+    "AutomaticallySendStatisticsToGoogle";
+
+// This should match the strings listed here:
+// https://crsrc.org/c/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_types.js;l=8-71;drc=7df206933530e6ac65a7e17a88757cbb780c829e
+// These are possible values for their corresponding enum type.
+constexpr char kJapaneseInputModeKana[] = "Kana";
+constexpr char kJapaneseInputModeRomaji[] = "Romaji";
+constexpr char kJapanesePunctuationStyleKutenTouten[] = "KutenTouten";
+constexpr char kJapanesePunctuationStyleCommaPeriod[] = "CommaPeriod";
+constexpr char kJapanesePunctuationStyleKutenPeriod[] = "KutenPeriod";
+constexpr char kJapanesePunctuationStyleCommaTouten[] = "CommaTouten";
+constexpr char kJapaneseSymbolStyleCornerBracketMiddleDot[] =
+    "CornerBracketMiddleDot";
+constexpr char kJapaneseSymbolStyleSquareBracketSlash[] = "SquareBracketSlash";
+constexpr char kJapaneseSymbolStyleCornerBracketSlash[] = "CornerBracketSlash";
+constexpr char kJapaneseSymbolStyleSquareBracketMiddleDot[] =
+    "SquareBracketMiddleDot";
+constexpr char kJapaneseSpaceInputStyleInputMode[] = "InputMode";
+constexpr char kJapaneseSpaceInputStyleFullwidth[] = "Fullwidth";
+constexpr char kJapaneseSpaceInputStyleHalfwidth[] = "Halfwidth";
+constexpr char kJapaneseSelectionShortcutNoShortcut[] = "NoShortcut";
+constexpr char kJapaneseSelectionShortcutDigits123456789[] = "Digits123456789";
+constexpr char kJapaneseSelectionShortcutAsdfghjkl[] = "ASDFGHJKL";
+constexpr char kJapaneseKeymapStyleCustom[] = "Custom";
+constexpr char kJapaneseKeymapStyleAtok[] = "Atok";
+constexpr char kJapaneseKeymapStyleMsIme[] = "MsIme";
+constexpr char kJapaneseKeymapStyleKotoeri[] = "Kotoeri";
+constexpr char kJapaneseKeymapStyleMobile[] = "Mobile";
+constexpr char kJapaneseKeymapStyleChromeOs[] = "ChromeOs";
+constexpr char kJapaneseShiftKeyModeStyleOff[] = "Off";
+constexpr char kJapaneseShiftKeyModeStyleAlphanumeric[] = "Alphanumeric";
+constexpr char kJapaneseShiftKeyModeStyleKatakana[] = "Katakana";
+
 // The values here should be kept in sync with
 // chrome/browser/resources/settings/chromeos/os_languages_page/input_method_util.js
 // Although these strings look like UI strings, they are the actual internal
@@ -59,6 +117,15 @@
 constexpr char kZhuyinPrefsPageSize9[] = "9";
 constexpr char kZhuyinPrefsPageSize8[] = "8";
 
+constexpr char kJapaneseMigrationCompleteKey[] = "is_migration_complete";
+
+const base::Value::Dict* GetJapaneseInputMethodSpecificSettings(
+    const PrefService& prefs) {
+  const base::Value::Dict& all_input_method_prefs =
+      prefs.GetDict(::prefs::kLanguageInputMethodSpecificSettings);
+  return all_input_method_prefs.FindDict(kJapaneseEngineId);
+}
+
 std::string ValueOrEmpty(const std::string* str) {
   return str ? *str : "";
 }
@@ -260,6 +327,159 @@
              : fallback_dictionary;
 }
 
+// Port the Prefs settings onto a Dict object for setting the user Prefs.
+// This converts the code in the corresponding pages:
+// https://crsrc.org/c/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_util.js;drc=6c88edbfe6096489ccac66b3ef5c84d479892181;l=72
+// https://crsrc.org/c/chromeos/ash/services/ime/public/mojom/japanese_settings.mojom;drc=e250164fc5bdefca32cb94157e9835ff8c2c9ee6;l=73
+base::Value::Dict ConvertConfigToJapaneseSettings(
+    const ime::mojom::JapaneseConfig config) {
+  base::Value::Dict japanese_settings;
+  switch (config.input_mode) {
+    case (mojom::InputMode::kRomaji):
+      japanese_settings.Set(kJapaneseInputMode,
+                            std::string(kJapaneseInputModeRomaji));
+      break;
+    case (mojom::InputMode::kKana):
+      japanese_settings.Set(kJapaneseInputMode,
+                            std::string(kJapaneseInputModeKana));
+      break;
+  }
+  switch (config.punctuation_style) {
+    case (mojom::PunctuationStyle::kKutenTouten):
+      japanese_settings.Set(kJapanesePunctuationStyle,
+                            std::string(kJapanesePunctuationStyleKutenTouten));
+      break;
+    case (mojom::PunctuationStyle::kCommaTouten):
+      japanese_settings.Set(kJapanesePunctuationStyle,
+                            std::string(kJapanesePunctuationStyleCommaTouten));
+      break;
+    case (mojom::PunctuationStyle::kKutenPeriod):
+      japanese_settings.Set(kJapanesePunctuationStyle,
+                            std::string(kJapanesePunctuationStyleKutenPeriod));
+      break;
+    case (mojom::PunctuationStyle::kCommaPeriod):
+      japanese_settings.Set(kJapanesePunctuationStyle,
+                            std::string(kJapanesePunctuationStyleCommaPeriod));
+      break;
+  }
+  switch (config.symbol_style) {
+    case (mojom::SymbolStyle::kCornerBracketMiddleDot):
+      japanese_settings.Set(
+          kJapaneseSymbolStyle,
+          std::string(kJapaneseSymbolStyleCornerBracketMiddleDot));
+      break;
+    case (mojom::SymbolStyle::kCornerBracketSlash):
+      japanese_settings.Set(
+          kJapaneseSymbolStyle,
+          std::string(kJapaneseSymbolStyleCornerBracketSlash));
+      break;
+    case (mojom::SymbolStyle::kSquareBracketSlash):
+      japanese_settings.Set(
+          kJapaneseSymbolStyle,
+          std::string(kJapaneseSymbolStyleSquareBracketSlash));
+      break;
+    case (mojom::SymbolStyle::kSquareBracketMiddleDot):
+      japanese_settings.Set(
+          kJapaneseSymbolStyle,
+          std::string(kJapaneseSymbolStyleSquareBracketMiddleDot));
+      break;
+  }
+
+  switch (config.space_input_style) {
+    case (mojom::SpaceInputStyle::kInputMode):
+      japanese_settings.Set(kJapaneseSpaceInputStyle,
+                            std::string(kJapaneseSpaceInputStyleInputMode));
+      break;
+    case (mojom::SpaceInputStyle::kHalfwidth):
+      japanese_settings.Set(kJapaneseSpaceInputStyle,
+                            std::string(kJapaneseSpaceInputStyleHalfwidth));
+      break;
+    case (mojom::SpaceInputStyle::kFullwidth):
+      japanese_settings.Set(kJapaneseSpaceInputStyle,
+                            std::string(kJapaneseSpaceInputStyleFullwidth));
+      break;
+  }
+
+  switch (config.selection_shortcut) {
+    case (mojom::SelectionShortcut::kNoShortcut):
+      japanese_settings.Set(kJapaneseSelectionShortcut,
+                            std::string(kJapaneseSelectionShortcutNoShortcut));
+      break;
+    case (mojom::SelectionShortcut::kAsdfghjkl):
+      japanese_settings.Set(kJapaneseSelectionShortcut,
+                            std::string(kJapaneseSelectionShortcutAsdfghjkl));
+      break;
+    case (mojom::SelectionShortcut::kDigits123456789):
+      japanese_settings.Set(
+          kJapaneseSelectionShortcut,
+          std::string(kJapaneseSelectionShortcutDigits123456789));
+      break;
+  }
+
+  switch (config.keymap_style) {
+    case (mojom::KeymapStyle::kCustom):
+      japanese_settings.Set(kJapaneseKeymapStyle,
+                            std::string(kJapaneseKeymapStyleCustom));
+      break;
+    case (mojom::KeymapStyle::kAtok):
+      japanese_settings.Set(kJapaneseKeymapStyle,
+                            std::string(kJapaneseKeymapStyleAtok));
+      break;
+    case (mojom::KeymapStyle::kMsIme):
+      japanese_settings.Set(kJapaneseKeymapStyle,
+                            std::string(kJapaneseKeymapStyleMsIme));
+      break;
+    case (mojom::KeymapStyle::kKotoeri):
+      japanese_settings.Set(kJapaneseKeymapStyle,
+                            std::string(kJapaneseKeymapStyleKotoeri));
+      break;
+    case (mojom::KeymapStyle::kMobile):
+      japanese_settings.Set(kJapaneseKeymapStyle,
+                            std::string(kJapaneseKeymapStyleMobile));
+      break;
+    case (mojom::KeymapStyle::kChromeOs):
+      japanese_settings.Set(kJapaneseKeymapStyle,
+                            std::string(kJapaneseKeymapStyleChromeOs));
+      break;
+    case (mojom::KeymapStyle::kNone):
+      // Note: For None type, we just default to MsIme. That is the default,
+      // since None seems to be unused.
+      japanese_settings.Set(kJapaneseKeymapStyle,
+                            std::string(kJapaneseKeymapStyleMsIme));
+      break;
+  }
+
+  japanese_settings.Set(kJapaneseAutomaticallySwitchToHalfwidth,
+                        config.automatically_switch_to_halfwidth);
+
+  switch (config.shift_key_mode_switch) {
+    case (mojom::ShiftKeyModeSwitch::kOff):
+      japanese_settings.Set(kJapaneseShiftKeyModeStyle,
+                            std::string(kJapaneseShiftKeyModeStyleOff));
+      break;
+    case (mojom::ShiftKeyModeSwitch::kAlphanumeric):
+      japanese_settings.Set(
+          kJapaneseShiftKeyModeStyle,
+          std::string(kJapaneseShiftKeyModeStyleAlphanumeric));
+      break;
+    case (mojom::ShiftKeyModeSwitch::kKatakana):
+      japanese_settings.Set(kJapaneseShiftKeyModeStyle,
+                            std::string(kJapaneseShiftKeyModeStyleKatakana));
+      break;
+  }
+
+  japanese_settings.Set(kJapaneseUseInputHistory, config.use_input_history);
+  japanese_settings.Set(kJapaneseUseSystemDictionary,
+                        config.use_system_dictionary);
+  japanese_settings.Set(kJapaneseNumberOfSuggestions,
+                        static_cast<int>(config.number_of_suggestions));
+  japanese_settings.Set(kJapaneseDisablePersonalizedSuggestions,
+                        config.disable_personalized_suggestions);
+  japanese_settings.Set(kJapaneseAutomaticallySendStatisticsToGoogle,
+                        config.send_statistics_to_google);
+  return japanese_settings;
+}
+
 }  // namespace
 
 mojom::InputMethodSettingsPtr CreateSettingsFromPrefs(
@@ -285,9 +505,75 @@
     return mojom::InputMethodSettings::NewZhuyinSettings(
         CreateZhuyinSettings(input_method_specific_pref));
   }
+  // TODO(b/232341104): Add the code to send the Japanese settings to
+  // the engine if the engine_id is nacl_mozc_jp or nacl_mozc_us.
+  // This will do the inverse of ConvertConfigToJapaneseSettings.
+  // This will be something like InputMethodSettings::NewJapaneseSettings(...)
 
   return nullptr;
 }
 
+bool IsJapaneseSettingsMigrationComplete(const PrefService& prefs) {
+  const base::Value::Dict* input_method_specific_pref_or_null =
+      GetJapaneseInputMethodSpecificSettings(prefs);
+  const base::Value::Dict empty_value;
+  const base::Value::Dict& input_method_specific_pref =
+      input_method_specific_pref_or_null ? *input_method_specific_pref_or_null
+                                         : empty_value;
+  const absl::optional<bool> value =
+      input_method_specific_pref.FindBool(kJapaneseMigrationCompleteKey);
+  return value.has_value() && *value;
+}
+
+void SetJapaneseSettingsMigrationComplete(PrefService& prefs, bool value) {
+  // To set just the migration flag, this copies the whole prefs object
+  // to change one entry - is_migrated, then re-set the whole
+  // InputMethodSpecificPrefs object.  Maybe there is a better way to do this?
+  const base::Value::Dict* input_method_specific_pref_or_null =
+      GetJapaneseInputMethodSpecificSettings(prefs);
+
+  base::Value::Dict japanese_settings =
+      (input_method_specific_pref_or_null != nullptr)
+          ? input_method_specific_pref_or_null->Clone()
+          : base::Value::Dict();
+  japanese_settings.Set(kJapaneseMigrationCompleteKey, value);
+
+  base::Value::Dict all_input_method_prefs =
+      prefs.GetDict(::prefs::kLanguageInputMethodSpecificSettings).Clone();
+  all_input_method_prefs.Set(kJapaneseEngineId, std::move(japanese_settings));
+
+  prefs.SetDict(::prefs::kLanguageInputMethodSpecificSettings,
+                std::move(all_input_method_prefs));
+}
+
+// Migrate the settings to the prefs service and mark the migration as
+// completed.
+void MigrateJapaneseSettingsToPrefs(PrefService& prefs,
+                                    ime::mojom::JapaneseConfig config) {
+  const base::Value::Dict* input_method_specific_pref_or_null =
+      GetJapaneseInputMethodSpecificSettings(prefs);
+  base::Value::Dict japanese_settings =
+      (input_method_specific_pref_or_null != nullptr)
+          ? input_method_specific_pref_or_null->Clone()
+          : base::Value::Dict();
+
+  // Health check. This code should never be called if the migration has already
+  // happened.
+  CHECK(!japanese_settings.FindBool(kJapaneseMigrationCompleteKey));
+
+  japanese_settings.Merge(ConvertConfigToJapaneseSettings(config));
+
+  // Mark the Migration as completed.
+  japanese_settings.Set(kJapaneseMigrationCompleteKey, true);
+
+  // Set the config
+  base::Value::Dict all_input_method_prefs =
+      prefs.GetDict(::prefs::kLanguageInputMethodSpecificSettings).Clone();
+  all_input_method_prefs.Set(kJapaneseEngineId, std::move(japanese_settings));
+
+  prefs.SetDict(::prefs::kLanguageInputMethodSpecificSettings,
+                std::move(all_input_method_prefs));
+}
+
 }  // namespace input_method
 }  // namespace ash
diff --git a/chrome/browser/ash/input_method/input_method_settings.h b/chrome/browser/ash/input_method/input_method_settings.h
index 05eaad1..996dba7e 100644
--- a/chrome/browser/ash/input_method/input_method_settings.h
+++ b/chrome/browser/ash/input_method/input_method_settings.h
@@ -15,6 +15,13 @@
     const PrefService& prefs,
     const std::string& engine_id);
 
+bool IsJapaneseSettingsMigrationComplete(const PrefService& prefs);
+
+void SetJapaneseSettingsMigrationComplete(PrefService& prefs, bool value);
+
+void MigrateJapaneseSettingsToPrefs(PrefService& prefs,
+                                    ime::mojom::JapaneseConfig config);
+
 }  // namespace input_method
 }  // namespace ash
 
diff --git a/chrome/browser/ash/input_method/input_method_settings_unittest.cc b/chrome/browser/ash/input_method/input_method_settings_unittest.cc
index 1647f7b..1096031 100644
--- a/chrome/browser/ash/input_method/input_method_settings_unittest.cc
+++ b/chrome/browser/ash/input_method/input_method_settings_unittest.cc
@@ -8,8 +8,11 @@
 #include "ash/constants/ash_pref_names.h"
 #include "base/feature_list.h"
 #include "base/strings/strcat.h"
+#include "base/test/gtest_util.h"
 #include "base/test/scoped_feature_list.h"
 #include "chrome/common/pref_names.h"
+#include "chromeos/ash/services/ime/public/mojom/input_method.mojom-shared.h"
+#include "chromeos/ash/services/ime/public/mojom/japanese_settings.mojom.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/testing_pref_service.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -26,6 +29,60 @@
 constexpr char kPinyinEngineId[] = "zh-t-i0-pinyin";
 constexpr char kZhuyinEngineId[] = "zh-hant-t-i0-und";
 
+constexpr char kJapaneseEngineId[] = "nacl_mozc_jp";
+
+// This should be kept in sync with the values on the settings page's
+// InputMethodOptions. This should match
+// https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/resources/settings/chromeos/os_languages_page/input_method_util.js;l=71-88;drc=6c88edbfe6096489ccac66b3ef5c84d479892181.
+constexpr char kJapaneseInputMode[] = "JapaneseInputMode";
+constexpr char kJapanesePunctuationStyle[] = "JapanesePunctuationStyle";
+constexpr char kJapaneseSymbolStyle[] = "JapaneseSymbolStyle";
+constexpr char kJapaneseSpaceInputStyle[] = "JapaneseSpaceInputStyle";
+constexpr char kJapaneseSelectionShortcut[] = "JapaneseSectionShortcut";
+constexpr char kJapaneseKeymapStyle[] = "JapaneseKeymapStyle";
+constexpr char kJapaneseUseInputHistory[] = "UseInputHistory";
+constexpr char kJapaneseUseSystemDictionary[] = "UseSystemDictionary";
+constexpr char kJapaneseNumberOfSuggestions[] = "numberOfSuggestions";
+constexpr char kJapaneseAutomaticallySwitchToHalfwidth[] =
+    "AutomaticallySwitchToHalfwidth";
+constexpr char kJapaneseShiftKeyModeStyle[] = "ShiftKeyModeStyle";
+constexpr char kJapaneseDisablePersonalizedSuggestions[] =
+    "JapaneseDisableSuggestions";
+constexpr char kJapaneseAutomaticallySendStatisticsToGoogle[] =
+    "AutomaticallySendStatisticsToGoogle";
+
+// This should match the strings listed here:
+//
+// https://crsrc.org/c/chrome/browser/resources/settings/chromeos/os_languages_page/input_method_types.js;l=8-71;drc=7df206933530e6ac65a7e17a88757cbb780c829e
+// These are possible values for their corresponding enum type.
+constexpr char kJapaneseInputModeKana[] = "Kana";
+constexpr char kJapaneseInputModeRomaji[] = "Romaji";
+constexpr char kJapanesePunctuationStyleKutenTouten[] = "KutenTouten";
+constexpr char kJapanesePunctuationStyleCommaPeriod[] = "CommaPeriod";
+constexpr char kJapanesePunctuationStyleKutenPeriod[] = "KutenPeriod";
+constexpr char kJapanesePunctuationStyleCommaTouten[] = "CommaTouten";
+constexpr char kJapaneseSymbolStyleCornerBracketMiddleDot[] =
+    "CornerBracketMiddleDot";
+constexpr char kJapaneseSymbolStyleSquareBracketSlash[] = "SquareBracketSlash";
+constexpr char kJapaneseSymbolStyleCornerBracketSlash[] = "CornerBracketSlash";
+constexpr char kJapaneseSymbolStyleSquareBracketMiddleDot[] =
+    "SquareBracketMiddleDot";
+constexpr char kJapaneseSpaceInputStyleInputMode[] = "InputMode";
+constexpr char kJapaneseSpaceInputStyleFullwidth[] = "Fullwidth";
+constexpr char kJapaneseSpaceInputStyleHalfwidth[] = "Halfwidth";
+constexpr char kJapaneseSelectionShortcutNoShortcut[] = "NoShortcut";
+constexpr char kJapaneseSelectionShortcutDigits123456789[] = "Digits123456789";
+constexpr char kJapaneseSelectionShortcutAsdfghjkl[] = "ASDFGHJKL";
+constexpr char kJapaneseKeymapStyleCustom[] = "Custom";
+constexpr char kJapaneseKeymapStyleAtok[] = "Atok";
+constexpr char kJapaneseKeymapStyleMsIme[] = "MsIme";
+constexpr char kJapaneseKeymapStyleKotoeri[] = "Kotoeri";
+constexpr char kJapaneseKeymapStyleMobile[] = "Mobile";
+constexpr char kJapaneseKeymapStyleChromeOs[] = "ChromeOs";
+constexpr char kJapaneseShiftKeyModeStyleOff[] = "Off";
+constexpr char kJapaneseShiftKeyModeStyleAlphanumeric[] = "Alphanumeric";
+constexpr char kJapaneseShiftKeyModeStyleKatakana[] = "Katakana";
+
 void RegisterTestingPrefs(TestingPrefServiceSimple& prefs,
                           const base::DictionaryValue& dict) {
   prefs.registry()->RegisterDictionaryPref(
@@ -46,6 +103,471 @@
   EXPECT_FALSE(latin_settings.predictive_writing);
 }
 
+class SetJapanesePrefsFromSettingsTest : public ::testing::Test {
+ protected:
+  void SetUp() override { RegisterTestingPrefs(prefs, dict); }
+
+ public:
+  const base::Value::Dict* GetJapaneseDict() {
+    return prefs.GetDict(::prefs::kLanguageInputMethodSpecificSettings)
+        .FindDict(kJapaneseEngineId);
+  }
+
+  base::DictionaryValue dict;
+  TestingPrefServiceSimple prefs;
+};
+
+TEST_F(SetJapanesePrefsFromSettingsTest,
+       JapaneseMigrationIsNotCompleteByDefault) {
+  EXPECT_FALSE(IsJapaneseSettingsMigrationComplete(prefs));
+}
+
+TEST_F(SetJapanesePrefsFromSettingsTest, SetJapaneseMigrationDone) {
+  SetJapaneseSettingsMigrationComplete(prefs, true);
+
+  EXPECT_TRUE(IsJapaneseSettingsMigrationComplete(prefs));
+}
+
+TEST_F(SetJapanesePrefsFromSettingsTest, SetJapaneseMigrationToFalse) {
+  SetJapaneseSettingsMigrationComplete(prefs, true);
+  SetJapaneseSettingsMigrationComplete(prefs, false);
+
+  EXPECT_FALSE(IsJapaneseSettingsMigrationComplete(prefs));
+}
+
+TEST_F(SetJapanesePrefsFromSettingsTest,
+       SetJapaneseSettingsIfMigratedCausesDeath) {
+  SetJapaneseSettingsMigrationComplete(prefs, true);
+  mojom::JapaneseConfig config;
+
+  EXPECT_CHECK_DEATH(MigrateJapaneseSettingsToPrefs(prefs, config));
+}
+
+TEST_F(SetJapanesePrefsFromSettingsTest,
+       SetJapaneseSettingsWillMarkMigrationAsDone) {
+  mojom::JapaneseConfig config;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+
+  EXPECT_TRUE(IsJapaneseSettingsMigrationComplete(prefs));
+}
+
+// Test Japanese settings persistence
+// Test input mode is set.
+
+TEST_F(SetJapanesePrefsFromSettingsTest, SetJapaneseInputModeToRomaji) {
+  mojom::JapaneseConfig config;
+  config.input_mode = mojom::InputMode::kRomaji;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+
+  EXPECT_EQ(*(result_dict->FindString(kJapaneseInputMode)),
+            std::string(kJapaneseInputModeRomaji));
+}
+
+TEST_F(SetJapanesePrefsFromSettingsTest, SetJapaneseInputModeToKana) {
+  mojom::JapaneseConfig config;
+  config.input_mode = mojom::InputMode::kKana;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_EQ(*(result_dict->FindString(kJapaneseInputMode)),
+            std::string(kJapaneseInputModeKana));
+}
+
+// Test Punctuation style is set.
+TEST_F(SetJapanesePrefsFromSettingsTest,
+       SetJapanesePunctuationStyleToKutenTouten) {
+  mojom::JapaneseConfig config;
+  config.punctuation_style = mojom::PunctuationStyle::kKutenTouten;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_EQ(*(result_dict->FindString(kJapanesePunctuationStyle)),
+            std::string(kJapanesePunctuationStyleKutenTouten));
+}
+
+TEST_F(SetJapanesePrefsFromSettingsTest,
+       SetJapanesePunctuationStyleToCommaPeriod) {
+  mojom::JapaneseConfig config;
+  config.punctuation_style = mojom::PunctuationStyle::kCommaPeriod;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_EQ(*(result_dict->FindString(kJapanesePunctuationStyle)),
+            std::string(kJapanesePunctuationStyleCommaPeriod));
+}
+
+TEST_F(SetJapanesePrefsFromSettingsTest,
+       SetJapanesePunctuationStyleToKutenPeriod) {
+  mojom::JapaneseConfig config;
+  config.punctuation_style = mojom::PunctuationStyle::kKutenPeriod;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_EQ(*(result_dict->FindString(kJapanesePunctuationStyle)),
+            std::string(kJapanesePunctuationStyleKutenPeriod));
+}
+
+TEST_F(SetJapanesePrefsFromSettingsTest,
+       SetJapanesePunctuationStyleToCommaTouten) {
+  mojom::JapaneseConfig config;
+  config.punctuation_style = mojom::PunctuationStyle::kCommaTouten;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_EQ(*(result_dict->FindString(kJapanesePunctuationStyle)),
+            std::string(kJapanesePunctuationStyleCommaTouten));
+}
+
+// Test symbol style is set.
+
+TEST_F(SetJapanesePrefsFromSettingsTest,
+       SetJapaneseSymbolStyleToCornerBracketMiddleDot) {
+  mojom::JapaneseConfig config;
+  config.symbol_style = mojom::SymbolStyle::kCornerBracketMiddleDot;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_EQ(*(result_dict->FindString(kJapaneseSymbolStyle)),
+            std::string(kJapaneseSymbolStyleCornerBracketMiddleDot));
+}
+
+TEST_F(SetJapanesePrefsFromSettingsTest,
+       SetJapaneseSymbolStyleToSquareBracketSlash) {
+  mojom::JapaneseConfig config;
+  config.symbol_style = mojom::SymbolStyle::kSquareBracketSlash;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_EQ(*(result_dict->FindString(kJapaneseSymbolStyle)),
+            std::string(kJapaneseSymbolStyleSquareBracketSlash));
+}
+
+TEST_F(SetJapanesePrefsFromSettingsTest,
+       SetJapaneseSymbolStyleToCornerBracketSlash) {
+  mojom::JapaneseConfig config;
+  config.symbol_style = mojom::SymbolStyle::kCornerBracketSlash;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_EQ(*(result_dict->FindString(kJapaneseSymbolStyle)),
+            std::string(kJapaneseSymbolStyleCornerBracketSlash));
+}
+
+TEST_F(SetJapanesePrefsFromSettingsTest,
+       SetJapaneseSymbolStyleToSquareBracketMiddleDot) {
+  mojom::JapaneseConfig config;
+  config.symbol_style = mojom::SymbolStyle::kSquareBracketMiddleDot;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_EQ(*(result_dict->FindString(kJapaneseSymbolStyle)),
+            std::string(kJapaneseSymbolStyleSquareBracketMiddleDot));
+}
+
+// Test setting space input style.
+
+TEST_F(SetJapanesePrefsFromSettingsTest,
+       SetJapaneseSpaceInputStyleToInputMode) {
+  mojom::JapaneseConfig config;
+  config.space_input_style = mojom::SpaceInputStyle::kInputMode;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_EQ(*(result_dict->FindString(kJapaneseSpaceInputStyle)),
+            std::string(kJapaneseSpaceInputStyleInputMode));
+}
+
+TEST_F(SetJapanesePrefsFromSettingsTest,
+       SetJapaneseSpaceInputStyleToFullwidth) {
+  mojom::JapaneseConfig config;
+  config.space_input_style = mojom::SpaceInputStyle::kFullwidth;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_EQ(*(result_dict->FindString(kJapaneseSpaceInputStyle)),
+            std::string(kJapaneseSpaceInputStyleFullwidth));
+}
+
+TEST_F(SetJapanesePrefsFromSettingsTest,
+       SetJapaneseSpaceInputStyleToHalfwidth) {
+  mojom::JapaneseConfig config;
+  config.space_input_style = mojom::SpaceInputStyle::kHalfwidth;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_EQ(*(result_dict->FindString(kJapaneseSpaceInputStyle)),
+            std::string(kJapaneseSpaceInputStyleHalfwidth));
+}
+
+// Test Japanese selection shortcut.
+
+TEST_F(SetJapanesePrefsFromSettingsTest,
+       SetJapaneseSelectionShortcutToNoShortcut) {
+  mojom::JapaneseConfig config;
+  config.selection_shortcut = mojom::SelectionShortcut::kNoShortcut;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_EQ(*(result_dict->FindString(kJapaneseSelectionShortcut)),
+            std::string(kJapaneseSelectionShortcutNoShortcut));
+}
+
+TEST_F(SetJapanesePrefsFromSettingsTest,
+       SetJapaneseSelectionShortcutToDigits123456789) {
+  mojom::JapaneseConfig config;
+  config.selection_shortcut = mojom::SelectionShortcut::kDigits123456789;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_EQ(*(result_dict->FindString(kJapaneseSelectionShortcut)),
+            std::string(kJapaneseSelectionShortcutDigits123456789));
+}
+
+TEST_F(SetJapanesePrefsFromSettingsTest,
+       SetJapaneseSelectionShortcutToAsdfghjkl) {
+  mojom::JapaneseConfig config;
+  config.selection_shortcut = mojom::SelectionShortcut::kAsdfghjkl;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_EQ(*(result_dict->FindString(kJapaneseSelectionShortcut)),
+            std::string(kJapaneseSelectionShortcutAsdfghjkl));
+}
+
+// Test Japanese keymap style.
+
+TEST_F(SetJapanesePrefsFromSettingsTest, SetJapaneseKeymapStyleToCustom) {
+  mojom::JapaneseConfig config;
+  config.keymap_style = mojom::KeymapStyle::kCustom;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_EQ(*(result_dict->FindString(kJapaneseKeymapStyle)),
+            std::string(kJapaneseKeymapStyleCustom));
+}
+
+TEST_F(SetJapanesePrefsFromSettingsTest, SetJapaneseKeymapStyleToAtok) {
+  mojom::JapaneseConfig config;
+  config.keymap_style = mojom::KeymapStyle::kAtok;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_EQ(*(result_dict->FindString(kJapaneseKeymapStyle)),
+            std::string(kJapaneseKeymapStyleAtok));
+}
+
+TEST_F(SetJapanesePrefsFromSettingsTest, SetJapaneseKeymapStyleToMsIme) {
+  mojom::JapaneseConfig config;
+  config.keymap_style = mojom::KeymapStyle::kMsIme;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_EQ(*(result_dict->FindString(kJapaneseKeymapStyle)),
+            std::string(kJapaneseKeymapStyleMsIme));
+}
+
+TEST_F(SetJapanesePrefsFromSettingsTest, SetJapaneseKeymapStyleToKotoeri) {
+  mojom::JapaneseConfig config;
+  config.keymap_style = mojom::KeymapStyle::kKotoeri;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_EQ(*(result_dict->FindString(kJapaneseKeymapStyle)),
+            std::string(kJapaneseKeymapStyleKotoeri));
+}
+
+TEST_F(SetJapanesePrefsFromSettingsTest, SetJapaneseKeymapStyleToMobile) {
+  mojom::JapaneseConfig config;
+  config.keymap_style = mojom::KeymapStyle::kMobile;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_EQ(*(result_dict->FindString(kJapaneseKeymapStyle)),
+            std::string(kJapaneseKeymapStyleMobile));
+}
+
+TEST_F(SetJapanesePrefsFromSettingsTest, SetJapaneseKeymapStyleToChromeOs) {
+  mojom::JapaneseConfig config;
+  config.keymap_style = mojom::KeymapStyle::kChromeOs;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_EQ(*(result_dict->FindString(kJapaneseKeymapStyle)),
+            std::string(kJapaneseKeymapStyleChromeOs));
+}
+
+// Test automatically switch to halfwidth.
+
+TEST_F(SetJapanesePrefsFromSettingsTest,
+       SetAutomaticallySwitchToHalfwitdhToTrue) {
+  mojom::JapaneseConfig config;
+  config.automatically_switch_to_halfwidth = true;
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_TRUE(*result_dict->FindBool(kJapaneseAutomaticallySwitchToHalfwidth));
+}
+
+TEST_F(SetJapanesePrefsFromSettingsTest,
+       SetAutomaticallySwitchToHalfwitdhToFalse) {
+  mojom::JapaneseConfig config;
+  config.automatically_switch_to_halfwidth = false;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_FALSE(*result_dict->FindBool(kJapaneseAutomaticallySwitchToHalfwidth));
+}
+
+// Test Japanese shift key mode switch.
+
+TEST_F(SetJapanesePrefsFromSettingsTest, SetJapaneseShiftKeyModeStyleToOff) {
+  mojom::JapaneseConfig config;
+  config.shift_key_mode_switch = mojom::ShiftKeyModeSwitch::kOff;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_EQ(*(result_dict->FindString(kJapaneseShiftKeyModeStyle)),
+            std::string(kJapaneseShiftKeyModeStyleOff));
+}
+
+TEST_F(SetJapanesePrefsFromSettingsTest,
+       SetJapaneseShiftKeyModeStyleToAlphanumeric) {
+  mojom::JapaneseConfig config;
+  config.shift_key_mode_switch = mojom::ShiftKeyModeSwitch::kAlphanumeric;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_EQ(*(result_dict->FindString(kJapaneseShiftKeyModeStyle)),
+            std::string(kJapaneseShiftKeyModeStyleAlphanumeric));
+}
+
+TEST_F(SetJapanesePrefsFromSettingsTest,
+       SetJapaneseShiftKeyModeStyleToKatakana) {
+  mojom::JapaneseConfig config;
+  config.shift_key_mode_switch = mojom::ShiftKeyModeSwitch::kKatakana;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_EQ(*(result_dict->FindString(kJapaneseShiftKeyModeStyle)),
+            std::string(kJapaneseShiftKeyModeStyleKatakana));
+}
+
+// Test Japanese use input history.
+
+TEST_F(SetJapanesePrefsFromSettingsTest, SetUseInputHistoryToTrue) {
+  mojom::JapaneseConfig config;
+  config.use_input_history = true;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_TRUE(*result_dict->FindBool(kJapaneseUseInputHistory));
+}
+
+TEST_F(SetJapanesePrefsFromSettingsTest, SetUseInputHistoryToFalse) {
+  mojom::JapaneseConfig config;
+  config.use_input_history = false;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_FALSE(*result_dict->FindBool(kJapaneseUseInputHistory));
+}
+
+// Test use system dictionary.
+
+TEST_F(SetJapanesePrefsFromSettingsTest, SetUseSystemDictionaryToTrue) {
+  mojom::JapaneseConfig config;
+  config.use_system_dictionary = true;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_TRUE(*result_dict->FindBool(kJapaneseUseSystemDictionary));
+}
+
+TEST_F(SetJapanesePrefsFromSettingsTest, SetUseSystemDictionaryToFalse) {
+  mojom::JapaneseConfig config;
+  config.use_system_dictionary = false;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_FALSE(*result_dict->FindBool(kJapaneseUseSystemDictionary));
+}
+
+// Test number of suggestions.
+
+TEST_F(SetJapanesePrefsFromSettingsTest, SetNumberOfSuggestionsTo1) {
+  mojom::JapaneseConfig config;
+  config.number_of_suggestions = 1;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_EQ(*result_dict->FindInt(kJapaneseNumberOfSuggestions), 1);
+}
+
+TEST_F(SetJapanesePrefsFromSettingsTest, SetNumberOfSuggestionsTo5) {
+  mojom::JapaneseConfig config;
+  config.number_of_suggestions = 5;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_EQ(*result_dict->FindInt(kJapaneseNumberOfSuggestions), 5);
+}
+
+TEST_F(SetJapanesePrefsFromSettingsTest, SetNumberOfSuggestionsTo9) {
+  mojom::JapaneseConfig config;
+  config.number_of_suggestions = 9;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_EQ(*result_dict->FindInt(kJapaneseNumberOfSuggestions), 9);
+}
+// Test disable personalized suggestions.
+
+TEST_F(SetJapanesePrefsFromSettingsTest,
+       SetDisablePersonalizedSuggestionsToTrue) {
+  mojom::JapaneseConfig config;
+  config.disable_personalized_suggestions = true;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_TRUE(*result_dict->FindBool(kJapaneseDisablePersonalizedSuggestions));
+}
+
+TEST_F(SetJapanesePrefsFromSettingsTest,
+       SetDisablePersonalizedSuggestionsToFalse) {
+  mojom::JapaneseConfig config;
+  config.disable_personalized_suggestions = false;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_FALSE(*result_dict->FindBool(kJapaneseDisablePersonalizedSuggestions));
+}
+
+// Test sending statistics to Google.
+
+TEST_F(SetJapanesePrefsFromSettingsTest, SetSendStatisticsToGoogleToTrue) {
+  mojom::JapaneseConfig config;
+  config.send_statistics_to_google = true;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_TRUE(
+      *result_dict->FindBool(kJapaneseAutomaticallySendStatisticsToGoogle));
+}
+
+TEST_F(SetJapanesePrefsFromSettingsTest, SetSendStatisticsToGoogleToFalse) {
+  mojom::JapaneseConfig config;
+  config.send_statistics_to_google = false;
+
+  MigrateJapaneseSettingsToPrefs(prefs, std::move(config));
+  const base::Value::Dict* result_dict = GetJapaneseDict();
+  EXPECT_FALSE(
+      *result_dict->FindBool(kJapaneseAutomaticallySendStatisticsToGoogle));
+}
+
+// End of Japanese tests
+
 TEST(CreateSettingsFromPrefsTest, CreateLatinSettings) {
   base::test::ScopedFeatureList features;
   features.InitWithFeatures({features::kAssistMultiWord}, {});
diff --git a/chrome/browser/ash/input_method/longpress_diacritics_suggester.cc b/chrome/browser/ash/input_method/longpress_diacritics_suggester.cc
index 8d5bdb2..562f9ee 100644
--- a/chrome/browser/ash/input_method/longpress_diacritics_suggester.cc
+++ b/chrome/browser/ash/input_method/longpress_diacritics_suggester.cc
@@ -32,7 +32,14 @@
                            base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
 }
 
-std::vector<std::u16string> GetDiacriticsFor(char key_character) {
+std::vector<std::u16string> GetDiacriticsFor(char key_character,
+                                             base::StringPiece engine_id) {
+  // Currently only supporting US English.
+  // TODO(b/260915965): Add support for other engines.
+  if (engine_id != "xkb:us::eng") {
+    return {};
+  }
+
   // Current diacritics ordering is based on the Gboard ordering so it keeps
   // distance from target key consistent.
   // TODO(b/260915965): Add more sets here for other engines.
@@ -108,7 +115,7 @@
     return false;
   }
   std::vector<std::u16string> diacritics_candidates =
-      GetDiacriticsFor(key_character);
+      GetDiacriticsFor(key_character, engine_id_);
   if (!diacritics_candidates.empty()) {
     AssistiveWindowProperties properties;
     properties.type =
@@ -131,6 +138,10 @@
   return false;
 }
 
+void LongpressDiacriticsSuggester::SetEngineId(const std::string& engine_id) {
+  engine_id_ = engine_id;
+}
+
 void LongpressDiacriticsSuggester::OnFocus(int context_id) {
   Reset();
   focused_context_id_ = context_id;
@@ -324,7 +335,7 @@
   if (displayed_window_base_character_ == absl::nullopt) {
     return {};
   }
-  return GetDiacriticsFor(*displayed_window_base_character_);
+  return GetDiacriticsFor(*displayed_window_base_character_, engine_id_);
 }
 
 void LongpressDiacriticsSuggester::Reset() {
diff --git a/chrome/browser/ash/input_method/longpress_diacritics_suggester.h b/chrome/browser/ash/input_method/longpress_diacritics_suggester.h
index 889575ec..4726ebf4 100644
--- a/chrome/browser/ash/input_method/longpress_diacritics_suggester.h
+++ b/chrome/browser/ash/input_method/longpress_diacritics_suggester.h
@@ -44,6 +44,7 @@
   ~LongpressDiacriticsSuggester() override;
 
   bool TrySuggestOnLongpress(char key_character);
+  void SetEngineId(const std::string& engine_id);
 
   // Suggester overrides:
   void OnFocus(int context_id) override;
@@ -70,6 +71,8 @@
   absl::optional<char> displayed_window_base_character_;
   // Highlighted index can be nullopt even if window displayed.
   absl::optional<size_t> highlighted_index_;
+  // Current engine id
+  std::string engine_id_ = "";
 };
 
 }  // namespace input_method
diff --git a/chrome/browser/ash/input_method/longpress_diacritics_suggester_unittest.cc b/chrome/browser/ash/input_method/longpress_diacritics_suggester_unittest.cc
index c2f7620..a43d0ad 100644
--- a/chrome/browser/ash/input_method/longpress_diacritics_suggester_unittest.cc
+++ b/chrome/browser/ash/input_method/longpress_diacritics_suggester_unittest.cc
@@ -35,7 +35,7 @@
 using AssistiveWindowButton = ui::ime::AssistiveWindowButton;
 
 const int kContextId = 24601;
-
+const char kUSEngineId[] = "xkb:us::eng";
 const auto kDigitToDomCode = base::MakeFixedFlatMap<int, ui::DomCode>({
     {0, ui::DomCode::DIGIT0},
     {1, ui::DomCode::DIGIT1},
@@ -86,6 +86,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -101,6 +102,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -111,10 +113,24 @@
       GetParam().invalid_surrounding_text.size()));
 }
 
+TEST_P(LongpressDiacriticsSuggesterTest, DoesNotSuggestForInvalidEngineId) {
+  FakeSuggestionHandler suggestion_handler;
+  LongpressDiacriticsSuggester suggester =
+      LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId("xkb::someunsupportedengine");
+  suggester.OnFocus(kContextId);
+
+  suggester.TrySuggestOnLongpress('a');
+
+  EXPECT_FALSE(suggestion_handler.GetShowingSuggestion());
+  EXPECT_EQ(suggestion_handler.GetSuggestionText(), u"");
+}
+
 TEST_P(LongpressDiacriticsSuggesterTest, DoesNotSuggestForInvalidKeyChar) {
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress('~');  // Char doesn't have diacritics.
@@ -127,6 +143,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.OnBlur();
@@ -140,6 +157,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -159,6 +177,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -179,6 +198,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -201,6 +221,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -223,6 +244,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -244,6 +266,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -267,6 +290,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -288,6 +312,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
   suggester.HandleKeyEvent(CreateKeyEventFromCode(ui::DomCode::ARROW_RIGHT));
@@ -312,6 +337,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
   suggester.HandleKeyEvent(CreateKeyEventFromCode(ui::DomCode::ARROW_RIGHT));
@@ -335,6 +361,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
   suggester.HandleKeyEvent(CreateKeyEventFromCode(ui::DomCode::ARROW_RIGHT));
@@ -358,6 +385,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(1);
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
   suggester.HandleKeyEvent(CreateKeyEventFromCode(ui::DomCode::ARROW_RIGHT));
@@ -380,6 +408,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -397,6 +426,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -410,6 +440,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -426,6 +457,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -447,6 +479,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -468,6 +501,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -489,6 +523,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -510,6 +545,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -531,6 +567,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -552,6 +589,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -574,6 +612,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -587,6 +626,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -603,6 +643,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -619,6 +660,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -637,6 +679,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -653,6 +696,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   EXPECT_EQ(suggester.GetProposeActionType(),
@@ -665,6 +709,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   int histogram_accept_count = 0;
@@ -690,6 +735,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -704,6 +750,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -719,6 +766,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -735,6 +783,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -750,6 +799,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -765,6 +815,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -783,6 +834,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -801,6 +853,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
@@ -819,6 +872,7 @@
   FakeSuggestionHandler suggestion_handler;
   LongpressDiacriticsSuggester suggester =
       LongpressDiacriticsSuggester(&suggestion_handler);
+  suggester.SetEngineId(kUSEngineId);
   suggester.OnFocus(kContextId);
 
   suggester.TrySuggestOnLongpress(GetParam().longpress_char);
diff --git a/chrome/browser/ash/input_method/native_input_method_engine_observer.cc b/chrome/browser/ash/input_method/native_input_method_engine_observer.cc
index efef14a..8e82e3a 100644
--- a/chrome/browser/ash/input_method/native_input_method_engine_observer.cc
+++ b/chrome/browser/ash/input_method/native_input_method_engine_observer.cc
@@ -29,6 +29,7 @@
 #include "chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom.h"
 #include "chrome/common/pref_names.h"
 #include "chromeos/ash/services/ime/public/mojom/input_method.mojom.h"
+#include "chromeos/ash/services/ime/public/mojom/japanese_settings.mojom.h"
 #include "components/prefs/pref_service.h"
 #include "ui/base/ime/ash/extension_ime_util.h"
 #include "ui/base/ime/ash/ime_bridge.h"
@@ -616,6 +617,28 @@
   connection_factory_.reset();
 }
 
+void NativeInputMethodEngineObserver::OnJapaneseSettingsReceived(
+    ime::mojom::JapaneseConfigPtr config) {
+  MigrateJapaneseSettingsToPrefs(*prefs_, *config);
+}
+
+void NativeInputMethodEngineObserver::OnJapaneseDecoderConnected(bool bound) {
+  if (!bound) {
+    return;
+  }
+  if (!base::FeatureList::IsEnabled(features::kSystemJapanesePhysicalTyping) &&
+      IsJapaneseSettingsMigrationComplete(*prefs_)) {
+    SetJapaneseSettingsMigrationComplete(*prefs_, false);
+    return;
+  }
+  if (IsJapaneseSettingsMigrationComplete(*prefs_)) {
+    return;
+  }
+  japanese_decoder_->FetchJapaneseConfig(base::BindOnce(
+      &NativeInputMethodEngineObserver::OnJapaneseSettingsReceived,
+      weak_ptr_factory_.GetWeakPtr()));
+}
+
 void NativeInputMethodEngineObserver::ConnectToImeService(
     mojom::ConnectionTarget connection_target,
     const std::string& engine_id) {
@@ -631,6 +654,8 @@
   // Deactivate any existing engine.
   connection_factory_.reset();
   input_method_.reset();
+  // Always reconnect the Japanese decoder.
+  japanese_decoder_.reset();
   host_receiver_.reset();
 
   remote_manager_->InitializeConnectionFactory(
@@ -638,6 +663,22 @@
       base::BindOnce(&NativeInputMethodEngineObserver::OnConnectionFactoryBound,
                      weak_ptr_factory_.GetWeakPtr()));
 
+  // TODO(b/232341104): Add metrics to track how long this takes to init the
+  // connection.
+  connection_factory_->ConnectToJapaneseDecoder(
+      japanese_decoder_.BindNewEndpointAndPassReceiver(),
+      base::BindOnce(
+          &NativeInputMethodEngineObserver::OnJapaneseDecoderConnected,
+          weak_ptr_factory_.GetWeakPtr()));
+  // If this is fast enough, maybe this code can block the ConnectToInputMethod
+  // function on waiting for the migration if and only if the input_method
+  // engine is JP.
+  // TODO(b/232341104): Once sending Japanese settings in ConnectToInputMethod
+  // is supported, add the functionality to send it over using the
+  // JapaneseSettings mojom object. Ideally this should only be done after we
+  // have waited for the connection to the Japanese decoder and have finished
+  // the migration.
+
   mojo::PendingAssociatedRemote<ime::mojom::InputMethodHost> input_method_host;
   host_receiver_.Bind(input_method_host.InitWithNewEndpointAndPassReceiver());
 
diff --git a/chrome/browser/ash/input_method/native_input_method_engine_observer.h b/chrome/browser/ash/input_method/native_input_method_engine_observer.h
index 0f2e896..26bfb14 100644
--- a/chrome/browser/ash/input_method/native_input_method_engine_observer.h
+++ b/chrome/browser/ash/input_method/native_input_method_engine_observer.h
@@ -19,6 +19,7 @@
 #include "chromeos/ash/services/ime/public/mojom/input_engine.mojom.h"
 #include "chromeos/ash/services/ime/public/mojom/input_method.mojom.h"
 #include "chromeos/ash/services/ime/public/mojom/input_method_host.mojom.h"
+#include "chromeos/ash/services/ime/public/mojom/japanese_settings.mojom.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "components/prefs/pref_service.h"
 #include "mojo/public/cpp/bindings/associated_receiver.h"
@@ -158,6 +159,9 @@
   bool ShouldRouteToNativeMojoEngine(const std::string& engine_id) const;
 
   void OnConnectionFactoryBound(bool bound);
+
+  void OnJapaneseSettingsReceived(ime::mojom::JapaneseConfigPtr config);
+  void OnJapaneseDecoderConnected(bool bound);
   void ConnectToImeService(ime::mojom::ConnectionTarget connection_target,
                            const std::string& engine_id);
 
@@ -178,6 +182,9 @@
   mojo::Remote<ime::mojom::InputEngineManager> remote_manager_;
   mojo::Remote<ime::mojom::ConnectionFactory> connection_factory_;
   mojo::AssociatedRemote<ime::mojom::InputMethod> input_method_;
+  // TODO(b/232341104): Delete this connection once Japanese settings have been
+  // migrated completely
+  mojo::AssociatedRemote<ime::mojom::JapaneseDecoder> japanese_decoder_;
   mojo::AssociatedReceiver<ime::mojom::InputMethodHost> host_receiver_{this};
 
   std::unique_ptr<AssistiveSuggester> assistive_suggester_;
diff --git a/chrome/browser/ash/login/screens/gaia_password_changed_screen.cc b/chrome/browser/ash/login/screens/gaia_password_changed_screen.cc
index 5047f54..6bc7e66 100644
--- a/chrome/browser/ash/login/screens/gaia_password_changed_screen.cc
+++ b/chrome/browser/ash/login/screens/gaia_password_changed_screen.cc
@@ -18,13 +18,25 @@
 constexpr const char kUserActionResyncData[] = "resync";
 constexpr const char kUserActionMigrateUserData[] = "migrate-user-data";
 
-}  // namespace
-
-void RecordEulaScreenAction(GaiaPasswordChangedScreen::UserAction value) {
+void RecordScreenAction(GaiaPasswordChangedScreen::UserAction value) {
   base::UmaHistogramEnumeration("OOBE.GaiaPasswordChangedScreen.UserActions",
                                 value);
 }
 
+}  // namespace
+
+// static
+std::string GaiaPasswordChangedScreen::GetResultString(Result result) {
+  switch (result) {
+    case Result::CANCEL:
+      return "Cancel";
+    case Result::MIGRATE:
+      return "Migrate";
+    case Result::RESYNC:
+      return "Resync";
+  }
+}
+
 GaiaPasswordChangedScreen::GaiaPasswordChangedScreen(
     const ScreenExitCallback& exit_callback,
     base::WeakPtr<GaiaPasswordChangedView> view)
@@ -52,17 +64,17 @@
   account_id_ = account_id;
   show_error_ = after_incorrect_attempt;
   if (after_incorrect_attempt)
-    RecordEulaScreenAction(UserAction::kIncorrectOldPassword);
+    RecordScreenAction(UserAction::kIncorrectOldPassword);
 }
 
 void GaiaPasswordChangedScreen::OnUserAction(const base::Value::List& args) {
   const std::string& action_id = args[0].GetString();
 
   if (action_id == kUserActionCancelLogin) {
-    RecordEulaScreenAction(UserAction::kCancel);
+    RecordScreenAction(UserAction::kCancel);
     CancelPasswordChangedFlow();
   } else if (action_id == kUserActionResyncData) {
-    RecordEulaScreenAction(UserAction::kResyncUserData);
+    RecordScreenAction(UserAction::kResyncUserData);
     // LDH will pass control to ExistingUserController to proceed with clearing
     // cryptohome.
     exit_callback_.Run(Result::RESYNC);
@@ -77,11 +89,10 @@
 
 void GaiaPasswordChangedScreen::MigrateUserData(
     const std::string& old_password) {
-  RecordEulaScreenAction(UserAction::kMigrateUserData);
+  RecordScreenAction(UserAction::kMigrateUserData);
   // LDH will pass control to ExistingUserController to proceed with updating
   // cryptohome keys.
-  if (LoginDisplayHost::default_host())
-    LoginDisplayHost::default_host()->MigrateUserData(old_password);
+  LoginDisplayHost::default_host()->MigrateUserData(old_password);
 }
 
 void GaiaPasswordChangedScreen::CancelPasswordChangedFlow() {
diff --git a/chrome/browser/ash/login/screens/gaia_password_changed_screen.h b/chrome/browser/ash/login/screens/gaia_password_changed_screen.h
index 7578151..f222d31 100644
--- a/chrome/browser/ash/login/screens/gaia_password_changed_screen.h
+++ b/chrome/browser/ash/login/screens/gaia_password_changed_screen.h
@@ -27,6 +27,8 @@
     MIGRATE,
   };
 
+  static std::string GetResultString(Result result);
+
   using ScreenExitCallback = base::RepeatingCallback<void(Result result)>;
 
   explicit GaiaPasswordChangedScreen(
@@ -49,8 +51,6 @@
     kMaxValue = kIncorrectOldPassword
   };
 
-  void MigrateUserData(const std::string& old_password);
-
   void Configure(const AccountId& account_id, bool after_incorrect_attempt);
 
  private:
@@ -59,6 +59,7 @@
   void HideImpl() override;
   void OnUserAction(const base::Value::List& args) override;
 
+  void MigrateUserData(const std::string& old_password);
   void CancelPasswordChangedFlow();
   void OnCookiesCleared();
 
diff --git a/chrome/browser/ash/login/wizard_controller.cc b/chrome/browser/ash/login/wizard_controller.cc
index 6209daac5..7bfc622 100644
--- a/chrome/browser/ash/login/wizard_controller.cc
+++ b/chrome/browser/ash/login/wizard_controller.cc
@@ -1199,8 +1199,8 @@
 
 void WizardController::OnPasswordChangeScreenExit(
     GaiaPasswordChangedScreen::Result result) {
-  if (!LoginDisplayHost::default_host())
-    return;
+  OnScreenExit(GaiaPasswordChangedView::kScreenId,
+               GaiaPasswordChangedScreen::GetResultString(result));
   switch (result) {
     case GaiaPasswordChangedScreen::Result::CANCEL:
       LoginDisplayHost::default_host()->CancelPasswordChangedFlow();
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/apps/app_events_observer.cc b/chrome/browser/ash/policy/reporting/metrics_reporting/apps/app_events_observer.cc
index 58dc41a..9cdf76d 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/apps/app_events_observer.cc
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/apps/app_events_observer.cc
@@ -92,14 +92,12 @@
   MetricData metric_data;
   metric_data.mutable_event_data()->set_type(MetricEventType::APP_INSTALLED);
 
-  AppTelemetry* const app_telemetry_data =
-      metric_data.mutable_telemetry_data()->mutable_app_telemetry();
-  app_telemetry_data->set_app_id(app_id);
-  app_telemetry_data->set_app_type(
+  auto* const app_install_data = metric_data.mutable_telemetry_data()
+                                     ->mutable_app_telemetry()
+                                     ->mutable_app_install_data();
+  app_install_data->set_app_id(app_id);
+  app_install_data->set_app_type(
       ::apps::ConvertAppTypeToProtoApplicationType(app_type));
-
-  AppInstallData* const app_install_data =
-      app_telemetry_data->mutable_app_install_data();
   app_install_data->set_app_install_source(
       ::apps::ConvertInstallSourceToProtoApplicationInstallSource(
           app_install_source));
@@ -124,14 +122,12 @@
   MetricData metric_data;
   metric_data.mutable_event_data()->set_type(MetricEventType::APP_LAUNCHED);
 
-  AppTelemetry* const app_telemetry_data =
-      metric_data.mutable_telemetry_data()->mutable_app_telemetry();
-  app_telemetry_data->set_app_id(app_id);
-  app_telemetry_data->set_app_type(
+  auto* const app_launch_data = metric_data.mutable_telemetry_data()
+                                    ->mutable_app_telemetry()
+                                    ->mutable_app_launch_data();
+  app_launch_data->set_app_id(app_id);
+  app_launch_data->set_app_type(
       ::apps::ConvertAppTypeToProtoApplicationType(app_type));
-
-  AppLaunchData* const app_launch_data =
-      app_telemetry_data->mutable_app_launch_data();
   app_launch_data->set_app_launch_source(
       ::apps::ConvertLaunchSourceToProtoApplicationLaunchSource(
           app_launch_source));
@@ -151,14 +147,12 @@
   MetricData metric_data;
   metric_data.mutable_event_data()->set_type(MetricEventType::APP_UNINSTALLED);
 
-  AppTelemetry* const app_telemetry_data =
-      metric_data.mutable_telemetry_data()->mutable_app_telemetry();
-  app_telemetry_data->set_app_id(app_id);
-  app_telemetry_data->set_app_type(
+  auto* const app_uninstall_data = metric_data.mutable_telemetry_data()
+                                       ->mutable_app_telemetry()
+                                       ->mutable_app_uninstall_data();
+  app_uninstall_data->set_app_id(app_id);
+  app_uninstall_data->set_app_type(
       ::apps::ConvertAppTypeToProtoApplicationType(app_type));
-
-  AppUninstallData* const app_uninstall_data =
-      app_telemetry_data->mutable_app_uninstall_data();
   app_uninstall_data->set_app_uninstall_source(
       ::apps::ConvertUninstallSourceToProtoApplicationUninstallSource(
           app_uninstall_source));
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/apps/app_events_observer_unittest.cc b/chrome/browser/ash/policy/reporting/metrics_reporting/apps/app_events_observer_unittest.cc
index ed80a3b..d4517e07 100644
--- a/chrome/browser/ash/policy/reporting/metrics_reporting/apps/app_events_observer_unittest.cc
+++ b/chrome/browser/ash/policy/reporting/metrics_reporting/apps/app_events_observer_unittest.cc
@@ -139,17 +139,14 @@
     EXPECT_THAT(result.event_data().type(), Eq(MetricEventType::APP_INSTALLED));
     ASSERT_TRUE(result.has_telemetry_data());
     ASSERT_TRUE(result.telemetry_data().has_app_telemetry());
-
-    const AppTelemetry& app_telemetry_data =
-        result.telemetry_data().app_telemetry();
-    EXPECT_THAT(app_telemetry_data.app_id(), StrEq(app_id));
-    EXPECT_THAT(
-        app_telemetry_data.app_type(),
-        Eq(::apps::ApplicationType::APPLICATION_TYPE_STANDALONE_BROWSER));
-    ASSERT_TRUE(app_telemetry_data.has_app_install_data());
+    ASSERT_TRUE(result.telemetry_data().app_telemetry().has_app_install_data());
 
     const AppInstallData& app_install_data =
         result.telemetry_data().app_telemetry().app_install_data();
+    EXPECT_THAT(app_install_data.app_id(), StrEq(app_id));
+    EXPECT_THAT(
+        app_install_data.app_type(),
+        Eq(::apps::ApplicationType::APPLICATION_TYPE_STANDALONE_BROWSER));
     EXPECT_THAT(
         app_install_data.app_install_reason(),
         Eq(::apps::ApplicationInstallReason::APPLICATION_INSTALL_REASON_USER));
@@ -184,16 +181,13 @@
     EXPECT_THAT(result.event_data().type(), Eq(MetricEventType::APP_LAUNCHED));
     ASSERT_TRUE(result.has_telemetry_data());
     ASSERT_TRUE(result.telemetry_data().has_app_telemetry());
-
-    const AppTelemetry& app_telemetry_data =
-        result.telemetry_data().app_telemetry();
-    EXPECT_THAT(app_telemetry_data.app_id(), StrEq(kTestAppId));
-    EXPECT_THAT(app_telemetry_data.app_type(),
-                Eq(::apps::ApplicationType::APPLICATION_TYPE_ARC));
-    ASSERT_TRUE(app_telemetry_data.has_app_launch_data());
+    ASSERT_TRUE(result.telemetry_data().app_telemetry().has_app_launch_data());
 
     const AppLaunchData& app_launch_data =
         result.telemetry_data().app_telemetry().app_launch_data();
+    EXPECT_THAT(app_launch_data.app_id(), StrEq(kTestAppId));
+    EXPECT_THAT(app_launch_data.app_type(),
+                Eq(::apps::ApplicationType::APPLICATION_TYPE_ARC));
     EXPECT_THAT(app_launch_data.app_launch_source(),
                 Eq(::apps::ApplicationLaunchSource::
                        APPLICATION_LAUNCH_SOURCE_COMMAND_LINE));
@@ -222,16 +216,14 @@
                 Eq(MetricEventType::APP_UNINSTALLED));
     ASSERT_TRUE(result.has_telemetry_data());
     ASSERT_TRUE(result.telemetry_data().has_app_telemetry());
-
-    const AppTelemetry& app_telemetry_data =
-        result.telemetry_data().app_telemetry();
-    EXPECT_THAT(app_telemetry_data.app_id(), StrEq(kTestAppId));
-    EXPECT_THAT(app_telemetry_data.app_type(),
-                Eq(::apps::ApplicationType::APPLICATION_TYPE_ARC));
-    ASSERT_TRUE(app_telemetry_data.has_app_uninstall_data());
+    ASSERT_TRUE(
+        result.telemetry_data().app_telemetry().has_app_uninstall_data());
 
     const AppUninstallData& app_uninstall_data =
         result.telemetry_data().app_telemetry().app_uninstall_data();
+    EXPECT_THAT(app_uninstall_data.app_id(), StrEq(kTestAppId));
+    EXPECT_THAT(app_uninstall_data.app_type(),
+                Eq(::apps::ApplicationType::APPLICATION_TYPE_ARC));
     EXPECT_THAT(app_uninstall_data.app_uninstall_source(),
                 Eq(::apps::ApplicationUninstallSource::
                        APPLICATION_UNINSTALL_SOURCE_APP_LIST));
diff --git a/chrome/browser/ash/policy/status_collector/child_status_collector_browsertest.cc b/chrome/browser/ash/policy/status_collector/child_status_collector_browsertest.cc
index a65334b4..b4e72ad 100644
--- a/chrome/browser/ash/policy/status_collector/child_status_collector_browsertest.cc
+++ b/chrome/browser/ash/policy/status_collector/child_status_collector_browsertest.cc
@@ -28,6 +28,7 @@
 #include "chrome/browser/ash/child_accounts/time_limits/app_time_controller.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_time_limits_policy_builder.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_types.h"
+#include "chrome/browser/ash/login/demo_mode/demo_setup_controller.h"
 #include "chrome/browser/ash/login/users/mock_user_manager.h"
 #include "chrome/browser/ash/ownership/fake_owner_settings_service.h"
 #include "chrome/browser/ash/policy/status_collector/child_status_collector.h"
@@ -198,6 +199,13 @@
     std::unique_ptr<base::Environment> env(base::Environment::Create());
     env->SetVar("TZ", "UTC");
 
+    // This pref registration is temporarily added because crrev/c/4076557 makes
+    // SystemWebAppManager (which is instantiated during creation of a
+    // TestProfile) dependent on the kDemoModeConfig pref.
+    // TODO(b/260117078): Delete this line after the DemoModeConfig pref is
+    // deprecated.
+    ash::DemoSetupController::RegisterLocalStatePrefs(local_state_.registry());
+
     TestingBrowserProcess::GetGlobal()->SetLocalState(&local_state_);
 
     // Use FakeUpdateEngineClient.
diff --git a/chrome/browser/ash/policy/status_collector/device_status_collector_browsertest.cc b/chrome/browser/ash/policy/status_collector/device_status_collector_browsertest.cc
index dca174d..149e99c 100644
--- a/chrome/browser/ash/policy/status_collector/device_status_collector_browsertest.cc
+++ b/chrome/browser/ash/policy/status_collector/device_status_collector_browsertest.cc
@@ -45,6 +45,7 @@
 #include "chrome/browser/ash/crostini/crostini_test_helper.h"
 #include "chrome/browser/ash/guest_os/guest_os_registry_service.h"
 #include "chrome/browser/ash/guest_os/guest_os_registry_service_factory.h"
+#include "chrome/browser/ash/login/demo_mode/demo_setup_controller.h"
 #include "chrome/browser/ash/login/users/mock_user_manager.h"
 #include "chrome/browser/ash/ownership/fake_owner_settings_service.h"
 #include "chrome/browser/ash/policy/core/device_local_account.h"
@@ -878,6 +879,13 @@
     TestingDeviceStatusCollector::RegisterProfilePrefs(
         profile_pref_service_.registry());
 
+    // This pref registration is temporarily added because crrev/c/4076557 makes
+    // SystemWebAppManager (which is instantiated during creation of a
+    // TestProfile) dependent on the kDemoModeConfig pref.
+    // TODO(b/260117078): Delete this line after the DemoModeConfig pref is
+    // deprecated.
+    ash::DemoSetupController::RegisterLocalStatePrefs(local_state_.registry());
+
     // Set up a fake local state for KioskAppManager and KioskCryptohomeRemover.
     TestingBrowserProcess::GetGlobal()->SetLocalState(&local_state_);
     ash::KioskAppManager::RegisterLocalStatePrefs(local_state_.registry());
diff --git a/chrome/browser/ash/system_web_apps/system_web_app_manager_browsertest.cc b/chrome/browser/ash/system_web_apps/system_web_app_manager_browsertest.cc
index 094be9ae..1cbc911 100644
--- a/chrome/browser/ash/system_web_apps/system_web_app_manager_browsertest.cc
+++ b/chrome/browser/ash/system_web_apps/system_web_app_manager_browsertest.cc
@@ -32,6 +32,7 @@
 #include "chrome/browser/apps/app_service/launch_utils.h"
 #include "chrome/browser/ash/accessibility/accessibility_manager.h"
 #include "chrome/browser/ash/accessibility/speech_monitor.h"
+#include "chrome/browser/ash/app_list/test/chrome_app_list_test_support.h"
 #include "chrome/browser/ash/extensions/default_app_order.h"
 #include "chrome/browser/ash/file_manager/file_manager_test_util.h"
 #include "chrome/browser/ash/system_web_apps/system_web_app_manager.h"
@@ -44,7 +45,6 @@
 #include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h"
 #include "chrome/browser/ui/app_list/app_list_client_impl.h"
 #include "chrome/browser/ui/app_list/app_list_model_updater.h"
-#include "chrome/browser/ui/app_list/test/chrome_app_list_test_support.h"
 #include "chrome/browser/ui/ash/shelf/chrome_shelf_controller_util.h"
 #include "chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.h"
 #include "chrome/browser/ui/browser_finder.h"
diff --git a/chrome/browser/ash/web_applications/os_feedback_system_web_app_info.cc b/chrome/browser/ash/web_applications/os_feedback_system_web_app_info.cc
index cca755b..d953464 100644
--- a/chrome/browser/ash/web_applications/os_feedback_system_web_app_info.cc
+++ b/chrome/browser/ash/web_applications/os_feedback_system_web_app_info.cc
@@ -9,6 +9,7 @@
 #include "ash/constants/ash_features.h"
 #include "ash/webui/grit/ash_os_feedback_resources.h"
 #include "ash/webui/os_feedback_ui/url_constants.h"
+#include "base/memory/ref_counted_memory.h"
 #include "base/metrics/histogram_macros.h"
 #include "chrome/browser/apps/app_service/app_launch_params.h"
 #include "chrome/browser/ash/os_feedback/os_feedback_screenshot_manager.h"
diff --git a/chrome/browser/ash/web_applications/personalization_app/personalization_app_theme_provider_impl.cc b/chrome/browser/ash/web_applications/personalization_app/personalization_app_theme_provider_impl.cc
index cf633f6..1b25481 100644
--- a/chrome/browser/ash/web_applications/personalization_app/personalization_app_theme_provider_impl.cc
+++ b/chrome/browser/ash/web_applications/personalization_app/personalization_app_theme_provider_impl.cc
@@ -4,8 +4,10 @@
 
 #include "chrome/browser/ash/web_applications/personalization_app/personalization_app_theme_provider_impl.h"
 
+#include "ash/constants/ash_features.h"
 #include "ash/constants/ash_pref_names.h"
 #include "ash/public/cpp/schedule_enums.h"
+#include "ash/style/color_palette_controller.h"
 #include "ash/system/scheduled_feature/scheduled_feature.h"
 #include "chrome/browser/ash/web_applications/personalization_app/personalization_app_metrics.h"
 #include "chrome/browser/profiles/profile.h"
@@ -17,6 +19,9 @@
     content::WebUI* web_ui)
     : profile_(Profile::FromWebUI(web_ui)) {
   pref_change_registrar_.Init(profile_->GetPrefs());
+  if (ash::features::IsJellyEnabled()) {
+    color_palette_controller_ = ColorPaletteController::Create();
+  }
 }
 
 PersonalizationAppThemeProviderImpl::~PersonalizationAppThemeProviderImpl() =
@@ -106,4 +111,22 @@
       IsColorModeAutoScheduleEnabled());
 }
 
+void PersonalizationAppThemeProviderImpl::SetColorScheme(
+    ColorScheme color_scheme) {
+  if (!ash::features::IsJellyEnabled()) {
+    theme_receiver_.ReportBadMessage(
+        "Cannot call SetColorScheme without Jelly enabled.");
+    return;
+  }
+  color_palette_controller_->SetColorScheme(color_scheme, base::DoNothing());
+}
+
+void PersonalizationAppThemeProviderImpl::SetStaticColor(SkColor static_color) {
+  if (!ash::features::IsJellyEnabled()) {
+    theme_receiver_.ReportBadMessage(
+        "Cannot call SetStaticColor without Jelly enabled.");
+    return;
+  }
+  color_palette_controller_->SetStaticColor(static_color, base::DoNothing());
+}
 }  // namespace ash::personalization_app
diff --git a/chrome/browser/ash/web_applications/personalization_app/personalization_app_theme_provider_impl.h b/chrome/browser/ash/web_applications/personalization_app/personalization_app_theme_provider_impl.h
index 4012ce50..2d5bc53 100644
--- a/chrome/browser/ash/web_applications/personalization_app/personalization_app_theme_provider_impl.h
+++ b/chrome/browser/ash/web_applications/personalization_app/personalization_app_theme_provider_impl.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_ASH_WEB_APPLICATIONS_PERSONALIZATION_APP_PERSONALIZATION_APP_THEME_PROVIDER_IMPL_H_
 
 #include "ash/public/cpp/style/color_mode_observer.h"
+#include "ash/style/color_palette_controller.h"
 #include "ash/style/dark_light_mode_controller_impl.h"
 #include "ash/webui/personalization_app/personalization_app_theme_provider.h"
 #include "base/memory/raw_ptr.h"
@@ -51,6 +52,10 @@
 
   void IsDarkModeEnabled(IsDarkModeEnabledCallback callback) override;
 
+  void SetColorScheme(ColorScheme color_scheme) override;
+
+  void SetStaticColor(SkColor static_color) override;
+
   void IsColorModeAutoScheduleEnabled(
       IsColorModeAutoScheduleEnabledCallback callback) override;
 
@@ -68,6 +73,8 @@
 
   PrefChangeRegistrar pref_change_registrar_;
 
+  std::unique_ptr<ColorPaletteController> color_palette_controller_;
+
   base::ScopedObservation<ash::DarkLightModeControllerImpl,
                           ash::ColorModeObserver>
       color_mode_observer_{this};
diff --git a/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl_unittest.cc b/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl_unittest.cc
index c1c47a1..ac3b775 100644
--- a/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl_unittest.cc
+++ b/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl_unittest.cc
@@ -60,6 +60,7 @@
 #include "ui/base/webui/web_ui_util.h"
 #include "ui/gfx/codec/jpeg_codec.h"
 #include "ui/gfx/codec/png_codec.h"
+#include "ui/gfx/image/image_skia_rep.h"
 
 namespace ash::personalization_app {
 
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index 2da7c75..2893df3 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -204,7 +204,6 @@
 #include "ui/base/resource/resource_bundle_android.h"
 #else
 #include "chrome/browser/profiles/delete_profile_helper.h"
-#include "chrome/browser/resource_coordinator/tab_activity_watcher.h"
 #include "chrome/browser/resource_coordinator/tab_manager.h"
 #include "chrome/browser/resources_integrity.h"
 #include "chrome/browser/ui/browser.h"
@@ -1323,10 +1322,6 @@
                    base::BindOnce(&WebUsbDetector::Initialize,
                                   base::Unretained(web_usb_detector_.get())));
   }
-  if (base::FeatureList::IsEnabled(features::kTabMetricsLogging)) {
-    // Initialize the TabActivityWatcher to begin logging tab activity events.
-    resource_coordinator::TabActivityWatcher::GetInstance();
-  }
 #endif
 
   // At this point, StartupBrowserCreator::Start has run creating initial
diff --git a/chrome/browser/chrome_service_worker_browsertest.cc b/chrome/browser/chrome_service_worker_browsertest.cc
index 7657bfcf..b4f67f44 100644
--- a/chrome/browser/chrome_service_worker_browsertest.cc
+++ b/chrome/browser/chrome_service_worker_browsertest.cc
@@ -318,14 +318,13 @@
 }
 
 // TODO(crbug.com/1395715): The test is flaky. Re-enable it.
-#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN)
-#define MAYBE_SubresourceCount DISABLED_SubresourceCount
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_SubresourceCountUKM DISABLED_SubresourceCountUKM
 #else
-#define MAYBE_SubresourceCount SubresourceCount
+#define MAYBE_SubresourceCountUKM SubresourceCountUKM
 #endif
-IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerTest, MAYBE_SubresourceCount) {
+IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerTest, MAYBE_SubresourceCountUKM) {
   base::RunLoop ukm_loop;
-  base::HistogramTester histogram_tester;
   ukm::TestAutoSetUkmRecorder test_recorder;
   test_recorder.SetOnAddEntryCallback(
       ukm::builders::ServiceWorker_OnLoad::kEntryName, ukm_loop.QuitClosure());
@@ -398,6 +397,66 @@
   test_recorder.ExpectEntryMetric(
       entries[0],
       ukm::builders::ServiceWorker_OnLoad::kSubResourceFallbackRatioName, 50);
+}
+
+// TODO(crbug.com/1395715): The test is flaky. Re-enable it.
+#if BUILDFLAG(IS_FUCHSIA)
+#define MAYBE_SubresourceCountUMA DISABLED_SubresourceCountUMA
+#else
+#define MAYBE_SubresourceCountUMA SubresourceCountUMA
+#endif
+IN_PROC_BROWSER_TEST_F(ChromeServiceWorkerTest, MAYBE_SubresourceCountUMA) {
+  base::HistogramTester histogram_tester;
+
+  WriteFile(FILE_PATH_LITERAL("fallback.css"), "");
+  WriteFile(FILE_PATH_LITERAL("nofallback.css"), "");
+  WriteFile(FILE_PATH_LITERAL("subresources.html"),
+            "<link href='./fallback.css' rel='stylesheet'>"
+            "<link href='./nofallback.css' rel='stylesheet'>");
+  WriteFile(FILE_PATH_LITERAL("sw.js"),
+            "this.onactivate = function(event) {"
+            "  event.waitUntil(self.clients.claim());"
+            "};"
+            "this.onfetch = function(event) {"
+            // We will fallback fallback.css.
+            "  if (event.request.url.endsWith('/fallback.css')) {"
+            "    return;"
+            "  }"
+            "  event.respondWith(fetch(event.request));"
+            "};");
+  WriteFile(FILE_PATH_LITERAL("test.html"),
+            "<script>"
+            "navigator.serviceWorker.register('./sw.js', {scope: './'})"
+            "  .then(function(reg) {"
+            "      reg.addEventListener('updatefound', function() {"
+            "          var worker = reg.installing;"
+            "          worker.addEventListener('statechange', function() {"
+            "              if (worker.state == 'activated')"
+            "                document.title = 'READY';"
+            "            });"
+            "        });"
+            "    });"
+            "</script>");
+
+  InitializeServer();
+
+  {
+    // The message "READY" will be sent when the service worker is activated.
+    const std::u16string expected_title = u"READY";
+    content::TitleWatcher title_watcher(
+        browser()->tab_strip_model()->GetActiveWebContents(), expected_title);
+    ASSERT_TRUE(ui_test_utils::NavigateToURL(
+        browser(), embedded_test_server()->GetURL("/test.html")));
+    EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
+  }
+
+  // Navigate to the service worker controlled page.
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(
+      browser(), embedded_test_server()->GetURL("/subresources.html")));
+
+  // Navigate away to record metrics.
+  ASSERT_TRUE(
+      ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)));
 
   // Sync the histogram data between the renderer and browser processes.
   metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
diff --git a/chrome/browser/creator/android/BUILD.gn b/chrome/browser/creator/android/BUILD.gn
index f1bea674..e4811b1 100644
--- a/chrome/browser/creator/android/BUILD.gn
+++ b/chrome/browser/creator/android/BUILD.gn
@@ -24,6 +24,7 @@
     "//chrome/browser/feed/android:java",
     "//chrome/browser/feedback/android:java",
     "//chrome/browser/profiles/android:java",
+    "//chrome/browser/share:java",
     "//chrome/browser/ui/messages/android:java",
     "//chrome/browser/xsurface:java",
     "//components/browser_ui/bottomsheet/android:factory_java",
diff --git a/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinator.java b/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinator.java
index 4d304b6b..57c00a9 100644
--- a/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinator.java
+++ b/chrome/browser/creator/android/java/src/org/chromium/chrome/browser/creator/CreatorCoordinator.java
@@ -15,6 +15,7 @@
 import androidx.recyclerview.widget.RecyclerView.OnScrollListener;
 
 import org.chromium.base.Callback;
+import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.browser.feed.FeedActionDelegate;
 import org.chromium.chrome.browser.feed.FeedAutoplaySettingsDelegate;
 import org.chromium.chrome.browser.feed.FeedContentFirstLoadWatcher;
@@ -30,6 +31,7 @@
 import org.chromium.chrome.browser.feed.webfeed.WebFeedSubscriptionStatus;
 import org.chromium.chrome.browser.feedback.HelpAndFeedbackLauncher;
 import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.share.ShareDelegate;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
 import org.chromium.chrome.browser.xsurface.FeedLaunchReliabilityLogger;
 import org.chromium.chrome.browser.xsurface.HybridListRenderer;
@@ -129,10 +131,11 @@
 
     // Create a FeedStream and bind it to the RecyclerView
     public void initFeedStream(FeedActionDelegate feedActionDelegate,
-            HelpAndFeedbackLauncher helpAndFeedbackLauncher) {
+            HelpAndFeedbackLauncher helpAndFeedbackLauncher,
+            Supplier<ShareDelegate> shareDelegateSupplier) {
         mStream = new FeedStream(mActivity, mSnackbarManager, mBottomSheetController,
                 /* isPlaceholderShownInitially */ false, mWindowAndroid,
-                /* shareSupplier */ null, StreamKind.SINGLE_WEB_FEED,
+                /* shareSupplier */ shareDelegateSupplier, StreamKind.SINGLE_WEB_FEED,
                 /* FeedAutoplaySettingsDelegate */ this, feedActionDelegate,
                 helpAndFeedbackLauncher,
                 /* FeedContentFirstLoadWatcher */ this,
diff --git a/chrome/browser/devtools/device/android_device_manager.cc b/chrome/browser/devtools/device/android_device_manager.cc
index a6e7142a..0db0043 100644
--- a/chrome/browser/devtools/device/android_device_manager.cc
+++ b/chrome/browser/devtools/device/android_device_manager.cc
@@ -13,6 +13,7 @@
 #include "base/location.h"
 #include "base/memory/ptr_util.h"
 #include "base/message_loop/message_pump_type.h"
+#include "base/no_destructor.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
@@ -511,21 +512,16 @@
                                 std::move(provider_), std::move(serial_)));
 }
 
-AndroidDeviceManager::HandlerThread*
-AndroidDeviceManager::HandlerThread::instance_ = nullptr;
-
 // static
-scoped_refptr<AndroidDeviceManager::HandlerThread>
+AndroidDeviceManager::HandlerThread*
 AndroidDeviceManager::HandlerThread::GetInstance() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  if (!instance_)
-    new HandlerThread();
-  return instance_;
+  static base::NoDestructor<AndroidDeviceManager::HandlerThread> s_instance;
+  return s_instance.get();
 }
 
 AndroidDeviceManager::HandlerThread::HandlerThread() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  instance_ = this;
   thread_ = new base::Thread(kDevToolsAdbBridgeThreadName);
   base::Thread::Options options;
   options.message_pump_type = base::MessagePumpType::IO;
@@ -548,7 +544,6 @@
 
 AndroidDeviceManager::HandlerThread::~HandlerThread() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  instance_ = nullptr;
   if (!thread_)
     return;
   // Shut down thread on a thread other than UI so it can join a thread.
diff --git a/chrome/browser/devtools/device/android_device_manager.h b/chrome/browser/devtools/device/android_device_manager.h
index e54903f5..0b9f6b3 100644
--- a/chrome/browser/devtools/device/android_device_manager.h
+++ b/chrome/browser/devtools/device/android_device_manager.h
@@ -13,6 +13,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/ref_counted_delete_on_sequence.h"
 #include "base/memory/weak_ptr.h"
+#include "base/no_destructor.h"
 #include "base/sequence_checker.h"
 #include "base/task/single_thread_task_runner.h"
 #include "base/threading/thread.h"
@@ -228,18 +229,17 @@
   typedef std::vector<DeviceDescriptor> DeviceDescriptors;
 
  private:
-  class HandlerThread : public base::RefCountedThreadSafe<HandlerThread> {
+  class HandlerThread {
    public:
-    static scoped_refptr<HandlerThread> GetInstance();
+    static HandlerThread* GetInstance();
     scoped_refptr<base::SingleThreadTaskRunner> message_loop();
 
    private:
-    friend class base::RefCountedThreadSafe<HandlerThread>;
-    static HandlerThread* instance_;
+    friend class base::NoDestructor<HandlerThread>;
     static void StopThread(base::Thread* thread);
 
     HandlerThread();
-    virtual ~HandlerThread();
+    ~HandlerThread();
     base::Thread* thread_;
   };
 
@@ -250,7 +250,7 @@
 
   typedef std::map<std::string, base::WeakPtr<Device> > DeviceWeakMap;
 
-  scoped_refptr<HandlerThread> handler_thread_;
+  raw_ptr<HandlerThread> handler_thread_;
   DeviceProviders providers_;
   DeviceWeakMap devices_;
 
diff --git a/chrome/browser/enterprise/connectors/reporting/extension_install_event_router_unittest.cc b/chrome/browser/enterprise/connectors/reporting/extension_install_event_router_unittest.cc
index 91a6e56..aed0502 100644
--- a/chrome/browser/enterprise/connectors/reporting/extension_install_event_router_unittest.cc
+++ b/chrome/browser/enterprise/connectors/reporting/extension_install_event_router_unittest.cc
@@ -95,13 +95,12 @@
     settings.enabled_event_names.insert(
         ReportingServiceSettings::kExtensionInstallEvent);
 
-    base::DictionaryValue manifest;
-    manifest.SetStringPath(extensions::manifest_keys::kName,
-                           kFakeExtensionName);
-    manifest.SetStringPath(extensions::manifest_keys::kVersion, "1");
-    manifest.SetIntPath(extensions::manifest_keys::kManifestVersion, 2);
-    manifest.SetStringPath(extensions::manifest_keys::kDescription,
-                           kFakeExtensionDescription);
+    base::Value::Dict manifest;
+    manifest.Set(extensions::manifest_keys::kName, kFakeExtensionName);
+    manifest.Set(extensions::manifest_keys::kVersion, "1");
+    manifest.Set(extensions::manifest_keys::kManifestVersion, 2);
+    manifest.Set(extensions::manifest_keys::kDescription,
+                 kFakeExtensionDescription);
 
     std::string error;
     extension_chrome_ = extensions::Extension::Create(
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.cc b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
index a2b155cb2..8894dfa 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
@@ -443,7 +443,10 @@
                         hosts_to_withhold.Clone(), hosts_to_withhold.Clone()),
           *PermissionsManager::Get(context)->GetRevokablePermissions(extension),
           URLPatternSet::IntersectionBehavior::kDetailed);
-  DCHECK(!permissions_to_remove->IsEmpty());
+  if (permissions_to_remove->IsEmpty()) {
+    std::move(done_callback).Run();
+    return;
+  }
 
   PermissionsUpdater(context).RevokeRuntimePermissions(
       extension, *permissions_to_remove, std::move(done_callback));
@@ -2579,7 +2582,8 @@
   // changed.
   PermissionsManager* const permissions_manager =
       PermissionsManager::Get(browser_context());
-  std::vector<const Extension*> extensions_to_modify;
+  std::vector<std::pair<const Extension&, developer::HostAccess>>
+      extensions_to_modify;
   extensions_to_modify.reserve(params->updates.size());
   for (const auto& update : params->updates) {
     const Extension* extension = GetExtensionById(update.id);
@@ -2588,16 +2592,17 @@
     if (!permissions_manager->CanAffectExtension(*extension))
       return RespondNow(Error(kCannotChangeHostPermissions));
 
-    extensions_to_modify.push_back(extension);
+    extensions_to_modify.emplace_back(*extension, update.site_access);
   }
 
-  for (const auto& update : params->updates) {
-    const Extension* extension = GetExtensionById(update.id);
+  for (const auto& update : extensions_to_modify) {
+    const Extension& extension = update.first;
+
     std::unique_ptr<const PermissionSet> permissions;
-    ScriptingPermissionsModifier modifier(browser_context(), extension);
+    ScriptingPermissionsModifier modifier(browser_context(), &extension);
     bool has_withheld_permissions =
-        permissions_manager->HasWithheldHostPermissions(*extension);
-    switch (update.site_access) {
+        permissions_manager->HasWithheldHostPermissions(extension);
+    switch (update.second) {
       case developer::HOST_ACCESS_ON_CLICK:
         // If the extension has no withheld permissions and can run on all of
         // its requested hosts, withhold all of its host permissions as a
@@ -2608,7 +2613,7 @@
           modifier.RemoveAllGrantedHostPermissions();
           done_callback.Run();
         } else {
-          RevokePermissionsForSite(browser_context(), *extension, parsed_site,
+          RevokePermissionsForSite(browser_context(), extension, parsed_site,
                                    done_callback);
         }
         break;
@@ -2620,7 +2625,7 @@
           modifier.SetWithholdHostPermissions(true);
           modifier.RemoveAllGrantedHostPermissions();
         }
-        GrantPermissionsForSite(browser_context(), *extension, parsed_site,
+        GrantPermissionsForSite(browser_context(), extension, parsed_site,
                                 done_callback);
         break;
       case developer::HOST_ACCESS_ON_ALL_SITES:
diff --git a/chrome/browser/extensions/api/downloads/downloads_api.cc b/chrome/browser/extensions/api/downloads/downloads_api.cc
index 3453b209..2801288 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api.cc
+++ b/chrome/browser/extensions/api/downloads/downloads_api.cc
@@ -1003,7 +1003,7 @@
     content::BrowserContext* browser_context,
     Feature::Context target_context,
     const Extension* extension,
-    const base::DictionaryValue* listener_filter,
+    const base::Value::Dict* listener_filter,
     std::unique_ptr<base::Value::List>* event_args_out,
     mojom::EventFilteringInfoPtr* event_filtering_info_out) {
   *any_determiners = true;
diff --git a/chrome/browser/extensions/api/mdns/mdns_api.cc b/chrome/browser/extensions/api/mdns/mdns_api.cc
index 8e13d23c..a565a31 100644
--- a/chrome/browser/extensions/api/mdns/mdns_api.cc
+++ b/chrome/browser/extensions/api/mdns/mdns_api.cc
@@ -9,6 +9,7 @@
 
 #include "base/lazy_instance.h"
 #include "base/strings/stringprintf.h"
+#include "base/values.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "components/version_info/channel.h"
 #include "content/public/browser/render_frame_host.h"
@@ -215,10 +216,10 @@
     std::set<std::string>* extension_ids,
     ServiceTypeCounts* service_type_counts) {
   for (const auto& listener : GetEventListeners()) {
-    base::DictionaryValue* filter = listener->filter();
+    base::Value::Dict* filter = listener->filter();
 
     const std::string* service_type =
-        filter->FindStringKey(kEventFilterServiceTypeKey);
+        filter->FindString(kEventFilterServiceTypeKey);
     if (!service_type || service_type->empty() ||
         !base::IsStringASCII(*service_type))
       continue;
diff --git a/chrome/browser/extensions/api/mdns/mdns_api_unittest.cc b/chrome/browser/extensions/api/mdns/mdns_api_unittest.cc
index 8b050f3..f1c442b 100644
--- a/chrome/browser/extensions/api/mdns/mdns_api_unittest.cc
+++ b/chrome/browser/extensions/api/mdns/mdns_api_unittest.cc
@@ -47,8 +47,8 @@
     const std::string& extension_id,
     const std::string& service_type,
     extensions::EventListenerMap::ListenerList* listener_list) {
-  std::unique_ptr<base::DictionaryValue> filter(new base::DictionaryValue);
-  filter->SetStringKey(kEventFilterServiceTypeKey, service_type);
+  auto filter = std::make_unique<base::Value::Dict>();
+  filter->Set(kEventFilterServiceTypeKey, service_type);
   listener_list->push_back(EventListener::ForExtension(
       kEventFilterServiceTypeKey, extension_id, nullptr, std::move(filter)));
 }
@@ -357,8 +357,8 @@
   // There is a allowlist of mdns service types extensions may access, which
   // includes "_testing._tcp.local" and excludes "_trex._tcp.local"
   {
-    base::DictionaryValue filter;
-    filter.SetStringKey(kEventFilterServiceTypeKey, "_trex._tcp.local");
+    base::Value::Dict filter;
+    filter.Set(kEventFilterServiceTypeKey, "_trex._tcp.local");
 
     ASSERT_TRUE(dns_sd_registry());
     // Test that the extension is not able to listen to a non-allowlisted
@@ -378,8 +378,8 @@
                                       absl::nullopt, filter, false);
   }
   {
-    base::DictionaryValue filter;
-    filter.SetStringKey(kEventFilterServiceTypeKey, "_testing._tcp.local");
+    base::Value::Dict filter;
+    filter.Set(kEventFilterServiceTypeKey, "_testing._tcp.local");
 
     ASSERT_TRUE(dns_sd_registry());
     // Test that the extension is able to listen to a allowlisted service
@@ -411,8 +411,8 @@
   ASSERT_TRUE(extension->is_platform_app());
   auto param = mojom::EventListenerParam::NewExtensionId(kExtId);
 
-  base::DictionaryValue filter;
-  filter.SetStringKey(kEventFilterServiceTypeKey, "_trex._tcp.local");
+  base::Value::Dict filter;
+  filter.Set(kEventFilterServiceTypeKey, "_trex._tcp.local");
 
   ASSERT_TRUE(dns_sd_registry());
   // Test that the extension is able to listen to a non-allowlisted service
diff --git a/chrome/browser/extensions/api/tabs/tabs_event_router.cc b/chrome/browser/extensions/api/tabs/tabs_event_router.cc
index a39671b..0c8f79a 100644
--- a/chrome/browser/extensions/api/tabs/tabs_event_router.cc
+++ b/chrome/browser/extensions/api/tabs/tabs_event_router.cc
@@ -11,7 +11,6 @@
 #include <vector>
 
 #include "base/bind.h"
-#include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/api/tabs/tabs_constants.h"
 #include "chrome/browser/extensions/api/tabs/tabs_windows_api.h"
@@ -31,7 +30,6 @@
 #include "extensions/common/features/feature.h"
 #include "third_party/blink/public/common/page/page_zoom.h"
 
-using base::DictionaryValue;
 using base::Value;
 using content::WebContents;
 using zoom::ZoomController;
@@ -46,7 +44,7 @@
     content::BrowserContext* browser_context,
     Feature::Context target_context,
     const Extension* extension,
-    const base::DictionaryValue* listener_filter,
+    const base::Value::Dict* listener_filter,
     std::unique_ptr<base::Value::List>* event_args_out,
     mojom::EventFilteringInfoPtr* event_filtering_info_out) {
   ExtensionTabUtil::ScrubTabBehavior scrub_tab_behavior =
@@ -76,7 +74,7 @@
     content::BrowserContext* browser_context,
     Feature::Context target_context,
     const Extension* extension,
-    const base::DictionaryValue* listener_filter,
+    const base::Value::Dict* listener_filter,
     std::unique_ptr<base::Value::List>* event_args_out,
     mojom::EventFilteringInfoPtr* event_filtering_info_out) {
   ExtensionTabUtil::ScrubTabBehavior scrub_tab_behavior =
diff --git a/chrome/browser/extensions/api/tabs/windows_event_router.cc b/chrome/browser/extensions/api/tabs/windows_event_router.cc
index fe0782a..7f5c1c4 100644
--- a/chrome/browser/extensions/api/tabs/windows_event_router.cc
+++ b/chrome/browser/extensions/api/tabs/windows_event_router.cc
@@ -36,15 +36,15 @@
 
 bool ControllerVisibleToListener(WindowController* window_controller,
                                  const Extension* extension,
-                                 const base::DictionaryValue* listener_filter) {
+                                 const base::Value::Dict* listener_filter) {
   if (!window_controller)
     return false;
 
   // If there is no filter the visibility is based on the extension.
   const base::Value::List* filter_value = nullptr;
   if (listener_filter) {
-    filter_value = listener_filter->GetDict().FindList(
-        extensions::tabs_constants::kWindowTypesKey);
+    filter_value =
+        listener_filter->FindList(extensions::tabs_constants::kWindowTypesKey);
   }
 
   // TODO(https://crbug.com/807313): Remove this.
@@ -64,12 +64,12 @@
     BrowserContext* browser_context,
     Feature::Context target_context,
     const Extension* extension,
-    const base::DictionaryValue* listener_filter,
+    const base::Value::Dict* listener_filter,
     std::unique_ptr<base::Value::List>* event_args_out,
     mojom::EventFilteringInfoPtr* event_filtering_info_out) {
   bool has_filter =
       listener_filter &&
-      listener_filter->FindKey(extensions::tabs_constants::kWindowTypesKey);
+      listener_filter->contains(extensions::tabs_constants::kWindowTypesKey);
   // TODO(https://crbug.com/807313): Remove this.
   bool allow_dev_tools_windows = has_filter;
   if (!window_controller->IsVisibleToTabsAPIForExtension(
@@ -95,14 +95,14 @@
     BrowserContext* browser_context,
     Feature::Context target_context,
     const Extension* extension,
-    const base::DictionaryValue* listener_filter,
+    const base::Value::Dict* listener_filter,
     std::unique_ptr<base::Value::List>* event_args_out,
     mojom::EventFilteringInfoPtr* event_filtering_info_out) {
   int window_id = extension_misc::kUnknownWindowId;
   Profile* new_active_context = nullptr;
   bool has_filter =
       listener_filter &&
-      listener_filter->FindKey(extensions::tabs_constants::kWindowTypesKey);
+      listener_filter->contains(extensions::tabs_constants::kWindowTypesKey);
 
   // We might not have a window controller if the focus moves away
   // from chromium's windows.
diff --git a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
index cc9a274..7a00be8 100644
--- a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
+++ b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
@@ -596,6 +596,8 @@
   features.Append(GenerateFeatureFlag(
       "handwritinglibrarydlc",
       base::FeatureList::IsEnabled(ash::features::kHandwritingLibraryDlc)));
+  features.Append(
+      GenerateFeatureFlag("jelly", ash::features::IsJellyEnabled()));
 
   results.Set("features", std::move(features));
 
diff --git a/chrome/browser/extensions/extension_prefs_unittest.cc b/chrome/browser/extensions/extension_prefs_unittest.cc
index 9d3ba47..f809ff002 100644
--- a/chrome/browser/extensions/extension_prefs_unittest.cc
+++ b/chrome/browser/extensions/extension_prefs_unittest.cc
@@ -193,11 +193,12 @@
     std::unique_ptr<APIPermission> permission(
         permission_info->CreateAPIPermission());
     {
-      std::unique_ptr<base::ListValue> value(new base::ListValue());
-      value->Append("tcp-connect:*.example.com:80");
-      value->Append("udp-bind::8080");
-      value->Append("udp-send-to::8888");
-      ASSERT_TRUE(permission->FromValue(value.get(), nullptr, nullptr));
+      base::Value::List list;
+      list.Append("tcp-connect:*.example.com:80");
+      list.Append("udp-bind::8080");
+      list.Append("udp-send-to::8888");
+      base::Value value(std::move(list));
+      ASSERT_TRUE(permission->FromValue(&value, nullptr, nullptr));
     }
     api_perm_set1_.insert(std::move(permission));
 
@@ -470,11 +471,10 @@
  public:
   // Sets idle install information for one test extension.
   void SetIdleInfo(const std::string& id, int num) {
-    base::DictionaryValue manifest;
-    manifest.SetStringPath(manifest_keys::kName, "test");
-    manifest.SetStringPath(manifest_keys::kVersion,
-                           "1." + base::NumberToString(num));
-    manifest.SetIntPath(manifest_keys::kManifestVersion, 2);
+    base::Value::Dict manifest;
+    manifest.Set(manifest_keys::kName, "test");
+    manifest.Set(manifest_keys::kVersion, "1." + base::NumberToString(num));
+    manifest.Set(manifest_keys::kManifestVersion, 2);
     base::FilePath path =
         prefs_.extensions_dir().AppendASCII(base::NumberToString(num));
     std::string errors;
@@ -629,26 +629,25 @@
     EXPECT_FALSE(prefs()->GetDelayedInstallInfo(id_));
     EXPECT_EQ(std::string("Param"), prefs()->GetInstallParam(id_));
 
-    const base::DictionaryValue* manifest;
-    ASSERT_TRUE(prefs()->ReadPrefAsDictionary(id_, "manifest", &manifest));
-    ASSERT_TRUE(manifest);
-    ASSERT_TRUE(manifest->is_dict());
-    const base::Value::Dict& dict = manifest->GetDict();
-    const std::string* name = dict.FindString(manifest_keys::kName);
-    EXPECT_TRUE(name);
+    const base::Value::Dict* dict = prefs()->ReadPrefAsDict(id_, "manifest");
+    ASSERT_TRUE(dict);
+    const std::string* name = dict->FindString(manifest_keys::kName);
+    ASSERT_TRUE(name);
     EXPECT_EQ("test", *name);
-    const std::string* version = dict.FindString(manifest_keys::kVersion);
-    EXPECT_TRUE(version);
+    const std::string* version = dict->FindString(manifest_keys::kVersion);
+    ASSERT_TRUE(version);
     EXPECT_EQ("0.2", *version);
-    EXPECT_FALSE(dict.FindString(manifest_keys::kBackgroundPage));
-    const base::ListValue* scripts;
-    ASSERT_TRUE(manifest->GetList(manifest_keys::kBackgroundScripts, &scripts));
-    EXPECT_EQ(1u, scripts->GetList().size());
+    EXPECT_FALSE(dict->FindString(manifest_keys::kBackgroundPage));
+    const base::Value::List* scripts =
+        dict->FindListByDottedPath(manifest_keys::kBackgroundScripts);
+    ASSERT_TRUE(scripts);
+    EXPECT_EQ(1u, scripts->size());
   }
 
  protected:
   std::string id_;
 };
+
 TEST_F(ExtensionPrefsFinishDelayedInstallInfo, FinishDelayedInstallInfo) {}
 
 class ExtensionPrefsOnExtensionInstalled : public ExtensionPrefsTest {
@@ -730,18 +729,19 @@
 
   void Verify() override {
     auto* dict = prefs()->GetExtensionPref(extension_->id());
-    std::string first_install_time;
-    std::string last_update_time;
-    std::string old_install_time;
 
     // Verify the legacy install_time key has been removed and replaced by
     // the last_update_time key. Also verify that the first_install_time key
     // has been added and has the same value as the last_update_time key.
-    EXPECT_FALSE(dict->GetString(kOldInstallTimePrefKey, &old_install_time));
-    EXPECT_TRUE(dict->GetString(kFirstInstallTimePrefKey, &first_install_time));
-    EXPECT_TRUE(dict->GetString(kLastUpdateTimePrefKey, &last_update_time));
-    EXPECT_EQ(first_install_time, time_str_);
-    EXPECT_EQ(last_update_time, time_str_);
+    EXPECT_FALSE(dict->FindString(kOldInstallTimePrefKey));
+    const std::string* first_install_time =
+        dict->FindString(kFirstInstallTimePrefKey);
+    ASSERT_TRUE(first_install_time);
+    EXPECT_EQ(*first_install_time, time_str_);
+    const std::string* last_update_time =
+        dict->FindString(kLastUpdateTimePrefKey);
+    ASSERT_TRUE(last_update_time);
+    EXPECT_EQ(*last_update_time, time_str_);
   }
 
  private:
@@ -776,11 +776,10 @@
   }
 
   void Verify() override {
-    const base::DictionaryValue* ext =
-        prefs()->GetExtensionPref(extension_->id());
-    EXPECT_NE(nullptr, ext);
+    const base::Value::Dict* ext = prefs()->GetExtensionPref(extension_->id());
+    ASSERT_TRUE(ext);
     // The pref value should be cleared.
-    EXPECT_FALSE(ext->FindIntKey("disable_reasons"));
+    EXPECT_FALSE(ext->FindInt("disable_reasons"));
   }
 
  private:
@@ -838,12 +837,12 @@
 
 PrefsPrepopulatedTestBase::PrefsPrepopulatedTestBase()
     : ExtensionPrefsTest() {
-  base::DictionaryValue simple_dict;
+  base::Value::Dict simple_dict;
   std::string error;
 
-  simple_dict.SetStringPath(manifest_keys::kVersion, "1.0.0.0");
-  simple_dict.SetIntPath(manifest_keys::kManifestVersion, 2);
-  simple_dict.SetStringPath(manifest_keys::kName, "unused");
+  simple_dict.Set(manifest_keys::kVersion, "1.0.0.0");
+  simple_dict.Set(manifest_keys::kManifestVersion, 2);
+  simple_dict.Set(manifest_keys::kName, "unused");
 
   extension1_ = Extension::Create(prefs_.temp_dir().AppendASCII("ext1_"),
                                   ManifestLocation::kExternalPref, simple_dict,
@@ -1103,10 +1102,8 @@
     auto dictionary = std::make_unique<base::DictionaryValue>();
     prefs()->UpdateExtensionPref(extension_->id(), kPrefStringForIdMapping,
                                  std::move(dictionary));
-    const base::DictionaryValue* dictionary_value = nullptr;
-    EXPECT_TRUE(prefs()->ReadPrefAsDictionary(
-        extension_->id(), kPrefStringForIdMapping, &dictionary_value));
-    EXPECT_TRUE(dictionary_value);
+    EXPECT_TRUE(
+        prefs()->ReadPrefAsDict(extension_->id(), kPrefStringForIdMapping));
 
     prefs()->MigrateObsoleteExtensionPrefs();
   }
@@ -1118,9 +1115,8 @@
         &str_value));
 
     // TODO(crbug.com/1015619): Remove 2023-05. kPrefStringForIdMapping.
-    const base::DictionaryValue* dictionary_value = nullptr;
-    EXPECT_FALSE(prefs()->ReadPrefAsDictionary(
-        extension_->id(), kPrefStringForIdMapping, &dictionary_value));
+    EXPECT_FALSE(
+        prefs()->ReadPrefAsDict(extension_->id(), kPrefStringForIdMapping));
   }
 
  private:
@@ -1382,8 +1378,8 @@
   prefs.prefs()->SetTimePref(kTestTimePref, time);
   GURL url = GURL("https://example/com");
   prefs.prefs()->SetGURLPref(kTestGURLPref, url);
-  auto dict = std::make_unique<base::DictionaryValue>();
-  dict->SetStringKey("key", "val");
+  base::Value::Dict dict;
+  dict.Set("key", "val");
   prefs.prefs()->SetDictionaryPref(kTestDictPref, std::move(dict));
 
   EXPECT_TRUE(prefs.prefs()->GetPrefAsBoolean(kTestBooleanPref));
@@ -1391,10 +1387,8 @@
   EXPECT_EQ(prefs.prefs()->GetPrefAsString(kTestStringPref), "foo");
   EXPECT_EQ(prefs.prefs()->GetPrefAsTime(kTestTimePref), time);
   EXPECT_EQ(prefs.prefs()->GetPrefAsGURL(kTestGURLPref), url);
-  const std::string* string_ptr = prefs.prefs()
-                                      ->GetPrefAsDictionary(kTestDictPref)
-                                      ->GetDict()
-                                      .FindString("key");
+  const std::string* string_ptr =
+      prefs.prefs()->GetPrefAsDictionary(kTestDictPref).FindString("key");
   EXPECT_TRUE(string_ptr);
   EXPECT_EQ(*string_ptr, "val");
 }
@@ -1420,13 +1414,14 @@
   prefs.prefs()->SetBooleanPref(extension_id, kTestBooleanPref, true);
   prefs.prefs()->SetIntegerPref(extension_id, kTestIntegerPref, 1);
   prefs.prefs()->SetStringPref(extension_id, kTestStringPref, "foo");
-  auto dict = std::make_unique<base::DictionaryValue>();
-  dict->SetStringKey("key", "val");
+  base::Value::Dict dict;
+  dict.Set("key", "val");
   prefs.prefs()->SetDictionaryPref(extension_id, kTestDictPref,
                                    std::move(dict));
-  auto list = base::ListValue();
+  base::Value::List list;
   list.Append("list_val");
-  prefs.prefs()->SetListPref(extension_id, kTestListPref, std::move(list));
+  prefs.prefs()->SetListPref(extension_id, kTestListPref,
+                             base::Value(std::move(list)));
   base::Time time = base::Time::Now();
   prefs.prefs()->SetTimePref(extension_id, kTestTimePref, time);
 
@@ -1443,16 +1438,19 @@
                                               &string_value));
   EXPECT_EQ(string_value, "foo");
 
-  const base::DictionaryValue* dict_val = nullptr;
-  prefs.prefs()->ReadPrefAsDictionary(extension_id, kTestDictPref, &dict_val);
-  const std::string* string_ptr = dict_val->GetDict().FindString("key");
-  EXPECT_TRUE(string_ptr);
+  const base::Value::Dict* dict_val =
+      prefs.prefs()->ReadPrefAsDictionary(extension_id, kTestDictPref);
+  ASSERT_TRUE(dict_val);
+  const std::string* string_ptr = dict_val->FindString("key");
+  ASSERT_TRUE(string_ptr);
   EXPECT_EQ(*string_ptr, "val");
 
-  const base::ListValue* list_val = nullptr;
-  prefs.prefs()->ReadPrefAsList(extension_id, kTestListPref, &list_val);
-  EXPECT_TRUE(list_val->GetList()[0].is_string());
-  EXPECT_EQ(list_val->GetList()[0].GetString(), "list_val");
+  const base::Value::List* list_val =
+      prefs.prefs()->ReadPrefAsList(extension_id, kTestListPref);
+  ASSERT_TRUE(list_val);
+  ASSERT_FALSE(list_val->empty());
+  ASSERT_TRUE((*list_val)[0].is_string());
+  EXPECT_EQ((*list_val)[0].GetString(), "list_val");
 
   EXPECT_EQ(time, prefs.prefs()->ReadPrefAsTime(extension_id, kTestTimePref));
 }
diff --git a/chrome/browser/extensions/install_signer.cc b/chrome/browser/extensions/install_signer.cc
index 8b16712..d33560b0 100644
--- a/chrome/browser/extensions/install_signer.cc
+++ b/chrome/browser/extensions/install_signer.cc
@@ -320,16 +320,16 @@
 
   // The request protocol is JSON of the form:
   // {
-  //   "protocol_version": "1",
+  //   "protocol_version": 1,
   //   "hash": "<base64-encoded hash value here>",
-  //   "ids": [ "<id1>", "id2" ]
+  //   "ids": [ "<id1>", "<id2>" ]
   // }
-  base::DictionaryValue dictionary;
-  dictionary.SetIntKey(kProtocolVersionKey, 1);
-  dictionary.SetStringKey(kHashKey, hash_base64);
-  std::unique_ptr<base::ListValue> id_list(new base::ListValue);
-  for (auto i = ids_.begin(); i != ids_.end(); ++i) {
-    id_list->Append(*i);
+  base::Value::Dict dictionary;
+  dictionary.Set(kProtocolVersionKey, 1);
+  dictionary.Set(kHashKey, hash_base64);
+  base::Value::List id_list;
+  for (const ExtensionId& extension_id : ids_) {
+    id_list.Append(extension_id);
   }
   dictionary.Set(kIdsKey, std::move(id_list));
   std::string json;
@@ -373,7 +373,7 @@
 
   // The response is JSON of the form:
   // {
-  //   "protocol_version": "1",
+  //   "protocol_version": 1,
   //   "signature": "<base64-encoded signature>",
   //   "expiry": "<date in YYYY-MM-DD form>",
   //   "invalid_ids": [ "<id3>", "<id4>" ]
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 2f6159d..46c185e 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -4105,6 +4105,14 @@
     "expiry_milestone": 97
   },
   {
+    "name": "https-upgrades",
+    "owners": [
+      "cthomp",
+      "trusty-transport@chromium.org"
+    ],
+    "expiry_milestone": 118
+  },
+  {
     "name": "identity-status-consistency",
     "owners": [ "triploblastic", "chrome-signin-team" ],
     "expiry_milestone":120
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 70547ab..c62b12d 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1628,6 +1628,11 @@
     "Adds a setting under chrome://settings/security to opt-in to HTTPS-First "
     "Mode.";
 
+const char kHttpsUpgradesName[] = "HTTPS Upgrades";
+const char kHttpsUpgradesDescription[] =
+    "Enable automatically upgrading all top-level navigations to HTTPS with "
+    "fast fallback to HTTP.";
+
 const char kIgnoreGpuBlocklistName[] = "Override software rendering list";
 const char kIgnoreGpuBlocklistDescription[] =
     "Overrides the built-in software rendering list and enables "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 8159897..f53b12a 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -912,6 +912,9 @@
 extern const char kHttpsOnlyModeName[];
 extern const char kHttpsOnlyModeDescription[];
 
+extern const char kHttpsUpgradesName[];
+extern const char kHttpsUpgradesDescription[];
+
 extern const char kIgnoreGpuBlocklistName[];
 extern const char kIgnoreGpuBlocklistDescription[];
 
diff --git a/chrome/browser/history/history_service_factory.cc b/chrome/browser/history/history_service_factory.cc
index 47805db..54e05c5 100644
--- a/chrome/browser/history/history_service_factory.cc
+++ b/chrome/browser/history/history_service_factory.cc
@@ -7,6 +7,7 @@
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/history/chrome_history_client.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/common/channel_info.h"
 #include "components/bookmarks/browser/bookmark_model.h"
 #include "components/history/content/browser/content_visit_delegate.h"
 #include "components/history/content/browser/history_database_helper.h"
@@ -24,8 +25,8 @@
       std::make_unique<ChromeHistoryClient>(
           BookmarkModelFactory::GetForBrowserContext(context)),
       std::make_unique<history::ContentVisitDelegate>(context));
-  if (!history_service->Init(
-          history::HistoryDatabaseParamsForPath(context->GetPath()))) {
+  if (!history_service->Init(history::HistoryDatabaseParamsForPath(
+          context->GetPath(), chrome::GetChannel()))) {
     return nullptr;
   }
   return history_service;
diff --git a/chrome/browser/image_service/DIR_METADATA b/chrome/browser/image_service/DIR_METADATA
new file mode 100644
index 0000000..2ab835b9
--- /dev/null
+++ b/chrome/browser/image_service/DIR_METADATA
@@ -0,0 +1 @@
+mixins: "//components/image_service/COMMON_METADATA"
diff --git a/chrome/browser/image_service/OWNERS b/chrome/browser/image_service/OWNERS
index d912c7e..6e8c67c1 100644
--- a/chrome/browser/image_service/OWNERS
+++ b/chrome/browser/image_service/OWNERS
@@ -1,2 +1 @@
-sophiechang@chromium.org
-tommycli@chromium.org
+file://components/image_service/OWNERS
diff --git a/chrome/browser/image_service/README.md b/chrome/browser/image_service/README.md
index 921b7c82..811664de 100644
--- a/chrome/browser/image_service/README.md
+++ b/chrome/browser/image_service/README.md
@@ -1,4 +1,3 @@
 # //chrome/browser/image_service
 
-Service implementation for Chrome Images feature, to provide relevant images
-for Chrome UI usage.
\ No newline at end of file
+Please see //components/image_service/README.md.
\ No newline at end of file
diff --git a/chrome/browser/image_service/image_service_factory.cc b/chrome/browser/image_service/image_service_factory.cc
index e713a937f..9765eb4 100644
--- a/chrome/browser/image_service/image_service_factory.cc
+++ b/chrome/browser/image_service/image_service_factory.cc
@@ -6,16 +6,16 @@
 
 #include "base/no_destructor.h"
 #include "chrome/browser/autocomplete/chrome_autocomplete_provider_client.h"
-#include "chrome/browser/history_clusters/entity_image_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sync/sync_service_factory.h"
+#include "components/image_service/image_service.h"
 
 namespace image_service {
 
 // static
-history_clusters::EntityImageService* ImageServiceFactory::GetForBrowserContext(
+ImageService* ImageServiceFactory::GetForBrowserContext(
     content::BrowserContext* browser_context) {
-  return static_cast<history_clusters::EntityImageService*>(
+  return static_cast<ImageService*>(
       GetInstance().GetServiceForBrowserContext(browser_context, true));
 }
 
@@ -35,8 +35,7 @@
 KeyedService* ImageServiceFactory::BuildServiceInstanceFor(
     content::BrowserContext* context) const {
   auto* profile = Profile::FromBrowserContext(context);
-  // TODO(tommycli): Move EntityImageService to the image_service component.
-  return new history_clusters::EntityImageService(
+  return new ImageService(
       std::make_unique<ChromeAutocompleteProviderClient>(profile),
       SyncServiceFactory::GetForProfile(profile));
 }
diff --git a/chrome/browser/image_service/image_service_factory.h b/chrome/browser/image_service/image_service_factory.h
index 9f34a3f..50bf00a 100644
--- a/chrome/browser/image_service/image_service_factory.h
+++ b/chrome/browser/image_service/image_service_factory.h
@@ -12,18 +12,16 @@
 class BrowserContext;
 }
 
-namespace history_clusters {
-class EntityImageService;
-}
-
 namespace image_service {
 
+class ImageService;
+
 // Factory for BrowserContext keyed ImageService, which provides images for
 // Journeys related features.
 class ImageServiceFactory : public ProfileKeyedServiceFactory {
  public:
   // This can return nullptr in tests.
-  static history_clusters::EntityImageService* GetForBrowserContext(
+  static ImageService* GetForBrowserContext(
       content::BrowserContext* browser_context);
 
  private:
diff --git a/chrome/browser/lacros/standalone_browser_test_controller.cc b/chrome/browser/lacros/standalone_browser_test_controller.cc
index 7f391dd0..e848e1bc 100644
--- a/chrome/browser/lacros/standalone_browser_test_controller.cc
+++ b/chrome/browser/lacros/standalone_browser_test_controller.cc
@@ -163,14 +163,15 @@
 void StandaloneBrowserTestController::TtsSpeak(
     crosapi::mojom::TtsUtterancePtr mojo_utterance,
     mojo::PendingRemote<crosapi::mojom::TtsUtteranceClient> utterance_client) {
-  std::unique_ptr<content::TtsUtterance> utterance =
-      tts_crosapi_util::FromMojo(mojo_utterance);
+  std::unique_ptr<content::TtsUtterance> lacros_utterance =
+      tts_crosapi_util::CreateUtteranceFromMojo(
+          mojo_utterance, /*should_always_be_spoken=*/true);
   auto event_delegate = std::make_unique<LacrosUtteranceEventDelegate>(
       this, std::move(utterance_client));
-  utterance->SetEventDelegate(event_delegate.get());
-  lacros_utterance_event_delegates_.emplace(utterance->GetId(),
+  lacros_utterance->SetEventDelegate(event_delegate.get());
+  lacros_utterance_event_delegates_.emplace(lacros_utterance->GetId(),
                                             std ::move(event_delegate));
-  tts_crosapi_util::SpeakForTesting(std::move(utterance));
+  tts_crosapi_util::SpeakForTesting(std::move(lacros_utterance));
 }
 
 void StandaloneBrowserTestController::OnUtteranceFinished(int utterance_id) {
diff --git a/chrome/browser/media/cast_mirroring_performance_browsertest.cc b/chrome/browser/media/cast_mirroring_performance_browsertest.cc
index 489edded..7d17726c 100644
--- a/chrome/browser/media/cast_mirroring_performance_browsertest.cc
+++ b/chrome/browser/media/cast_mirroring_performance_browsertest.cc
@@ -886,7 +886,8 @@
         mirroring::mojom::SessionType::AUDIO_AND_VIDEO, endpoint.address(),
         "model_name", "friendly_name", "sender-123", "receiver-456",
         base::Milliseconds(kTargetPlayoutDelayMs),
-        false /* is_remote_playback */, absl::nullopt);
+        false /* is_remote_playback */, absl::nullopt /** refresh_interval */,
+        false /** force_letterboxing */);
     host_->Start(std::move(session_params), std::move(observer_remote),
                  std::move(channel_remote),
                  channel_to_service_.BindNewPipeAndPassReceiver());
@@ -901,6 +902,7 @@
   void DidStop() override {}
   void LogInfoMessage(const std::string& message) override {}
   void LogErrorMessage(const std::string& message) override {}
+  void OnSourceChanged() override {}
 
   // CastMessageChannel implementation (inbound).
   void OnMessage(mirroring::mojom::CastMessagePtr message) override {
diff --git a/chrome/browser/media/cast_mirroring_service_host.cc b/chrome/browser/media/cast_mirroring_service_host.cc
index 1da286f..60c8606 100644
--- a/chrome/browser/media/cast_mirroring_service_host.cc
+++ b/chrome/browser/media/cast_mirroring_service_host.cc
@@ -245,6 +245,16 @@
   ShowCaptureIndicator();
 }
 
+void CastMirroringServiceHost::GetTabSourceId(
+    GetTabSourceIdCallback get_tab_source_id_callback) {
+  if (web_contents()) {
+    std::move(get_tab_source_id_callback)
+        .Run(web_contents()->GetPrimaryMainFrame()->GetFrameTreeNodeId());
+  } else {
+    std::move(get_tab_source_id_callback).Run(-1);
+  }
+}
+
 // static
 gfx::Size CastMirroringServiceHost::GetCaptureResolutionConstraint() {
   absl::optional<gfx::Size> screen_resolution = GetScreenResolution();
diff --git a/chrome/browser/media/cast_mirroring_service_host.h b/chrome/browser/media/cast_mirroring_service_host.h
index 39c4560..b538273 100644
--- a/chrome/browser/media/cast_mirroring_service_host.h
+++ b/chrome/browser/media/cast_mirroring_service_host.h
@@ -77,6 +77,8 @@
              mojo::PendingRemote<mojom::CastMessageChannel> outbound_channel,
              mojo::PendingReceiver<mojom::CastMessageChannel> inbound_channel)
       override;
+  void GetTabSourceId(
+      GetTabSourceIdCallback get_tab_source_id_callback) override;
 
  private:
   friend class CastMirroringServiceHostBrowserTest;
diff --git a/chrome/browser/media/cast_mirroring_service_host_browsertest.cc b/chrome/browser/media/cast_mirroring_service_host_browsertest.cc
index ec19d3c..369876b8 100644
--- a/chrome/browser/media/cast_mirroring_service_host_browsertest.cc
+++ b/chrome/browser/media/cast_mirroring_service_host_browsertest.cc
@@ -8,6 +8,7 @@
 #include "base/containers/flat_map.h"
 #include "base/memory/raw_ptr.h"
 #include "base/run_loop.h"
+#include "base/test/mock_callback.h"
 #include "base/test/test_timeouts.h"
 #include "build/build_config.h"
 #include "chrome/browser/media/router/discovery/access_code/access_code_cast_feature.h"
@@ -197,9 +198,29 @@
     content::WebContents* web_contents =
         browser()->tab_strip_model()->GetActiveWebContents();
     ASSERT_TRUE(web_contents);
+    int web_contents_source_tab_id =
+        web_contents->GetPrimaryMainFrame()->GetFrameTreeNodeId();
+
+    base::MockCallback<CastMirroringServiceHost::GetTabSourceIdCallback>
+        before_update_callback;
+    base::MockCallback<CastMirroringServiceHost::GetTabSourceIdCallback>
+        after_update_callback;
+
+    EXPECT_CALL(before_update_callback, Run(_))
+        .WillOnce([&web_contents_source_tab_id](int32_t source_tab_id) {
+          ASSERT_NE(web_contents_source_tab_id, source_tab_id);
+        });
+
+    EXPECT_CALL(after_update_callback, Run(_))
+        .WillOnce([&web_contents_source_tab_id](int32_t source_tab_id) {
+          ASSERT_EQ(web_contents_source_tab_id, source_tab_id);
+        });
+
+    host_->GetTabSourceId(before_update_callback.Get());
     ASSERT_NE(host_->web_contents(), web_contents);
     host_->SwitchMirroringSourceTab(BuildMediaIdForTabMirroring(web_contents));
     ASSERT_EQ(host_->web_contents(), web_contents);
+    host_->GetTabSourceId(after_update_callback.Get());
   }
 
   void GetVideoCaptureHost() {
@@ -260,17 +281,18 @@
 
  private:
   // mojom::SessionObserver mocks.
-  MOCK_METHOD1(OnError, void(mojom::SessionError));
-  MOCK_METHOD0(DidStart, void());
-  MOCK_METHOD0(DidStop, void());
-  MOCK_METHOD1(LogInfoMessage, void(const std::string&));
-  MOCK_METHOD1(LogErrorMessage, void(const std::string&));
+  MOCK_METHOD(void, OnError, (mojom::SessionError));
+  MOCK_METHOD(void, DidStart, ());
+  MOCK_METHOD(void, DidStop, ());
+  MOCK_METHOD(void, LogInfoMessage, (const std::string&));
+  MOCK_METHOD(void, LogErrorMessage, (const std::string&));
+  MOCK_METHOD(void, OnSourceChanged, ());
 
   // mojom::CastMessageChannel mock implementation (inbound messages).
-  MOCK_METHOD1(OnMessage, void(mojom::CastMessagePtr));
+  MOCK_METHOD(void, OnMessage, (mojom::CastMessagePtr));
 
   // mojom::AudioStreamCreatorClient mocks.
-  MOCK_METHOD0(OnAudioStreamCreated, void());
+  MOCK_METHOD(void, OnAudioStreamCreated, ());
   void StreamCreated(
       mojo::PendingRemote<media::mojom::AudioInputStream> stream,
       mojo::PendingReceiver<media::mojom::AudioInputStreamClient>
diff --git a/chrome/browser/media/router/providers/cast/cast_activity_manager.cc b/chrome/browser/media/router/providers/cast/cast_activity_manager.cc
index 32c6902b..7e1848c3 100644
--- a/chrome/browser/media/router/providers/cast/cast_activity_manager.cc
+++ b/chrome/browser/media/router/providers/cast/cast_activity_manager.cc
@@ -302,7 +302,7 @@
     activity = FindActivityForAutoJoin(cast_source, origin, frame_tree_node_id);
     if (!activity && cast_source.default_action_policy() !=
                          DefaultActionPolicy::kCastThisTab) {
-      auto sink = ConvertMirrorToCast(frame_tree_node_id);
+      auto sink = GetSinkForMirroringActivity(frame_tree_node_id);
       if (sink) {
         LaunchSession(cast_source, *sink, presentation_id, origin,
                       frame_tree_node_id, off_the_record, std::move(callback));
@@ -633,6 +633,26 @@
   }
 }
 
+void CastActivityManager::OnSourceChanged(const std::string& media_route_id,
+                                          int old_frame_tree_node_id,
+                                          int frame_tree_node_id) {
+  auto current_it = routes_by_frame_.find(old_frame_tree_node_id);
+  if (current_it == routes_by_frame_.end() ||
+      current_it->second != media_route_id) {
+    return;
+  }
+
+  auto route_it = routes_by_frame_.find(frame_tree_node_id);
+  if (route_it != routes_by_frame_.end()) {
+    // Session is terminated as to not allow 2 cast sessions to have the same
+    // source tab.
+    TerminateSession(route_it->second, base::DoNothing());
+  }
+
+  routes_by_frame_.erase(old_frame_tree_node_id);
+  routes_by_frame_[frame_tree_node_id] = media_route_id;
+}
+
 // This method is only called in one place, so it should probably be inlined.
 cast_channel::ResultCallback CastActivityManager::MakeResultCallbackForRoute(
     const std::string& route_id,
@@ -1007,8 +1027,8 @@
   media_router_->OnIssue(info);
 }
 
-absl::optional<MediaSinkInternal> CastActivityManager::ConvertMirrorToCast(
-    int frame_tree_node_id) {
+absl::optional<MediaSinkInternal>
+CastActivityManager::GetSinkForMirroringActivity(int frame_tree_node_id) const {
   auto route_it = routes_by_frame_.find(frame_tree_node_id);
   if (route_it == routes_by_frame_.end()) {
     return absl::nullopt;
diff --git a/chrome/browser/media/router/providers/cast/cast_activity_manager.h b/chrome/browser/media/router/providers/cast/cast_activity_manager.h
index 65967c0..81d1d25 100644
--- a/chrome/browser/media/router/providers/cast/cast_activity_manager.h
+++ b/chrome/browser/media/router/providers/cast/cast_activity_manager.h
@@ -119,6 +119,9 @@
   void OnMediaStatusUpdated(const MediaSinkInternal& sink,
                             const base::Value::Dict& media_status,
                             absl::optional<int> request_id) override;
+  void OnSourceChanged(const std::string& media_route_id,
+                       int old_frame_tree_node_id,
+                       int frame_tree_node_id) override;
 
   static void SetActitityFactoryForTest(CastActivityFactoryForTest* factory) {
     cast_activity_factory_for_test_ = factory;
@@ -282,7 +285,8 @@
 
   // Returns a sink used to convert a mirroring activity to a cast activity.
   // If no conversion should occur, returns absl::nullopt.
-  absl::optional<MediaSinkInternal> ConvertMirrorToCast(int frame_tree_node_id);
+  absl::optional<MediaSinkInternal> GetSinkForMirroringActivity(
+      int frame_tree_node_id) const;
 
   std::string ChooseAppId(const CastMediaSource& source,
                           const MediaSinkInternal& sink) const;
diff --git a/chrome/browser/media/router/providers/cast/cast_activity_manager_unittest.cc b/chrome/browser/media/router/providers/cast/cast_activity_manager_unittest.cc
index bffcbf5a..4e9063c 100644
--- a/chrome/browser/media/router/providers/cast/cast_activity_manager_unittest.cc
+++ b/chrome/browser/media/router/providers/cast/cast_activity_manager_unittest.cc
@@ -351,8 +351,6 @@
   }
 
   void LaunchNonSdkMirroringSession() {
-    CallLaunchSessionSuccess(cast_streaming_app_id_, /* app_params */ "",
-                             /* client_id */ "");
     mirroring_activity_callback_ =
         base::BindLambdaForTesting([this](MockMirroringActivity* activity) {
           EXPECT_CALL(*activity, OnSessionSet).WillOnce([this]() {
@@ -361,6 +359,9 @@
           mirroring_activity_callback_ = base::DoNothing();
         });
 
+    CallLaunchSessionSuccess(cast_streaming_app_id_, /* app_params */ "",
+                             /* client_id */ "");
+
     ResolveMirroringSessionLaunch();
   }
 
@@ -475,6 +476,50 @@
     session_tracker_->SetSessionForTest(sink_id, std::move(session));
   }
 
+  // This method starts out with `route_id_to_move` associated with
+  // `frame_id_before`, and `route_id_to_terminate` with `frame_id_after`. We
+  // move `route_id_to_move` to `frame_id_after`, and that results in the
+  // termination of `route_id_to_terminate`.
+  void UpdateRouteSourceTabInRoutesMap(
+      int frame_id_before,
+      const MediaRoute::Id& route_id_to_move,
+      int frame_id_after,
+      const MediaRoute::Id& route_id_to_terminate) {
+    EXPECT_EQ(2u, manager_->GetRoutes().size());
+
+    // `route_id_to_move` is connected to `sink_`.
+    EXPECT_TRUE(manager_->GetRoute(route_id_to_move));
+    EXPECT_EQ(manager_->GetSinkForMirroringActivity(frame_id_before), sink_);
+
+    // `route_id_to_terminate` is connected to `sink2_`.
+    EXPECT_TRUE(manager_->GetRoute(route_id_to_terminate));
+    EXPECT_EQ(manager_->GetSinkForMirroringActivity(frame_id_after), sink2_);
+
+    session_tracker_->OnSourceChanged(route_id_to_move, frame_id_before,
+                                      frame_id_after);
+    // The route with id `route_id_to_terminate` should be terminated.
+    // `frame_id_before` should have no route connected to it.
+    // `frame_id_after` should be connected to `route_id_to_move`.
+
+    // Verify that `route_id_to_terminate` was terminated.
+    EXPECT_EQ(1u, manager_->GetRoutes().size());
+    EXPECT_FALSE(manager_->GetRoute(route_id_to_terminate));
+    EXPECT_TRUE(manager_->GetRoute(route_id_to_move));
+
+    // Verify that the source tab has been updated.
+    EXPECT_FALSE(manager_->GetSinkForMirroringActivity(frame_id_before));
+    EXPECT_EQ(manager_->GetSinkForMirroringActivity(frame_id_after), sink_);
+
+    session_tracker_->OnSourceChanged(route_id_to_move, frame_id_before,
+                                      frame_id_after);
+    // Nothing is expected to happen as there is no route exist for the given
+    // `frame_id_before`.
+    EXPECT_EQ(1u, manager_->GetRoutes().size());
+    EXPECT_TRUE(manager_->GetRoute(route_id_to_move));
+    EXPECT_FALSE(manager_->GetSinkForMirroringActivity(frame_id_before));
+    EXPECT_EQ(manager_->GetSinkForMirroringActivity(frame_id_after), sink_);
+  }
+
  protected:
   content::BrowserTaskEnvironment task_environment_;
   data_decoder::test::InProcessDataDecoder in_process_data_decoder_;
@@ -887,4 +932,39 @@
   }
 }
 
+TEST_F(CastActivityManagerTest, OnSourceChanged) {
+  LaunchNonSdkMirroringSession();
+
+  MediaRoute::Id route_id = MediaRoute::GetMediaRouteId(
+      kPresentationId, sink_.id(),
+      MediaSource(MakeSourceId(cast_streaming_app_id_, /* app_params */ "",
+                               /* client_id */ "")));
+
+  // Launch a 2nd session from a different tab on a different sink.
+  media_sink_service_.AddOrUpdateSink(sink2_);
+  EXPECT_CALL(message_handler_,
+              LaunchSession(kChannelId2, cast_streaming_app_id_, _, _, _, _))
+      .WillOnce(WithArg<5>([this](auto callback) {
+        launch_session_callback_ = std::move(callback);
+      }));
+
+  auto source2 =
+      CastMediaSource::FromMediaSourceId(MakeSourceId(cast_streaming_app_id_));
+  manager_->LaunchSession(
+      *source2, sink2_, kPresentationId2, origin_,
+      kFrameTreeNodeId2, /*incognito*/
+      false,
+      base::BindOnce(&CastActivityManagerTest::ExpectLaunchSessionSuccess,
+                     base::Unretained(this)));
+
+  RunUntilIdle();
+  ReceiveLaunchSuccessResponseFromReceiver(cast_streaming_app_id_);
+
+  MediaRoute::Id route_id2 = MediaRoute::GetMediaRouteId(
+      kPresentationId2, sink2_.id(), MediaSource(source2->source_id()));
+
+  UpdateRouteSourceTabInRoutesMap(kFrameTreeNodeId, route_id, kFrameTreeNodeId2,
+                                  route_id2);
+}
+
 }  // namespace media_router
diff --git a/chrome/browser/media/router/providers/cast/cast_session_tracker.cc b/chrome/browser/media/router/providers/cast/cast_session_tracker.cc
index e19dabd..edf8c304 100644
--- a/chrome/browser/media/router/providers/cast/cast_session_tracker.cc
+++ b/chrome/browser/media/router/providers/cast/cast_session_tracker.cc
@@ -54,6 +54,15 @@
   return it != sessions_by_sink_id_.end() ? it->second.get() : nullptr;
 }
 
+void CastSessionTracker::OnSourceChanged(const std::string& media_route_id,
+                                         int old_frame_tree_node_id,
+                                         int frame_tree_node_id) {
+  for (auto& observer : observers_) {
+    observer.OnSourceChanged(media_route_id, old_frame_tree_node_id,
+                             frame_tree_node_id);
+  }
+}
+
 CastSessionTracker::CastSessionTracker(
     MediaSinkServiceBase* media_sink_service,
     cast_channel::CastMessageHandler* message_handler,
diff --git a/chrome/browser/media/router/providers/cast/cast_session_tracker.h b/chrome/browser/media/router/providers/cast/cast_session_tracker.h
index 15fcb685..1c39f7731 100644
--- a/chrome/browser/media/router/providers/cast/cast_session_tracker.h
+++ b/chrome/browser/media/router/providers/cast/cast_session_tracker.h
@@ -38,6 +38,9 @@
     virtual void OnMediaStatusUpdated(const MediaSinkInternal& sink,
                                       const base::Value::Dict& media_status,
                                       absl::optional<int> request_id) = 0;
+    virtual void OnSourceChanged(const std::string& media_route_id,
+                                 int old_frame_tree_node_id,
+                                 int frame_tree_node_id) = 0;
   };
 
   CastSessionTracker(const CastSessionTracker&) = delete;
@@ -60,6 +63,10 @@
   // Returns nullptr if there is no session with the specified ID.
   CastSession* GetSessionById(const std::string& session_id) const;
 
+  void OnSourceChanged(const std::string& media_route_id,
+                       int old_frame_tree_node_id,
+                       int frame_tree_node_id);
+
  private:
   friend class CastSessionTrackerTest;
   friend class CastActivityManagerTest;
diff --git a/chrome/browser/media/router/providers/cast/cast_session_tracker_unittest.cc b/chrome/browser/media/router/providers/cast/cast_session_tracker_unittest.cc
index 1add3b42..432da378 100644
--- a/chrome/browser/media/router/providers/cast/cast_session_tracker_unittest.cc
+++ b/chrome/browser/media/router/providers/cast/cast_session_tracker_unittest.cc
@@ -69,13 +69,20 @@
   MockCastSessionObserver() = default;
   ~MockCastSessionObserver() override = default;
 
-  MOCK_METHOD2(OnSessionAddedOrUpdated,
-               void(const MediaSinkInternal& sink, const CastSession& session));
-  MOCK_METHOD1(OnSessionRemoved, void(const MediaSinkInternal& sink));
-  MOCK_METHOD3(OnMediaStatusUpdated,
-               void(const MediaSinkInternal& sink,
-                    const base::Value::Dict& media_status,
-                    absl::optional<int> request_id));
+  MOCK_METHOD(void,
+              OnSessionAddedOrUpdated,
+              (const MediaSinkInternal& sink, const CastSession& session));
+  MOCK_METHOD(void, OnSessionRemoved, (const MediaSinkInternal& sink));
+  MOCK_METHOD(void,
+              OnMediaStatusUpdated,
+              (const MediaSinkInternal& sink,
+               const base::Value::Dict& media_status,
+               absl::optional<int> request_id));
+  MOCK_METHOD(void,
+              OnSourceChanged,
+              (const std::string& media_route_id,
+               int old_frame_tree_node_id,
+               int frame_tree_node_id));
 };
 
 class CastSessionTrackerTest : public testing::Test {
diff --git a/chrome/browser/media/router/providers/cast/mirroring_activity.cc b/chrome/browser/media/router/providers/cast/mirroring_activity.cc
index bb33a399..02a6cc1d 100644
--- a/chrome/browser/media/router/providers/cast/mirroring_activity.cc
+++ b/chrome/browser/media/router/providers/cast/mirroring_activity.cc
@@ -10,12 +10,14 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/command_line.h"
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/user_metrics.h"
 #include "base/metrics/user_metrics_action.h"
 #include "base/strings/strcat.h"
+#include "base/strings/string_piece.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
@@ -131,6 +133,15 @@
   return absl::nullopt;
 }
 
+// TODO(crbug.com/1363512): Remove support for sender side letterboxing.
+bool ShouldForceLetterboxing(base::StringPiece model_name) {
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          "disable-cast-letterboxing")) {
+    return false;
+  }
+  return model_name.find("Nest Hub") != base::StringPiece::npos;
+}
+
 }  // namespace
 
 MirroringActivity::MirroringActivity(
@@ -282,6 +293,20 @@
                     route_.media_source().id(), route_.presentation_id());
 }
 
+void MirroringActivity::OnSourceChanged() {
+  host_->GetTabSourceId(base::BindOnce(&MirroringActivity::UpdateSourceTab,
+                                       weak_ptr_factory_.GetWeakPtr()));
+}
+
+void MirroringActivity::UpdateSourceTab(int32_t frame_tree_node_id) {
+  if (frame_tree_node_id == -1 || frame_tree_node_id == frame_tree_node_id_)
+    return;
+
+  session_tracker_->OnSourceChanged(route_.media_route_id(),
+                                    frame_tree_node_id_, frame_tree_node_id);
+  frame_tree_node_id_ = frame_tree_node_id;
+}
+
 void MirroringActivity::OnMessage(mirroring::mojom::CastMessagePtr message) {
   DCHECK(message);
   DVLOG(2) << "Relaying message to receiver: " << message->json_format_data;
@@ -466,7 +491,8 @@
           sink_.sink().name(), session.destination_id(),
           message_handler_->source_id(), cast_source->target_playout_delay(),
           route().media_source().IsRemotePlaybackSource(),
-          GetMirroringRefreshInterval()),
+          GetMirroringRefreshInterval(),
+          ShouldForceLetterboxing(cast_data_.model_name)),
       std::move(observer_remote), std::move(channel_remote),
       std::move(channel_to_service_receiver_));
 }
diff --git a/chrome/browser/media/router/providers/cast/mirroring_activity.h b/chrome/browser/media/router/providers/cast/mirroring_activity.h
index 507c91d..1fb933c 100644
--- a/chrome/browser/media/router/providers/cast/mirroring_activity.h
+++ b/chrome/browser/media/router/providers/cast/mirroring_activity.h
@@ -61,6 +61,7 @@
   void DidStop() override;
   void LogInfoMessage(const std::string& message) override;
   void LogErrorMessage(const std::string& message) override;
+  void OnSourceChanged() override;
 
   // CastMessageChannel implementation
   void OnMessage(mirroring::mojom::CastMessagePtr message) override;
@@ -78,12 +79,15 @@
 
  private:
   FRIEND_TEST_ALL_PREFIXES(MirroringActivityTest, GetScrubbedLogMessage);
+  FRIEND_TEST_ALL_PREFIXES(MirroringActivityTest, OnSourceChanged);
 
   void HandleParseJsonResult(const std::string& route_id,
                              data_decoder::DataDecoder::ValueOrError result);
 
   void StopMirroring();
 
+  void UpdateSourceTab(int32_t frame_tree_node_id);
+
   // Scrubs AES related data in messages with type "OFFER".
   static std::string GetScrubbedLogMessage(const base::Value::Dict& message);
 
@@ -116,7 +120,7 @@
   const absl::optional<MirroringType> mirroring_type_;
 
   // The FrameTreeNode ID to retrieve the WebContents of the tab to mirror.
-  const int frame_tree_node_id_;
+  int frame_tree_node_id_;
   const CastSinkExtraData cast_data_;
   OnStopCallback on_stop_;
   base::WeakPtrFactory<MirroringActivity> weak_ptr_factory_{this};
diff --git a/chrome/browser/media/router/providers/cast/mirroring_activity_unittest.cc b/chrome/browser/media/router/providers/cast/mirroring_activity_unittest.cc
index 8a3df35..60405ef 100644
--- a/chrome/browser/media/router/providers/cast/mirroring_activity_unittest.cc
+++ b/chrome/browser/media/router/providers/cast/mirroring_activity_unittest.cc
@@ -50,21 +50,43 @@
 constexpr char kHistogramSessionLengthTab[] =
     "MediaRouter.CastStreaming.Session.Length.Tab";
 
+class MockCastSessionTrackerObserver : public CastSessionTracker::Observer {
+ public:
+  MockCastSessionTrackerObserver() = default;
+  ~MockCastSessionTrackerObserver() override = default;
+
+  MOCK_METHOD(void,
+              OnSessionAddedOrUpdated,
+              (const MediaSinkInternal& sink, const CastSession& session));
+  MOCK_METHOD(void, OnSessionRemoved, (const MediaSinkInternal& sink));
+  MOCK_METHOD(void,
+              OnMediaStatusUpdated,
+              (const MediaSinkInternal& sink,
+               const base::Value::Dict& media_status,
+               absl::optional<int> request_id));
+  MOCK_METHOD(void,
+              OnSourceChanged,
+              (const std::string& media_route_id,
+               int old_frame_tree_node_id,
+               int frame_tree_node_id));
+};
+
 class MockMirroringServiceHost : public mirroring::mojom::MirroringServiceHost {
  public:
-  MOCK_METHOD4(
-      Start,
-      void(mirroring::mojom::SessionParametersPtr params,
-           mojo::PendingRemote<mirroring::mojom::SessionObserver> observer,
-           mojo::PendingRemote<mirroring::mojom::CastMessageChannel>
-               outbound_channel,
-           mojo::PendingReceiver<mirroring::mojom::CastMessageChannel>
-               inbound_channel));
+  MOCK_METHOD(void,
+              Start,
+              (mirroring::mojom::SessionParametersPtr params,
+               mojo::PendingRemote<mirroring::mojom::SessionObserver> observer,
+               mojo::PendingRemote<mirroring::mojom::CastMessageChannel>
+                   outbound_channel,
+               mojo::PendingReceiver<mirroring::mojom::CastMessageChannel>
+                   inbound_channel));
+  MOCK_METHOD(void, GetTabSourceId, (GetTabSourceIdCallback callback));
 };
 
 class MockCastMessageChannel : public mirroring::mojom::CastMessageChannel {
  public:
-  MOCK_METHOD1(OnMessage, void(mirroring::mojom::CastMessagePtr message));
+  MOCK_METHOD(void, OnMessage, (mirroring::mojom::CastMessagePtr message));
 };
 
 }  // namespace
@@ -437,4 +459,32 @@
   activity_->SendMessageToClient(kClientId, std::move(message));
 }
 
+TEST_F(MirroringActivityTest, OnSourceChanged) {
+  MakeActivity();
+  MockCastSessionTrackerObserver session_tracker_observer_;
+  session_tracker_.AddObserver(&session_tracker_observer_);
+
+  // A random int indicating the new tab source.
+  const int new_tab_source = 3;
+
+  EXPECT_CALL(*mirroring_service_, GetTabSourceId(_))
+      .WillOnce([](MockMirroringServiceHost::GetTabSourceIdCallback callback) {
+        std::move(callback).Run(new_tab_source);
+      });
+
+  EXPECT_CALL(session_tracker_observer_,
+              OnSourceChanged(kRouteId, kFrameTreeNodeId, new_tab_source));
+
+  EXPECT_EQ(activity_->frame_tree_node_id_, kFrameTreeNodeId);
+  activity_->OnSourceChanged();
+  RunUntilIdle();
+  EXPECT_EQ(activity_->frame_tree_node_id_, new_tab_source);
+  testing::Mock::VerifyAndClearExpectations(mirroring_service_);
+  testing::Mock::VerifyAndClearExpectations(&session_tracker_observer_);
+
+  // Nothing should happen as -1 is invalid value for tab source.
+  activity_->UpdateSourceTab(-1);
+  EXPECT_EQ(activity_->frame_tree_node_id_, new_tab_source);
+}
+
 }  // namespace media_router
diff --git a/chrome/browser/net/net_error_tab_helper.cc b/chrome/browser/net/net_error_tab_helper.cc
index 4c78453..ba717d41 100644
--- a/chrome/browser/net/net_error_tab_helper.cc
+++ b/chrome/browser/net/net_error_tab_helper.cc
@@ -31,6 +31,11 @@
 #include "components/offline_pages/core/client_namespace_constants.h"
 #endif  // BUILDFLAG(ENABLE_OFFLINE_PAGES)
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+#include "ash/constants/ash_features.h"
+#include "chrome/browser/ui/ash/network/network_portal_signin_controller.h"
+#endif
+
 using content::BrowserContext;
 using content::BrowserThread;
 using content::WebContents;
@@ -159,6 +164,23 @@
 }
 #endif  // BUILDFLAG(ENABLE_OFFLINE_PAGES)
 
+#if BUILDFLAG(IS_CHROMEOS)
+void NetErrorTabHelper::ShowPortalSignin() {
+  // TODO(b/247618374): Lacros implementation.
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  if (!ash::features::IsCaptivePortalErrorPageEnabled()) {
+    mojo::ReportBadMessage("Captive Portal Error Page feature not enabled");
+    return;
+  }
+  if (!portal_signin_controller_) {
+    portal_signin_controller_ =
+        std::make_unique<ash::NetworkPortalSigninController>();
+  }
+  portal_signin_controller_->ShowSignin();
+#endif
+}
+#endif
+
 NetErrorTabHelper::NetErrorTabHelper(WebContents* contents)
     : WebContentsObserver(contents),
       content::WebContentsUserData<NetErrorTabHelper>(*contents),
diff --git a/chrome/browser/net/net_error_tab_helper.h b/chrome/browser/net/net_error_tab_helper.h
index 84e58dd..5751ba61 100644
--- a/chrome/browser/net/net_error_tab_helper.h
+++ b/chrome/browser/net/net_error_tab_helper.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_NET_NET_ERROR_TAB_HELPER_H_
 #define CHROME_BROWSER_NET_NET_ERROR_TAB_HELPER_H_
 
+#include <memory>
 #include <string>
 
 #include "base/bind.h"
@@ -21,6 +22,12 @@
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_contents_user_data.h"
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+namespace ash {
+class NetworkPortalSigninController;
+}
+#endif
+
 namespace user_prefs {
 class PrefRegistrySyncable;
 }  // namespace user_prefs
@@ -92,6 +99,9 @@
   void SetIsShowingDownloadButtonInErrorPage(
       bool showing_download_button) override;
 #endif  // BUILDFLAG(ENABLE_OFFLINE_PAGES)
+#if BUILDFLAG(IS_CHROMEOS)
+  void ShowPortalSignin() override;
+#endif
 
  protected:
   // |contents| is the WebContents of the tab this NetErrorTabHelper is
@@ -173,6 +183,10 @@
   // Preference storing the user's current easter egg game high score.
   IntegerPrefMember easter_egg_high_score_;
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+  std::unique_ptr<ash::NetworkPortalSigninController> portal_signin_controller_;
+#endif
+
   base::WeakPtrFactory<NetErrorTabHelper> weak_factory_{this};
 
   WEB_CONTENTS_USER_DATA_KEY_DECL();
diff --git a/chrome/browser/page_load_metrics/integration_tests/cross_document_resource_reuse_test.cc b/chrome/browser/page_load_metrics/integration_tests/cross_document_resource_reuse_test.cc
index 509338b..b0c69270 100644
--- a/chrome/browser/page_load_metrics/integration_tests/cross_document_resource_reuse_test.cc
+++ b/chrome/browser/page_load_metrics/integration_tests/cross_document_resource_reuse_test.cc
@@ -30,6 +30,6 @@
   metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
 
   ExpectUniqueUMABucketCount(
-      "Blink.MemoryCache.CrossDocumentCachedResource",
+      "Blink.MemoryCache.CrossDocumentCachedResource2",
       static_cast<base::Histogram::Sample>(blink::ResourceType::kImage), 1);
 }
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
index 85e093e..607eaf2 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
+++ b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
@@ -3381,6 +3381,23 @@
         ->DiscardTab(mojom::LifecycleUnitDiscardReason::URGENT);
   }
 
+  void CloseTab(content::WebContents* contents) {
+    auto* tab_strip_model = browser()->tab_strip_model();
+    // Get the total count of tabs.
+    int tab_count = tab_strip_model->count();
+
+    // Get the tab index of the given WebContents.
+    int tab_index = tab_strip_model->GetIndexOfWebContents(contents);
+    // Expect the tab index of the given WebContents is found.
+    EXPECT_NE(tab_index, TabStripModel::kNoTab);
+
+    // Close the tab corresponding to the given WebContents.
+    tab_strip_model->CloseWebContentsAt(tab_index,
+                                        TabCloseTypes::CLOSE_USER_GESTURE);
+    // Verify tab is closed.
+    EXPECT_EQ(tab_strip_model->count(), tab_count - 1);
+  }
+
   std::string ScriptForGettingLCPTimeFromEmittedLCPEntry() {
     return R"(
    (async () => {
@@ -3402,43 +3419,26 @@
   }
 };
 
-IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTestTerminatedPage,
-                       UkmIsRecordedForDiscardedForegroundTabPage) {
-  // Open a new foreground tab and navigate. The new tab would be of index 1
-  // which would be used below in verifying the tab is discarded.
-  content::WebContents* contents = OpenTabAndNavigate();
+class PageLoadMetricsBrowserTestDiscardedPage
+    : public PageLoadMetricsBrowserTestTerminatedPage,
+      public ::testing::WithParamInterface<bool> {};
 
-  // Wait for LCP emission and observation. This is to ensure there is an LCP
-  // entry to report at the time of discardin the page.
-  double lcp_time = GetLCPTimeFromEmittedLCPEntry(contents);
-
-  // Discard tab.
-  DiscardTab(contents);
-
-  // Verify tab is discarded.
-  EXPECT_TRUE(
-      browser()->tab_strip_model()->GetWebContentsAt(1)->WasDiscarded());
-
-  // Verify page load metric is recorded.
-  EXPECT_NEAR(
-      GetUKMPageLoadMetric(
-          PageLoad::kPaintTiming_NavigationToLargestContentfulPaint2Name),
-      lcp_time, 10);
-}
-
-IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTestTerminatedPage,
-                       UkmIsRecordedForDiscardedBackgroundTabPage) {
+IN_PROC_BROWSER_TEST_P(PageLoadMetricsBrowserTestDiscardedPage,
+                       UkmIsRecordedForDiscardedTabPage) {
   // Open a new foreground tab and navigate.
   content::WebContents* contents = OpenTabAndNavigate();
 
   // Wait for LCP emission and observation.
   double lcp_time = GetLCPTimeFromEmittedLCPEntry(contents);
 
-  // Add a new tab.
-  AddNewTab();
+  // Background current tab by adding a new tab if provided param is true.
+  if (GetParam()) {
+    // Add a new tab.
+    AddNewTab();
 
-  // Verify the first tab is backgrounded.
-  EXPECT_NE(contents, browser()->tab_strip_model()->GetActiveWebContents());
+    // Verify the first tab is backgrounded.
+    EXPECT_NE(contents, browser()->tab_strip_model()->GetActiveWebContents());
+  }
 
   // Discard tab.
   DiscardTab(contents);
@@ -3454,6 +3454,47 @@
       lcp_time, 10);
 }
 
+INSTANTIATE_TEST_SUITE_P(DiscardedPages,
+                         PageLoadMetricsBrowserTestDiscardedPage,
+                         testing::Bool());
+
+class PageLoadMetricsBrowserTestClosedPage
+    : public PageLoadMetricsBrowserTestTerminatedPage,
+      public ::testing::WithParamInterface<bool> {};
+
+IN_PROC_BROWSER_TEST_P(PageLoadMetricsBrowserTestClosedPage,
+                       UkmIsRecordedForClosedTabPage) {
+  // Open a new foreground tab and navigate. The new tab would be of index 1
+  // which would be used below in verifying the tab is discarded.
+  content::WebContents* contents = OpenTabAndNavigate();
+
+  // Wait for LCP emission and observation. This is to ensure there is an LCP
+  // entry to report at the time of closing the page.
+  double lcp_time = GetLCPTimeFromEmittedLCPEntry(contents);
+
+  // Background current tab by adding a new tab if provided param is true.
+  if (GetParam()) {
+    // Add a new tab.
+    AddNewTab();
+
+    // Verify the tab is backgrounded.
+    EXPECT_NE(contents, browser()->tab_strip_model()->GetActiveWebContents());
+  }
+
+  // close tab.
+  CloseTab(contents);
+
+  // Verify page load metric is recorded.
+  EXPECT_NEAR(
+      GetUKMPageLoadMetric(
+          PageLoad::kPaintTiming_NavigationToLargestContentfulPaint2Name),
+      lcp_time, 10);
+}
+
+INSTANTIATE_TEST_SUITE_P(ClosedPages,
+                         PageLoadMetricsBrowserTestClosedPage,
+                         testing::Bool());
+
 // This test is to verify page load metrics are recorded in case when the
 // render process is shut down.
 IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTestTerminatedPage,
diff --git a/chrome/browser/pdf/pdf_extension_interactive_uitest.cc b/chrome/browser/pdf/pdf_extension_interactive_uitest.cc
index b118fc2..7818e16 100644
--- a/chrome/browser/pdf/pdf_extension_interactive_uitest.cc
+++ b/chrome/browser/pdf/pdf_extension_interactive_uitest.cc
@@ -195,16 +195,15 @@
 }
 
 IN_PROC_BROWSER_TEST_F(PDFExtensionInteractiveUITest, FocusReverseTraversal) {
-  content::WebContents* guest_contents = LoadPdfGetGuestContents(
+  extensions::MimeHandlerViewGuest* guest = LoadPdfGetMimeHandlerView(
       embedded_test_server()->GetURL("/pdf/test.pdf#toolbar=0"));
 
   // Tab in.
-  content::FocusedNodeDetails details =
-      TabAndWait(guest_contents, /*forward=*/false);
+  content::FocusedNodeDetails details = TabAndWait(guest, /*forward=*/false);
   EXPECT_EQ(blink::mojom::FocusType::kBackward, details.focus_type);
 
   // Tab out.
-  details = TabAndWait(guest_contents, /*forward=*/false);
+  details = TabAndWait(guest, /*forward=*/false);
   EXPECT_EQ(blink::mojom::FocusType::kNone, details.focus_type);
 }
 
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc
index acf9c1b..fce09322 100644
--- a/chrome/browser/pdf/pdf_extension_test.cc
+++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -102,6 +102,7 @@
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/fenced_frame_test_util.h"
+#include "content/public/test/hit_test_region_observer.h"
 #include "content/public/test/prerender_test_util.h"
 #include "content/public/test/scoped_time_zone.h"
 #include "content/public/test/test_navigation_observer.h"
@@ -388,6 +389,20 @@
     return content::GetAccessibilityTreeSnapshotFromId(pdf_tree_id);
   }
 
+  void SimulateMouseClickAt(extensions::MimeHandlerViewGuest* guest,
+                            int modifiers,
+                            blink::WebMouseEvent::Button button,
+                            const gfx::Point& point_in_guest) {
+    auto* guest_main_frame = guest->GetGuestMainFrame();
+    content::WaitForHitTestData(guest_main_frame);
+
+    const gfx::Point point_in_root_coords =
+        guest_main_frame->GetView()->TransformPointToRootCoordSpace(
+            point_in_guest);
+    content::SimulateMouseClickAt(guest->embedder_web_contents(), modifiers,
+                                  button, point_in_root_coords);
+  }
+
   // Hooks to set up feature flags.
   virtual std::vector<base::test::FeatureRef> GetEnabledFeatures() const {
     return {};
@@ -2065,25 +2080,23 @@
 IN_PROC_BROWSER_TEST_F(
     PDFExtensionTest,
     DISABLED_ContextMenuPrintCommandEmbeddedExtensionMainFrame) {
-  content::WebContents* guest_contents = LoadPdfGetGuestContents(
+  MimeHandlerViewGuest* guest = LoadPdfGetMimeHandlerView(
       embedded_test_server()->GetURL("/pdf/pdf_embed.html"));
-  content::RenderFrameHost* plugin_frame = GetPluginFrame(guest_contents);
+  content::RenderFrameHost* plugin_frame = GetPluginFrame(guest);
   ASSERT_TRUE(plugin_frame);
 
+  content::RenderFrameHost* guest_main_frame = guest->GetGuestMainFrame();
   // Makes sure that the correct frame invoked the context menu.
-  content::ContextMenuInterceptor menu_interceptor(
-      guest_contents->GetPrimaryMainFrame());
+  content::ContextMenuInterceptor menu_interceptor(guest_main_frame);
 
   // Executes the print command as soon as the context menu is shown.
   ContextMenuNotificationObserver context_menu_observer(IDC_PRINT);
 
   PrintObserver print_observer(plugin_frame);
-  content::SimulateMouseClickAt(guest_contents,
-                                blink::WebInputEvent::kNoModifiers,
-                                blink::WebMouseEvent::Button::kLeft, {1, 1});
-  guest_contents->GetPrimaryMainFrame()
-      ->GetRenderWidgetHost()
-      ->ShowContextMenuAtPoint({1, 1}, ui::MENU_SOURCE_MOUSE);
+  SimulateMouseClickAt(guest, blink::WebInputEvent::kNoModifiers,
+                       blink::WebMouseEvent::Button::kLeft, {1, 1});
+  guest_main_frame->GetRenderWidgetHost()->ShowContextMenuAtPoint(
+      {1, 1}, ui::MENU_SOURCE_MOUSE);
   print_observer.WaitForPrintPreview();
   menu_interceptor.Wait();
 }
@@ -2111,9 +2124,9 @@
 // TODO(crbug.com/1330032): Fix flakiness.
 IN_PROC_BROWSER_TEST_F(PDFExtensionTest,
                        DISABLED_ContextMenuPrintCommandEmbeddedPluginFrame) {
-  content::WebContents* guest_contents = LoadPdfGetGuestContents(
+  MimeHandlerViewGuest* guest = LoadPdfGetMimeHandlerView(
       embedded_test_server()->GetURL("/pdf/pdf_embed.html"));
-  content::RenderFrameHost* plugin_frame = GetPluginFrame(guest_contents);
+  content::RenderFrameHost* plugin_frame = GetPluginFrame(guest);
   ASSERT_TRUE(plugin_frame);
 
   // Makes sure that the correct frame invoked the context menu.
@@ -2123,7 +2136,7 @@
   ContextMenuNotificationObserver context_menu_observer(IDC_PRINT);
 
   PrintObserver print_observer(plugin_frame);
-  SetInputFocusOnPlugin(guest_contents);
+  SetInputFocusOnPlugin(guest);
   plugin_frame->GetRenderWidgetHost()->ShowContextMenuAtPoint(
       {1, 1}, ui::MENU_SOURCE_MOUSE);
   print_observer.WaitForPrintPreview();
@@ -4366,17 +4379,18 @@
                        LinkNavigation) {
   // Enable accessibility and load the test file.
   content::BrowserAccessibilityState::GetInstance()->EnableAccessibility();
-  WebContents* guest_contents = LoadPdfGetGuestContents(
+  MimeHandlerViewGuest* guest = LoadPdfGetMimeHandlerView(
       embedded_test_server()->GetURL("/pdf/accessibility/weblinks.pdf"));
-  ASSERT_TRUE(guest_contents);
-  WaitForAccessibilityTreeToContainNodeWithName(guest_contents, "Page 1");
+  ASSERT_TRUE(guest);
+  WaitForAccessibilityTreeToContainNodeWithName(GetActiveWebContents(),
+                                                "Page 1");
 
   // Find the specific link node.
   content::FindAccessibilityNodeCriteria find_criteria;
   find_criteria.role = ax::mojom::Role::kLink;
   find_criteria.name = "http://bing.com";
   ui::AXPlatformNodeDelegate* link_node =
-      content::FindAccessibilityNode(guest_contents, find_criteria);
+      content::FindAccessibilityNode(GetActiveWebContents(), find_criteria);
   ASSERT_TRUE(link_node);
 
   // Invoke action on a link and wait for navigation to complete.
@@ -4481,17 +4495,20 @@
 #define MAYBE_SubmitForm SubmitForm
 #endif
 IN_PROC_BROWSER_TEST_F(PDFExtensionSubmitFormTest, MAYBE_SubmitForm) {
-  WebContents* guest_contents = LoadPdfGetGuestContents(
+  MimeHandlerViewGuest* guest = LoadPdfGetMimeHandlerView(
       embedded_test_server()->GetURL("/pdf/submit_form.pdf"));
-  ASSERT_TRUE(guest_contents);
+  ASSERT_TRUE(guest);
+
+  content::RenderFrameHost* guest_mainframe = guest->GetGuestMainFrame();
+  ASSERT_TRUE(guest_mainframe);
 
   std::unique_ptr<base::RunLoop> run_loop = CreateFormSubmissionRunLoop();
 
   // Click on the "Submit Form" button.
   content::SimulateMouseClickAt(
-      guest_contents, blink::WebInputEvent::kNoModifiers,
+      GetActiveWebContents(), blink::WebInputEvent::kNoModifiers,
       blink::WebMouseEvent::Button::kLeft,
-      ConvertPageCoordToScreenCoord(guest_contents, {200, 200}));
+      ConvertPageCoordToScreenCoord(guest_mainframe, {200, 200}));
 
   run_loop->Run();
 }
diff --git a/chrome/browser/picture_in_picture/video_picture_in_picture_window_controller_browsertest.cc b/chrome/browser/picture_in_picture/video_picture_in_picture_window_controller_browsertest.cc
index d631bb1..303a8eee 100644
--- a/chrome/browser/picture_in_picture/video_picture_in_picture_window_controller_browsertest.cc
+++ b/chrome/browser/picture_in_picture/video_picture_in_picture_window_controller_browsertest.cc
@@ -26,11 +26,6 @@
 #include "chrome/browser/ui/views/overlay/skip_ad_label_button.h"
 #include "chrome/browser/ui/views/overlay/toggle_camera_button.h"
 #include "chrome/browser/ui/views/overlay/toggle_microphone_button.h"
-#include "chrome/browser/ui/web_applications/app_browser_controller.h"
-#include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h"
-#include "chrome/browser/ui/web_applications/web_app_controller_browsertest.h"
-#include "chrome/browser/web_applications/user_display_mode.h"
-#include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/viz/common/frame_sinks/copy_output_request.h"
@@ -2011,381 +2006,6 @@
   WaitForTitle(active_web_contents, u"leavepictureinpicture");
 }
 
-class AutoVideoPictureInPictureWindowControllerBrowserTest
-    : public VideoPictureInPictureWindowControllerBrowserTest {
- public:
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    VideoPictureInPictureWindowControllerBrowserTest::SetUpCommandLine(
-        command_line);
-    command_line->AppendSwitchASCII(switches::kEnableBlinkFeatures,
-                                    "AutoPictureInPicture");
-  }
-};
-
-// Hide page and check that entering Auto Picture-in-Picture is not triggered.
-// This test is most likely going to be flaky the day the tested thing fails.
-// Do NOT disable test. Ping /chrome/browser/picture_in_picture/OWNERS instead.
-IN_PROC_BROWSER_TEST_F(AutoVideoPictureInPictureWindowControllerBrowserTest,
-                       AutoEnterPictureInPictureIsNotTriggeredInRegularWebApp) {
-  GURL test_page_url = ui_test_utils::GetTestUrl(
-      base::FilePath(base::FilePath::kCurrentDirectory),
-      base::FilePath(kPictureInPictureWindowSizePage));
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_page_url));
-
-  content::WebContents* active_web_contents =
-      browser()->tab_strip_model()->GetActiveWebContents();
-  ASSERT_NE(nullptr, active_web_contents);
-
-  ASSERT_TRUE(ExecJs(active_web_contents, "video.play();"));
-  ASSERT_TRUE(
-      ExecJs(active_web_contents, "video.autoPictureInPicture = true;"));
-  ASSERT_TRUE(
-      ExecJs(active_web_contents, "addVisibilityChangeEventListener();"));
-
-  // Hide page and check that there is no video that enters Picture-in-Picture
-  // automatically.
-  active_web_contents->WasHidden();
-  WaitForTitle(active_web_contents, u"hidden");
-
-  EXPECT_EQ(false, EvalJs(active_web_contents, "isInPictureInPicture();"));
-}
-
-// Show page and check that exiting Auto Picture-in-Picture is triggered.
-// This test is most likely going to be flaky the day the tested thing fails.
-// Do NOT disable test. Ping /chrome/browser/picture_in_picture/OWNERS instead.
-IN_PROC_BROWSER_TEST_F(AutoVideoPictureInPictureWindowControllerBrowserTest,
-                       AutoExitPictureInPictureIsTriggeredInRegularWebApp) {
-  GURL test_page_url = ui_test_utils::GetTestUrl(
-      base::FilePath(base::FilePath::kCurrentDirectory),
-      base::FilePath(kPictureInPictureWindowSizePage));
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_page_url));
-
-  content::WebContents* active_web_contents =
-      browser()->tab_strip_model()->GetActiveWebContents();
-  ASSERT_NE(nullptr, active_web_contents);
-
-  ASSERT_TRUE(ExecJs(active_web_contents, "video.play();"));
-  ASSERT_TRUE(
-      ExecJs(active_web_contents, "video.autoPictureInPicture = true;"));
-
-  // Enter Picture-in-Picture manually.
-  ASSERT_EQ(true, EvalJs(active_web_contents, "enterPictureInPicture();"));
-
-  active_web_contents->WasHidden();
-
-  // Show page and check that video left Picture-in-Picture automatically.
-  active_web_contents->WasShown();
-  WaitForTitle(active_web_contents, u"leavepictureinpicture");
-
-  EXPECT_EQ(false, EvalJs(active_web_contents, "isInPictureInPicture();"));
-}
-
-namespace {
-
-class ChromeContentBrowserClientOverrideWebAppScope
-    : public ChromeContentBrowserClient {
- public:
-  ChromeContentBrowserClientOverrideWebAppScope() = default;
-  ~ChromeContentBrowserClientOverrideWebAppScope() override = default;
-
-  void OverrideWebkitPrefs(
-      content::WebContents* web_contents,
-      blink::web_pref::WebPreferences* web_prefs) override {
-    ChromeContentBrowserClient::OverrideWebkitPrefs(web_contents, web_prefs);
-
-    web_prefs->web_app_scope = web_app_scope_;
-  }
-
-  void set_web_app_scope(const GURL& web_app_scope) {
-    web_app_scope_ = web_app_scope;
-  }
-
- private:
-  GURL web_app_scope_;
-};
-
-}  // namespace
-
-class WebAppVideoPictureInPictureWindowControllerBrowserTest
-    : public web_app::WebAppControllerBrowserTest {
- public:
-  WebAppVideoPictureInPictureWindowControllerBrowserTest() = default;
-
-  WebAppVideoPictureInPictureWindowControllerBrowserTest(
-      const WebAppVideoPictureInPictureWindowControllerBrowserTest&) = delete;
-  WebAppVideoPictureInPictureWindowControllerBrowserTest& operator=(
-      const WebAppVideoPictureInPictureWindowControllerBrowserTest&) = delete;
-
-  ~WebAppVideoPictureInPictureWindowControllerBrowserTest() override = default;
-
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    command_line->AppendSwitch(
-        switches::kEnableExperimentalWebPlatformFeatures);
-    web_app::WebAppControllerBrowserTest::SetUpCommandLine(command_line);
-  }
-
-  GURL main_url() {
-    return https_server()->GetURL(
-        "/extensions/auto_picture_in_picture/main.html");
-  }
-
-  Browser* InstallAndLaunchPWA(const GURL& start_url) {
-    auto web_app_info = std::make_unique<WebAppInstallInfo>();
-    web_app_info->start_url = start_url;
-    web_app_info->scope = start_url.DeprecatedGetOriginAsURL();
-    web_app_info->user_display_mode = web_app::UserDisplayMode::kStandalone;
-    const web_app::AppId app_id = InstallWebApp(std::move(web_app_info));
-
-    Browser* app_browser = LaunchWebAppBrowserAndWait(app_id);
-    web_contents_ = app_browser->tab_strip_model()->GetActiveWebContents();
-    EXPECT_TRUE(content::WaitForLoadStop(web_contents_));
-    return app_browser;
-  }
-
-  content::WebContents* web_contents() { return web_contents_; }
-
- private:
-  raw_ptr<content::WebContents, DanglingUntriaged> web_contents_ = nullptr;
-};
-
-// Hide pwa page and check that Picture-in-Picture is entered automatically.
-IN_PROC_BROWSER_TEST_F(WebAppVideoPictureInPictureWindowControllerBrowserTest,
-                       AutoEnterPictureInPicture) {
-  InstallAndLaunchPWA(main_url());
-  ASSERT_EQ(true, EvalJs(web_contents(), "playVideo();"));
-  ASSERT_TRUE(ExecJs(web_contents(), "video.autoPictureInPicture = true;"));
-
-  // Hide page and check that video entered Picture-in-Picture automatically.
-  web_contents()->WasHidden();
-  WaitForTitle(web_contents(), u"video.enterpictureinpicture");
-}
-
-// Show pwa page and check that Auto Picture-in-Picture is exited automatically.
-IN_PROC_BROWSER_TEST_F(WebAppVideoPictureInPictureWindowControllerBrowserTest,
-                       AutoExitPictureInPicture) {
-  InstallAndLaunchPWA(main_url());
-  ASSERT_EQ(true, EvalJs(web_contents(), "playVideo();"));
-  ASSERT_TRUE(ExecJs(web_contents(), "video.autoPictureInPicture = true;"));
-  ASSERT_EQ(true, EvalJs(web_contents(), "enterPictureInPicture();"));
-
-  web_contents()->WasHidden();
-
-  // Show page and check that video left Picture-in-Picture automatically.
-  web_contents()->WasShown();
-  WaitForTitle(web_contents(), u"video.leavepictureinpicture");
-}
-
-// Show pwa page and check that Auto Picture-in-Picture is not triggered if
-// document is not inside the scope specified in the Web App Manifest.
-IN_PROC_BROWSER_TEST_F(
-    WebAppVideoPictureInPictureWindowControllerBrowserTest,
-    AutoPictureInPictureNotTriggeredIfDocumentNotInWebAppScope) {
-  // We open a web app with a different scope
-  // Then go to our usual test page.
-  Browser* app_browser = InstallAndLaunchPWA(
-      https_server()->GetURL("www.foobar.com", "/web_apps/basic.html"));
-  web_app::NavigateToURLAndWait(app_browser, main_url());
-  EXPECT_TRUE(app_browser->app_controller()->ShouldShowCustomTabBar());
-
-  ASSERT_EQ(true, EvalJs(web_contents(), "playVideo();"));
-  ASSERT_TRUE(ExecJs(web_contents(), "video.autoPictureInPicture = true;"));
-
-  // Hide page and check that the video did not entered
-  // Picture-in-Picture automatically.
-  web_contents()->WasHidden();
-  WaitForTitle(web_contents(), u"hidden");
-
-  EXPECT_EQ(false, EvalJs(web_contents(), "isInPictureInPicture();"));
-}
-
-// Show pwa page and check that Auto Picture-in-Picture is not triggered if
-// video is not playing.
-IN_PROC_BROWSER_TEST_F(WebAppVideoPictureInPictureWindowControllerBrowserTest,
-                       AutoPictureInPictureNotTriggeredIfVideoNotPlaying) {
-  InstallAndLaunchPWA(main_url());
-  ASSERT_TRUE(ExecJs(web_contents(), "video.autoPictureInPicture = true;"));
-  EXPECT_EQ(true, EvalJs(web_contents(), "isPaused();"));
-
-  // Hide page and check that the video did not entered
-  // Picture-in-Picture automatically.
-  web_contents()->WasHidden();
-  WaitForTitle(web_contents(), u"hidden");
-
-  EXPECT_EQ(false, EvalJs(web_contents(), "isInPictureInPicture();"));
-}
-
-// Check that Auto Picture-in-Picture is not triggered if there's already a
-// video in Picture-in-Picture.
-IN_PROC_BROWSER_TEST_F(
-    WebAppVideoPictureInPictureWindowControllerBrowserTest,
-    AutoPictureInPictureWhenPictureInPictureWindowAlreadyVisible) {
-  InstallAndLaunchPWA(main_url());
-
-  // Enter Picture-in-Picture for the first video and set Auto
-  // Picture-in-Picture for the second video.
-  ASSERT_EQ(true, EvalJs(web_contents(), "playVideo();"));
-  ASSERT_EQ(true, EvalJs(web_contents(), "enterPictureInPicture();"));
-  ASSERT_EQ(true, EvalJs(web_contents(), "playSecondVideo();"));
-  ASSERT_TRUE(
-      ExecJs(web_contents(), "secondVideo.autoPictureInPicture = true;"));
-
-  // Hide page and check that the second video did not entered
-  // Picture-in-Picture automatically.
-  web_contents()->WasHidden();
-  WaitForTitle(web_contents(), u"hidden");
-
-  // Check that the first video is still in Picture-in-Picture.
-  EXPECT_EQ(true, EvalJs(web_contents(), "isInPictureInPicture();"));
-}
-
-// Check that video does not leave Picture-in-Picture automatically when it
-// doesn't have the Auto Picture-in-Picture attribute set.
-IN_PROC_BROWSER_TEST_F(
-    WebAppVideoPictureInPictureWindowControllerBrowserTest,
-    AutoPictureInPictureNotTriggeredOnPageShownIfNoAttribute) {
-  InstallAndLaunchPWA(main_url());
-  ASSERT_TRUE(ExecJs(web_contents(), "video.autoPictureInPicture = false;"));
-
-  ASSERT_EQ(true, EvalJs(web_contents(), "playVideo();"));
-  ASSERT_EQ(true, EvalJs(web_contents(), "enterPictureInPicture();"));
-
-  web_contents()->WasHidden();
-
-  // Show page and check that video did not leave Picture-in-Picture
-  // automatically as it doesn't have the Auto Picture-in-Picture attribute
-  // set.
-  web_contents()->WasShown();
-  WaitForTitle(web_contents(), u"visible");
-
-  // Check that the video is still in Picture-in-Picture.
-  EXPECT_EQ(true, EvalJs(web_contents(), "isInPictureInPicture();"));
-}
-
-// Check that Auto Picture-in-Picture applies only to the video element whose
-// autoPictureInPicture attribute was set most recently.
-IN_PROC_BROWSER_TEST_F(WebAppVideoPictureInPictureWindowControllerBrowserTest,
-                       AutoPictureInPictureAttributeAppliesToLastElement) {
-  InstallAndLaunchPWA(main_url());
-  ASSERT_TRUE(ExecJs(web_contents(),
-                     "video.autoPictureInPicture = true;"
-                     "secondVideo.autoPictureInPicture = true;"));
-  ASSERT_EQ(true, EvalJs(web_contents(), "playVideo();"));
-  ASSERT_EQ(true, EvalJs(web_contents(), "playSecondVideo();"));
-
-  // Hide page and check that second video is the video that enters
-  // Picture-in-Picture automatically.
-  web_contents()->WasHidden();
-  WaitForTitle(web_contents(), u"secondVideo.enterpictureinpicture");
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppVideoPictureInPictureWindowControllerBrowserTest,
-                       AutoPictureInPictureAttributeAppliesToInsertedElement) {
-  InstallAndLaunchPWA(main_url());
-  ASSERT_TRUE(ExecJs(web_contents(), "video.autoPictureInPicture = true;"));
-  ASSERT_EQ(true, EvalJs(web_contents(), "playVideo();"));
-  ASSERT_EQ(true,
-            EvalJs(web_contents(), "addHtmlVideoWithAutoPictureInPicture();"));
-
-  // Hide the page and check that the inserted video is the video that enters
-  // Picture-in-Picture automatically.
-  web_contents()->WasHidden();
-  WaitForTitle(web_contents(), u"htmlVideo.enterpictureinpicture");
-}
-
-IN_PROC_BROWSER_TEST_F(WebAppVideoPictureInPictureWindowControllerBrowserTest,
-                       AutoPictureInPictureCanBeUnset) {
-  InstallAndLaunchPWA(main_url());
-  ASSERT_TRUE(ExecJs(web_contents(), "video.autoPictureInPicture = true;"));
-  ASSERT_EQ(true, EvalJs(web_contents(), "playVideo();"));
-
-  // Unset autoPictureInPicture and check that the video doesn't enter
-  // Picture-in-Picture automatically.
-  ASSERT_TRUE(ExecJs(web_contents(), "video.autoPictureInPicture = false;"));
-
-  EXPECT_EQ(false, EvalJs(web_contents(), "isInPictureInPicture();"));
-
-  web_contents()->WasHidden();
-  WaitForTitle(web_contents(), u"hidden");
-
-  EXPECT_EQ(false, EvalJs(web_contents(), "isInPictureInPicture();"));
-}
-
-// TODO(crbug.com/1314591): Re-enable this test
-#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS_LACROS)
-#define MAYBE_AutoPictureInPictureAppliesAfterUnsetOnAnotherVideo \
-  DISABLED_AutoPictureInPictureAppliesAfterUnsetOnAnotherVideo
-#else
-#define MAYBE_AutoPictureInPictureAppliesAfterUnsetOnAnotherVideo \
-  AutoPictureInPictureAppliesAfterUnsetOnAnotherVideo
-#endif
-IN_PROC_BROWSER_TEST_F(
-    WebAppVideoPictureInPictureWindowControllerBrowserTest,
-    MAYBE_AutoPictureInPictureAppliesAfterUnsetOnAnotherVideo) {
-  InstallAndLaunchPWA(main_url());
-  ASSERT_TRUE(ExecJs(web_contents(),
-                     "video.autoPictureInPicture = true;"
-                     "secondVideo.autoPictureInPicture = true;"));
-  ASSERT_EQ(true, EvalJs(web_contents(), "playVideo();"));
-  ASSERT_EQ(true, EvalJs(web_contents(), "playSecondVideo();"));
-
-  // Unset autoPictureInPicture on the element where it was set last, and check
-  // that the first video enters Picture-in-Picture automatically.
-  ASSERT_TRUE(
-      ExecJs(web_contents(), "secondVideo.autoPictureInPicture = false;"));
-
-  EXPECT_EQ(false, EvalJs(web_contents(), "isInPictureInPicture();"));
-
-  web_contents()->WasHidden();
-  WaitForTitle(web_contents(), u"video.enterpictureinpicture");
-
-  EXPECT_EQ(true, EvalJs(web_contents(), "isInPictureInPicture();"));
-}
-
-// Check that video does not leave Picture-in-Picture automatically when it is
-// not the most recent element with the Auto Picture-in-Picture attribute set.
-IN_PROC_BROWSER_TEST_F(
-    WebAppVideoPictureInPictureWindowControllerBrowserTest,
-    AutoPictureInPictureNotTriggeredOnPageShownIfNotEnteredAutoPictureInPicture) {
-  InstallAndLaunchPWA(main_url());
-  ASSERT_TRUE(ExecJs(web_contents(),
-                     "video.autoPictureInPicture = true;"
-                     "secondVideo.autoPictureInPicture = true;"));
-  ASSERT_EQ(true, EvalJs(web_contents(), "playVideo();"));
-  ASSERT_EQ(true, EvalJs(web_contents(), "playSecondVideo();"));
-  ASSERT_EQ(true, EvalJs(web_contents(), "enterPictureInPicture();"));
-
-  web_contents()->WasHidden();
-
-  // Show page and check that video did not leave Picture-in-Picture
-  // automatically as it's not the most recent element with the Auto
-  // Picture-in-Picture attribute set.
-  web_contents()->WasShown();
-  WaitForTitle(web_contents(), u"visible");
-
-  // Check that the video is still in Picture-in-Picture.
-  EXPECT_EQ(true, EvalJs(web_contents(), "isInPictureInPicture();"));
-}
-
-// Check that video with no audio that is paused when hidden is still eligible
-// to enter Auto Picture-in-Picture and resumes playback.
-IN_PROC_BROWSER_TEST_F(
-    WebAppVideoPictureInPictureWindowControllerBrowserTest,
-    AutoPictureInPictureTriggeredOnPageHiddenIfVideoPausedWhenHidden) {
-  InstallAndLaunchPWA(main_url());
-
-  ASSERT_EQ(true,
-            EvalJs(web_contents(), "changeVideoSrcToNoAudioTrackVideo();"));
-  ASSERT_TRUE(ExecJs(web_contents(), "video.autoPictureInPicture = true;"));
-
-  // Hide page and check that video entered Picture-in-Picture automatically
-  // and is playing.
-  web_contents()->WasHidden();
-  WaitForTitle(web_contents(), u"video.enterpictureinpicture");
-
-  // Check that video playback is still playing.
-  EXPECT_EQ(false, EvalJs(web_contents(), "isPaused();"));
-}
-
 // Check that video with no audio that is paused when hidden resumes playback
 // when it enters Picture-in-Picture.
 IN_PROC_BROWSER_TEST_F(VideoPictureInPictureWindowControllerBrowserTest,
diff --git a/chrome/browser/profile_resetter/profile_resetter_unittest.cc b/chrome/browser/profile_resetter/profile_resetter_unittest.cc
index 7da1161a..1766eca 100644
--- a/chrome/browser/profile_resetter/profile_resetter_unittest.cc
+++ b/chrome/browser/profile_resetter/profile_resetter_unittest.cc
@@ -349,20 +349,19 @@
                                          ManifestLocation location,
                                          extensions::Manifest::Type type,
                                          bool installed_by_default) {
-  base::DictionaryValue manifest;
-  manifest.SetStringPath(extensions::manifest_keys::kVersion, "1.0.0.0");
-  manifest.SetStringPath(extensions::manifest_keys::kName, name);
-  manifest.SetIntPath(extensions::manifest_keys::kManifestVersion, 2);
+  base::Value::Dict manifest;
+  manifest.Set(extensions::manifest_keys::kVersion, "1.0.0.0");
+  manifest.Set(extensions::manifest_keys::kName, name);
+  manifest.Set(extensions::manifest_keys::kManifestVersion, 2);
   switch (type) {
     case extensions::Manifest::TYPE_THEME:
-      manifest.SetKey(extensions::manifest_keys::kTheme,
-                      base::DictionaryValue());
+      manifest.Set(extensions::manifest_keys::kTheme, base::DictionaryValue());
       break;
     case extensions::Manifest::TYPE_HOSTED_APP:
-      manifest.SetStringPath(extensions::manifest_keys::kLaunchWebURL,
-                             "http://www.google.com");
-      manifest.SetStringPath(extensions::manifest_keys::kUpdateURL,
-                             "http://clients2.google.com/service/update2/crx");
+      manifest.SetByDottedPath(extensions::manifest_keys::kLaunchWebURL,
+                               "http://www.google.com");
+      manifest.Set(extensions::manifest_keys::kUpdateURL,
+                   "http://clients2.google.com/service/update2/crx");
       break;
     case extensions::Manifest::TYPE_EXTENSION:
       // do nothing
@@ -370,7 +369,7 @@
     default:
       NOTREACHED();
   }
-  manifest.SetStringPath(extensions::manifest_keys::kOmniboxKeyword, name);
+  manifest.SetByDottedPath(extensions::manifest_keys::kOmniboxKeyword, name);
   std::string error;
   scoped_refptr<Extension> extension = Extension::Create(
       path,
diff --git a/chrome/browser/profiles/profile_downloader.cc b/chrome/browser/profiles/profile_downloader.cc
index da08620..9dd29df6 100644
--- a/chrome/browser/profiles/profile_downloader.cc
+++ b/chrome/browser/profiles/profile_downloader.cc
@@ -180,9 +180,9 @@
   net::NetworkTrafficAnnotationTag traffic_annotation =
       net::DefineNetworkTrafficAnnotation("signed_in_profile_avatar", R"(
         semantics {
-          sender: "Profile G+ Image Downloader"
+          sender: "Profile Google Image Downloader"
           description:
-            "Signed in users use their G+ profile image as their Chrome "
+            "Signed in users use their Google account image as their Chrome "
             "profile image, unless they explicitly select otherwise. This "
             "fetcher uses the sign-in token and the image URL provided by GAIA "
             "to fetch the image."
@@ -195,8 +195,8 @@
           setting: "This feature cannot be disabled by settings."
           policy_exception_justification:
             "Not implemented, considered not useful as no content is being "
-            "uploaded or saved; this request merely downloads the user's G+ "
-            "profile image."
+            "uploaded or saved; this request merely downloads the user's "
+            "Google account image."
         })");
 
   VLOG(1) << "Loading profile image from " << image_url_to_fetch;
diff --git a/chrome/browser/resource_coordinator/tab_activity_watcher.cc b/chrome/browser/resource_coordinator/tab_activity_watcher.cc
deleted file mode 100644
index 0891418..0000000
--- a/chrome/browser/resource_coordinator/tab_activity_watcher.cc
+++ /dev/null
@@ -1,655 +0,0 @@
-// Copyright 2017 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/resource_coordinator/tab_activity_watcher.h"
-
-#include <limits>
-
-#include "base/metrics/histogram_macros.h"
-#include "base/no_destructor.h"
-#include "base/rand_util.h"
-#include "base/time/time.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/resource_coordinator/lifecycle_unit.h"
-#include "chrome/browser/resource_coordinator/tab_lifecycle_unit_external.h"
-#include "chrome/browser/resource_coordinator/tab_manager_features.h"
-#include "chrome/browser/resource_coordinator/tab_metrics_logger.h"
-#include "chrome/browser/resource_coordinator/tab_ranker/mru_features.h"
-#include "chrome/browser/resource_coordinator/tab_ranker/tab_features.h"
-#include "chrome/browser/resource_coordinator/time.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_finder.h"
-#include "chrome/browser/ui/browser_list.h"
-#include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/navigation_handle.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/render_widget_host.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_observer.h"
-#include "content/public/browser/web_contents_user_data.h"
-#include "services/metrics/public/cpp/ukm_source_id.h"
-#include "third_party/blink/public/common/input/web_input_event.h"
-
-namespace resource_coordinator {
-namespace {
-using tab_ranker::TabFeatures;
-
-// Used for decay Frecency scores.
-constexpr float kFrecencyScoreDecay = 0.8f;
-// Records how many tab reactivations till now.
-static int32_t reactivation_index = 0;
-// Used for generating label_ids and query_ids.
-int64_t internal_id_for_logging = 0;
-// Returns an int64_t number as label_id or query_id.
-int64_t NewInt64ForLabelIdOrQueryId() {
-  // The id is shifted 16 bits so that the lower bits are reserved for counting
-  // multiple queries.
-  // We choose 16 so that the lower bits for counting multiple queries and
-  // higher bits for labeling queries are both unlikely to overflow. (lower bits
-  // only overflows when we have more than 65536 queries without labeling
-  // events; higher bits only overflow when we have more than 100 billion
-  // discards.
-  constexpr int kIdShiftBits = 16;
-  return (++internal_id_for_logging) << kIdShiftBits;
-}
-
-}  // namespace
-
-// Per-WebContents helper class that observes its WebContents, notifying
-// TabActivityWatcher when interesting events occur. Also provides
-// per-WebContents data that TabActivityWatcher uses to log the tab.
-class TabActivityWatcher::WebContentsData
-    : public content::WebContentsObserver,
-      public content::WebContentsUserData<WebContentsData>,
-      public content::RenderWidgetHost::InputEventObserver {
- public:
-  WebContentsData(const WebContentsData&) = delete;
-  WebContentsData& operator=(const WebContentsData&) = delete;
-
-  ~WebContentsData() override = default;
-
-  // Calculates the tab reactivation score for a background tab. Returns nullopt
-  // if the score could not be calculated, e.g. because the tab is in the
-  // foreground.
-  absl::optional<float> CalculateReactivationScore() {
-    if (web_contents()->IsBeingDestroyed() || backgrounded_time_.is_null())
-      return absl::nullopt;
-
-    // No log for CalculateReactivationScore.
-    absl::optional<TabFeatures> tab = GetTabFeatures();
-    if (!tab.has_value())
-      return absl::nullopt;
-
-    float score = 0.0f;
-    const tab_ranker::TabRankerResult result =
-        TabActivityWatcher::GetInstance()->predictor_->ScoreTab(tab.value(),
-                                                                &score);
-    if (result == tab_ranker::TabRankerResult::kSuccess)
-      return score;
-    return absl::nullopt;
-  }
-
-  // Call when the associated WebContents has been replaced.
-  void WasReplaced() { was_replaced_ = true; }
-
-  // Call when the associated WebContents has replaced the WebContents of
-  // another tab. Copies info from the other WebContentsData so future events
-  // can be logged consistently.
-  void DidReplace(const WebContentsData& replaced_tab) {
-    // Copy creation and foregrounded times to retain the replaced tab's MRU
-    // position.
-    creation_time_ = replaced_tab.creation_time_;
-    foregrounded_time_ = replaced_tab.foregrounded_time_;
-
-    // Copy background status so ForegroundOrClosed can potentially be logged.
-    backgrounded_time_ = replaced_tab.backgrounded_time_;
-
-    // Copy the replaced tab's stats.
-    page_metrics_ = replaced_tab.page_metrics_;
-
-    // Recover the ukm_source_id from the |replaced_tab|.
-    ukm_source_id_ = replaced_tab.ukm_source_id_;
-
-    // Copy the replaced label_id_.
-    label_id_ = replaced_tab.label_id_;
-
-    // Copy the frecency score.
-    frecency_score_ = replaced_tab.frecency_score_;
-  }
-
-  // Call when the WebContents is detached from its tab. If the tab is later
-  // re-inserted elsewhere, we use the state it had before being detached.
-  void TabDetached() { is_detached_ = true; }
-
-  // Call when the tab is inserted into a tab strip to update state.
-  void TabInserted(bool foreground) {
-    if (is_detached_) {
-      is_detached_ = false;
-
-      // Dragged tabs are normally inserted into their new tab strip in the
-      // "background", then "activated", even though the user perceives the tab
-      // staying active the whole time. So don't update |background_time_| here.
-      //
-      // TODO(michaelpg): If a background tab is dragged (as part of a group)
-      // and inserted, it may be treated as being foregrounded (depending on tab
-      // order). This is a small edge case, but can be fixed by the plan to
-      // merge the ForegroundedOrClosed and TabMetrics events.
-      return;
-    }
-
-    if (foreground) {
-      foregrounded_time_ = NowTicks();
-      UpdateFrecencyScoreOnReactivation();
-    } else {
-      // This is a new tab that was opened in the background.
-      backgrounded_time_ = NowTicks();
-    }
-  }
-
-  // Logs TabMetrics for the tab if it is considered to be backgrounded.
-  void LogTabIfBackgrounded() {
-    if (backgrounded_time_.is_null() || DisableBackgroundLogWithTabRanker())
-      return;
-
-    absl::optional<TabFeatures> tab = GetTabFeatures();
-    if (tab.has_value()) {
-      // Background time logging always logged with label_id == 0, since we
-      // only use label_id for query time logging for now.
-      TabActivityWatcher::GetInstance()->tab_metrics_logger_->LogTabMetrics(
-          ukm_source_id_, tab.value(), web_contents(), 0);
-    }
-  }
-
-  // Logs current TabFeatures; skips if current tab is null.
-  void LogCurrentTabFeatures(const absl::optional<TabFeatures>& tab) {
-    if (!tab.has_value())
-      return;
-    // Update label_id_: a new label_id is generated for this query if the
-    // label_id_ is 0; otherwise the old label_id_ is incremented. This allows
-    // us to better pairing TabMetrics with ForegroundedOrClosed events offline.
-    // The same label_id_ will be logged with ForegroundedOrClosed event later
-    // on so that TabFeatures can be paired with ForegroundedOrClosed.
-    label_id_ = label_id_ ? label_id_ + 1 : NewInt64ForLabelIdOrQueryId();
-
-    TabActivityWatcher::GetInstance()->tab_metrics_logger_->LogTabMetrics(
-        ukm_source_id_, tab.value(), web_contents(), label_id_);
-  }
-
-  // Sets foregrounded_time_ to NowTicks() so this becomes the
-  // most-recently-used tab.
-  void TabWindowActivated() { foregrounded_time_ = NowTicks(); }
-
- private:
-  friend class content::WebContentsUserData<WebContentsData>;
-  friend class TabActivityWatcher;
-
-  // A FrecencyScore is used as a measurement of both frequency and recency.
-  // (1) The score is decayed by kFrecencyScoreDecay every time any tab is
-  // reactivated.
-  // (2) The score is incremented by 1.0 - kFrecencyScoreDecay when this tab is
-  // reactivated.
-  struct FrecencyScore {
-    int32_t update_index = 0;
-    float score = 0.0f;
-  };
-
-  explicit WebContentsData(content::WebContents* web_contents)
-      : WebContentsObserver(web_contents),
-        content::WebContentsUserData<WebContentsData>(*web_contents) {
-    DCHECK(!web_contents->GetBrowserContext()->IsOffTheRecord());
-    web_contents->GetPrimaryMainFrame()
-        ->GetRenderViewHost()
-        ->GetWidget()
-        ->AddInputEventObserver(this);
-
-    creation_time_ = NowTicks();
-
-    // A navigation may already have completed if this is a replacement tab.
-    ukm_source_id_ = web_contents->GetPrimaryMainFrame()->GetPageUkmSourceId();
-
-    // When a tab is discarded, a new null_web_contents will be created (with
-    // WasDiscarded set as true) applied as a replacement of the discarded tab.
-    // We want to record this discarded state for later logging.
-    discarded_since_backgrounded_ = web_contents->WasDiscarded();
-  }
-
-  void WasHidden() {
-    // The tab may not be in the tabstrip if it's being moved or replaced.
-    Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
-    if (!browser)
-      return;
-
-    DCHECK(!browser->tab_strip_model()->closing_all());
-
-    if (browser->tab_strip_model()->GetActiveWebContents() == web_contents() &&
-        !browser->window()->IsMinimized()) {
-      // The active tab is considered to be in the foreground unless its window
-      // is minimized. It might still get hidden, e.g. when the browser is about
-      // to close, but that shouldn't count as a backgrounded event.
-      //
-      // TODO(michaelpg): On Mac, hiding the application (e.g. via Cmd+H) should
-      // log tabs as backgrounded. Check NSApplication's isHidden property.
-      return;
-    }
-
-    backgrounded_time_ = NowTicks();
-    discarded_since_backgrounded_ = false;
-    LogTabIfBackgrounded();
-  }
-
-  void WasShown() {
-    UpdateFrecencyScoreOnReactivation();
-
-    if (backgrounded_time_.is_null())
-      return;
-
-    Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
-    if (browser && browser->tab_strip_model()->closing_all())
-      return;
-
-    // Log the event before updating times.
-    LogForegroundedOrClosedMetrics(true /* is_foregrounded */);
-
-    backgrounded_time_ = base::TimeTicks();
-    foregrounded_time_ = NowTicks();
-
-    page_metrics_.num_reactivations++;
-  }
-
-  // content::WebContentsObserver:
-  void RenderViewHostChanged(content::RenderViewHost* old_host,
-                             content::RenderViewHost* new_host) override {
-    if (old_host != nullptr)
-      old_host->GetWidget()->RemoveInputEventObserver(this);
-    new_host->GetWidget()->AddInputEventObserver(this);
-  }
-
-  void DidFinishNavigation(
-      content::NavigationHandle* navigation_handle) override {
-    if (!navigation_handle->HasCommitted() ||
-        !navigation_handle->IsInPrimaryMainFrame() ||
-        navigation_handle->IsSameDocument()) {
-      return;
-    }
-
-    // Use the same SourceId that SourceUrlRecorderWebContentsObserver populates
-    // and updates.
-    ukm::SourceId new_source_id = ukm::ConvertToSourceId(
-        navigation_handle->GetNavigationId(), ukm::SourceIdType::NAVIGATION_ID);
-    DCHECK_NE(new_source_id, ukm_source_id_)
-        << "Expected a unique Source ID for the navigation";
-    ukm_source_id_ = new_source_id;
-
-    // Reset the per-page data.
-    page_metrics_ = {};
-
-    // Update navigation info.
-    page_metrics_.page_transition = navigation_handle->GetPageTransition();
-  }
-
-  // Logs metrics for the tab when it stops loading instead of immediately
-  // after a navigation commits, so we can have some idea of its status and
-  // contents.
-  void DidStopLoading() override {
-    // Ignore load events in foreground tabs. The tab state of a foreground tab
-    // will be logged if/when it is backgrounded.
-    LogTabIfBackgrounded();
-  }
-
-  void OnVisibilityChanged(content::Visibility visibility) override {
-    // Record background tab UKMs and do associated bookkepping.
-    if (!web_contents()->IsBeingDestroyed()) {
-      // TODO(michaelpg): Consider treating occluded tabs as hidden.
-      if (visibility == content::Visibility::HIDDEN) {
-        WasHidden();
-      } else {
-        WasShown();
-      }
-    }
-  }
-
-  void WebContentsDestroyed() override {
-    if (was_replaced_)
-      return;
-
-    // Log necessary metrics.
-    TabActivityWatcher::GetInstance()->OnTabClosed(this);
-  }
-
-  // content::RenderWidgetHost::InputEventObserver:
-  void OnInputEvent(const blink::WebInputEvent& event) override {
-    if (blink::WebInputEvent::IsMouseEventType(event.GetType()))
-      page_metrics_.mouse_event_count++;
-    else if (blink::WebInputEvent::IsKeyboardEventType(event.GetType()))
-      page_metrics_.key_event_count++;
-    else if (blink::WebInputEvent::IsTouchEventType(event.GetType()))
-      page_metrics_.touch_event_count++;
-  }
-
-  // Iterates through tabstrips to determine the index of |contents| in
-  // most-recently-used order out of all non-incognito tabs.
-  // Linear in the number of tabs (most users have <10 tabs open).
-  tab_ranker::MRUFeatures GetMRUFeatures() {
-    // If not in closing_all mode, calculate |mru_features_|.
-    mru_features_.index = 0;
-    mru_features_.total = 0;
-    for (Browser* browser : *BrowserList::GetInstance()) {
-      // Ignore incognito browsers.
-      if (browser->profile()->IsOffTheRecord())
-        continue;
-
-      int count = browser->tab_strip_model()->count();
-      mru_features_.total += count;
-
-      // Increment the MRU index for each WebContents that was foregrounded more
-      // recently than this one.
-      for (int i = 0; i < count; i++) {
-        auto* other = WebContentsData::FromWebContents(
-            browser->tab_strip_model()->GetWebContentsAt(i));
-        if (!other || this == other)
-          continue;
-
-        if (!MoreRecentlyUsed(this, other))
-          mru_features_.index++;
-      }
-    }
-    return mru_features_;
-  }
-
-  // Returns whether |webcontents_a| is more recently used than |webcontents_b|.
-  // A webcontents is more recently used iff it has larger (later)
-  // |foregrounded_time_|; or |creation_time_| if they were never foregrounded.
-  static bool MoreRecentlyUsed(
-      TabActivityWatcher::WebContentsData* webcontents_a,
-      TabActivityWatcher::WebContentsData* const webcontents_b) {
-    return webcontents_a->foregrounded_time_ >
-               webcontents_b->foregrounded_time_ ||
-           (webcontents_a->foregrounded_time_ ==
-                webcontents_b->foregrounded_time_ &&
-            webcontents_a->creation_time_ > webcontents_b->creation_time_);
-  }
-
-  // Returns the tabfeatures of current tab by combining TabMetrics,
-  // WindowFeatures and MRUFeatures.
-  // TODO(charleszhao): refactor TabMetricsLogger::GetTabFeatures to return a
-  // full TabFeatures instead of a partial TabFeatures.
-  absl::optional<TabFeatures> GetTabFeatures() {
-    if (web_contents()->IsBeingDestroyed() || backgrounded_time_.is_null())
-      return absl::nullopt;
-    // For tab features.
-    absl::optional<TabFeatures> tab =
-        TabMetricsLogger::GetTabFeatures(page_metrics_, web_contents());
-    if (!tab.has_value())
-      return tab;
-
-    tab->time_from_backgrounded =
-        backgrounded_time_.is_null()
-            ? 0
-            : (NowTicks() - backgrounded_time_).InMilliseconds();
-
-    // For mru features.
-    const tab_ranker::MRUFeatures& mru = GetMRUFeatures();
-    tab->mru_index = mru.index;
-    tab->total_tab_count = mru.total;
-
-    // For frecency_score;
-    tab->frecency_score = GetFrecencyScore();
-
-    return tab;
-  }
-
-  // Collect current ForegroundedOrClosedMetrics and send to ukm.
-  void LogForegroundedOrClosedMetrics(bool is_foregrounded) {
-    TabMetricsLogger::ForegroundedOrClosedMetrics metrics;
-    metrics.is_foregrounded = is_foregrounded;
-    metrics.is_discarded = discarded_since_backgrounded_;
-    metrics.time_from_backgrounded =
-        (NowTicks() - backgrounded_time_).InMilliseconds();
-    metrics.label_id = label_id_;
-
-    TabActivityWatcher::GetInstance()
-        ->tab_metrics_logger_->LogForegroundedOrClosedMetrics(ukm_source_id_,
-                                                              metrics);
-    // label_id_ is reset whenever a label is logged.
-    // A new label_id_ is generated when a query happens inside
-    // CalculateReactivationScore, after that this ForegroundedOrClosed logging
-    // can happen many times (tabs may get backgrounded and reactivated several
-    // times). In such cases, we only count the first time as the true label,
-    // the rest are considered to be query time logging irrelevant, for which we
-    // log with label_id == 0.
-    label_id_ = 0;
-  }
-
-  // Returns frecency score of this tab.
-  // NOTE: we don't apply decay for all reactivations, instead we accumulate
-  // them as reactivations_since_last_update and applied all together when the
-  // score is queried.
-  float GetFrecencyScore() {
-    const int reactivations_since_last_update =
-        reactivation_index - frecency_score_.update_index;
-    if (reactivations_since_last_update > 0) {
-      frecency_score_.score *=
-          std::pow(kFrecencyScoreDecay, reactivations_since_last_update);
-      frecency_score_.update_index = reactivation_index;
-    }
-    return frecency_score_.score;
-  }
-
-  // Updates frecency score of current tab when it is reactivated.
-  void UpdateFrecencyScoreOnReactivation() {
-    ++reactivation_index;
-    // Updates the current score.
-    frecency_score_.score = GetFrecencyScore() + 1.0f - kFrecencyScoreDecay;
-  }
-
-  // Updated when a navigation is finished.
-  ukm::SourceId ukm_source_id_ = 0;
-
-  // When the tab was created.
-  base::TimeTicks creation_time_;
-
-  // The most recent time the tab became backgrounded. This happens when a
-  // different tab in the tabstrip is activated or the tab's window is hidden.
-  base::TimeTicks backgrounded_time_;
-
-  // The most recent time the tab became foregrounded. This happens when the
-  // tab becomes the active tab in the tabstrip or when the active tab's window
-  // is activated.
-  base::TimeTicks foregrounded_time_;
-
-  // Stores current page stats for the tab.
-  TabMetricsLogger::PageMetrics page_metrics_;
-
-  // Set to true when the WebContents has been detached from its tab.
-  bool is_detached_ = false;
-
-  // If true, future events such as the tab being destroyed won't be logged.
-  bool was_replaced_ = false;
-
-  // MRUFeatures of this WebContents, updated only before ForegroundedOrClosed
-  // event is logged.
-  tab_ranker::MRUFeatures mru_features_;
-
-  // Whether this tab is currently in discarded state.
-  bool discarded_since_backgrounded_ = false;
-
-  // An int64 random label to pair TabFeatures with ForegroundedOrClosed event.
-  int64_t label_id_ = 0;
-
-  // Fecency score of this tab.
-  FrecencyScore frecency_score_;
-
-  WEB_CONTENTS_USER_DATA_KEY_DECL();
-};
-
-WEB_CONTENTS_USER_DATA_KEY_IMPL(TabActivityWatcher::WebContentsData);
-
-TabActivityWatcher::TabActivityWatcher()
-    : tab_metrics_logger_(std::make_unique<TabMetricsLogger>()),
-      browser_tab_strip_tracker_(this, this),
-      predictor_(std::make_unique<tab_ranker::TabScorePredictor>()) {
-  BrowserList::AddObserver(this);
-  browser_tab_strip_tracker_.Init();
-}
-
-TabActivityWatcher::~TabActivityWatcher() {
-  BrowserList::RemoveObserver(this);
-}
-
-absl::optional<float> TabActivityWatcher::CalculateReactivationScore(
-    content::WebContents* web_contents) {
-  WebContentsData* web_contents_data =
-      WebContentsData::FromWebContents(web_contents);
-  if (!web_contents_data)
-    return absl::nullopt;
-  return web_contents_data->CalculateReactivationScore();
-}
-
-void TabActivityWatcher::LogAndMaybeSortLifecycleUnitWithTabRanker(
-    std::vector<LifecycleUnit*>* tabs) {
-  // Set query_id so that all TabFeatures logged in this query can be joined.
-  tab_metrics_logger_->set_query_id(NewInt64ForLabelIdOrQueryId());
-
-  const bool should_sort_tabs =
-      base::FeatureList::IsEnabled(features::kTabRanker);
-
-  std::map<int32_t, absl::optional<TabFeatures>> tab_features;
-  for (auto* lifecycle_unit : *tabs) {
-    auto* lifecycle_unit_external =
-        lifecycle_unit->AsTabLifecycleUnitExternal();
-    // the lifecycle_unit_external is nullptr in the unit test
-    // TabManagerDelegateTest::KillMultipleProcesses.
-    if (!lifecycle_unit_external) {
-      tab_features[lifecycle_unit->GetID()] = absl::nullopt;
-      continue;
-    }
-    WebContentsData* web_contents_data = WebContentsData::FromWebContents(
-        lifecycle_unit_external->GetWebContents());
-
-    // The web_contents_data can be nullptr in some cases.
-    // TODO(crbug.com/1019482): move the creation of WebContentsData to
-    // TabHelpers::AttachTabHelpers.
-    if (!web_contents_data) {
-      tab_features[lifecycle_unit->GetID()] = absl::nullopt;
-      continue;
-    }
-
-    const absl::optional<TabFeatures> tab = web_contents_data->GetTabFeatures();
-    web_contents_data->LogCurrentTabFeatures(tab);
-
-    // No reason to store TabFeatures if TabRanker is disabled.
-    if (should_sort_tabs) {
-      tab_features[lifecycle_unit->GetID()] = tab;
-    }
-  }
-
-  // Directly return if TabRanker is disabled.
-  if (!should_sort_tabs)
-    return;
-
-  const std::map<int32_t, float> reactivation_scores =
-      predictor_->ScoreTabs(tab_features);
-  // Sort with larger reactivation_score first (desending importance).
-  std::sort(tabs->begin(), tabs->end(),
-            [&reactivation_scores](const LifecycleUnit* const a,
-                                   const LifecycleUnit* const b) {
-              return reactivation_scores.at(a->GetID()) >
-                     reactivation_scores.at(b->GetID());
-            });
-}
-
-void TabActivityWatcher::OnBrowserSetLastActive(Browser* browser) {
-  if (browser->tab_strip_model()->closing_all())
-    return;
-
-  content::WebContents* active_contents =
-      browser->tab_strip_model()->GetActiveWebContents();
-  if (!active_contents)
-    return;
-
-  // Don't assume the WebContentsData already exists in case activation happens
-  // before the tabstrip is fully updated.
-  WebContentsData* web_contents_data =
-      WebContentsData::FromWebContents(active_contents);
-  if (web_contents_data)
-    web_contents_data->TabWindowActivated();
-}
-
-void TabActivityWatcher::OnTabStripModelChanged(
-    TabStripModel* tab_strip_model,
-    const TabStripModelChange& change,
-    const TabStripSelectionChange& selection) {
-  switch (change.type()) {
-    case TabStripModelChange::kInserted: {
-      for (const auto& contents : change.GetInsert()->contents) {
-        // Ensure the WebContentsData is created to observe this WebContents
-        // since it may represent a newly created tab.
-        WebContentsData::CreateForWebContents(contents.contents);
-        WebContentsData::FromWebContents(contents.contents)
-            ->TabInserted(selection.new_contents == contents.contents);
-      }
-      break;
-    }
-    case TabStripModelChange::kRemoved: {
-      for (const auto& contents : change.GetRemove()->contents)
-        WebContentsData::FromWebContents(contents.contents)->TabDetached();
-      break;
-    }
-    case TabStripModelChange::kReplaced: {
-      auto* replace = change.GetReplace();
-      WebContentsData* old_web_contents_data =
-          WebContentsData::FromWebContents(replace->old_contents);
-      old_web_contents_data->WasReplaced();
-
-      // Ensure the WebContentsData is created to observe this WebContents
-      // since it likely hasn't been inserted into a tabstrip before.
-      WebContentsData::CreateForWebContents(replace->new_contents);
-
-      WebContentsData::FromWebContents(replace->new_contents)
-          ->DidReplace(*old_web_contents_data);
-      break;
-    }
-    case TabStripModelChange::kMoved:
-    case TabStripModelChange::kSelectionOnly:
-      break;
-  }
-}
-
-void TabActivityWatcher::TabPinnedStateChanged(TabStripModel* tab_strip_model,
-                                               content::WebContents* contents,
-                                               int index) {
-  WebContentsData::FromWebContents(contents)->LogTabIfBackgrounded();
-}
-
-bool TabActivityWatcher::ShouldTrackBrowser(Browser* browser) {
-  // Don't track incognito browsers. This is also enforced by UKM.
-  // TODO(michaelpg): Keep counters for incognito browsers so we can score them
-  // using the TabScorePredictor. We should be able to do this without logging
-  // these values.
-  return !browser->profile()->IsOffTheRecord();
-}
-
-void TabActivityWatcher::ResetForTesting() {
-  tab_metrics_logger_ = std::make_unique<TabMetricsLogger>();
-  predictor_ = std::make_unique<tab_ranker::TabScorePredictor>();
-  internal_id_for_logging = 0;
-}
-
-// static
-TabActivityWatcher* TabActivityWatcher::GetInstance() {
-  static base::NoDestructor<TabActivityWatcher> instance;
-  return instance.get();
-}
-
-void TabActivityWatcher::OnTabClosed(WebContentsData* web_contents_data) {
-  // Log ForegroundedOrClosed event.
-  if (!web_contents_data->backgrounded_time_.is_null()) {
-    web_contents_data->LogForegroundedOrClosedMetrics(
-        false /*is_foregrounded */);
-  }
-}
-
-}  // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/tab_activity_watcher.h b/chrome/browser/resource_coordinator/tab_activity_watcher.h
deleted file mode 100644
index 255dea8..0000000
--- a/chrome/browser/resource_coordinator/tab_activity_watcher.h
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2017 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_TAB_ACTIVITY_WATCHER_H_
-#define CHROME_BROWSER_RESOURCE_COORDINATOR_TAB_ACTIVITY_WATCHER_H_
-
-#include <memory>
-
-#include "chrome/browser/resource_coordinator/tab_ranker/tab_score_predictor.h"
-#include "chrome/browser/ui/browser_list_observer.h"
-#include "chrome/browser/ui/browser_tab_strip_tracker.h"
-#include "chrome/browser/ui/browser_tab_strip_tracker_delegate.h"
-#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
-
-class TabMetricsLogger;
-
-namespace resource_coordinator {
-
-class LifecycleUnit;
-
-// Observes background tab activity in order to log UKMs for tabs and score tabs
-// using the Tab Ranker. Metrics will be compared against tab reactivation/close
-// events to determine the end state of each background tab.
-class TabActivityWatcher : public BrowserListObserver,
-                           public TabStripModelObserver,
-                           public BrowserTabStripTrackerDelegate {
- public:
-  TabActivityWatcher();
-
-  TabActivityWatcher(const TabActivityWatcher&) = delete;
-  TabActivityWatcher& operator=(const TabActivityWatcher&) = delete;
-
-  ~TabActivityWatcher() override;
-
-  // Uses the Tab Ranker model to predict a score for the tab, where a higher
-  // value indicates a higher likelihood of being reactivated.
-  // Returns the score if the tab could be scored.
-  // This is only used in chrome://discards and unit tests.
-  absl::optional<float> CalculateReactivationScore(
-      content::WebContents* web_contents);
-
-  // Logs TabMetrics of all |tabs|; and sorts them by descending importance,
-  // so that the last tab is the first candidate that will be discarded.
-  void LogAndMaybeSortLifecycleUnitWithTabRanker(
-      std::vector<LifecycleUnit*>* tabs);
-
-  // Returns the single instance, creating it if necessary.
-  static TabActivityWatcher* GetInstance();
-
- private:
-  friend class TabActivityWatcherTest;
-
-  // Helper class to observe WebContents.
-  // TODO(michaelpg): Merge this into TabLifecycleUnit.
-  class WebContentsData;
-
-  // Called When A Tab is closed, log necessary metrics and erase the
-  // |web_contents_data| pointer in |all_closing_tabs_|.
-  void OnTabClosed(WebContentsData* web_contents_data);
-
-  // BrowserListObserver:
-  void OnBrowserSetLastActive(Browser* browser) override;
-
-  // TabStripModelObserver:
-  void OnTabStripModelChanged(
-      TabStripModel* tab_strip_model,
-      const TabStripModelChange& change,
-      const TabStripSelectionChange& selection) override;
-  void TabPinnedStateChanged(TabStripModel* tab_strip_model,
-                             content::WebContents* contents,
-                             int index) override;
-
-  // BrowserTabStripTrackerDelegate:
-  bool ShouldTrackBrowser(Browser* browser) override;
-
-  // Resets internal state.
-  void ResetForTesting();
-
-  std::unique_ptr<TabMetricsLogger> tab_metrics_logger_;
-
-  // Manages registration of this class as an observer of all TabStripModels as
-  // browsers are created and destroyed.
-  BrowserTabStripTracker browser_tab_strip_tracker_;
-
-  // Loads the Tab Ranker model on first use and calculates tab scores.
-  std::unique_ptr<tab_ranker::TabScorePredictor> predictor_;
-};
-
-}  // namespace resource_coordinator
-
-#endif  // CHROME_BROWSER_RESOURCE_COORDINATOR_TAB_ACTIVITY_WATCHER_H_
diff --git a/chrome/browser/resource_coordinator/tab_activity_watcher_browsertest.cc b/chrome/browser/resource_coordinator/tab_activity_watcher_browsertest.cc
deleted file mode 100644
index 2eff63d..0000000
--- a/chrome/browser/resource_coordinator/tab_activity_watcher_browsertest.cc
+++ /dev/null
@@ -1,883 +0,0 @@
-// Copyright 2018 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/resource_coordinator/tab_activity_watcher.h"
-
-#include <memory>
-
-#include "base/test/scoped_feature_list.h"
-#include "base/test/simple_test_tick_clock.h"
-#include "chrome/browser/resource_coordinator/tab_lifecycle_unit.h"
-#include "chrome/browser/resource_coordinator/tab_lifecycle_unit_external.h"
-#include "chrome/browser/resource_coordinator/tab_lifecycle_unit_source.h"
-#include "chrome/browser/resource_coordinator/tab_manager_features.h"
-#include "chrome/browser/resource_coordinator/tab_metrics_event.pb.h"
-#include "chrome/browser/resource_coordinator/time.h"
-#include "chrome/browser/resource_coordinator/utils.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/tabs/tab_ukm_test_helper.h"
-#include "chrome/test/base/in_process_browser_test.h"
-#include "chrome/test/base/ui_test_utils.h"
-#include "components/ukm/test_ukm_recorder.h"
-#include "content/public/test/browser_test.h"
-#include "content/public/test/prerender_test_util.h"
-#include "content/public/test/web_contents_tester.h"
-#include "net/test/embedded_test_server/embedded_test_server.h"
-#include "services/metrics/public/cpp/ukm_builders.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ukm::builders::TabManager_TabMetrics;
-using ukm::builders::TabManager_Background_ForegroundedOrClosed;
-
-namespace resource_coordinator {
-namespace {
-
-const char* kTabMetricsEntryName = TabManager_TabMetrics::kEntryName;
-const char* kFOCEntryName =
-    TabManager_Background_ForegroundedOrClosed::kEntryName;
-
-// The default metric values for a tab.
-const UkmMetricMap kBasicMetricValues({
-    {TabManager_TabMetrics::kHasBeforeUnloadHandlerName, 0},
-    {TabManager_TabMetrics::kHasFormEntryName, 0},
-    {TabManager_TabMetrics::kIsPinnedName, 0},
-    {TabManager_TabMetrics::kKeyEventCountName, 0},
-    {TabManager_TabMetrics::kNavigationEntryCountName, 1},
-    {TabManager_TabMetrics::kSiteEngagementScoreName, 0},
-    {TabManager_TabMetrics::kTouchEventCountName, 0},
-    {TabManager_TabMetrics::kWasRecentlyAudibleName, 0},
-    // TODO(michaelpg): Test TabManager_TabMetrics::kMouseEventCountName.
-    // Depending on the test environment, the browser may receive mouse events
-    // from the mouse cursor during tests, so we currently don't check this
-    // metric.
-});
-
-// These parameters don't affect logging.
-const bool kCheckNavigationSuccess = true;
-const int64_t kIdShift = 1 << 16;
-
-}  // namespace
-
-// Tests UKM entries generated by TabActivityWatcher/TabMetricsLogger as tabs
-// are backgrounded and foregrounded.
-// Modeled after the TabActivityWatcherTest unit tests, these browser tests
-// focus on end-to-end testing from the first browser launch onwards, verifying
-// that window and browser commands are really triggering the paths that lead
-// to UKM logs.
-class TabActivityWatcherTest : public InProcessBrowserTest {
- public:
-  TabActivityWatcherTest(const TabActivityWatcherTest&) = delete;
-  TabActivityWatcherTest& operator=(const TabActivityWatcherTest&) = delete;
-
- protected:
-  TabActivityWatcherTest() {
-    scoped_feature_list_.InitAndEnableFeatureWithParameters(
-        features::kTabRanker,
-        {{"disable_background_log_with_TabRanker", "false"}});
-  }
-
-  // TabActivityWatcherTest:
-  void PreRunTestOnMainThread() override {
-    InProcessBrowserTest::PreRunTestOnMainThread();
-    ukm_entry_checker_ = std::make_unique<UkmEntryChecker>();
-    test_ukm_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>();
-  }
-
-  void SetUpOnMainThread() override {
-    InProcessBrowserTest::SetUpOnMainThread();
-    ASSERT_TRUE(embedded_test_server()->Start());
-    test_urls_ = {embedded_test_server()->GetURL("/title1.html"),
-                  embedded_test_server()->GetURL("/title2.html"),
-                  embedded_test_server()->GetURL("/title3.html")};
-    // Browser created in BrowserMain() shouldn't result in a background tab
-    // being logged.
-    EXPECT_EQ(0u, ukm_entry_checker_->NumEntries(kTabMetricsEntryName));
-  }
-
-  void TearDown() override {
-    EXPECT_EQ(0,
-              ukm_entry_checker_->NumNewEntriesRecorded(kTabMetricsEntryName));
-    InProcessBrowserTest::TearDown();
-  }
-
- protected:
-  void ExpectNewForegroundedEntry(const GURL& url) {
-    // TODO(michaelpg): Add an interactive_ui_test to test MRU metrics since
-    // they can be affected by window activation.
-    UkmMetricMap expected_metrics = {
-        {TabManager_Background_ForegroundedOrClosed::kIsForegroundedName, 1},
-    };
-    ukm_entry_checker_->ExpectNewEntry(kFOCEntryName, url, expected_metrics);
-  }
-
-  void ExpectNewClosedEntry(const GURL& url) {
-    UkmMetricMap expected_metrics = {
-        {TabManager_Background_ForegroundedOrClosed::kIsForegroundedName, 0},
-    };
-    ukm_entry_checker_->ExpectNewEntry(kFOCEntryName, url, expected_metrics);
-  }
-
-  // Uses test_ukm_recorder_ to check new event metrics including:
-  // (1) the number of UkmEntry with given event_name should be equal to |size|.
-  // (2) the newest entry should have source_url equal to |url|.
-  // (3) the newest entry should have source_id equal to |source_id| if
-  //     |source_id| is not 0 (skip for the case of 0).
-  // (4) the newest entry should contain all metrics in |expected_metrics|.
-  // Also returns the source_id of the newest entry.
-  ukm::SourceId ExpectNewEntryWithSourceId(const GURL& url,
-                                           const std::string& event_name,
-                                           size_t num_entries,
-                                           const UkmMetricMap& expected_metrics,
-                                           ukm::SourceId source_id = 0) {
-    const std::vector<const ukm::mojom::UkmEntry*> entries =
-        test_ukm_recorder_->GetEntriesByName(event_name);
-    // Check size.
-    EXPECT_EQ(entries.size(), num_entries);
-    const ukm::mojom::UkmEntry* entry = entries.back();
-    // Check source_url.
-    test_ukm_recorder_->ExpectEntrySourceHasUrl(entry, url);
-    // Check source_id.
-    if (source_id != 0) {
-      EXPECT_EQ(source_id, entry->source_id);
-    }
-    // Check expected_metrics.
-    for (const auto& metric : expected_metrics) {
-      test_ukm_recorder_->ExpectEntryMetric(entry, metric.first,
-                                            *metric.second);
-    }
-
-    return entry->source_id;
-  }
-
-  // Gets the latest metric value from the event with given |metric_name|.
-  int64_t GetLatestMetricValue(const std::string& event_name,
-                               const std::string& metric_name) {
-    const std::vector<const ukm::mojom::UkmEntry*> entries =
-        test_ukm_recorder_->GetEntriesByName(event_name);
-    // Check nonemptiness.
-    EXPECT_FALSE(entries.empty());
-
-    return *(test_ukm_recorder_->GetEntryMetric(entries.back(), metric_name));
-  }
-
-  // Logs tab@i.
-  void LogTabFeaturesAt(const int i) {
-    resource_coordinator::LifecycleUnit* lifecycle_unit =
-        GetTabLifecycleUnitSource()->GetTabLifecycleUnit(
-            browser()->tab_strip_model()->GetWebContentsAt(i));
-
-    std::vector<resource_coordinator::LifecycleUnit*> lifecycle_unit_vec = {
-        lifecycle_unit};
-
-    // Calling LogAndMaybeSortLifecycleUnitWithTabRanker will log the
-    // TabFeatures.
-    TabActivityWatcher::GetInstance()
-        ->LogAndMaybeSortLifecycleUnitWithTabRanker(&lifecycle_unit_vec);
-  }
-
-  std::vector<GURL> test_urls_;
-  std::unique_ptr<UkmEntryChecker> ukm_entry_checker_;
-  std::unique_ptr<ukm::TestAutoSetUkmRecorder> test_ukm_recorder_;
-
- private:
-  base::test::ScopedFeatureList scoped_feature_list_;
-};
-
-class TabActivityWatcherTestWithBackgroundLogDisabled
-    : public TabActivityWatcherTest {
- public:
-  TabActivityWatcherTestWithBackgroundLogDisabled() {
-    feature_list_.InitAndEnableFeatureWithParameters(
-        features::kTabRanker,
-        {{"disable_background_log_with_TabRanker", "true"}});
-  }
-
- private:
-  base::test::ScopedFeatureList feature_list_;
-};
-
-// Tests calculating tab scores using the Tab Ranker.
-IN_PROC_BROWSER_TEST_F(TabActivityWatcherTestWithBackgroundLogDisabled,
-                       CalculateReactivationScore) {
-  // Use test clock so tabs have non-zero backgrounded times.
-  base::SimpleTestTickClock test_clock;
-  ScopedSetTickClockForTesting scoped_set_tick_clock_for_testing(&test_clock);
-  test_clock.Advance(base::Minutes(1));
-
-  ASSERT_TRUE(AddTabAtIndex(1, test_urls_[0], ui::PAGE_TRANSITION_LINK));
-  test_clock.Advance(base::Minutes(1));
-
-  browser()->tab_strip_model()->ActivateTabAt(
-      0, TabStripUserGestureDetails(
-             TabStripUserGestureDetails::GestureType::kOther));
-  test_clock.Advance(base::Minutes(1));
-
-  // A background tab is scored successfully.
-  absl::optional<float> background_score =
-      TabActivityWatcher::GetInstance()->CalculateReactivationScore(
-          browser()->tab_strip_model()->GetWebContentsAt(1));
-  EXPECT_TRUE(background_score.has_value());
-
-  // Foreground tabs are not modeled by the tab ranker and should not be scored.
-  absl::optional<float> foreground_score =
-      TabActivityWatcher::GetInstance()->CalculateReactivationScore(
-          browser()->tab_strip_model()->GetWebContentsAt(0));
-  EXPECT_FALSE(foreground_score.has_value());
-
-  CloseBrowserSynchronously(browser());
-}
-
-// Tests TabMetrics UKMs logged by creating and switching between tabs.
-IN_PROC_BROWSER_TEST_F(TabActivityWatcherTest, SwitchTabs) {
-  const GURL kTabUrls[] = {
-      GURL(),  // "about:blank" tab doesn't have a UKM source.
-      test_urls_[0], test_urls_[1],
-  };
-
-  EXPECT_EQ(0u, ukm_entry_checker_->NumEntries(kTabMetricsEntryName));
-
-  UkmMetricMap expected_metrics = kBasicMetricValues;
-
-  // Adding a new foreground tab logs the previously active tab.
-  ASSERT_TRUE(AddTabAtIndex(1, kTabUrls[1], ui::PAGE_TRANSITION_LINK));
-  {
-    SCOPED_TRACE("");
-    ukm_entry_checker_->ExpectNewEntry(kTabMetricsEntryName, kTabUrls[0],
-                                       expected_metrics);
-  }
-
-  ASSERT_TRUE(AddTabAtIndex(2, kTabUrls[2], ui::PAGE_TRANSITION_LINK));
-  {
-    SCOPED_TRACE("");
-    ukm_entry_checker_->ExpectNewEntry(kTabMetricsEntryName, kTabUrls[1],
-                                       expected_metrics);
-  }
-
-  // Switching to another tab logs the previously active tab.
-  browser()->tab_strip_model()->ActivateTabAt(
-      0, TabStripUserGestureDetails(
-             TabStripUserGestureDetails::GestureType::kOther));
-  {
-    SCOPED_TRACE("");
-    ukm_entry_checker_->ExpectNewEntry(kTabMetricsEntryName, kTabUrls[2],
-                                       expected_metrics);
-    ExpectNewForegroundedEntry(kTabUrls[0]);
-  }
-
-  browser()->tab_strip_model()->ActivateTabAt(
-      1, TabStripUserGestureDetails(
-             TabStripUserGestureDetails::GestureType::kOther));
-  {
-    SCOPED_TRACE("");
-    ukm_entry_checker_->ExpectNewEntry(kTabMetricsEntryName, kTabUrls[0],
-                                       expected_metrics);
-    ExpectNewForegroundedEntry(kTabUrls[1]);
-  }
-
-  // Closing the window doesn't log more TabMetrics UKMs (tested in TearDown()).
-  CloseBrowserSynchronously(browser());
-  {
-    SCOPED_TRACE("");
-    ExpectNewClosedEntry(kTabUrls[2]);
-    ExpectNewClosedEntry(kTabUrls[0]);
-  }
-}
-
-// Tests that switching between multiple windows doesn't affect TabMetrics UKMs.
-// This is a sanity check; window activation shouldn't make any difference to
-// what we log. If we needed to actually test different behavior based on window
-// focus, we would run these tests in interactive_ui_tests.
-IN_PROC_BROWSER_TEST_F(TabActivityWatcherTest, SwitchWindows) {
-  Browser* browser_2 = CreateBrowser(browser()->profile());
-  EXPECT_EQ(0, ukm_entry_checker_->NumNewEntriesRecorded(kTabMetricsEntryName));
-
-  EXPECT_EQ(
-      AddTabAtIndexToBrowser(browser(), 1, test_urls_[0],
-                             ui::PAGE_TRANSITION_LINK, kCheckNavigationSuccess),
-      kCheckNavigationSuccess);
-  {
-    SCOPED_TRACE("");
-    ukm_entry_checker_->ExpectNewEntry(kTabMetricsEntryName, GURL(),
-                                       kBasicMetricValues);
-  }
-
-  EXPECT_EQ(
-      AddTabAtIndexToBrowser(browser_2, 1, test_urls_[1],
-                             ui::PAGE_TRANSITION_LINK, kCheckNavigationSuccess),
-      kCheckNavigationSuccess);
-  {
-    SCOPED_TRACE("");
-    ukm_entry_checker_->ExpectNewEntry(kTabMetricsEntryName, GURL(),
-                                       kBasicMetricValues);
-  }
-
-  browser()->window()->Activate();
-  browser_2->window()->Activate();
-  EXPECT_EQ(0, ukm_entry_checker_->NumNewEntriesRecorded(kTabMetricsEntryName));
-
-  // Closing each window doesn't log more TabMetrics UKMs.
-  CloseBrowserSynchronously(browser_2);
-  CloseBrowserSynchronously(browser());
-}
-
-// Tests page with a beforeunload handler.
-IN_PROC_BROWSER_TEST_F(TabActivityWatcherTest, BeforeUnloadHandler) {
-  // Navigate to a page with a beforeunload handler.
-  GURL url(embedded_test_server()->GetURL("/beforeunload.html"));
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
-
-  // Log metrics for the first tab by switching to a new tab.
-  ASSERT_TRUE(AddTabAtIndex(1, test_urls_[0], ui::PAGE_TRANSITION_LINK));
-  UkmMetricMap expected_metrics = kBasicMetricValues;
-  expected_metrics[TabManager_TabMetrics::kHasBeforeUnloadHandlerName] = 1;
-  expected_metrics[TabManager_TabMetrics::kNavigationEntryCountName] = 2;
-  {
-    SCOPED_TRACE("");
-    ukm_entry_checker_->ExpectNewEntry(kTabMetricsEntryName, url,
-                                       expected_metrics);
-  }
-
-  // Sanity check: the new tab doesn't have a beforeunload handler.
-  browser()->tab_strip_model()->ActivateTabAt(
-      0, TabStripUserGestureDetails(
-             TabStripUserGestureDetails::GestureType::kOther));
-  {
-    SCOPED_TRACE("");
-    ukm_entry_checker_->ExpectNewEntry(kTabMetricsEntryName, test_urls_[0],
-                                       kBasicMetricValues);
-  }
-}
-
-// Tests events logged when dragging a tab between browsers.
-IN_PROC_BROWSER_TEST_F(TabActivityWatcherTest, TabDrag) {
-  // This test will navigate 3 tabs.
-  const GURL kBrowserStartUrl = test_urls_[0];
-  const GURL kBrowser2StartUrl = test_urls_[1];
-  const GURL kDraggedTabUrl = test_urls_[2];
-
-  Browser* browser_2 = CreateBrowser(browser()->profile());
-
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), kBrowserStartUrl));
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser_2, kBrowser2StartUrl));
-
-  // Adding a tab backgrounds the original tab in the window.
-  EXPECT_EQ(
-      AddTabAtIndexToBrowser(browser(), 1, kDraggedTabUrl,
-                             ui::PAGE_TRANSITION_LINK, kCheckNavigationSuccess),
-      kCheckNavigationSuccess);
-  {
-    SCOPED_TRACE("");
-    UkmMetricMap expected_metrics_1 = kBasicMetricValues;
-    expected_metrics_1[TabManager_TabMetrics::kNavigationEntryCountName] = 2;
-    ukm_entry_checker_->ExpectNewEntry(kTabMetricsEntryName, kBrowserStartUrl,
-                                       expected_metrics_1);
-  }
-
-  // "Drag" the new tab out of its browser.
-  content::WebContents* dragged_contents =
-      browser()->tab_strip_model()->GetWebContentsAt(1);
-  std::unique_ptr<content::WebContents> owned_dragged_contents =
-      browser()->tab_strip_model()->DetachWebContentsAtForInsertion(1);
-  dragged_contents->WasHidden();
-  // The other tab in the browser is now foregrounded.
-  ExpectNewForegroundedEntry(kBrowserStartUrl);
-
-  // "Drop" the tab into the other browser. This requires showing and
-  // reactivating the tab, but to the user, it never leaves the foreground, so
-  // we don't log a foregrounded event for it.
-  browser_2->tab_strip_model()->InsertWebContentsAt(
-      1, std::move(owned_dragged_contents), AddTabTypes::ADD_NONE);
-  dragged_contents->WasShown();
-  browser_2->tab_strip_model()->ActivateTabAt(
-      1, TabStripUserGestureDetails(
-             TabStripUserGestureDetails::GestureType::kOther));
-  EXPECT_EQ(0, ukm_entry_checker_->NumNewEntriesRecorded(kFOCEntryName));
-
-  // The first tab in this window was backgrounded when the new one was
-  // inserted.
-  {
-    SCOPED_TRACE("");
-    UkmMetricMap expected_metrics_2 = kBasicMetricValues;
-    expected_metrics_2[TabManager_TabMetrics::kNavigationEntryCountName] = 2;
-    ukm_entry_checker_->ExpectNewEntry(kTabMetricsEntryName, kBrowser2StartUrl,
-                                       expected_metrics_2);
-  }
-
-  // Closing the window with 2 tabs means we log the backgrounded tab as closed.
-  CloseBrowserSynchronously(browser_2);
-  ExpectNewClosedEntry(kBrowser2StartUrl);
-
-  CloseBrowserSynchronously(browser());
-  EXPECT_EQ(0, ukm_entry_checker_->NumNewEntriesRecorded(kTabMetricsEntryName));
-  EXPECT_EQ(0, ukm_entry_checker_->NumNewEntriesRecorded(kFOCEntryName));
-}
-
-class TabActivityWatcherTestWithBackgroundLogEnabled
-    : public TabActivityWatcherTest {
- public:
-  TabActivityWatcherTestWithBackgroundLogEnabled() {
-    feature_list_.InitAndEnableFeatureWithParameters(
-        features::kTabRanker,
-        {{"number_of_oldest_tabs_to_log_with_TabRanker", "1"},
-         {"disable_background_log_with_TabRanker", "false"}});
-  }
-
- private:
-  base::test::ScopedFeatureList feature_list_;
-};
-
-// Tests discarded tab is recorded correctly.
-IN_PROC_BROWSER_TEST_F(TabActivityWatcherTestWithBackgroundLogEnabled,
-                       DiscardedTabGetsPreviousSourceId) {
-  ukm::SourceId ukm_source_id_for_tab_0 = 0;
-  ukm::SourceId ukm_source_id_for_tab_1 = 0;
-
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_urls_[0]));
-  EXPECT_EQ(0u, ukm_entry_checker_->NumEntries(kTabMetricsEntryName));
-
-  // Adding a new foreground tab logs the previously active tab.
-  ASSERT_TRUE(AddTabAtIndex(1, test_urls_[1], ui::PAGE_TRANSITION_LINK));
-  {
-    SCOPED_TRACE("");
-    ukm_entry_checker_->ExpectNewEntry(
-        kTabMetricsEntryName, test_urls_[0],
-        {{TabManager_TabMetrics::kNavigationEntryCountName, 2}});
-
-    ukm_source_id_for_tab_0 = ExpectNewEntryWithSourceId(
-        test_urls_[0], kTabMetricsEntryName, 1,
-        {{TabManager_TabMetrics::kNavigationEntryCountName, 2}});
-  }
-
-  // Discard the first tab.
-  content::WebContents* first_contents =
-      browser()->tab_strip_model()->GetWebContentsAt(0);
-  resource_coordinator::GetTabLifecycleUnitSource()
-      ->GetTabLifecycleUnitExternal(first_contents)
-      ->DiscardTab(LifecycleUnitDiscardReason::URGENT);
-
-  // Logs tab@0.
-  LogTabFeaturesAt(0);
-  {
-    SCOPED_TRACE("");
-    // tab feature of tab@0 should be logged correctly.
-    UkmMetricMap expected_tab_feature_values = kBasicMetricValues;
-    expected_tab_feature_values[TabManager_TabMetrics::kMRUIndexName] = 1;
-    expected_tab_feature_values
-        [TabManager_TabMetrics::kNumReactivationBeforeName] = 0;
-    expected_tab_feature_values[TabManager_TabMetrics::kTotalTabCountName] = 2;
-    expected_tab_feature_values[TabManager_TabMetrics::kWindowTabCountName] = 2;
-    expected_tab_feature_values[TabManager_TabMetrics::kLabelIdName] =
-        2 * kIdShift;
-    expected_tab_feature_values[TabManager_TabMetrics::kQueryIdName] =
-        1 * kIdShift;
-    expected_tab_feature_values
-        [TabManager_TabMetrics::kNavigationEntryCountName] = 2;
-
-    ukm_entry_checker_->ExpectNewEntry(kTabMetricsEntryName, test_urls_[0],
-                                       expected_tab_feature_values);
-    ExpectNewEntryWithSourceId(test_urls_[0], kTabMetricsEntryName, 2,
-                               expected_tab_feature_values,
-                               ukm_source_id_for_tab_0);
-  }
-
-  // Switching to first tab logs a forgrounded event for test_urls_[0]
-  // and a backgrounded event for test_urls_[1].
-  browser()->tab_strip_model()->ActivateTabAt(
-      0, TabStripUserGestureDetails(
-             TabStripUserGestureDetails::GestureType::kOther));
-  {
-    SCOPED_TRACE("");
-    ukm_entry_checker_->ExpectNewEntry(kTabMetricsEntryName, test_urls_[1],
-                                       kBasicMetricValues);
-
-    ukm_source_id_for_tab_1 = ExpectNewEntryWithSourceId(
-        test_urls_[1], kTabMetricsEntryName, 3, kBasicMetricValues);
-
-    ExpectNewEntryWithSourceId(
-        test_urls_[0], kFOCEntryName, 1,
-        {{TabManager_Background_ForegroundedOrClosed::kIsForegroundedName, 1},
-         {TabManager_Background_ForegroundedOrClosed::kIsDiscardedName, 1}},
-        ukm_source_id_for_tab_0);
-  }
-
-  // Discard the second tab.
-  content::WebContents* second_content =
-      browser()->tab_strip_model()->GetWebContentsAt(1);
-  resource_coordinator::GetTabLifecycleUnitSource()
-      ->GetTabLifecycleUnitExternal(second_content)
-      ->DiscardTab(LifecycleUnitDiscardReason::URGENT);
-
-  CloseBrowserSynchronously(browser());
-  {
-    SCOPED_TRACE("");
-
-    ExpectNewEntryWithSourceId(
-        test_urls_[1], kFOCEntryName, 2,
-        {{TabManager_Background_ForegroundedOrClosed::kIsForegroundedName, 0},
-         {TabManager_Background_ForegroundedOrClosed::kIsDiscardedName, 1}},
-        ukm_source_id_for_tab_1);
-  }
-}
-
-// Tests that all window metrics are logged with correct value which are
-// different from their default values in TabFeatures.
-IN_PROC_BROWSER_TEST_F(TabActivityWatcherTest, AllWindowMetricsArePopulated) {
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_urls_[0]));
-
-  // Adding a new foreground tab logs the previously active tab.
-  ASSERT_TRUE(AddTabAtIndex(1, test_urls_[1], ui::PAGE_TRANSITION_LINK));
-  {
-    SCOPED_TRACE("");
-    UkmMetricMap expected_metrics = {
-        {"WindowShowState", metrics::WindowMetricsEvent::SHOW_STATE_NORMAL},
-        {"WindowTabCount", 2},
-        {"WindowType", metrics::WindowMetricsEvent::TYPE_TABBED},
-    };
-    ukm_entry_checker_->ExpectNewEntry(kTabMetricsEntryName, test_urls_[0],
-                                       expected_metrics);
-  }
-}
-
-class TabActivityWatcherTestWithBackgroundLogDisabledAndOnlyOneOldestTab
-    : public TabActivityWatcherTest {
- public:
-  TabActivityWatcherTestWithBackgroundLogDisabledAndOnlyOneOldestTab() {
-    // Set Feature params for this test.
-    // (1) background log is disabled, so that only query time logging and
-    // corresponding labels should be logged.
-    // (2) number of oldest tabs to log is set to 1, so that only 1 tab should
-    // be logged.
-    feature_list_.InitAndEnableFeatureWithParameters(
-        features::kTabRanker,
-        {{"number_of_oldest_tabs_to_log_with_TabRanker", "1"},
-         {"disable_background_log_with_TabRanker", "true"}});
-  }
-
- private:
-  base::test::ScopedFeatureList feature_list_;
-};
-
-// Test the query time logging is correct.
-IN_PROC_BROWSER_TEST_F(
-    TabActivityWatcherTestWithBackgroundLogDisabledAndOnlyOneOldestTab,
-    LogOldestNTabFeatures) {
-  // Use test clock so tabs have non-zero backgrounded times.
-  base::SimpleTestTickClock test_clock;
-  ScopedSetTickClockForTesting scoped_set_tick_clock_for_testing(&test_clock);
-  test_clock.Advance(base::Minutes(1));
-
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_urls_[0]));
-  // Insert the tab@1.
-  ASSERT_TRUE(AddTabAtIndex(1, test_urls_[1], ui::PAGE_TRANSITION_LINK));
-  test_clock.Advance(base::Minutes(1));
-  // Insert the tab@2.
-  ASSERT_TRUE(AddTabAtIndex(2, test_urls_[2], ui::PAGE_TRANSITION_LINK));
-  test_clock.Advance(base::Minutes(1));
-  // Activate tab@0.
-  browser()->tab_strip_model()->ActivateTabAt(
-      0, TabStripUserGestureDetails(
-             TabStripUserGestureDetails::GestureType::kOther));
-  test_clock.Advance(base::Minutes(1));
-
-  // TabManager_TabMetrics should not have been logged yet.
-  EXPECT_EQ(0, ukm_entry_checker_->NumNewEntriesRecorded(kTabMetricsEntryName));
-
-  // TabManager_Background_ForegroundedOrClosed should have been logged when
-  // tab@0 was activated.
-  ukm_entry_checker_->ExpectNewEntry(
-      kFOCEntryName, test_urls_[0],
-      {{TabManager_Background_ForegroundedOrClosed::kIsForegroundedName, 1},
-       {TabManager_Background_ForegroundedOrClosed::kLabelIdName, 0},
-       {TabManager_Background_ForegroundedOrClosed::kIsDiscardedName, 0}});
-
-  // Logs tab@1.
-  LogTabFeaturesAt(1);
-  {
-    SCOPED_TRACE("");
-    // tab feature of tab@1 should be logged correctly.
-    UkmMetricMap expected_tab_feature_values = kBasicMetricValues;
-    expected_tab_feature_values[TabManager_TabMetrics::kMRUIndexName] = 2;
-    expected_tab_feature_values
-        [TabManager_TabMetrics::kNumReactivationBeforeName] = 0;
-    expected_tab_feature_values[TabManager_TabMetrics::kTotalTabCountName] = 3;
-    expected_tab_feature_values[TabManager_TabMetrics::kWindowTabCountName] = 3;
-    expected_tab_feature_values[TabManager_TabMetrics::kLabelIdName] =
-        2 * kIdShift;
-    expected_tab_feature_values[TabManager_TabMetrics::kQueryIdName] =
-        1 * kIdShift;
-
-    ukm_entry_checker_->ExpectNewEntry(kTabMetricsEntryName, test_urls_[1],
-                                       expected_tab_feature_values);
-  }
-
-  // Reactivate tab@1 should log a ForegroundedOrClosed event with LabelId as
-  // label_id_1.
-  browser()->tab_strip_model()->ActivateTabAt(
-      1, TabStripUserGestureDetails(
-             TabStripUserGestureDetails::GestureType::kOther));
-  test_clock.Advance(base::Minutes(1));
-  {
-    SCOPED_TRACE("");
-    ukm_entry_checker_->ExpectNewEntry(
-        kFOCEntryName, test_urls_[1],
-        {{TabManager_Background_ForegroundedOrClosed::kIsForegroundedName, 1},
-         {TabManager_Background_ForegroundedOrClosed::kLabelIdName,
-          2 * kIdShift},
-         {TabManager_Background_ForegroundedOrClosed::kIsDiscardedName, 0}});
-  }
-
-  // Logs tab@2.
-  LogTabFeaturesAt(2);
-  {
-    SCOPED_TRACE("");
-    // tab feature of tab@2 should be logged correctly.
-    UkmMetricMap expected_tab_feature_values = kBasicMetricValues;
-    expected_tab_feature_values[TabManager_TabMetrics::kMRUIndexName] = 2;
-    expected_tab_feature_values
-        [TabManager_TabMetrics::kNumReactivationBeforeName] = 0;
-    expected_tab_feature_values[TabManager_TabMetrics::kTotalTabCountName] = 3;
-    expected_tab_feature_values[TabManager_TabMetrics::kWindowTabCountName] = 3;
-    expected_tab_feature_values[TabManager_TabMetrics::kLabelIdName] =
-        4 * kIdShift;
-    expected_tab_feature_values[TabManager_TabMetrics::kQueryIdName] =
-        3 * kIdShift;
-
-    ukm_entry_checker_->ExpectNewEntry(kTabMetricsEntryName, test_urls_[2],
-                                       expected_tab_feature_values);
-  }
-
-  // No ForegroundedOrClosed event is logged for tab@1 because it's foregrounded
-  CloseBrowserSynchronously(browser());
-  {
-    SCOPED_TRACE("");
-    // No ForegroundedOrClosed event is logged for tab@1 because it was
-    // foregrounded. The event should be logged for tab@0 and tab@2.
-
-    // tab@2
-    ukm_entry_checker_->ExpectNewEntry(
-        kFOCEntryName, test_urls_[2],
-        {{TabManager_Background_ForegroundedOrClosed::kIsForegroundedName, 0},
-         {TabManager_Background_ForegroundedOrClosed::kLabelIdName,
-          4 * kIdShift},
-         {TabManager_Background_ForegroundedOrClosed::kIsDiscardedName, 0}});
-
-    // tab@0
-    ukm_entry_checker_->ExpectNewEntry(
-        kFOCEntryName, test_urls_[0],
-        {{TabManager_Background_ForegroundedOrClosed::kIsForegroundedName, 0},
-         {TabManager_Background_ForegroundedOrClosed::kLabelIdName, 0},
-         {TabManager_Background_ForegroundedOrClosed::kIsDiscardedName, 0}});
-  }
-}
-
-// Tests label id is recorded correctly for discarded tabs.
-IN_PROC_BROWSER_TEST_F(
-    TabActivityWatcherTestWithBackgroundLogDisabledAndOnlyOneOldestTab,
-    DiscardedTabGetsCorrectLabelId) {
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_urls_[0]));
-  ASSERT_TRUE(AddTabAtIndex(1, test_urls_[1], ui::PAGE_TRANSITION_LINK));
-  // No TabMetrics events are logged till now.
-  EXPECT_EQ(0u, ukm_entry_checker_->NumEntries(kTabMetricsEntryName));
-
-  // Logs tab@0.
-  LogTabFeaturesAt(0);
-  {
-    SCOPED_TRACE("");
-    UkmMetricMap expected_metrics = kBasicMetricValues;
-    expected_metrics[TabManager_TabMetrics::kNavigationEntryCountName] = 2;
-    expected_metrics[TabManager_TabMetrics::kLabelIdName] = 2 * kIdShift;
-    expected_metrics[TabManager_TabMetrics::kQueryIdName] = 1 * kIdShift;
-    // tab feature of tab@0 should be logged correctly.
-    ukm_entry_checker_->ExpectNewEntry(kTabMetricsEntryName, test_urls_[0],
-                                       expected_metrics);
-  }
-
-  // Discard the first tab.
-  content::WebContents* first_contents =
-      browser()->tab_strip_model()->GetWebContentsAt(0);
-  resource_coordinator::GetTabLifecycleUnitSource()
-      ->GetTabLifecycleUnitExternal(first_contents)
-      ->DiscardTab(LifecycleUnitDiscardReason::URGENT);
-
-  // Switching to first tab logs a forgrounded event for test_urls_[0].
-  browser()->tab_strip_model()->ActivateTabAt(
-      0, TabStripUserGestureDetails(
-             TabStripUserGestureDetails::GestureType::kOther));
-  {
-    SCOPED_TRACE("");
-    UkmMetricMap expected_metrics = {
-        {TabManager_Background_ForegroundedOrClosed::kIsForegroundedName, 1},
-        {TabManager_Background_ForegroundedOrClosed::kIsDiscardedName, 1},
-        {TabManager_Background_ForegroundedOrClosed::kLabelIdName,
-         2 * kIdShift}};
-
-    ukm_entry_checker_->ExpectNewEntry(kFOCEntryName, test_urls_[0],
-                                       expected_metrics);
-  }
-
-  // Logs tab@1.
-  LogTabFeaturesAt(1);
-  {
-    SCOPED_TRACE("");
-    // tab feature of tab@1 should be logged correctly.
-    UkmMetricMap expected_metrics = kBasicMetricValues;
-    expected_metrics[TabManager_TabMetrics::kLabelIdName] = 4 * kIdShift;
-    expected_metrics[TabManager_TabMetrics::kQueryIdName] = 3 * kIdShift;
-    ukm_entry_checker_->ExpectNewEntry(kTabMetricsEntryName, test_urls_[1],
-                                       expected_metrics);
-  }
-
-  // Discard the second tab.
-  content::WebContents* second_content =
-      browser()->tab_strip_model()->GetWebContentsAt(1);
-  resource_coordinator::GetTabLifecycleUnitSource()
-      ->GetTabLifecycleUnitExternal(second_content)
-      ->DiscardTab(LifecycleUnitDiscardReason::URGENT);
-
-  CloseBrowserSynchronously(browser());
-  {
-    SCOPED_TRACE("");
-    UkmMetricMap expected_metrics = {
-        {TabManager_Background_ForegroundedOrClosed::kIsForegroundedName, 0},
-        {TabManager_Background_ForegroundedOrClosed::kIsDiscardedName, 1},
-        {TabManager_Background_ForegroundedOrClosed::kLabelIdName,
-         4 * kIdShift}};
-
-    ukm_entry_checker_->ExpectNewEntry(kFOCEntryName, test_urls_[1],
-                                       expected_metrics);
-  }
-}
-
-// Tests label_id is incremented if the LogOldestNTabFeatures is called second
-// times without logging the label first.
-IN_PROC_BROWSER_TEST_F(
-    TabActivityWatcherTestWithBackgroundLogDisabledAndOnlyOneOldestTab,
-    TabsAlreadyHaveLabelIdGetIncrementalLabelIds) {
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_urls_[0]));
-  ASSERT_TRUE(AddTabAtIndex(1, test_urls_[1], ui::PAGE_TRANSITION_LINK));
-  // No TabMetrics events are logged till now.
-  EXPECT_EQ(0u, ukm_entry_checker_->NumEntries(kTabMetricsEntryName));
-
-  // Logs tab@0.
-  LogTabFeaturesAt(0);
-  {
-    SCOPED_TRACE("");
-    UkmMetricMap expected_metrics = kBasicMetricValues;
-    expected_metrics[TabManager_TabMetrics::kNavigationEntryCountName] = 2;
-    expected_metrics[TabManager_TabMetrics::kLabelIdName] = 2 * kIdShift;
-    expected_metrics[TabManager_TabMetrics::kQueryIdName] = 1 * kIdShift;
-    // tab feature of tab@0 should be logged correctly.
-    ukm_entry_checker_->ExpectNewEntry(kTabMetricsEntryName, test_urls_[0],
-                                       expected_metrics);
-  }
-
-  LogTabFeaturesAt(0);
-  {
-    SCOPED_TRACE("");
-    UkmMetricMap expected_metrics = kBasicMetricValues;
-    expected_metrics[TabManager_TabMetrics::kNavigationEntryCountName] = 2;
-    expected_metrics[TabManager_TabMetrics::kLabelIdName] = 2 * kIdShift + 1;
-    expected_metrics[TabManager_TabMetrics::kQueryIdName] = 3 * kIdShift;
-    // tab feature of tab@0 should be logged correctly.
-    ukm_entry_checker_->ExpectNewEntry(kTabMetricsEntryName, test_urls_[0],
-                                       expected_metrics);
-  }
-}
-
-class TabActivityWatcherPrerenderingTest : public TabActivityWatcherTest {
- public:
-  TabActivityWatcherPrerenderingTest()
-      : prerender_test_helper_(base::BindRepeating(
-            &TabActivityWatcherPrerenderingTest::GetWebContents,
-            base::Unretained(this))) {}
-  ~TabActivityWatcherPrerenderingTest() override = default;
-
-  void SetUp() override {
-    prerender_test_helper_.SetUp(embedded_test_server());
-    TabActivityWatcherTest::SetUp();
-  }
-
-  content::test::PrerenderTestHelper& prerender_helper() {
-    return prerender_test_helper_;
-  }
-
-  content::WebContents* GetWebContents() {
-    return browser()->tab_strip_model()->GetWebContentsAt(0);
-  }
-
- private:
-  content::test::PrerenderTestHelper prerender_test_helper_;
-};
-
-// Tests that all tabs metrics are logged with correct value and should not be
-// logged in prerendering.
-IN_PROC_BROWSER_TEST_F(TabActivityWatcherPrerenderingTest,
-                       SwitchTabsWithPrerendering) {
-  ukm::SourceId ukm_source_id_for_tab_0 = 0;
-  ukm::SourceId ukm_source_id_for_activated_page = 0;
-
-  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_urls_[0]));
-  EXPECT_EQ(0u, ukm_entry_checker_->NumEntries(kTabMetricsEntryName));
-
-  // Load a page in the prerender.
-  GURL prerender_url = embedded_test_server()->GetURL("/simple.html");
-  prerender_helper().AddPrerender(prerender_url);
-
-  // Adding a new foreground tab logs the previously active tab.
-  ASSERT_TRUE(AddTabAtIndex(1, test_urls_[1], ui::PAGE_TRANSITION_LINK));
-  {
-    SCOPED_TRACE("");
-    ukm_entry_checker_->ExpectNewEntry(
-        kTabMetricsEntryName, test_urls_[0],
-        {{TabManager_TabMetrics::kNavigationEntryCountName, 2}});
-
-    ukm_source_id_for_tab_0 = ExpectNewEntryWithSourceId(
-        test_urls_[0], kTabMetricsEntryName, 1,
-        {{TabManager_TabMetrics::kNavigationEntryCountName, 2}});
-  }
-
-  // Switching to another tab logs the previously active tab.
-  browser()->tab_strip_model()->ActivateTabAt(
-      0, TabStripUserGestureDetails(
-             TabStripUserGestureDetails::GestureType::kOther));
-  {
-    SCOPED_TRACE("");
-    ukm_entry_checker_->ExpectNewEntry(kTabMetricsEntryName, test_urls_[1],
-                                       kBasicMetricValues);
-
-    ExpectNewEntryWithSourceId(test_urls_[1], kTabMetricsEntryName, 2,
-                               kBasicMetricValues);
-
-    ExpectNewEntryWithSourceId(
-        test_urls_[0], kFOCEntryName, 1,
-        {{TabManager_Background_ForegroundedOrClosed::kIsForegroundedName, 1}},
-        ukm_source_id_for_tab_0);
-  }
-  // Activating the prerendered page on the current active tab.
-  prerender_helper().NavigatePrimaryPage(prerender_url);
-
-  // Switching to another tab logs the previously active tab.
-  browser()->tab_strip_model()->ActivateTabAt(
-      1, TabStripUserGestureDetails(
-             TabStripUserGestureDetails::GestureType::kOther));
-  {
-    SCOPED_TRACE("");
-    UkmMetricMap expected_metrics = kBasicMetricValues;
-    expected_metrics[TabManager_TabMetrics::kNavigationEntryCountName] = 3;
-
-    // A new entry should be added by the prerendering activation.
-    ukm_entry_checker_->ExpectNewEntry(kTabMetricsEntryName, prerender_url,
-                                       expected_metrics);
-
-    ukm_source_id_for_activated_page = ExpectNewEntryWithSourceId(
-        prerender_url, kTabMetricsEntryName, 3, expected_metrics);
-  }
-
-  // ukm::SourceId is updated when the prerendered page is activated.
-  EXPECT_NE(ukm_source_id_for_tab_0, ukm_source_id_for_activated_page);
-}
-
-}  // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/tab_activity_watcher_unittest.cc b/chrome/browser/resource_coordinator/tab_activity_watcher_unittest.cc
deleted file mode 100644
index 130aeeda..0000000
--- a/chrome/browser/resource_coordinator/tab_activity_watcher_unittest.cc
+++ /dev/null
@@ -1,926 +0,0 @@
-// Copyright 2017 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/resource_coordinator/tab_activity_watcher.h"
-
-#include <memory>
-
-#include "base/no_destructor.h"
-#include "base/test/scoped_feature_list.h"
-#include "base/test/simple_test_tick_clock.h"
-#include "build/chromeos_buildflags.h"
-#include "chrome/browser/resource_coordinator/lifecycle_unit.h"
-#include "chrome/browser/resource_coordinator/tab_lifecycle_unit.h"
-#include "chrome/browser/resource_coordinator/tab_lifecycle_unit_source.h"
-#include "chrome/browser/resource_coordinator/tab_manager_features.h"
-#include "chrome/browser/resource_coordinator/time.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/recently_audible_helper.h"
-#include "chrome/browser/ui/tabs/tab_activity_simulator.h"
-#include "chrome/browser/ui/tabs/tab_enums.h"
-#include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/tabs/tab_ukm_test_helper.h"
-#include "chrome/test/base/chrome_render_view_host_test_harness.h"
-#include "chrome/test/base/test_browser_window.h"
-#include "chrome/test/base/testing_profile.h"
-#include "components/site_engagement/content/site_engagement_service.h"
-#include "components/ukm/content/source_url_recorder.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/render_widget_host.h"
-#include "content/public/test/navigation_simulator.h"
-#include "content/public/test/web_contents_tester.h"
-#include "services/metrics/public/cpp/ukm_builders.h"
-#include "services/metrics/public/cpp/ukm_source.h"
-#include "services/metrics/public/mojom/ukm_interface.mojom.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/input/web_input_event.h"
-#include "third_party/blink/public/common/input/web_mouse_event.h"
-
-using blink::WebInputEvent;
-using content::WebContentsTester;
-using ukm::builders::TabManager_TabMetrics;
-using ForegroundedOrClosed =
-    ukm::builders::TabManager_Background_ForegroundedOrClosed;
-
-namespace resource_coordinator {
-namespace {
-
-const char* kTabMetricsEntryName = TabManager_TabMetrics::kEntryName;
-
-const int64_t kIdShift = 1 << 16;
-
-// Test URLs need to be from different origins to test site engagement score.
-const std::vector<GURL>& TestUrls() {
-  static base::NoDestructor<std::vector<GURL>> test_urls{
-      {GURL("https://test1.example.com"), GURL("https://test3.example.com"),
-       GURL("https://test2.example.com"), GURL("https://test4.example.com")}};
-  return *test_urls;
-}
-
-// The default metric values for a tab.
-const UkmMetricMap kBasicMetricValues({
-    {TabManager_TabMetrics::kHasBeforeUnloadHandlerName, 0},
-    {TabManager_TabMetrics::kHasFormEntryName, 0},
-    {TabManager_TabMetrics::kIsPinnedName, 0},
-    {TabManager_TabMetrics::kKeyEventCountName, 0},
-    {TabManager_TabMetrics::kMouseEventCountName, 0},
-    {TabManager_TabMetrics::kSiteEngagementScoreName, 0},
-    {TabManager_TabMetrics::kTouchEventCountName, 0},
-    {TabManager_TabMetrics::kWasRecentlyAudibleName, 0},
-});
-
-blink::WebMouseEvent CreateMouseEvent(WebInputEvent::Type event_type) {
-  return blink::WebMouseEvent(event_type, WebInputEvent::kNoModifiers,
-                              WebInputEvent::GetStaticTimeStampForTests());
-}
-
-}  // namespace
-
-// Base class for testing tab UKM (URL-Keyed Metrics) entries logged by
-// TabMetricsLogger via TabActivityWatcher.
-class TabActivityWatcherTest : public ChromeRenderViewHostTestHarness {
- public:
-  TabActivityWatcherTest() = default;
-  // Reset TabActivityWatcher with given |params|.
-  // This should only be called from test constructors, to avoid tsan data races
-  // with the  FeatureList.
-  void SetParams(const base::FieldTrialParams& params) {
-    feature_list_.InitAndEnableFeatureWithParameters(features::kTabRanker,
-                                                     params);
-    TabActivityWatcher::GetInstance()->ResetForTesting();
-  }
-
-  TabActivityWatcherTest(const TabActivityWatcherTest&) = delete;
-  TabActivityWatcherTest& operator=(const TabActivityWatcherTest&) = delete;
-
-  ~TabActivityWatcherTest() override = default;
-
-  LifecycleUnit* AddNewTab(TabStripModel* tab_strip_model, int i) {
-    LifecycleUnit* result = TabLifecycleUnitSource::GetTabLifecycleUnit(
-        tab_activity_simulator_.AddWebContentsAndNavigate(tab_strip_model,
-                                                          TestUrls()[i]));
-    if (i == 0)
-      tab_strip_model->ActivateTabAt(i);
-    else
-      tab_activity_simulator_.SwitchToTabAt(tab_strip_model, i);
-
-    return result;
-  }
-
-  // Calculate reactivation score of the |lifecycle_unit| using tab_ranker.
-  absl::optional<float> GetReactivationScore(
-      LifecycleUnit* const lifecycle_unit) {
-    return TabActivityWatcher::GetInstance()->CalculateReactivationScore(
-        lifecycle_unit->AsTabLifecycleUnitExternal()->GetWebContents());
-  }
-
- protected:
-  UkmEntryChecker ukm_entry_checker_;
-  TabActivitySimulator tab_activity_simulator_;
-  base::test::ScopedFeatureList feature_list_;
-};
-
-class TabActivityWatcherScorerType0Test : public TabActivityWatcherTest {
- public:
-  TabActivityWatcherScorerType0Test() { SetParams({{"scorer_type", "0"}}); }
-};
-
-// Test that lifecycleunits are sorted with high activation score first order.
-TEST_F(TabActivityWatcherScorerType0Test,
-       LogAndMaybeSortLifecycleUnitWithTabRanker) {
-  Browser::CreateParams params(profile(), true);
-  std::unique_ptr<Browser> browser =
-      CreateBrowserWithTestWindowForParams(params);
-  TabStripModel* tab_strip_model = browser->tab_strip_model();
-
-  // Create lifecycleunits.
-  LifecycleUnit* tab0 = AddNewTab(tab_strip_model, 0);
-  LifecycleUnit* tab1 = AddNewTab(tab_strip_model, 1);
-  LifecycleUnit* tab2 = AddNewTab(tab_strip_model, 2);
-  LifecycleUnit* tab3 = AddNewTab(tab_strip_model, 3);
-  std::vector<LifecycleUnit*> lifecycleunits = {tab0, tab2, tab3, tab1};
-
-  // Sort and check the new order.
-  TabActivityWatcher::GetInstance()->LogAndMaybeSortLifecycleUnitWithTabRanker(
-      &lifecycleunits);
-  EXPECT_EQ(lifecycleunits[0], tab3);
-  EXPECT_EQ(lifecycleunits[1], tab2);
-  EXPECT_EQ(lifecycleunits[2], tab1);
-  EXPECT_EQ(lifecycleunits[3], tab0);
-
-  tab_strip_model->CloseAllTabs();
-}
-
-class TabActivityWatcherScorerType3Test : public TabActivityWatcherTest {
- public:
-  TabActivityWatcherScorerType3Test() { SetParams({{"scorer_type", "3"}}); }
-};
-
-// Test that lifecycleunits are sorted with high frecency score first order.
-TEST_F(TabActivityWatcherScorerType3Test, SortLifecycleUnitWithFrecencyScorer) {
-  Browser::CreateParams params(profile(), true);
-  std::unique_ptr<Browser> browser =
-      CreateBrowserWithTestWindowForParams(params);
-  TabStripModel* tab_strip_model = browser->tab_strip_model();
-
-  // Create lifecycleunits.
-  LifecycleUnit* tab0 = AddNewTab(tab_strip_model, 0);
-  LifecycleUnit* tab1 = AddNewTab(tab_strip_model, 1);
-  LifecycleUnit* tab2 = AddNewTab(tab_strip_model, 2);
-  LifecycleUnit* tab3 = AddNewTab(tab_strip_model, 3);
-
-  for (int i = 0; i < 10; ++i) {
-    tab_activity_simulator_.SwitchToTabAt(tab_strip_model, 0);
-    tab_activity_simulator_.SwitchToTabAt(tab_strip_model, 1);
-  }
-  tab_activity_simulator_.SwitchToTabAt(tab_strip_model, 3);
-  tab_activity_simulator_.SwitchToTabAt(tab_strip_model, 2);
-  std::vector<LifecycleUnit*> lifecycleunits = {tab0, tab1, tab2, tab3};
-  // Sort and check the new order.
-  TabActivityWatcher::GetInstance()->LogAndMaybeSortLifecycleUnitWithTabRanker(
-      &lifecycleunits);
-  // tab2 is the first one because it is foregrounded.
-  EXPECT_EQ(lifecycleunits[0], tab2);
-  // tab1 and tab0 are in front of tab3 because they are reactived many times.
-  EXPECT_EQ(lifecycleunits[1], tab1);
-  EXPECT_EQ(lifecycleunits[2], tab0);
-  // tab3 comes last.
-  EXPECT_EQ(lifecycleunits[3], tab3);
-
-  tab_strip_model->CloseAllTabs();
-}
-
-// Test that frecency scores are calculated correctly.
-TEST_F(TabActivityWatcherScorerType3Test, GetFrecencyScore) {
-  Browser::CreateParams params(profile(), true);
-  std::unique_ptr<Browser> browser =
-      CreateBrowserWithTestWindowForParams(params);
-  TabStripModel* tab_strip_model = browser->tab_strip_model();
-
-  LifecycleUnit* tab0 = AddNewTab(tab_strip_model, 0);
-  // Foregrounded tab doesn't have a reactivation score.
-  EXPECT_FALSE(GetReactivationScore(tab0).has_value());
-
-  LifecycleUnit* tab1 = AddNewTab(tab_strip_model, 1);
-  // Foregrounded tab doesn't have a reactivation score.
-  EXPECT_FALSE(GetReactivationScore(tab1).has_value());
-  EXPECT_FLOAT_EQ(GetReactivationScore(tab0).value(), 0.16f);
-
-  LifecycleUnit* tab2 = AddNewTab(tab_strip_model, 2);
-  // Foregrounded tab doesn't have a reactivation score.
-  EXPECT_FALSE(GetReactivationScore(tab2).has_value());
-  EXPECT_FLOAT_EQ(GetReactivationScore(tab1).value(), 0.16f);
-  EXPECT_FLOAT_EQ(GetReactivationScore(tab0).value(), 0.128f);
-
-  tab_activity_simulator_.SwitchToTabAt(tab_strip_model, 1);
-  // Foregrounded tab doesn't have a reactivation score.
-  EXPECT_FALSE(GetReactivationScore(tab1).has_value());
-  EXPECT_FLOAT_EQ(GetReactivationScore(tab2).value(), 0.16f);
-  EXPECT_FLOAT_EQ(GetReactivationScore(tab0).value(), 0.1024f);
-
-  tab_activity_simulator_.SwitchToTabAt(tab_strip_model, 0);
-  // Foregrounded tab doesn't have a reactivation score.
-  EXPECT_FALSE(GetReactivationScore(tab0).has_value());
-  EXPECT_FLOAT_EQ(GetReactivationScore(tab1).value(), 0.2624f);
-  EXPECT_FLOAT_EQ(GetReactivationScore(tab2).value(), 0.128f);
-
-  tab_strip_model->CloseAllTabs();
-}
-
-class TabActiveWatcherDisableBackgroundLogTest : public TabActivityWatcherTest {
- public:
-  TabActiveWatcherDisableBackgroundLogTest() {
-    SetParams({{"disable_background_log_with_TabRanker", "true"}});
-  }
-};
-
-// Test that lifecycleunits are correctly logged inside
-// LogAndMaybeSortLifecycleUnitWithTabRanker.
-TEST_F(TabActiveWatcherDisableBackgroundLogTest,
-       LogInsideLogAndMaybeSortLifecycleUnitWithTabRanker) {
-  Browser::CreateParams params(profile(), true);
-  std::unique_ptr<Browser> browser =
-      CreateBrowserWithTestWindowForParams(params);
-  TabStripModel* tab_strip_model = browser->tab_strip_model();
-
-  // Create lifecycleunits.
-  LifecycleUnit* tab0 = AddNewTab(tab_strip_model, 0);
-  LifecycleUnit* tab1 = AddNewTab(tab_strip_model, 1);
-  LifecycleUnit* tab2 = AddNewTab(tab_strip_model, 2);
-  std::vector<LifecycleUnit*> lifecycleunits = {tab0};
-
-  // Call LogAndMaybeSortLifecycleUnitWithTabRanker on tab0 should log the
-  // TabMetrics for tab0.
-  TabActivityWatcher::GetInstance()->LogAndMaybeSortLifecycleUnitWithTabRanker(
-      &lifecycleunits);
-  {
-    SCOPED_TRACE("");
-    ukm_entry_checker_.ExpectNewEntry(
-        kTabMetricsEntryName, TestUrls()[0],
-        {
-            {TabManager_TabMetrics::kQueryIdName, 1 * kIdShift},
-            {TabManager_TabMetrics::kLabelIdName, 2 * kIdShift},
-        });
-  }
-
-  // Call LogAndMaybeSortLifecycleUnitWithTabRanker on tab0 should log the
-  // TabMetrics for tab0.
-  TabActivityWatcher::GetInstance()->LogAndMaybeSortLifecycleUnitWithTabRanker(
-      &lifecycleunits);
-  {
-    SCOPED_TRACE("");
-    ukm_entry_checker_.ExpectNewEntry(
-        kTabMetricsEntryName, TestUrls()[0],
-        {
-            {TabManager_TabMetrics::kQueryIdName, 3 * kIdShift},
-            {TabManager_TabMetrics::kLabelIdName, 2 * kIdShift + 1},
-        });
-  }
-
-  // Call LogAndMaybeSortLifecycleUnitWithTabRanker on tab2 should not log the
-  // TabMetrics for tab2 because it is foregrounded.
-  lifecycleunits = {tab2};
-  TabActivityWatcher::GetInstance()->LogAndMaybeSortLifecycleUnitWithTabRanker(
-      &lifecycleunits);
-  {
-    SCOPED_TRACE("");
-    EXPECT_EQ(ukm_entry_checker_.NumNewEntriesRecorded(kTabMetricsEntryName),
-              0);
-  }
-
-  // Call LogAndMaybeSortLifecycleUnitWithTabRanker on all three tabs should log
-  // two TabMetrics events for tab0 and tab1.
-  lifecycleunits = {tab0, tab1, tab2};
-  TabActivityWatcher::GetInstance()->LogAndMaybeSortLifecycleUnitWithTabRanker(
-      &lifecycleunits);
-  {
-    SCOPED_TRACE("");
-    EXPECT_EQ(ukm_entry_checker_.NumNewEntriesRecorded(kTabMetricsEntryName),
-              2);
-
-    ukm_entry_checker_.ExpectNewEntry(
-        kTabMetricsEntryName, TestUrls()[0],
-        {
-            {TabManager_TabMetrics::kQueryIdName, 5 * kIdShift},
-            {TabManager_TabMetrics::kLabelIdName, 2 * kIdShift + 2},
-        });
-
-    ukm_entry_checker_.ExpectNewEntry(
-        kTabMetricsEntryName, TestUrls()[1],
-        {
-            {TabManager_TabMetrics::kQueryIdName, 5 * kIdShift},
-            {TabManager_TabMetrics::kLabelIdName, 6 * kIdShift},
-        });
-  }
-
-  tab_strip_model->CloseAllTabs();
-}
-
-// Tests TabManager.TabMetrics UKM entries generated when tabs are backgrounded.
-class TabMetricsTest : public TabActivityWatcherTest {
- public:
-  TabMetricsTest() {
-    SetParams({{"scorer_type", "0"},
-               {"disable_background_log_with_TabRanker", "false"}});
-  }
-
-  TabMetricsTest(const TabMetricsTest&) = delete;
-  TabMetricsTest& operator=(const TabMetricsTest&) = delete;
-
-  ~TabMetricsTest() override = default;
-
- protected:
-  // Expects that a new TabMetrics event has been logged for |source_url|
-  // with the expected metrics and the next available SequenceId.
-  void ExpectNewEntry(const GURL& source_url,
-                      const UkmMetricMap& expected_metrics) {
-    ukm_entry_checker_.ExpectNewEntry(kEntryName, source_url, expected_metrics);
-
-    const size_t num_entries = ukm_entry_checker_.NumEntries(kEntryName);
-    EXPECT_EQ(num_entries, ++num_previous_entries);
-  }
-
- protected:
-  const char* kEntryName = TabManager_TabMetrics::kEntryName;
-  size_t num_previous_entries = 0;
-};
-
-TEST_F(TabMetricsTest, Basic) {
-  Browser::CreateParams params(profile(), true);
-  std::unique_ptr<Browser> browser =
-      CreateBrowserWithTestWindowForParams(params);
-
-  TabStripModel* tab_strip_model = browser->tab_strip_model();
-  content::WebContents* fg_contents =
-      tab_activity_simulator_.AddWebContentsAndNavigate(tab_strip_model,
-                                                        TestUrls()[0]);
-  tab_strip_model->ActivateTabAt(0);
-  WebContentsTester::For(fg_contents)->TestSetIsLoading(false);
-
-  // Adding, loading and activating a foreground tab doesn't trigger logging.
-  EXPECT_EQ(0, ukm_entry_checker_.NumNewEntriesRecorded(kEntryName));
-
-  // The second web contents is added as a background tab, so it logs an entry
-  // when it stops loading.
-  content::WebContents* bg_contents =
-      tab_activity_simulator_.AddWebContentsAndNavigate(tab_strip_model,
-                                                        TestUrls()[1]);
-  WebContentsTester::For(bg_contents)->TestSetIsLoading(false);
-  ExpectNewEntry(TestUrls()[1], kBasicMetricValues);
-
-  // Activating a tab logs the deactivated tab.
-  tab_activity_simulator_.SwitchToTabAt(tab_strip_model, 1);
-  {
-    SCOPED_TRACE("");
-    ExpectNewEntry(TestUrls()[0], kBasicMetricValues);
-  }
-
-  tab_activity_simulator_.SwitchToTabAt(tab_strip_model, 0);
-  {
-    SCOPED_TRACE("");
-    ExpectNewEntry(TestUrls()[1], kBasicMetricValues);
-  }
-
-  // Closing the tabs destroys the WebContentses but should not trigger logging.
-  // We verify in TearDown() that no logging occurred.
-  tab_strip_model->CloseAllTabs();
-}
-
-// Tests when tab events like pinning and navigating trigger logging.
-TEST_F(TabMetricsTest, TabEvents) {
-  Browser::CreateParams params(profile(), true);
-  std::unique_ptr<Browser> browser =
-      CreateBrowserWithTestWindowForParams(params);
-
-  TabStripModel* tab_strip_model = browser->tab_strip_model();
-  content::WebContents* test_contents_1 =
-      tab_activity_simulator_.AddWebContentsAndNavigate(tab_strip_model,
-                                                        TestUrls()[0]);
-  tab_strip_model->ActivateTabAt(0);
-
-  // Opening the background tab triggers logging once the page finishes loading.
-  content::WebContents* test_contents_2 =
-      tab_activity_simulator_.AddWebContentsAndNavigate(tab_strip_model,
-                                                        TestUrls()[1]);
-  EXPECT_EQ(0, ukm_entry_checker_.NumNewEntriesRecorded(kEntryName));
-  WebContentsTester::For(test_contents_2)->TestSetIsLoading(false);
-  {
-    SCOPED_TRACE("");
-    ExpectNewEntry(TestUrls()[1], kBasicMetricValues);
-  }
-
-  // Navigating the active tab doesn't trigger logging.
-  WebContentsTester::For(test_contents_1)->NavigateAndCommit(TestUrls()[2]);
-  EXPECT_EQ(0, ukm_entry_checker_.NumNewEntriesRecorded(kEntryName));
-
-  // Pinning the active tab doesn't trigger logging.
-  tab_strip_model->SetTabPinned(0, true);
-  EXPECT_EQ(0, ukm_entry_checker_.NumNewEntriesRecorded(kEntryName));
-
-  // Pinning and unpinning the background tab triggers logging.
-  tab_strip_model->SetTabPinned(1, true);
-  UkmMetricMap expected_metrics(kBasicMetricValues);
-  expected_metrics[TabManager_TabMetrics::kIsPinnedName] = 1;
-  {
-    SCOPED_TRACE("");
-    ExpectNewEntry(TestUrls()[1], expected_metrics);
-  }
-  tab_strip_model->SetTabPinned(1, false);
-  expected_metrics[TabManager_TabMetrics::kIsPinnedName] = 0;
-  {
-    SCOPED_TRACE("");
-    ExpectNewEntry(TestUrls()[1], kBasicMetricValues);
-  }
-
-  // Navigating the background tab triggers logging once the page finishes
-  // loading.
-  auto navigation = content::NavigationSimulator::CreateBrowserInitiated(
-      TestUrls()[0], test_contents_2);
-  navigation->SetKeepLoading(true);
-  navigation->Commit();
-  EXPECT_EQ(0, ukm_entry_checker_.NumNewEntriesRecorded(kEntryName));
-  navigation->StopLoading();
-  {
-    SCOPED_TRACE("");
-    ExpectNewEntry(TestUrls()[0], kBasicMetricValues);
-  }
-
-  tab_strip_model->CloseAllTabs();
-}
-
-// Tests setting and changing tab metrics.
-TEST_F(TabMetricsTest, TabMetrics) {
-  Browser::CreateParams params(profile(), true);
-  std::unique_ptr<Browser> browser =
-      CreateBrowserWithTestWindowForParams(params);
-
-  TabStripModel* tab_strip_model = browser->tab_strip_model();
-  content::WebContents* test_contents_1 =
-      tab_activity_simulator_.AddWebContentsAndNavigate(tab_strip_model,
-                                                        TestUrls()[0]);
-  tab_strip_model->ActivateTabAt(0);
-
-  // Expected metrics for tab event.
-  UkmMetricMap expected_metrics(kBasicMetricValues);
-
-  // Load background contents and verify UKM entry.
-  content::WebContents* test_contents_2 =
-      tab_activity_simulator_.AddWebContentsAndNavigate(tab_strip_model,
-                                                        TestUrls()[1]);
-  WebContentsTester::For(test_contents_2)->TestSetIsLoading(false);
-  {
-    SCOPED_TRACE("");
-    ExpectNewEntry(TestUrls()[1], expected_metrics);
-  }
-
-  // Site engagement score should round down to the nearest 10.
-  site_engagement::SiteEngagementService::Get(profile())->ResetBaseScoreForURL(
-      TestUrls()[1], 45);
-  expected_metrics[TabManager_TabMetrics::kSiteEngagementScoreName] = 40;
-
-  auto* audible_helper_2 =
-      RecentlyAudibleHelper::FromWebContents(test_contents_2);
-  audible_helper_2->SetRecentlyAudibleForTesting();
-  expected_metrics[TabManager_TabMetrics::kWasRecentlyAudibleName] = 1;
-
-  // Pin the background tab to log an event. (This moves it to index 0.)
-  tab_strip_model->SetTabPinned(1, true);
-  expected_metrics[TabManager_TabMetrics::kIsPinnedName] = 1;
-  {
-    SCOPED_TRACE("");
-    ExpectNewEntry(TestUrls()[1], expected_metrics);
-  }
-
-  // Unset WasRecentlyAudible and navigate the background tab to a new domain.
-  // Site engagement score for the new domain is 0.
-  audible_helper_2->SetNotRecentlyAudibleForTesting();
-  expected_metrics[TabManager_TabMetrics::kWasRecentlyAudibleName] = 0;
-  WebContentsTester::For(test_contents_2)->NavigateAndCommit(TestUrls()[2]);
-  expected_metrics[TabManager_TabMetrics::kSiteEngagementScoreName] = 0;
-
-  WebContentsTester::For(test_contents_2)->TestSetIsLoading(false);
-  {
-    SCOPED_TRACE("");
-    ExpectNewEntry(TestUrls()[2], expected_metrics);
-  }
-
-  // Navigate the active tab and switch away from it. The entry should reflect
-  // the new URL (even when the page hasn't finished loading).
-  WebContentsTester::For(test_contents_1)->NavigateAndCommit(TestUrls()[2]);
-  tab_activity_simulator_.SwitchToTabAt(tab_strip_model, 0);
-  {
-    SCOPED_TRACE("");
-    // This tab still has the default metrics.
-    ExpectNewEntry(TestUrls()[2], kBasicMetricValues);
-  }
-
-  tab_strip_model->CloseAllTabs();
-}
-
-// Tests counting input events. TODO(michaelpg): Currently only tests mouse
-// events.
-TEST_F(TabMetricsTest, InputEvents) {
-  Browser::CreateParams params(profile(), true);
-  std::unique_ptr<Browser> browser =
-      CreateBrowserWithTestWindowForParams(params);
-
-  TabStripModel* tab_strip_model = browser->tab_strip_model();
-  content::WebContents* test_contents_1 =
-      tab_activity_simulator_.AddWebContentsAndNavigate(tab_strip_model,
-                                                        TestUrls()[0]);
-  content::WebContents* test_contents_2 =
-      tab_activity_simulator_.AddWebContentsAndNavigate(tab_strip_model,
-                                                        TestUrls()[1]);
-
-  // RunUntilIdle is needed because the widget input handler is initialized
-  // asynchronously via mojo (see SetupWidgetInputHandler).
-  base::RunLoop().RunUntilIdle();
-  tab_strip_model->ActivateTabAt(0);
-
-  UkmMetricMap expected_metrics_1(kBasicMetricValues);
-  UkmMetricMap expected_metrics_2(kBasicMetricValues);
-
-  // Fake some input events.
-  content::RenderWidgetHost* widget_1 =
-      test_contents_1->GetPrimaryMainFrame()->GetRenderViewHost()->GetWidget();
-  widget_1->ForwardMouseEvent(
-      CreateMouseEvent(WebInputEvent::Type::kMouseDown));
-  widget_1->ForwardMouseEvent(CreateMouseEvent(WebInputEvent::Type::kMouseUp));
-  widget_1->ForwardMouseEvent(
-      CreateMouseEvent(WebInputEvent::Type::kMouseMove));
-  expected_metrics_1[TabManager_TabMetrics::kMouseEventCountName] = 3;
-
-  // Switch to the background tab. The current tab is deactivated and logged.
-  tab_activity_simulator_.SwitchToTabAt(tab_strip_model, 1);
-  {
-    SCOPED_TRACE("");
-    ExpectNewEntry(TestUrls()[0], expected_metrics_1);
-  }
-
-  // The second tab's counts are independent of the other's.
-  content::RenderWidgetHost* widget_2 =
-      test_contents_2->GetPrimaryMainFrame()->GetRenderViewHost()->GetWidget();
-  widget_2->ForwardMouseEvent(
-      CreateMouseEvent(WebInputEvent::Type::kMouseMove));
-  expected_metrics_2[TabManager_TabMetrics::kMouseEventCountName] = 1;
-
-  // Switch back to the first tab to log the second tab.
-  tab_activity_simulator_.SwitchToTabAt(tab_strip_model, 0);
-  {
-    SCOPED_TRACE("");
-    ExpectNewEntry(TestUrls()[1], expected_metrics_2);
-  }
-
-  // New events are added to the first tab's existing counts.
-  widget_1->ForwardMouseEvent(
-      CreateMouseEvent(WebInputEvent::Type::kMouseMove));
-  widget_1->ForwardMouseEvent(
-      CreateMouseEvent(WebInputEvent::Type::kMouseMove));
-  expected_metrics_1[TabManager_TabMetrics::kMouseEventCountName] = 5;
-  tab_activity_simulator_.SwitchToTabAt(tab_strip_model, 1);
-  {
-    SCOPED_TRACE("");
-    ExpectNewEntry(TestUrls()[0], expected_metrics_1);
-  }
-  tab_activity_simulator_.SwitchToTabAt(tab_strip_model, 0);
-  {
-    SCOPED_TRACE("");
-    ExpectNewEntry(TestUrls()[1], expected_metrics_2);
-  }
-
-  // After a navigation, test that the counts are reset.
-  WebContentsTester::For(test_contents_1)->NavigateAndCommit(TestUrls()[2]);
-  // The widget may have been invalidated by the navigation.
-  widget_1 =
-      test_contents_1->GetPrimaryMainFrame()->GetRenderViewHost()->GetWidget();
-  widget_1->ForwardMouseEvent(
-      CreateMouseEvent(WebInputEvent::Type::kMouseMove));
-  expected_metrics_1[TabManager_TabMetrics::kMouseEventCountName] = 1;
-  tab_activity_simulator_.SwitchToTabAt(tab_strip_model, 1);
-  {
-    SCOPED_TRACE("");
-    ExpectNewEntry(TestUrls()[2], expected_metrics_1);
-  }
-
-  tab_strip_model->CloseAllTabs();
-}
-
-// Tests that logging doesn't occur when the WebContents is hidden while still
-// the active tab, e.g. when the browser window hides before closing.
-// Flaky on chromeos: https://crbug.com/923147
-TEST_F(TabMetricsTest, DISABLED_HideWebContents) {
-  Browser::CreateParams params(profile(), true);
-  std::unique_ptr<Browser> browser =
-      CreateBrowserWithTestWindowForParams(params);
-
-  TabStripModel* tab_strip_model = browser->tab_strip_model();
-  content::WebContents* test_contents =
-      tab_activity_simulator_.AddWebContentsAndNavigate(tab_strip_model,
-                                                        TestUrls()[0]);
-  tab_strip_model->ActivateTabAt(0);
-
-  // Hiding the window doesn't trigger a log entry, unless the window was
-  // minimized.
-  // TODO(michaelpg): Test again with the window minimized using the
-  // FakeBrowserWindow from window_activity_watcher_unittest.cc.
-  test_contents->WasHidden();
-  EXPECT_EQ(0, ukm_entry_checker_.NumNewEntriesRecorded(kEntryName));
-  test_contents->WasShown();
-  EXPECT_EQ(0, ukm_entry_checker_.NumNewEntriesRecorded(kEntryName));
-
-  tab_strip_model->CloseAllTabs();
-}
-
-// Tests navigation-related metrics.
-TEST_F(TabMetricsTest, Navigations) {
-  Browser::CreateParams params(profile(), true);
-  auto browser = CreateBrowserWithTestWindowForParams(params);
-  TabStripModel* tab_strip_model = browser->tab_strip_model();
-
-  // Set up first tab.
-  tab_activity_simulator_.AddWebContentsAndNavigate(tab_strip_model,
-                                                    TestUrls()[0]);
-  tab_strip_model->ActivateTabAt(0);
-
-  // Expected metrics for tab event.
-  UkmMetricMap expected_metrics(kBasicMetricValues);
-
-  // Load background contents and verify UKM entry.
-  content::WebContents* test_contents =
-      tab_activity_simulator_.AddWebContentsAndNavigate(
-          tab_strip_model, TestUrls()[1],
-          ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED |
-                                    ui::PAGE_TRANSITION_FROM_ADDRESS_BAR));
-  WebContentsTester::For(test_contents)->TestSetIsLoading(false);
-  expected_metrics[TabManager_TabMetrics::kPageTransitionCoreTypeName] =
-      absl::nullopt;
-  expected_metrics[TabManager_TabMetrics::kPageTransitionFromAddressBarName] =
-      true;
-  expected_metrics[TabManager_TabMetrics::kPageTransitionIsRedirectName] =
-      false;
-  expected_metrics[TabManager_TabMetrics::kNavigationEntryCountName] = 1;
-  {
-    SCOPED_TRACE("");
-    ExpectNewEntry(TestUrls()[1], expected_metrics);
-  }
-
-  // Navigate background tab (not all transition types make sense in the
-  // background, but this is simpler than juggling two tabs to trigger logging).
-  tab_activity_simulator_.Navigate(test_contents, TestUrls()[2],
-                                   ui::PAGE_TRANSITION_LINK);
-  WebContentsTester::For(test_contents)->TestSetIsLoading(false);
-  expected_metrics[TabManager_TabMetrics::kPageTransitionCoreTypeName] =
-      ui::PAGE_TRANSITION_LINK;
-  expected_metrics[TabManager_TabMetrics::kPageTransitionFromAddressBarName] =
-      false;
-  expected_metrics[TabManager_TabMetrics::kPageTransitionIsRedirectName] =
-      false;
-  expected_metrics[TabManager_TabMetrics::kNavigationEntryCountName].value()++;
-  {
-    SCOPED_TRACE("");
-    ExpectNewEntry(TestUrls()[2], expected_metrics);
-  }
-
-  tab_activity_simulator_.Navigate(
-      test_contents, TestUrls()[0],
-      ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK |
-                                ui::PAGE_TRANSITION_SERVER_REDIRECT));
-  WebContentsTester::For(test_contents)->TestSetIsLoading(false);
-  expected_metrics[TabManager_TabMetrics::kPageTransitionCoreTypeName] =
-      ui::PAGE_TRANSITION_LINK;
-  expected_metrics[TabManager_TabMetrics::kPageTransitionFromAddressBarName] =
-      false;
-  expected_metrics[TabManager_TabMetrics::kPageTransitionIsRedirectName] = true;
-  expected_metrics[TabManager_TabMetrics::kNavigationEntryCountName].value()++;
-  {
-    SCOPED_TRACE("");
-    ExpectNewEntry(TestUrls()[0], expected_metrics);
-  }
-
-  tab_activity_simulator_.Navigate(test_contents, TestUrls()[0],
-                                   ui::PAGE_TRANSITION_RELOAD);
-  WebContentsTester::For(test_contents)->TestSetIsLoading(false);
-  expected_metrics[TabManager_TabMetrics::kPageTransitionCoreTypeName] =
-      ui::PAGE_TRANSITION_RELOAD;
-  expected_metrics[TabManager_TabMetrics::kNavigationEntryCountName].value();
-  expected_metrics[TabManager_TabMetrics::kPageTransitionFromAddressBarName] =
-      false;
-  expected_metrics[TabManager_TabMetrics::kPageTransitionIsRedirectName] =
-      false;
-  {
-    SCOPED_TRACE("");
-    ExpectNewEntry(TestUrls()[0], expected_metrics);
-  }
-
-  tab_activity_simulator_.Navigate(test_contents, TestUrls()[1],
-                                   ui::PAGE_TRANSITION_AUTO_BOOKMARK);
-  WebContentsTester::For(test_contents)->TestSetIsLoading(false);
-  expected_metrics[TabManager_TabMetrics::kPageTransitionCoreTypeName] =
-      ui::PAGE_TRANSITION_AUTO_BOOKMARK;
-  // FromAddressBar and IsRedirect should still be false, no need to update
-  // their values in |expected_metrics|.
-  expected_metrics[TabManager_TabMetrics::kNavigationEntryCountName].value()++;
-  {
-    SCOPED_TRACE("");
-    ExpectNewEntry(TestUrls()[1], expected_metrics);
-  }
-
-  tab_activity_simulator_.Navigate(test_contents, TestUrls()[1],
-                                   ui::PAGE_TRANSITION_FORM_SUBMIT);
-  WebContentsTester::For(test_contents)->TestSetIsLoading(false);
-  expected_metrics[TabManager_TabMetrics::kPageTransitionCoreTypeName] =
-      ui::PAGE_TRANSITION_FORM_SUBMIT;
-  expected_metrics[TabManager_TabMetrics::kNavigationEntryCountName].value();
-  {
-    SCOPED_TRACE("");
-    ExpectNewEntry(TestUrls()[1], expected_metrics);
-  }
-
-  // Test non-reportable core type.
-  tab_activity_simulator_.Navigate(
-      test_contents, TestUrls()[0],
-      ui::PageTransitionFromInt(ui::PAGE_TRANSITION_KEYWORD |
-                                ui::PAGE_TRANSITION_FROM_ADDRESS_BAR));
-  WebContentsTester::For(test_contents)->TestSetIsLoading(false);
-  expected_metrics[TabManager_TabMetrics::kPageTransitionCoreTypeName] =
-      absl::nullopt;
-  expected_metrics[TabManager_TabMetrics::kPageTransitionFromAddressBarName] =
-      true;
-  expected_metrics[TabManager_TabMetrics::kNavigationEntryCountName].value()++;
-  {
-    SCOPED_TRACE("");
-    ExpectNewEntry(TestUrls()[0], expected_metrics);
-  }
-
-  tab_strip_model->CloseAllTabs();
-}
-
-// Tests that replacing a foreground tab doesn't log new tab metrics until the
-// new tab is backgrounded.
-TEST_F(TabMetricsTest, ReplaceForegroundTab) {
-  Browser::CreateParams params(profile(), true);
-  std::unique_ptr<Browser> browser =
-      CreateBrowserWithTestWindowForParams(params);
-
-  TabStripModel* tab_strip_model = browser->tab_strip_model();
-  content::WebContents* orig_contents =
-      tab_activity_simulator_.AddWebContentsAndNavigate(tab_strip_model,
-                                                        TestUrls()[0]);
-  tab_strip_model->ActivateTabAt(0);
-  WebContentsTester::For(orig_contents)->TestSetIsLoading(false);
-
-  // Build the replacement contents.
-  std::unique_ptr<content::WebContents> new_contents =
-      tab_activity_simulator_.CreateWebContents(profile());
-
-  // Ensure the test URL gets a UKM source ID upon navigating.
-  // Normally this happens when the browser or prerenderer attaches tab helpers.
-  ukm::InitializeSourceUrlRecorderForWebContents(new_contents.get());
-
-  tab_activity_simulator_.Navigate(new_contents.get(), TestUrls()[1]);
-  WebContentsTester::For(new_contents.get())->TestSetIsLoading(false);
-
-  // Replace and delete the old contents.
-  std::unique_ptr<content::WebContents> old_contents =
-      tab_strip_model->ReplaceWebContentsAt(0, std::move(new_contents));
-  ASSERT_EQ(old_contents.get(), orig_contents);
-  old_contents.reset();
-  tab_strip_model->GetWebContentsAt(0)->WasShown();
-
-  EXPECT_EQ(0, ukm_entry_checker_.NumNewEntriesRecorded(kEntryName));
-
-  // Add a new tab so the first tab is backgrounded.
-  tab_activity_simulator_.AddWebContentsAndNavigate(tab_strip_model,
-                                                    TestUrls()[2]);
-  tab_activity_simulator_.SwitchToTabAt(tab_strip_model, 1);
-  {
-    SCOPED_TRACE("");
-    // Replaced tab uses the orig source_id; so the metrics is logged to
-    // TestUrls()[0].
-    ExpectNewEntry(TestUrls()[0], kBasicMetricValues);
-  }
-
-  tab_strip_model->CloseAllTabs();
-}
-
-// Tests TabManager.Background.ForegroundedOrClosed UKMs logged by
-// TabActivityWatcher.
-class ForegroundedOrClosedTest : public TabActivityWatcherTest {
- public:
-  ForegroundedOrClosedTest()
-      : scoped_set_tick_clock_for_testing_(&test_clock_) {
-    // Start at a nonzero time.
-    AdvanceClock();
-    SetParams({{"scorer_type", "0"},
-               {"disable_background_log_with_TabRanker", "false"}});
-  }
-
-  ForegroundedOrClosedTest(const ForegroundedOrClosedTest&) = delete;
-  ForegroundedOrClosedTest& operator=(const ForegroundedOrClosedTest&) = delete;
-
-  ~ForegroundedOrClosedTest() override = default;
-
- protected:
-  const char* kEntryName = ForegroundedOrClosed::kEntryName;
-
-  void AdvanceClock() { test_clock_.Advance(base::Seconds(1)); }
-
- private:
-  base::SimpleTestTickClock test_clock_;
-  resource_coordinator::ScopedSetTickClockForTesting
-      scoped_set_tick_clock_for_testing_;
-};
-
-// Tests TabManager.Backgrounded.ForegroundedOrClosed UKM logging.
-// Flaky on ChromeOS. http://crbug.com/924864
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-#define MAYBE_SingleTab DISABLED_SingleTab
-#else
-#define MAYBE_SingleTab SingleTab
-#endif
-TEST_F(ForegroundedOrClosedTest, MAYBE_SingleTab) {
-  Browser::CreateParams params(profile(), true);
-  std::unique_ptr<Browser> browser =
-      CreateBrowserWithTestWindowForParams(params);
-
-  TabStripModel* tab_strip_model = browser->tab_strip_model();
-  tab_activity_simulator_.AddWebContentsAndNavigate(tab_strip_model,
-                                                    TestUrls()[0]);
-
-  // The tab is in the foreground, so it isn't logged as a background tab.
-  tab_strip_model->CloseWebContentsAt(0, TabCloseTypes::CLOSE_USER_GESTURE);
-  EXPECT_EQ(0, ukm_entry_checker_.NumNewEntriesRecorded(kEntryName));
-}
-
-// Tests TabManager.Backgrounded.ForegroundedOrClosed UKM logging.
-TEST_F(ForegroundedOrClosedTest, MultipleTabs) {
-  Browser::CreateParams params(profile(), true);
-  std::unique_ptr<Browser> browser =
-      CreateBrowserWithTestWindowForParams(params);
-
-  TabStripModel* tab_strip_model = browser->tab_strip_model();
-  tab_activity_simulator_.AddWebContentsAndNavigate(tab_strip_model,
-                                                    TestUrls()[0]);
-  tab_strip_model->ActivateTabAt(0);
-  tab_activity_simulator_.AddWebContentsAndNavigate(tab_strip_model,
-                                                    TestUrls()[1]);
-  AdvanceClock();
-  tab_activity_simulator_.AddWebContentsAndNavigate(tab_strip_model,
-                                                    TestUrls()[2]);
-  AdvanceClock();
-  // MRU ordering by tab indices:
-  // 0 (foreground), 2 (created last), 1 (created first),
-
-  // Foreground a tab to log an event.
-  tab_activity_simulator_.SwitchToTabAt(tab_strip_model, 2);
-  {
-    SCOPED_TRACE("");
-    ukm_entry_checker_.ExpectNewEntry(
-        kEntryName, TestUrls()[2],
-        {
-            {ForegroundedOrClosed::kIsForegroundedName, 1},
-        });
-  }
-  AdvanceClock();
-  // MRU ordering by tab indices:
-  // 2 (foreground), 0 (foregrounded earlier), 1 (never foregrounded)
-
-  // Foreground the middle tab to log another event.
-  tab_activity_simulator_.SwitchToTabAt(tab_strip_model, 1);
-  {
-    SCOPED_TRACE("");
-    ukm_entry_checker_.ExpectNewEntry(
-        kEntryName, TestUrls()[1],
-        {
-            {ForegroundedOrClosed::kIsForegroundedName, 1},
-        });
-  }
-  AdvanceClock();
-  // MRU ordering by tab indices:
-  // 1 (foreground), 2 (foregrounded earlier), 0 (foregrounded even earlier)
-
-  // Close all tabs. Background tabs are logged as closed.
-  tab_strip_model->CloseAllTabs();
-  {
-    SCOPED_TRACE("");
-    // The rightmost tab was in the background and was closed.
-    ukm_entry_checker_.ExpectNewEntry(
-        kEntryName, TestUrls()[2],
-        {
-            {ForegroundedOrClosed::kIsForegroundedName, 0},
-        });
-
-    // The leftmost tab was in the background and was closed.
-    ukm_entry_checker_.ExpectNewEntry(
-        kEntryName, TestUrls()[0],
-        {
-            {ForegroundedOrClosed::kIsForegroundedName, 0},
-        });
-
-    // No event is logged for the middle tab, which was in the foreground.
-    EXPECT_EQ(0, ukm_entry_checker_.NumNewEntriesRecorded(kEntryName));
-  }
-}
-
-}  // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
index f9e98cd8..cf68995 100644
--- a/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
+++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
@@ -23,7 +23,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/resource_coordinator/intervention_policy_database.h"
 #include "chrome/browser/resource_coordinator/lifecycle_unit_state.mojom.h"
-#include "chrome/browser/resource_coordinator/tab_activity_watcher.h"
 #include "chrome/browser/resource_coordinator/tab_helper.h"
 #include "chrome/browser/resource_coordinator/tab_lifecycle_observer.h"
 #include "chrome/browser/resource_coordinator/tab_lifecycle_unit_source.h"
diff --git a/chrome/browser/resources/app_home/BUILD.gn b/chrome/browser/resources/app_home/BUILD.gn
index 012beeda..b8244f12 100644
--- a/chrome/browser/resources/app_home/BUILD.gn
+++ b/chrome/browser/resources/app_home/BUILD.gn
@@ -12,7 +12,10 @@
 
   static_files = [ "app_home.html" ]
 
-  web_component_files = [ "app_list.ts" ]
+  web_component_files = [
+    "app_list.ts",
+    "app_item.ts",
+  ]
 
   non_web_component_files = [ "browser_proxy.ts" ]
 
diff --git a/chrome/browser/resources/app_home/app_home.html b/chrome/browser/resources/app_home/app_home.html
index 889b4d7..e1503ce 100644
--- a/chrome/browser/resources/app_home/app_home.html
+++ b/chrome/browser/resources/app_home/app_home.html
@@ -9,6 +9,7 @@
 <head>
   <meta charset="utf-8">
   <meta name="color-scheme" content="light dark">
+  <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
   <base href="chrome://apps">
   <title>app home</title>
   <script type="module" src="app_list.js"></script>
diff --git a/chrome/browser/resources/app_home/app_item.html b/chrome/browser/resources/app_home/app_item.html
new file mode 100644
index 0000000..34c363e
--- /dev/null
+++ b/chrome/browser/resources/app_home/app_item.html
@@ -0,0 +1,37 @@
+<style>
+/* TODO(crbug.com/1350406): update the style after UI design
+   spec is finalized.*/
+
+:host {
+  display: block;
+  margin: 20px;
+  text-align: center;
+  width: 100px;
+}
+
+.icon-container {
+  border-radius: 50px;
+  box-shadow: 0 0 10px rgba(100,100,100);
+  height: 100px;
+  margin-inline-end: auto;
+  margin-inline-start: auto;
+  width: 100px;
+}
+
+.text-container {
+  font-size: 16px;
+  margin-top: 20px;
+}
+
+.icon-image {
+  height: 64px;
+  margin-top: 18px;
+  width: 64px;
+}
+
+</style>
+
+<div class="icon-container">
+  <img src="[[data.iconUrl.url]]" class="icon-image" alt="App's icon"></img>
+</div>
+<div class="text-container">[[data.name]]</div>
diff --git a/chrome/browser/resources/app_home/app_item.ts b/chrome/browser/resources/app_home/app_item.ts
new file mode 100644
index 0000000..150a3e2
--- /dev/null
+++ b/chrome/browser/resources/app_home/app_item.ts
@@ -0,0 +1,54 @@
+// 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 {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {AppInfo} from './app_home.mojom-webui.js';
+import {getTemplate} from './app_item.html.js';
+
+export class AppItemElement extends PolymerElement {
+  static get is() {
+    return 'app-item';
+  }
+
+  static get template() {
+    return getTemplate();
+  }
+
+  static get properties() {
+    return {
+      data: Object,
+    };
+  }
+
+  data: AppInfo;
+
+  override ready() {
+    super.ready();
+    this.addEventListener('contextmenu', this.handleContextMenu_);
+  }
+
+  private handleContextMenu_(e: MouseEvent) {
+    this.fire_('open-menu', {
+      data: this.data,
+      event: e,
+    });
+
+    e.preventDefault();
+    e.stopPropagation();
+  }
+
+  private fire_(eventName: string, detail?: any) {
+    this.dispatchEvent(
+        new CustomEvent(eventName, {bubbles: true, composed: true, detail}));
+  }
+}
+
+declare global {
+  interface HTMLElementTagNameMap {
+    'app-item': AppItemElement;
+  }
+}
+
+customElements.define(AppItemElement.is, AppItemElement);
\ No newline at end of file
diff --git a/chrome/browser/resources/app_home/app_list.html b/chrome/browser/resources/app_home/app_list.html
index 5d496bc..a3bab8f 100644
--- a/chrome/browser/resources/app_home/app_list.html
+++ b/chrome/browser/resources/app_home/app_list.html
@@ -1,58 +1,66 @@
 <style>
-/* TODO(crbug.com/1350406): update the style after UI design 
+  /* TODO(crbug.com/1350406): update the style after UI design
    spec is finalized.*/
+  #container {
+    align-content: center;
+    align-items: center;
+    display: grid;
+    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
+    height: auto;
+    justify-content: center;
+    justify-items: center;
+    margin: 0 auto;
+    max-width: 1500px;
+    padding: 50px;
+    width: auto;
+  }
 
-#container {
-  align-content: center;
-  align-items: center;
-  display: grid;
-  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
-  height: auto;
-  justify-content: center;
-  justify-items: center;
-  margin: 0 auto;
-  max-width: 1500px;
-  padding: 50px;
-  width: auto;
-}
+  .dropdown-item-label {
+    flex: 1;
+    padding-inline-end: 30px;
+  }
 
-.icon-container {
-  border-radius: 50px;
-  box-shadow: 0 0 10px rgba(100,100,100);
-  height: 100px;
-  text-align: center;
-  width: 100px;
-}
+  hr {
+    border-top: var(--cr-separator-line);
+    height: 0;
+  }
 
-.text-container {
-  font-size: 16px;
-  font-weight: 600;
-  margin-top: 20px;
-  text-align: center;
-}
-
-.element-container {
-  align-content: center;
-  justify-content: center;
-  margin: 20px;
-  width: 100px;
-}
-
-.icon-image {
-  height: 64px;
-  margin-top: 18px;
-  width: 64px;
-}
-
+  cr-checkbox::part(label-container) {
+    clip: rect(0,0,0,0);
+    display: block;
+    position: fixed;
+  }
 </style>
 
 <div id="container">
   <template is="dom-repeat" items="[[apps_]]">
-    <div class="element-container">
-      <div class="icon-container">
-        <img src="[[item.iconUrl.url]]" class="icon-image"></img>
-      </div>
-      <div class="text-container">[[item.name]]</div>
-    </div>
+    <app-item data="[[item]]"></app-item>
   </template>
 </div>
+
+<cr-action-menu id="menu">
+  <div tabindex="0" class="dropdown-item"
+      on-click="onOpenInWindowItemClick_">
+    <div class="dropdown-item-label">
+      Open in window
+    </div>
+    <cr-checkbox>Enable opening app in window</cr-checkbox>
+  </div>
+  <div tabindex="0" class="dropdown-item"
+      on-click="onLaunchOnStartupItemClick_">
+    <div class="dropdown-item-label">
+      Launch on startup
+    </div>
+    <cr-checkbox>Enable launching app on startup</cr-checkbox>
+  </div>
+  <button class="dropdown-item" on-click="onCreateAShortcutItemClick_">
+    Create a shortcut
+  </button>
+  <hr>
+  <button class="dropdown-item" on-click="onUninstallItemClick_">
+    Uninstall
+  </button>
+  <button class="dropdown-item" on-click="onAppSettingsItemClick_">
+    App settings
+  </button>
+</cr-action-menu>
diff --git a/chrome/browser/resources/app_home/app_list.ts b/chrome/browser/resources/app_home/app_list.ts
index 36af767..32fb6f8 100644
--- a/chrome/browser/resources/app_home/app_list.ts
+++ b/chrome/browser/resources/app_home/app_list.ts
@@ -1,14 +1,31 @@
-// Copyright 2022 The Chromium Authors. All rights reserved.
+// Copyright 2022 The Chromium Authors
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import './app_item.js';
+import '//resources/cr_elements/cr_action_menu/cr_action_menu.js';
+import '//resources/cr_elements/cr_checkbox/cr_checkbox.js';
+
+import {CrActionMenuElement} from '//resources/cr_elements/cr_action_menu/cr_action_menu.js';
+import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {assert} from 'chrome://resources/js/assert_ts.js';
-import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {AppInfo, PageCallbackRouter} from './app_home.mojom-webui.js';
 import {getTemplate} from './app_list.html.js';
 import {BrowserProxy} from './browser_proxy.js';
 
+export interface ActionMenuModel {
+  data: AppInfo;
+  event: MouseEvent;
+}
+
+type OpenMenuEvent = CustomEvent<ActionMenuModel>;
+
+export interface AppListElement {
+  $: {
+    menu: CrActionMenuElement,
+  };
+}
 
 export class AppListElement extends PolymerElement {
   static get is() {
@@ -44,6 +61,11 @@
     });
   }
 
+  override ready() {
+    super.ready();
+    this.addEventListener('open-menu', this.onOpenMenu_);
+  }
+
   override connectedCallback() {
     super.connectedCallback();
 
@@ -78,6 +100,39 @@
       this.splice('apps_', index, 1);
     }
   }
+
+  private onOpenInWindowItemClick_() {
+    this.$.menu.close();
+  }
+
+  private onLaunchOnStartupItemClick_() {
+    this.$.menu.close();
+  }
+
+  private onCreateAShortcutItemClick_() {
+    this.$.menu.close();
+  }
+
+  private onUninstallItemClick_() {
+    this.$.menu.close();
+  }
+
+  private onAppSettingsItemClick_() {
+    this.$.menu.close();
+  }
+
+  private onOpenMenu_(event: OpenMenuEvent) {
+    this.$.menu.showAtPosition({
+      top: event.detail.event.clientY,
+      left: event.detail.event.clientX,
+    });
+  }
+}
+
+declare global {
+  interface HTMLElementEventMap {
+    'open-menu': OpenMenuEvent;
+  }
 }
 
 declare global {
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/accessibility_common_loader.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/accessibility_common_loader.js
index 7c3d505f..1603b801 100644
--- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/accessibility_common_loader.js
+++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/accessibility_common_loader.js
@@ -21,6 +21,10 @@
     /** @private {Dictation} */
     this.dictation_ = null;
 
+    // For tests.
+    /** @private {?function()} */
+    this.autoclickLoadCallbackForTest_ = null;
+
     this.init_();
   }
 
@@ -82,6 +86,11 @@
     if (details.value && !this.autoclick_) {
       // Initialize the Autoclick extension.
       this.autoclick_ = new Autoclick();
+      if (this.autoclickLoadCallbackForTest_) {
+        this.autoclick_.setOnLoadDesktopCallbackForTest(
+            this.autoclickLoadCallbackForTest_);
+        this.autoclickLoadCallbackForTest_ = null;
+      }
     } else if (!details.value && this.autoclick_) {
       // TODO(crbug.com/1096759): Consider using XHR to load/unload autoclick
       // rather than relying on a destructor to clean up state.
@@ -118,6 +127,20 @@
       this.dictation_ = null;
     }
   }
+
+  /**
+   * Used by C++ tests to ensure Autoclick load is completed.
+   * Set on AccessibilityCommon in case Autoclick has not started up yet.
+   * @param {!function()} callback Callback for Autoclick JS load complete.
+   */
+  setAutoclickLoadCallbackForTest(callback) {
+    if (!this.autoclick_) {
+      this.autoclickLoadCallbackForTest_ = callback;
+      return;
+    }
+    // Autoclick already loaded.
+    this.autoclick_.setOnLoadDesktopCallbackForTest(callback);
+  }
 }
 
 InstanceChecker.closeExtraInstances();
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/autoclick/autoclick.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/autoclick/autoclick.js
index e5683590..9818bbd 100644
--- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/autoclick/autoclick.js
+++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/autoclick/autoclick.js
@@ -47,6 +47,9 @@
         [], chrome.automation.EventType.MOUSE_PRESSED,
         event => this.onAutomationHitTestResult_(event), {capture: true});
 
+    /** @private {?function()} */
+    this.onLoadDesktopCallbackForTest_ = null;
+
     this.init_();
   }
 
@@ -82,6 +85,11 @@
       // at that point, in order to find the scrollable area.
       this.hitTestHandler_.setNodes(this.desktop_);
       this.hitTestHandler_.start();
+
+      if (this.onLoadDesktopCallbackForTest_) {
+        this.onLoadDesktopCallbackForTest_();
+        this.onLoadDesktopCallbackForTest_ = null;
+      }
     });
 
     chrome.accessibilityPrivate.onScrollableBoundsForPointRequested.addListener(
@@ -177,4 +185,18 @@
     // which will do the logic for finding the scrolling container.
     this.desktop_.hitTest(x, y, chrome.automation.EventType.MOUSE_PRESSED);
   }
+
+  /**
+   * Used by C++ tests to ensure Autoclick JS load is completed.
+   * @param {!function()} callback Callback for when desktop is loaded from
+   * automation.
+   */
+  setOnLoadDesktopCallbackForTest(callback) {
+    if (!this.desktop_) {
+      this.onLoadDesktopCallbackForTest_ = callback;
+      return;
+    }
+    // Desktop already loaded.
+    callback();
+  }
 }
diff --git a/chrome/browser/resources/chromeos/cloud_upload/BUILD.gn b/chrome/browser/resources/chromeos/cloud_upload/BUILD.gn
index f8e43fc..3ce6133 100644
--- a/chrome/browser/resources/chromeos/cloud_upload/BUILD.gn
+++ b/chrome/browser/resources/chromeos/cloud_upload/BUILD.gn
@@ -14,9 +14,8 @@
     "icons/office.svg",
     "icons/sheets.svg",
     "icons/slides.svg",
-    "images/connect_to_one_drive.svg",
+    "images/connect_one_drive.png",
     "images/install_office.svg",
-    "images/office.png",
     "images/one_drive_success.svg",
     "images/welcome.svg",
     "main.html",
diff --git a/chrome/browser/resources/chromeos/cloud_upload/images/connect_one_drive.png b/chrome/browser/resources/chromeos/cloud_upload/images/connect_one_drive.png
new file mode 100644
index 0000000..231646d
--- /dev/null
+++ b/chrome/browser/resources/chromeos/cloud_upload/images/connect_one_drive.png
Binary files differ
diff --git a/chrome/browser/resources/chromeos/cloud_upload/images/install_office.svg b/chrome/browser/resources/chromeos/cloud_upload/images/install_office.svg
index a7834c73..51dfe65 100644
--- a/chrome/browser/resources/chromeos/cloud_upload/images/install_office.svg
+++ b/chrome/browser/resources/chromeos/cloud_upload/images/install_office.svg
@@ -1 +1 @@
-<svg id="EXPORT_image" width="448" height="200" viewBox="0 0 448 200" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#a)"><circle cx="225" cy="100" r="82.5" stroke="var(--cros-illustration-color-1-shade-2)" stroke-width="3"/><circle cx="225" cy="100" r="174" stroke="var(--cros-illustration-color-1-shade-2)" stroke-width="3" stroke-linecap="round" stroke-dasharray="4 12"/><circle cx="225.5" cy="100.5" r="41.5" fill="var(--cros-illustration-base-color)"/><image x="206" y="81" width="40" height="40" href="images/office.png"/></g><defs><clipPath id="a"><rect width="448" height="200" rx="12" fill="var(--cros-illustration-base-color)"/></clipPath></defs></svg>
\ No newline at end of file
+<svg id="EXPORT_image" width="448" height="200" viewBox="0 0 448 200" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#a)"><circle cx="225" cy="100" r="82.5" stroke="var(--cros-illustration-color-1-shade-2)" stroke-width="3"/><circle cx="225" cy="100" r="174" stroke="var(--cros-illustration-color-1-shade-2)" stroke-width="3" stroke-linecap="round" stroke-dasharray="4 12"/><circle cx="225.5" cy="100.5" r="41.5" fill="var(--cros-illustration-base-color)"/><image x="206" y="81" width="40" height="40" href="icons/office.svg"/></g><defs><clipPath id="a"><rect width="448" height="200" rx="12" fill="var(--cros-illustration-base-color)"/></clipPath></defs></svg>
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/cloud_upload/images/office.png b/chrome/browser/resources/chromeos/cloud_upload/images/office.png
deleted file mode 100644
index 7263235..0000000
--- a/chrome/browser/resources/chromeos/cloud_upload/images/office.png
+++ /dev/null
Binary files differ
diff --git a/chrome/browser/resources/chromeos/cloud_upload/one_drive_upload_page.html b/chrome/browser/resources/chromeos/cloud_upload/one_drive_upload_page.html
index b40e4ed0e..5023a32 100644
--- a/chrome/browser/resources/chromeos/cloud_upload/one_drive_upload_page.html
+++ b/chrome/browser/resources/chromeos/cloud_upload/one_drive_upload_page.html
@@ -11,8 +11,8 @@
     <div id="file-name" style="margin-top: 1rem"></div>
   </div>
   <p>
-    Other Word, Powerpoint, and Excel files will move to OneDrive and open in
-    Microsoft 365 by default. You can change this later in Settings.
+    Word, Powerpoint, and Excel files will now open in Microsoft 365 by default.
+    You can change this later in Settings.
   </p>
 </div>
 <div slot="button-container">
diff --git a/chrome/browser/resources/chromeos/cloud_upload/one_drive_upload_page.ts b/chrome/browser/resources/chromeos/cloud_upload/one_drive_upload_page.ts
index 12c0444..a34ba75 100644
--- a/chrome/browser/resources/chromeos/cloud_upload/one_drive_upload_page.ts
+++ b/chrome/browser/resources/chromeos/cloud_upload/one_drive_upload_page.ts
@@ -53,7 +53,7 @@
     // TODO(b/251046341): Show multiple files.
     if (this.fileNames.length > 0) {
       fileContainerElement.hidden = false;
-      fileNameElement.innerText = `File name: ${this.fileNames[0]}`;
+      fileNameElement.innerText = this.fileNames[0] || '';
     }
 
     uploadButton.addEventListener('click', () => this.onUploadButtonClick());
diff --git a/chrome/browser/resources/chromeos/cloud_upload/sign_in_page.html b/chrome/browser/resources/chromeos/cloud_upload/sign_in_page.html
index cf5ddcf..dca3cec99 100644
--- a/chrome/browser/resources/chromeos/cloud_upload/sign_in_page.html
+++ b/chrome/browser/resources/chromeos/cloud_upload/sign_in_page.html
@@ -1,18 +1,23 @@
+<style>
+  a {
+    color: var(--cros-text-color-prominent);
+  }
+</style>
+
 <!-- TODO(b/254586358): Use localized strings -->
-<svg slot="header-image">
-  <use href="images/connect_to_one_drive.svg#EXPORT_image"></use>
-</svg>
+<img src="images/connect_one_drive.png" slot="header-image"></img>
 <div slot="title">
-  Connect to Microsoft OneDrive
+  Connect to Microsoft OneDrive to open files in Microsoft 365
 </div>
 <div slot="body">
   <p>
-    To use Office files on your Chromebook, files need to be stored in
-    Microsoft OneDrive cloud storage. Office files will automatically
-    move to OneDrive when opening.
+    To edit files in Microsoft 365, they need to be stored in Microsoft OneDrive
+    cloud storage. If you open a file not already in OneDrive, your Chromebook
+    can move it for you.
+    <a href="https://support.google.com/chromebook">Learn more</a>
   </p>
   <p>
-    You'll need to sign in with your Microsoft account to connect to OneDrive.
+    You'll need to sign in with your Microsoft account to continue.
   </p>
 </div>
 <div slot="button-container">
diff --git a/chrome/browser/resources/chromeos/cloud_upload/welcome_page.html b/chrome/browser/resources/chromeos/cloud_upload/welcome_page.html
index 5fe6c7c..21f8dfc 100644
--- a/chrome/browser/resources/chromeos/cloud_upload/welcome_page.html
+++ b/chrome/browser/resources/chromeos/cloud_upload/welcome_page.html
@@ -2,6 +2,14 @@
   a {
     color: var(--cros-text-color-prominent);
   }
+
+  .subtitle {
+    font-weight: 600;
+  }
+
+  ol {
+    padding-inline-start: 20px;
+  }
 </style>
 
 <!-- TODO(b/254586358): Use localized strings -->
@@ -9,16 +17,21 @@
   <use href="images/welcome.svg#EXPORT_image"></use>
 </svg>
 <div slot="title">
-  Set up Microsoft 365 for Chromebook
+  Set up Microsoft 365 for your Chromebook
 </div>
 <div slot="body">
-  <p>
-    You can open, edit, and save Word, Excel, and PowerPoint files on your
-    Chromebook by installing the Microsoft 365 app. You'll need to connect to
-    Microsoft OneDrive cloud storage and use a Microsoft account. A
-    subscription may be required for some features.
+  <p class="subtitle">
+    How it works:
   </p>
-  <p>View <a href="#">Microsoft terms and conditions.</a></p>
+  <ol>
+    <li>Install Microsoft 365</li>
+    <li>Connect to Microsoft OneDrive</li>
+    <li>Files will move to OneDrive when opening in Microsoft 365</li>
+  </ol>
+  <p>
+    A subscription may be required.
+    View <a href="#">Microsoft terms and conditions.</a>
+  </p>
 </div>
 <div slot="button-container">
   <cr-button class="cancel-button">Cancel</cr-button>
diff --git a/chrome/browser/resources/chromeos/emoji_picker/emoji_picker.ts b/chrome/browser/resources/chromeos/emoji_picker/emoji_picker.ts
index f627956d..b74f33d 100644
--- a/chrome/browser/resources/chromeos/emoji_picker/emoji_picker.ts
+++ b/chrome/browser/resources/chromeos/emoji_picker/emoji_picker.ts
@@ -64,6 +64,7 @@
       v2Enabled: {type: Boolean, value: false, reflectToAttribute: true},
       searchExtensionEnabled: {type: Boolean, value: false},
       incognito: {type: Boolean, value: true},
+      gifSupport: {type: Boolean, value: false},
     };
   }
   private category: CategoryEnum;
@@ -77,6 +78,7 @@
   private v2Enabled: boolean;
   private searchExtensionEnabled: boolean;
   private incognito: boolean;
+  private gifSupport: boolean;
 
   private scrollTimeout: number|null;
   private groupScrollTimeout: number|null;
@@ -297,6 +299,7 @@
     this.v2Enabled = featureList.includes(Feature.EMOJI_PICKER_EXTENSION);
     this.searchExtensionEnabled =
         featureList.includes(Feature.EMOJI_PICKER_SEARCH_EXTENSION);
+    this.gifSupport = featureList.includes(Feature.EMOJI_PICKER_GIF_SUPPORT);
   }
 
   fetchOrderingData(url: string): Promise<EmojiGroupData> {
diff --git a/chrome/browser/resources/component_extension_resources.grd b/chrome/browser/resources/component_extension_resources.grd
index dfff98b..9e431e5 100644
--- a/chrome/browser/resources/component_extension_resources.grd
+++ b/chrome/browser/resources/component_extension_resources.grd
@@ -80,6 +80,7 @@
       <include name="IDS_READ_ANYTHING_LIGHT_PNG" file="side_panel/images/read_anything_light.png" type="BINDATA" />
       <include name="IDS_READ_ANYTHING_DARK_PNG" file="side_panel/images/read_anything_dark.png" type="BINDATA" />
       <include name="IDS_READ_ANYTHING_YELLOW_PNG" file="side_panel/images/read_anything_yellow.png" type="BINDATA" />
+      <include name="IDS_READ_ANYTHING_BLUE_PNG" file="side_panel/images/read_anything_blue.png" type="BINDATA" />
     </includes>
   </release>
 </grit>
diff --git a/chrome/browser/resources/device_log_ui/device_log_ui.css b/chrome/browser/resources/device_log_ui/device_log_ui.css
index 2c720ca..40f980f 100644
--- a/chrome/browser/resources/device_log_ui/device_log_ui.css
+++ b/chrome/browser/resources/device_log_ui/device_log_ui.css
@@ -96,7 +96,7 @@
   margin-inline-end: 5px;
   margin-top: 2px;
   padding: 0 4px 2px 4px;
-  width: 65px;
+  width: 80px;
 }
 
 .log-type-login {
diff --git a/chrome/browser/resources/device_log_ui/device_log_ui.html b/chrome/browser/resources/device_log_ui/device_log_ui.html
index 0c7c912..3f37e39 100644
--- a/chrome/browser/resources/device_log_ui/device_log_ui.html
+++ b/chrome/browser/resources/device_log_ui/device_log_ui.html
@@ -73,6 +73,10 @@
       <input id="log-type-camera" type="checkbox">
       <span>$i18n{logTypeCameraText}</span>
     </label>
+    <label>
+      <input id="log-type-geolocation" type="checkbox">
+      <span>$i18n{logTypeGeolocationText}</span>
+    </label>
   </div>
   <div id="log-container"></div>
 </body>
diff --git a/chrome/browser/resources/discards/discards_tab.html b/chrome/browser/resources/discards/discards_tab.html
index abbb9f9f..4f3e27f 100644
--- a/chrome/browser/resources/discards/discards_tab.html
+++ b/chrome/browser/resources/discards/discards_tab.html
@@ -173,14 +173,6 @@
                 </div>
               </div>
             </th>
-            <th data-sort-key="reactivationScore" on-click="onSortClick">
-              <div class="header-cell-container">
-                <div>
-                  <div>Reactivation</div>
-                  <div>Score</div>
-                </div>
-              </div>
-            </th>
             <th data-sort-key="siteEngagementScore" on-click="onSortClick">
               <div class="header-cell-container">
                 <div>
@@ -252,7 +244,6 @@
               items="[[tabInfos_]]">
             <tr>
               <td>[[item.utilityRank]]</td>
-              <td>[[getReactivationScore_(item)]]</td>
               <td>[[getSiteEngagementScore_(item)]]</td>
               <td>
                 <div class="title-cell-container">
diff --git a/chrome/browser/resources/discards/discards_tab.ts b/chrome/browser/resources/discards/discards_tab.ts
index 77de4db7..b562395 100644
--- a/chrome/browser/resources/discards/discards_tab.ts
+++ b/chrome/browser/resources/discards/discards_tab.ts
@@ -71,7 +71,6 @@
         'loadingState',
         'discardCount',
         'utilityRank',
-        'reactivationScore',
         'lastActiveSeconds',
         'siteEngagementScore',
       ].includes(sortKey)) {
@@ -251,16 +250,6 @@
   }
 
   /**
-   * Formats an items reactivation for display.
-   * @param item The item in question.
-   * @return The formatted reactivation score.
-   */
-  private getReactivationScore_(item: TabDiscardsInfo): string {
-    return item.hasReactivationScore ? item.reactivationScore.toFixed(4) :
-                                       'N/A';
-  }
-
-  /**
    * Formats an items site engagement score for display.
    * @param item The item in question.
    * @return The formatted site engagemetn score.
diff --git a/chrome/browser/resources/extensions/service.ts b/chrome/browser/resources/extensions/service.ts
index b0ff02f..07950655 100644
--- a/chrome/browser/resources/extensions/service.ts
+++ b/chrome/browser/resources/extensions/service.ts
@@ -460,6 +460,13 @@
     });
   }
 
+  updateSiteAccess(
+      site: string,
+      updates: chrome.developerPrivate.ExtensionSiteAccessUpdate[]):
+      Promise<void> {
+    return chrome.developerPrivate.updateSiteAccess(site, updates);
+  }
+
   static getInstance(): ServiceInterface {
     return instance || (instance = new Service());
   }
diff --git a/chrome/browser/resources/extensions/site_permissions_edit_permissions_dialog.html b/chrome/browser/resources/extensions/site_permissions_edit_permissions_dialog.html
index 4abbbb0..49e92f0 100644
--- a/chrome/browser/resources/extensions/site_permissions_edit_permissions_dialog.html
+++ b/chrome/browser/resources/extensions/site_permissions_edit_permissions_dialog.html
@@ -75,10 +75,9 @@
           <div class="extension-row">
             <img class="extension-icon" src="[[item.iconUrl]]" alt="">
             <span class="extension-name">[[item.name]]</span>
-            <!-- TODO(crbug.com/1253673): Enable these after implementing an API
-                method to edit site access for multiple extensions. -->
             <select class="extension-host-access md-select"
-                value="[[item.siteAccess]]" disabled>
+                on-change="onHostAccessChange_"
+                value="[[getExtensionHostAccess_(item.id, item.siteAccess)]]">
               <option value="[[hostAccessEnum_.ON_CLICK]]">
                 $i18n{sitePermissionsOnClick}
               </option>
diff --git a/chrome/browser/resources/extensions/site_permissions_edit_permissions_dialog.ts b/chrome/browser/resources/extensions/site_permissions_edit_permissions_dialog.ts
index 4975b8c..410a10cd 100644
--- a/chrome/browser/resources/extensions/site_permissions_edit_permissions_dialog.ts
+++ b/chrome/browser/resources/extensions/site_permissions_edit_permissions_dialog.ts
@@ -14,7 +14,7 @@
 import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js';
 import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js';
 import {assert} from 'chrome://resources/js/assert_ts.js';
-import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {DomRepeatEvent, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {getTemplate} from './site_permissions_edit_permissions_dialog.html.js';
 import {SiteSettingsDelegate} from './site_settings_mixin.js';
@@ -125,8 +125,23 @@
       Map<string, chrome.developerPrivate.ExtensionInfo>;
   private extensionSiteAccessData_: ExtensionSiteAccessInfo[];
 
+  // Tracks any unsaved changes to HostAccess for each extension made by
+  // changing the value in the ".extension-host-access" <select> element. Any
+  // values in here should be different than the HostAccess for the extension
+  // inside `extensionSiteAccessData_`.
+  private unsavedExtensionsIdToHostAccess_:
+      Map<string, chrome.developerPrivate.HostAccess>;
+
+  constructor() {
+    super();
+    this.unsavedExtensionsIdToHostAccess_ = new Map();
+  }
+
   override ready() {
     super.ready();
+
+    // Setting this to an initial value will trigger a call to
+    // `updateExtensionSiteAccessData_`.
     this.siteSet_ = this.originalSiteSet;
 
     // If `this.site` matches subdomains, then it should not be a user specified
@@ -134,8 +149,6 @@
     assert(
         !this.matchesSubdomains_() ||
         this.originalSiteSet === EXTENSION_SPECIFIED);
-
-    this.updateExtensionSiteAccessData_(this.siteSet_);
   }
 
   private onExtensionsUpdated_(extensions:
@@ -171,16 +184,32 @@
     }
 
     const siteToCheck =
-        this.isSiteHostOnly_() ? `*://${this.site}/` : this.site;
+        this.isSiteHostOnly_() ? `*://${this.site}/` : `${this.site}/`;
+
     const matchingExtensionsInfo =
         await this.delegate.getMatchingExtensionsForSite(siteToCheck);
+
     const extensionSiteAccessData: ExtensionSiteAccessInfo[] = [];
     matchingExtensionsInfo.forEach(({id, siteAccess}) => {
       assert(this.extensionsIdToInfo_.has(id));
       const {name, iconUrl} = this.extensionsIdToInfo_.get(id)!;
       extensionSiteAccessData.push({id, name, iconUrl, siteAccess});
+
+      // Remove the unsaved HostAccess from `unsavedExtensionsIdToHostAccess_`
+      // if it is now the same as `siteAccess`.
+      if (this.unsavedExtensionsIdToHostAccess_.get(id) === siteAccess) {
+        this.unsavedExtensionsIdToHostAccess_.delete(id);
+      }
     });
 
+    // Remove any HostAccess from `unsavedExtensionsIdToHostAccess_` for
+    // extensions that are no longer in `extensionSiteAccessData`.
+    for (const extensionId of this.unsavedExtensionsIdToHostAccess_.keys()) {
+      if (!this.extensionsIdToInfo_.has(extensionId)) {
+        this.unsavedExtensionsIdToHostAccess_.delete(extensionId);
+      }
+    }
+
     this.extensionSiteAccessData_ = extensionSiteAccessData;
   }
 
@@ -188,30 +217,38 @@
     this.$.dialog.cancel();
   }
 
-  private onSubmitClick_() {
-    if (this.siteSet_ === this.originalSiteSet) {
-      this.$.dialog.close();
-      return;
+  private async onSubmitClick_() {
+    if (this.siteSet_ !== this.originalSiteSet) {
+      // If `this.site` has a scheme (and can be considered a full url), use it
+      // as is. Otherwise if `this.site` is just a host, append the http and
+      // https schemes to it.
+      const sitesToChange = this.isSiteHostOnly_() ?
+          [`http://${this.site}`, `https://${this.site}`] :
+          [this.site];
+      if (this.siteSet_ === EXTENSION_SPECIFIED) {
+        await this.delegate.removeUserSpecifiedSites(
+            this.originalSiteSet, sitesToChange);
+      } else {
+        await this.delegate.addUserSpecifiedSites(this.siteSet_, sitesToChange);
+      }
     }
 
-    // If `this.site` has a scheme (and can be considered a full url), use it
-    // as is. Otherwise if `this.site` is just a host, append the http and https
-    // schemes to it.
-    const sitesToChange = this.isSiteHostOnly_() ?
-        [`http://${this.site}`, `https://${this.site}`] :
-        [this.site];
-    if (this.siteSet_ === EXTENSION_SPECIFIED) {
-      this.delegate
-          .removeUserSpecifiedSites(this.originalSiteSet, sitesToChange)
-          .then(() => {
-            this.$.dialog.close();
-          });
-    } else {
-      this.delegate.addUserSpecifiedSites(this.siteSet_, sitesToChange)
-          .then(() => {
-            this.$.dialog.close();
-          });
+    if (this.siteSet_ === EXTENSION_SPECIFIED &&
+        this.unsavedExtensionsIdToHostAccess_.size) {
+      const updates: chrome.developerPrivate.ExtensionSiteAccessUpdate[] = [];
+      this.unsavedExtensionsIdToHostAccess_.forEach((val, key) => {
+        updates.push({id: key, siteAccess: val});
+      });
+
+      // For changing extensions' site access, first. the wildcard path "/*" is
+      // added to the end. Then, if the site does not specify a scheme, use the
+      // wildcard scheme.
+      const siteToUpdate =
+          this.isSiteHostOnly_() ? `*://${this.site}/` : `${this.site}/`;
+      await this.delegate.updateSiteAccess(siteToUpdate, updates);
     }
+
+    this.$.dialog.close();
   }
 
   private computeDialogTitle_(): string {
@@ -242,6 +279,33 @@
     return this.matchesSubdomains_() ? 'site-access-list' :
                                        'indented-site-access-list';
   }
+
+  // Returns the value to be displayed for the <select> element for the
+  // extension's host access. This shows the unsaved HostAccess value that was
+  // changed by the user. Otherwise, show the preexisting HostAccess value.
+  private getExtensionHostAccess_(
+      extensionId: string,
+      originalSiteAccess: chrome.developerPrivate.HostAccess):
+      chrome.developerPrivate.HostAccess {
+    return this.unsavedExtensionsIdToHostAccess_.get(extensionId) ||
+        originalSiteAccess;
+  }
+
+  private onHostAccessChange_(e: DomRepeatEvent<ExtensionSiteAccessInfo>) {
+    const selectMenu = this.shadowRoot!.querySelectorAll<HTMLSelectElement>(
+        '.extension-host-access')![e.model.index];
+    assert(selectMenu);
+
+    const originalSiteAccess = e.model.item.siteAccess;
+    const newSiteAccess =
+        selectMenu.value as chrome.developerPrivate.HostAccess;
+
+    if (originalSiteAccess === newSiteAccess) {
+      this.unsavedExtensionsIdToHostAccess_.delete(e.model.item.id);
+    } else {
+      this.unsavedExtensionsIdToHostAccess_.set(e.model.item.id, newSiteAccess);
+    }
+  }
 }
 
 declare global {
diff --git a/chrome/browser/resources/extensions/site_settings_mixin.ts b/chrome/browser/resources/extensions/site_settings_mixin.ts
index 3159942..8f1a08bd8 100644
--- a/chrome/browser/resources/extensions/site_settings_mixin.ts
+++ b/chrome/browser/resources/extensions/site_settings_mixin.ts
@@ -25,6 +25,10 @@
       Promise<chrome.developerPrivate.SiteGroup[]>;
   getMatchingExtensionsForSite(site: string):
       Promise<chrome.developerPrivate.MatchingExtensionInfo[]>;
+  updateSiteAccess(
+      site: string,
+      updates: chrome.developerPrivate.ExtensionSiteAccessUpdate[]):
+      Promise<void>;
   getUserSiteSettingsChangedTarget():
       ChromeEvent<(settings: chrome.developerPrivate.UserSiteSettings) => void>;
 }
diff --git a/chrome/browser/resources/settings/chromeos/BUILD.gn b/chrome/browser/resources/settings/chromeos/BUILD.gn
index 19de9d5..d4588bd 100644
--- a/chrome/browser/resources/settings/chromeos/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/BUILD.gn
@@ -299,7 +299,6 @@
     "multidevice_page:web_components",
     "nearby_share_page:web_components",
     "os_a11y_page:web_components",
-    "os_apps_page:web_components",
     "os_bluetooth_page:web_components",
     "os_people_page:web_components",
     "os_privacy_page:web_components",
@@ -314,7 +313,6 @@
     "internet_page:closure_compile_module",
     "multidevice_page:closure_compile_module",
     "os_a11y_page:closure_compile_module",
-    "os_apps_page:closure_compile_module",
     "os_bluetooth_page:closure_compile_module",
     "os_languages_page:closure_compile_module",
     "os_people_page:closure_compile_module",
diff --git a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_port_forwarding.ts b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_port_forwarding.ts
index 0a03d58..5787039 100644
--- a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_port_forwarding.ts
+++ b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_port_forwarding.ts
@@ -17,7 +17,7 @@
 import './crostini_port_forwarding_add_port_dialog.js';
 import '../../controls/settings_toggle_button.js';
 import '../os_settings_page/os_settings_section.js';
-import '../../settings_page_styles.css.js';
+import '../os_settings_page_styles.css.js';
 import '../../settings_shared.css.js';
 
 import {CrActionMenuElement} from 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.html b/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.html
index 02836756..047c7f3 100644
--- a/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.html
+++ b/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.html
@@ -1,4 +1,4 @@
-<style include="settings-shared settings-page-styles">
+<style include="settings-shared os-settings-page-styles">
   :host {
     --about-page-image-space: 10px;
   }
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 435832e..5c37ecc 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
@@ -19,7 +19,7 @@
 import '../os_settings_page/os_settings_animated_pages.js';
 import '../os_settings_page/os_settings_section.js';
 import '../os_settings_page/os_settings_subpage.js';
-import '../../settings_page_styles.css.js';
+import '../os_settings_page_styles.css.js';
 import '../../settings_shared.css.js';
 import '../os_settings_icons.html.js';
 import '../os_reset_page/os_powerwash_dialog.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/os_apps_page/BUILD.gn
deleted file mode 100644
index ec263f19..0000000
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/BUILD.gn
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright 2019 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/closure_compiler/compile_js.gni")
-import("//tools/polymer/html_to_js.gni")
-import("../os_settings.gni")
-
-js_type_check("closure_compile_module") {
-  closure_flags = os_settings_closure_flags
-  is_polymer3 = true
-  deps = [
-    ":android_apps_browser_proxy",
-    ":android_apps_subpage",
-  ]
-}
-
-js_library("android_apps_browser_proxy") {
-  externs_list = [ "$externs_path/chrome_send.js" ]
-}
-
-js_library("android_apps_subpage") {
-  deps = [
-    ":android_apps_browser_proxy",
-    "..:deep_linking_behavior",
-    "..:os_route",
-    "..:prefs_behavior",
-    "..:route_observer_behavior",
-    "../..:router",
-    "//ash/webui/common/resources:focus_without_ink_js",
-    "//ash/webui/common/resources:i18n_behavior",
-    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
-    "//ui/webui/resources/js:assert",
-  ]
-}
-
-html_to_js("web_components") {
-  js_files = [ "android_apps_subpage.js" ]
-}
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/android_apps_browser_proxy.js b/chrome/browser/resources/settings/chromeos/os_apps_page/android_apps_browser_proxy.js
deleted file mode 100644
index 2a3b679..0000000
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/android_apps_browser_proxy.js
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2016 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview A helper object used by the "Google Play Store" (ARC) section
- * to retrieve information about android apps.
- */
-
-/**
- * Type definition of AndroidAppsInfo entry. |playStoreEnabled| indicates that
- * Play Store is enabled. |settingsAppAvailable| indicates that Android settings
- * app is registered in the system.
- * @typedef {{
- *   playStoreEnabled: boolean,
- *   settingsAppAvailable: boolean,
- * }}
- * @see chrome/browser/ui/webui/settings/ash/android_apps_handler.cc
- */
-export let AndroidAppsInfo;
-
-/** @interface */
-export class AndroidAppsBrowserProxy {
-  requestAndroidAppsInfo() {}
-
-  /**
-   * @param {boolean} keyboardAction True if the app was opened using a
-   *     keyboard action.
-   */
-  showAndroidAppsSettings(keyboardAction) {}
-}
-
-/** @type {?AndroidAppsBrowserProxy} */
-let instance = null;
-
-/**
- * @implements {AndroidAppsBrowserProxy}
- */
-export class AndroidAppsBrowserProxyImpl {
-  /** @return {!AndroidAppsBrowserProxy} */
-  static getInstance() {
-    return instance || (instance = new AndroidAppsBrowserProxyImpl());
-  }
-
-  /** @param {!AndroidAppsBrowserProxy} obj */
-  static setInstanceForTesting(obj) {
-    instance = obj;
-  }
-
-  /** @override */
-  requestAndroidAppsInfo() {
-    chrome.send('requestAndroidAppsInfo');
-  }
-
-  /** @override */
-  showAndroidAppsSettings(keyboardAction) {
-    chrome.send('showAndroidAppsSettings', [keyboardAction]);
-  }
-}
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/android_apps_browser_proxy.ts b/chrome/browser/resources/settings/chromeos/os_apps_page/android_apps_browser_proxy.ts
new file mode 100644
index 0000000..4cd73c9
--- /dev/null
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/android_apps_browser_proxy.ts
@@ -0,0 +1,48 @@
+// Copyright 2016 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview A helper object used by the "Google Play Store" (ARC) section
+ * to retrieve information about android apps.
+ */
+
+/**
+ * Type definition of AndroidAppsInfo entry. |playStoreEnabled| indicates that
+ * Play Store is enabled. |settingsAppAvailable| indicates that Android settings
+ * app is registered in the system.
+ * @see chrome/browser/ui/webui/settings/ash/android_apps_handler.cc
+ */
+export interface AndroidAppsInfo {
+  playStoreEnabled: boolean;
+  settingsAppAvailable: boolean;
+}
+
+export interface AndroidAppsBrowserProxy {
+  requestAndroidAppsInfo(): void;
+
+  /**
+   * @param keyboardAction True if the app was opened using a keyboard action.
+   */
+  showAndroidAppsSettings(keyboardAction: boolean): void;
+}
+
+let instance: AndroidAppsBrowserProxy|null = null;
+
+export class AndroidAppsBrowserProxyImpl implements AndroidAppsBrowserProxy {
+  static getInstance(): AndroidAppsBrowserProxy {
+    return instance || (instance = new AndroidAppsBrowserProxyImpl());
+  }
+
+  static setInstanceForTesting(obj: AndroidAppsBrowserProxy): void {
+    instance = obj;
+  }
+
+  requestAndroidAppsInfo(): void {
+    chrome.send('requestAndroidAppsInfo');
+  }
+
+  showAndroidAppsSettings(keyboardAction: boolean): void {
+    chrome.send('showAndroidAppsSettings', [keyboardAction]);
+  }
+}
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/android_apps_subpage.js b/chrome/browser/resources/settings/chromeos/os_apps_page/android_apps_subpage.js
deleted file mode 100644
index 0c28d457..0000000
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/android_apps_subpage.js
+++ /dev/null
@@ -1,187 +0,0 @@
-// Copyright 2016 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview
- * 'android-apps-subpage' is the settings subpage for managing android apps.
- */
-
-import 'chrome://resources/cr_elements/cr_button/cr_button.js';
-import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js';
-import 'chrome://resources/cr_elements/cr_link_row/cr_link_row.js';
-import '../../settings_shared.css.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 {assert} from 'chrome://resources/js/assert.js';
-import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.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 {routes} from '../os_route.js';
-import {PrefsBehavior, PrefsBehaviorInterface} from '../prefs_behavior.js';
-import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js';
-
-import {AndroidAppsBrowserProxyImpl, AndroidAppsInfo} from './android_apps_browser_proxy.js';
-
-/**
- * @constructor
- * @extends {PolymerElement}
- * @implements {DeepLinkingBehaviorInterface}
- * @implements {I18nBehaviorInterface}
- * @implements {PrefsBehaviorInterface}
- * @implements {RouteObserverBehaviorInterface}
- */
-const SettingsAndroidAppsSubpageElementBase = mixinBehaviors(
-    [DeepLinkingBehavior, I18nBehavior, PrefsBehavior, RouteObserverBehavior],
-    PolymerElement);
-
-/** @polymer */
-class SettingsAndroidAppsSubpageElement extends
-    SettingsAndroidAppsSubpageElementBase {
-  static get is() {
-    return 'settings-android-apps-subpage';
-  }
-
-  static get template() {
-    return html`{__html_template__}`;
-  }
-
-  static get properties() {
-    return {
-      /** Preferences state. */
-      prefs: Object,
-
-      /** @private {!AndroidAppsInfo|undefined} */
-      androidAppsInfo: {
-        type: Object,
-      },
-
-      /** @private */
-      playStoreEnabled_: {
-        type: Boolean,
-        computed: 'computePlayStoreEnabled_(androidAppsInfo)',
-        observer: 'onPlayStoreEnabledChanged_',
-      },
-
-      /** @private */
-      dialogBody_: {
-        type: String,
-        value() {
-          return this.i18nAdvanced(
-              'androidAppsDisableDialogMessage',
-              {substitutions: [], tags: ['br']});
-        },
-      },
-
-      /** Whether Arc VM manage usb subpage should be shown. */
-      showArcvmManageUsb: Boolean,
-
-      /**
-       * Used by DeepLinkingBehavior to focus this page's deep links.
-       * @type {!Set<!Setting>}
-       */
-      supportedSettingIds: {
-        type: Object,
-        value: () => new Set([
-          Setting.kManageAndroidPreferences,
-          Setting.kRemovePlayStore,
-        ]),
-      },
-    };
-  }
-
-  /**
-   * @param {!Route} route
-   * @param {!Route=} oldRoute
-   */
-  currentRouteChanged(route, oldRoute) {
-    // Does not apply to this page.
-    if (route !== routes.ANDROID_APPS_DETAILS) {
-      return;
-    }
-
-    this.attemptDeepLink();
-  }
-
-  /** @private */
-  onPlayStoreEnabledChanged_(enabled) {
-    if (!enabled &&
-        Router.getInstance().getCurrentRoute() ===
-            routes.ANDROID_APPS_DETAILS) {
-      Router.getInstance().navigateToPreviousRoute();
-    }
-  }
-
-  /**
-   * @return {boolean}
-   * @private
-   */
-  computePlayStoreEnabled_() {
-    return this.androidAppsInfo.playStoreEnabled;
-  }
-
-  /**
-   * @return {boolean}
-   * @private
-   */
-  allowRemove_() {
-    return this.prefs.arc.enabled.enforcement !==
-        chrome.settingsPrivate.Enforcement.ENFORCED;
-  }
-
-  /**
-   * Shows a confirmation dialog when disabling android apps.
-   * @param {!Event} event
-   * @private
-   */
-  onRemoveTap_(event) {
-    this.$.confirmDisableDialog.showModal();
-  }
-
-  /**
-   * Handles the shared proxy confirmation dialog 'Confirm' button.
-   * @private
-   */
-  onConfirmDisableDialogConfirm_() {
-    this.setPrefValue('arc.enabled', false);
-    this.$.confirmDisableDialog.close();
-    // Sub-page will be closed in onAndroidAppsInfoUpdate_ call.
-  }
-
-  /**
-   * Handles the shared proxy confirmation dialog 'Cancel' button or a cancel
-   * event.
-   * @private
-   */
-  onConfirmDisableDialogCancel_() {
-    this.$.confirmDisableDialog.close();
-  }
-
-  /** @private */
-  onConfirmDisableDialogClose_() {
-    focusWithoutInk(assert(this.shadowRoot.querySelector('#remove')));
-  }
-
-  /**
-   * @param {!MouseEvent} event
-   * @private
-   */
-  onManageAndroidAppsTap_(event) {
-    // |event.detail| is the click count. Keyboard events will have 0 clicks.
-    const isKeyboardAction = event.detail === 0;
-    AndroidAppsBrowserProxyImpl.getInstance().showAndroidAppsSettings(
-        isKeyboardAction);
-  }
-
-  /** @private */
-  onSharedUsbDevicesClick_() {
-    Router.getInstance().navigateTo(
-        routes.ANDROID_APPS_DETAILS_ARC_VM_SHARED_USB_DEVICES);
-  }
-}
-
-customElements.define(
-    SettingsAndroidAppsSubpageElement.is, SettingsAndroidAppsSubpageElement);
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/android_apps_subpage.ts b/chrome/browser/resources/settings/chromeos/os_apps_page/android_apps_subpage.ts
new file mode 100644
index 0000000..b2be007
--- /dev/null
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/android_apps_subpage.ts
@@ -0,0 +1,172 @@
+// Copyright 2016 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview
+ * 'android-apps-subpage' is the settings subpage for managing android apps.
+ */
+
+import 'chrome://resources/cr_elements/cr_button/cr_button.js';
+import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js';
+import 'chrome://resources/cr_elements/cr_link_row/cr_link_row.js';
+import '../../settings_shared.css.js';
+
+import {focusWithoutInk} from 'chrome://resources/ash/common/focus_without_ink_js.js';
+import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js';
+import {I18nMixin, I18nMixinInterface} from 'chrome://resources/cr_elements/i18n_mixin.js';
+import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {Setting} from '../../mojom-webui/setting.mojom-webui.js';
+import {PrefsMixin, PrefsMixinInterface} from '../../prefs/prefs_mixin.js';
+import {Route, RouteObserverMixin, RouteObserverMixinInterface, Router} from '../../router.js';
+import {castExists} from '../assert_extras.js';
+import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.js';
+import {routes} from '../os_route.js';
+
+import {AndroidAppsBrowserProxyImpl, AndroidAppsInfo} from './android_apps_browser_proxy.js';
+import {getTemplate} from './android_apps_subpage.html.js';
+
+interface SettingsAndroidAppsSubpageElement {
+  $: {
+    confirmDisableDialog: CrDialogElement,
+  };
+}
+
+const SettingsAndroidAppsSubpageElementBase =
+    mixinBehaviors(
+        [DeepLinkingBehavior],
+        RouteObserverMixin(PrefsMixin(I18nMixin(PolymerElement)))) as {
+      new (): PolymerElement & I18nMixinInterface & PrefsMixinInterface &
+          RouteObserverMixinInterface & DeepLinkingBehaviorInterface,
+    };
+
+class SettingsAndroidAppsSubpageElement extends
+    SettingsAndroidAppsSubpageElementBase {
+  static get is() {
+    return 'settings-android-apps-subpage' as const;
+  }
+
+  static get template() {
+    return getTemplate();
+  }
+
+  static get properties() {
+    return {
+      androidAppsInfo: {
+        type: Object,
+      },
+
+      playStoreEnabled_: {
+        type: Boolean,
+        computed: 'computePlayStoreEnabled_(androidAppsInfo)',
+        observer: 'onPlayStoreEnabledChanged_',
+      },
+
+      dialogBody_: {
+        type: String,
+        value(this: SettingsAndroidAppsSubpageElement): string {
+          return this
+              .i18nAdvanced(
+                  'androidAppsDisableDialogMessage',
+                  {substitutions: [], tags: ['br']})
+              .toString();
+        },
+      },
+
+      /** Whether Arc VM manage usb subpage should be shown. */
+      showArcvmManageUsb: Boolean,
+
+      /**
+       * Used by DeepLinkingBehavior to focus this page's deep links.
+       */
+      supportedSettingIds: {
+        type: Object,
+        value: () => new Set([
+          Setting.kManageAndroidPreferences,
+          Setting.kRemovePlayStore,
+        ]),
+      },
+    };
+  }
+
+  androidAppsInfo: AndroidAppsInfo;
+  showArcvmManageUsb: boolean;
+  private dialogBody_: string;
+  private playStoreEnabled_: boolean;
+
+  override currentRouteChanged(route: Route) {
+    // Does not apply to this page.
+    if (route !== routes.ANDROID_APPS_DETAILS) {
+      return;
+    }
+
+    this.attemptDeepLink();
+  }
+
+  private onPlayStoreEnabledChanged_(enabled: boolean) {
+    if (!enabled &&
+        Router.getInstance().getCurrentRoute() ===
+            routes.ANDROID_APPS_DETAILS) {
+      Router.getInstance().navigateToPreviousRoute();
+    }
+  }
+
+  private computePlayStoreEnabled_(): boolean {
+    return this.androidAppsInfo.playStoreEnabled;
+  }
+
+  private allowRemove_(): boolean {
+    return this.prefs.arc.enabled.enforcement !==
+        chrome.settingsPrivate.Enforcement.ENFORCED;
+  }
+
+  /**
+   * Shows a confirmation dialog when disabling android apps.
+   */
+  private onRemoveTap_(): void {
+    this.$.confirmDisableDialog.showModal();
+  }
+
+  /**
+   * Handles the shared proxy confirmation dialog 'Confirm' button.
+   */
+  private onConfirmDisableDialogConfirm_(): void {
+    this.setPrefValue('arc.enabled', false);
+    this.$.confirmDisableDialog.close();
+    // Sub-page will be closed in onAndroidAppsInfoUpdate_ call.
+  }
+
+  /**
+   * Handles the shared proxy confirmation dialog 'Cancel' button or a cancel
+   * event.
+   */
+  private onConfirmDisableDialogCancel_(): void {
+    this.$.confirmDisableDialog.close();
+  }
+
+  private onConfirmDisableDialogClose_(): void {
+    focusWithoutInk(castExists(this.shadowRoot!.querySelector('#remove')));
+  }
+
+  private onManageAndroidAppsTap_(event: MouseEvent): void {
+    // |event.detail| is the click count. Keyboard events will have 0 clicks.
+    const isKeyboardAction = event.detail === 0;
+    AndroidAppsBrowserProxyImpl.getInstance().showAndroidAppsSettings(
+        isKeyboardAction);
+  }
+
+  private onSharedUsbDevicesClick_(): void {
+    Router.getInstance().navigateTo(
+        routes.ANDROID_APPS_DETAILS_ARC_VM_SHARED_USB_DEVICES);
+  }
+}
+
+declare global {
+  interface HTMLElementTagNameMap {
+    [SettingsAndroidAppsSubpageElement.is]: SettingsAndroidAppsSubpageElement;
+  }
+}
+
+customElements.define(
+    SettingsAndroidAppsSubpageElement.is, SettingsAndroidAppsSubpageElement);
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.gni b/chrome/browser/resources/settings/chromeos/os_settings.gni
index 3f922071..edf1754 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings.gni
+++ b/chrome/browser/resources/settings/chromeos/os_settings.gni
@@ -79,6 +79,7 @@
   "chromeos/os_about_page/edit_hostname_dialog.ts",
   "chromeos/os_about_page/os_about_page.ts",
   "chromeos/os_about_page/update_warning_dialog.ts",
+  "chromeos/os_apps_page/android_apps_subpage.ts",
   "chromeos/os_apps_page/app_management_page/app_detail_view.ts",
   "chromeos/os_apps_page/app_management_page/app_details_item.ts",
   "chromeos/os_apps_page/app_management_page/app_item.ts",
@@ -202,9 +203,9 @@
   "chromeos/os_languages_page/shared_vars.css",
   "chromeos/os_printing_page/cups_printer_shared.css",
   "chromeos/os_settings_icons.css",
+  "chromeos/os_settings_page_styles.css",
 
   # Files below are from Browser Settings and shared with ChromeOS Settings
-  "settings_page_styles.css",
   "settings_shared.css",
   "settings_vars.css",
 ]
@@ -260,7 +261,7 @@
   "chromeos/os_about_page/about_page_browser_proxy.ts",
   "chromeos/os_about_page/device_name_browser_proxy.ts",
   "chromeos/os_about_page/device_name_util.ts",
-  "chromeos/os_apps_page/android_apps_browser_proxy.js",
+  "chromeos/os_apps_page/android_apps_browser_proxy.ts",
   "chromeos/os_apps_page/app_management_page/actions.ts",
   "chromeos/os_apps_page/app_management_page/api_listener.ts",
   "chromeos/os_apps_page/app_management_page/browser_proxy.ts",
@@ -379,7 +380,6 @@
   "chromeos/nearby_share_page/nearby_share_receive_dialog.js",
   "chromeos/nearby_share_page/nearby_share_subpage.js",
   "chromeos/os_a11y_page/manage_a11y_page.js",
-  "chromeos/os_apps_page/android_apps_subpage.js",
   "chromeos/os_bluetooth_page/os_bluetooth_change_device_name_dialog.js",
   "chromeos/os_bluetooth_page/os_bluetooth_device_detail_subpage.js",
   "chromeos/os_bluetooth_page/os_bluetooth_devices_subpage.js",
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html b/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html
index fa8e4ff..392dbb2 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html
+++ b/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html
@@ -1,4 +1,4 @@
-<style include="settings-page-styles cr-hidden-style settings-shared">
+<style include="os-settings-page-styles cr-hidden-style settings-shared">
   :host([is-subpage-animating]) {
     /* Prevent an unwanted horizontal scrollbar when transitioning back from
       * a sub-page. */
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.ts b/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.ts
index 61403d4..d76dee2 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.ts
+++ b/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.ts
@@ -20,7 +20,7 @@
 import '../os_search_page/os_search_page.js';
 import '../personalization_page/personalization_page.js';
 import '../os_settings_page/os_settings_section.js';
-import '../../settings_page_styles.css.js';
+import '../os_settings_page_styles.css.js';
 import '../device_page/device_page.js';
 import '../internet_page/internet_page.js';
 import '../kerberos_page/kerberos_page.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_page_styles.css b/chrome/browser/resources/settings/chromeos/os_settings_page_styles.css
new file mode 100644
index 0000000..a988343
--- /dev/null
+++ b/chrome/browser/resources/settings/chromeos/os_settings_page_styles.css
@@ -0,0 +1,23 @@
+/* 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. */
+
+/* #css_wrapper_metadata_start
+ * #type=style
+ * #css_wrapper_metadata_end */
+
+:host(.showing-subpage) os-settings-section:not(.expanded) {
+  display: none;
+}
+
+:host > div > :not(.expanded) {
+  /* The margin and padding here are doing two things: make the total
+   * separation 24px; and make scrollIntoView align the section header
+   * with the top item in the side nav menu. Both things are desired
+   * by Alan (bettes@). */
+  margin-bottom: 3px;
+}
+
+.expanded {
+  min-height: 100%;
+}
diff --git a/chrome/browser/resources/side_panel/images/read_anything_blue.png b/chrome/browser/resources/side_panel/images/read_anything_blue.png
new file mode 100644
index 0000000..644591c
--- /dev/null
+++ b/chrome/browser/resources/side_panel/images/read_anything_blue.png
Binary files differ
diff --git a/chrome/browser/safe_browsing/chrome_ui_manager_delegate_unittest.cc b/chrome/browser/safe_browsing/chrome_ui_manager_delegate_unittest.cc
index 5c5ba2a..20d3b0ef 100644
--- a/chrome/browser/safe_browsing/chrome_ui_manager_delegate_unittest.cc
+++ b/chrome/browser/safe_browsing/chrome_ui_manager_delegate_unittest.cc
@@ -33,17 +33,17 @@
 
 #if BUILDFLAG(ENABLE_EXTENSIONS)
   // Create a WebContents instance that *is* hosting an extension.
-  base::DictionaryValue manifest;
-  manifest.SetString(extensions::manifest_keys::kName, "TestComponentApp");
-  manifest.SetString(extensions::manifest_keys::kVersion, "0.0.0.0");
-  manifest.SetString(extensions::manifest_keys::kApp, "true");
-  manifest.SetString(extensions::manifest_keys::kPlatformAppBackgroundPage,
-                     std::string());
+  base::Value::Dict manifest;
+  manifest.Set(extensions::manifest_keys::kName, "TestComponentApp");
+  manifest.Set(extensions::manifest_keys::kVersion, "0.0.0.0");
+  manifest.SetByDottedPath(
+      extensions::manifest_keys::kPlatformAppBackgroundPage, std::string());
   std::string error;
   scoped_refptr<extensions::Extension> app;
   app = extensions::Extension::Create(
       base::FilePath(), extensions::mojom::ManifestLocation::kComponent,
       manifest, 0, &error);
+  ASSERT_TRUE(app) << error;
   extensions::ProcessManager* extension_manager =
       extensions::ProcessManager::Get(web_contents()->GetBrowserContext());
   extension_manager->CreateBackgroundHost(app.get(), GURL("background.html"));
diff --git a/chrome/browser/safe_browsing/incident_reporting/last_download_finder_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/last_download_finder_unittest.cc
index c596c6d..bf55f6d1 100644
--- a/chrome/browser/safe_browsing/incident_reporting/last_download_finder_unittest.cc
+++ b/chrome/browser/safe_browsing/incident_reporting/last_download_finder_unittest.cc
@@ -69,8 +69,8 @@
           std::make_unique<ChromeHistoryClient>(
               BookmarkModelFactory::GetForBrowserContext(profile)),
           std::unique_ptr<history::VisitDelegate>()));
-  if (history_service->Init(
-          history::HistoryDatabaseParamsForPath(profile->GetPath()))) {
+  if (history_service->Init(history::HistoryDatabaseParamsForPath(
+          profile->GetPath(), version_info::Channel::UNKNOWN))) {
     return std::move(history_service);
   }
 
diff --git a/chrome/browser/speech/extension_api/tts_extension_api_lacros_browsertest.cc b/chrome/browser/speech/extension_api/tts_extension_api_lacros_browsertest.cc
index 1292fde..624202b7 100644
--- a/chrome/browser/speech/extension_api/tts_extension_api_lacros_browsertest.cc
+++ b/chrome/browser/speech/extension_api/tts_extension_api_lacros_browsertest.cc
@@ -7,9 +7,12 @@
 #include "base/run_loop.h"
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/speech/extension_api/tts_engine_extension_api.h"
+#include "chrome/browser/speech/tts_crosapi_util.h"
 #include "chrome/browser/speech/tts_lacros.h"
 #include "chromeos/crosapi/mojom/test_controller.mojom-test-utils.h"
 #include "chromeos/crosapi/mojom/test_controller.mojom.h"
+#include "chromeos/crosapi/mojom/tts.mojom.h"
+#include "chromeos/lacros/lacros_service.h"
 #include "chromeos/lacros/lacros_test_helper.h"
 #include "content/public/browser/tts_controller.h"
 #include "content/public/browser/tts_platform.h"
@@ -72,14 +75,14 @@
   bool VoicesChangedNotified() { return voices_changed_; }
   void ResetVoicesChanged() { voices_changed_ = false; }
 
-  void WaitUntilVoicesLoaded() {
-    while (!HasVoiceWithName("Alice")) {
+  void WaitUntilVoicesLoaded(const std::string& voice_name) {
+    while (!HasVoiceWithName(voice_name)) {
       GiveItSomeTime(base::Milliseconds(100));
     }
   }
 
-  void WaitUntilVoicesUnloaded() {
-    while (HasVoiceWithName("Alice")) {
+  void WaitUntilVoicesUnloaded(const std::string& voice_name) {
+    while (HasVoiceWithName(voice_name)) {
       GiveItSomeTime(base::Milliseconds(100));
     }
   }
@@ -94,8 +97,66 @@
     return waiter.GetTtsUtteranceQueueSize() == 0;
   }
 
+  bool FoundVoiceInMojoVoices(
+      const std::string& voice_name,
+      const std::vector<crosapi::mojom::TtsVoicePtr>& mojo_voices) {
+    for (const auto& voice : mojo_voices) {
+      if (voice_name == voice->voice_name)
+        return true;
+    }
+    return false;
+  }
+
+  void WaitUntilTtsEventReceivedByUtteranceEventDelegateInAsh() {
+    while (!tts_event_notified_in_ash_) {
+      GiveItSomeTime(base::Milliseconds(100));
+    }
+  }
+
+  void NotifyTtsEventReceivedInAsh(content::TtsEventType tts_event) {
+    tts_event_notified_in_ash_ = true;
+    tts_event_received_ = tts_event;
+  }
+
+  bool TtsEventNotifiedInAsh() { return tts_event_notified_in_ash_; }
+  bool TtsEventReceivedEq(content::TtsEventType expected_tts_event) {
+    return tts_event_received_ == expected_tts_event;
+  }
+
+  // Used to verify that the TtsEvent is received by the Ash utterance's
+  // UtteranceEventDelegate in Ash.
+  class EventDelegate : public crosapi::mojom::TtsUtteranceClient {
+   public:
+    explicit EventDelegate(extensions::LacrosTtsApiTest* owner)
+        : owner_(owner) {}
+    EventDelegate(const EventDelegate&) = delete;
+    EventDelegate& operator=(const EventDelegate&) = delete;
+    ~EventDelegate() override = default;
+
+    // crosapi::mojom::TtsUtteranceClient:
+    void OnTtsEvent(crosapi::mojom::TtsEventType mojo_tts_event,
+                    uint32_t char_index,
+                    uint32_t char_length,
+                    const std::string& error_message) override {
+      content::TtsEventType tts_event =
+          tts_crosapi_util::FromMojo(mojo_tts_event);
+      owner_->NotifyTtsEventReceivedInAsh(tts_event);
+    }
+
+    mojo::PendingRemote<crosapi::mojom::TtsUtteranceClient>
+    BindTtsUtteranceClient() {
+      return receiver_.BindNewPipeAndPassRemoteWithVersion();
+    }
+
+   private:
+    extensions::LacrosTtsApiTest* owner_;
+    mojo::Receiver<crosapi::mojom::TtsUtteranceClient> receiver_{this};
+  };
+
  private:
   bool voices_changed_ = false;
+  bool tts_event_notified_in_ash_ = false;
+  content::TtsEventType tts_event_received_;
 };
 
 //
@@ -119,7 +180,7 @@
       << message_;
 
   // Wait until Lacros gets the voices registered by the tts engine extension.
-  WaitUntilVoicesLoaded();
+  WaitUntilVoicesLoaded("Alice");
 
   // Verify TtsController notifies VoicesChangedDelegate for the voices change.
   EXPECT_TRUE(VoicesChangedNotified());
@@ -141,9 +202,10 @@
   UninstallExtension(last_loaded_extension_id());
   observer.WaitForExtensionUninstalled();
 
-  WaitUntilVoicesUnloaded();
+  WaitUntilVoicesUnloaded("Alice");
 
-  // Verify TtsController notifies VoicesChangedDelegate for the voices change.
+  // Verify TtsController notifies VoicesChangedDelegate for the voices
+  // change.
   EXPECT_TRUE(VoicesChangedNotified());
 
   // Verify the voices from the tts engine extensions are unloaded in Lacros
@@ -170,8 +232,92 @@
                        {}, {.ignore_manifest_warnings = true}))
       << message_;
 
-  // Verify the utterance issued from the testing extension is properly finished
-  // and the utterance queue is empty in Ash's TtsController.
+  // Verify the utterance issued from the testing extension is properly
+  // finished and the utterance queue is empty in Ash's TtsController.
+  ASSERT_TRUE(IsUtteranceQueueEmpty());
+}
+
+IN_PROC_BROWSER_TEST_F(LacrosTtsApiTest,
+                       SpeakAshUtteranceWithLacrosSpeechEngine) {
+  if (chromeos::LacrosService::Get()->GetInterfaceVersion(
+          crosapi::mojom::TestController::Uuid_) <
+      static_cast<int>(crosapi::mojom::TestController::MethodMinVersions::
+                           kGetTtsVoicesMinVersion)) {
+    GTEST_SKIP() << "Unsupported ash version.";
+  }
+
+  EXPECT_FALSE(VoicesChangedNotified());
+  EXPECT_FALSE(HasVoiceWithName("Alice"));
+  EXPECT_FALSE(HasVoiceWithName("Alex"));
+  EXPECT_FALSE(HasVoiceWithName("Amanda"));
+
+  ResetVoicesChanged();
+  content::TtsController::GetInstance()->AddVoicesChangedDelegate(this);
+
+  // Load speech engine extension in Lacros.
+  ASSERT_TRUE(
+      RunExtensionTest("tts_engine/lacros_tts_support/"
+                       "register_lacros_tts_engine",
+                       {}, {.ignore_manifest_warnings = true}))
+      << message_;
+
+  WaitUntilVoicesLoaded("Alice");
+
+  EXPECT_TRUE(VoicesChangedNotified());
+
+  // Verify all the voices from tts engine extension are laded in Lacros.
+  std::vector<content::VoiceData> voices;
+  content::TtsController::GetInstance()->GetVoices(profile(), GURL(), &voices);
+  EXPECT_TRUE(HasVoiceWithName("Alice"));
+  EXPECT_TRUE(HasVoiceWithName("Alex"));
+  EXPECT_TRUE(HasVoiceWithName("Amanda"));
+  // Verify a random dummy voice is not loaded.
+  EXPECT_FALSE(HasVoiceWithName("Tommy"));
+
+  // Verify the same voices are also loaded in Ash.
+  crosapi::mojom::TestControllerAsyncWaiter waiter(
+      chromeos::LacrosService::Get()
+          ->GetRemote<crosapi::mojom::TestController>()
+          .get());
+
+  std::vector<crosapi::mojom::TtsVoicePtr> mojo_voices;
+  while (mojo_voices.size() == 0) {
+    waiter.GetTtsVoices(&mojo_voices);
+    if (mojo_voices.size() > 0)
+      break;
+    GiveItSomeTime(base::Milliseconds(100));
+  }
+
+  EXPECT_TRUE(FoundVoiceInMojoVoices("Alice", mojo_voices));
+  EXPECT_TRUE(FoundVoiceInMojoVoices("Alex", mojo_voices));
+  EXPECT_TRUE(FoundVoiceInMojoVoices("Amanda", mojo_voices));
+  // Verify a random dummy voice is not loaded.
+  EXPECT_FALSE(FoundVoiceInMojoVoices("Tommy", mojo_voices));
+
+  std::unique_ptr<content::TtsUtterance> ash_utterance =
+      content::TtsUtterance::Create();
+  ash_utterance->SetText("Hello from Ash");
+  // Use a voice provided by Lacros speech engine to speak the ash utterance.
+  ash_utterance->SetVoiceName("Alice");
+  crosapi::mojom::TtsUtterancePtr mojo_utterance =
+      tts_crosapi_util::ToMojo(ash_utterance.get());
+  // Note: mojo_utterance requires a value for browser_context_id, but it will
+  // not used in Ash for the testing case.
+  mojo_utterance->browser_context_id = base::UnguessableToken::Create();
+  auto pending_client = std::make_unique<EventDelegate>(this);
+  chromeos::LacrosService::Get()
+      ->GetRemote<crosapi::mojom::TestController>()
+      ->TtsSpeak(std::move(mojo_utterance),
+                 pending_client->BindTtsUtteranceClient());
+
+  // Verify that the Tts event has been received by the UtteranceEventDelegate
+  // in Ash.
+  WaitUntilTtsEventReceivedByUtteranceEventDelegateInAsh();
+  EXPECT_TRUE(TtsEventNotifiedInAsh());
+  EXPECT_TRUE(TtsEventReceivedEq(content::TTS_EVENT_END));
+
+  // Verify the utterance issued from the testing extension is properly
+  // finished and the utterance queue is empty in Ash's TtsController.
   ASSERT_TRUE(IsUtteranceQueueEmpty());
 }
 
diff --git a/chrome/browser/speech/tts_ash.cc b/chrome/browser/speech/tts_ash.cc
index 65aee2df..5616852 100644
--- a/chrome/browser/speech/tts_ash.cc
+++ b/chrome/browser/speech/tts_ash.cc
@@ -102,6 +102,51 @@
 
 namespace crosapi {
 
+// This is bound as the pending remote of |ash_utterance_client| argument of
+// TtsClient::SpeakWithLacrosVoice when TtsAsh::SpeakWithLacrosVoice calls
+// this crosapi to send an Ash utterance to Lacros.
+// The remote passed to Lacros will call OnTtsEvent to forward the Tts event
+// generated by the remote speech engine (in Lacros) to the callback of the
+// original TtsUtterance in Ash.
+class TtsAsh::TtsUtteranceClient : public mojom::TtsUtteranceClient {
+ public:
+  TtsUtteranceClient(TtsAsh* owner, int utterance_id)
+      : owner_(owner), utterance_id_(utterance_id) {}
+
+  TtsUtteranceClient(const TtsUtteranceClient&) = delete;
+  TtsUtteranceClient& operator=(const TtsUtteranceClient&) = delete;
+  ~TtsUtteranceClient() override = default;
+
+  // crosapi::mojom::TtsUtteranceClient:
+  void OnTtsEvent(crosapi::mojom::TtsEventType mojo_tts_event,
+                  uint32_t char_index,
+                  uint32_t char_length,
+                  const std::string& error_message) override {
+    content::TtsEventType event_type =
+        tts_crosapi_util::FromMojo(mojo_tts_event);
+    content::TtsController::GetInstance()->OnTtsEvent(
+        utterance_id_, event_type, char_index, char_length, error_message);
+
+    if (content::IsFinalTtsEventType(event_type)) {
+      owner_->DeletePendingAshUtteranceClient(utterance_id_);
+      // Note: |this| is deleted at this point.
+    }
+  }
+
+  mojo::PendingRemote<crosapi::mojom::TtsUtteranceClient>
+  BindTtsUtteranceClient() {
+    return receiver_.BindNewPipeAndPassRemoteWithVersion();
+  }
+
+ private:
+  // TtsAsh is responsible for creating and destroying the instances of this
+  // class, and its lifetime is guaranteed to outlive |this|.
+  const raw_ptr<TtsAsh> owner_;  // not owned.
+  //  Id of the original TtsUtterance instance owned by Ash's TtsController.
+  int utterance_id_;
+  mojo::Receiver<crosapi::mojom::TtsUtteranceClient> receiver_{this};
+};
+
 TtsAsh::TtsAsh(ProfileManager* profile_manager)
     : profile_manager_(profile_manager),
       primary_profile_browser_context_id_(base::UnguessableToken::Null()) {
@@ -175,13 +220,15 @@
 void TtsAsh::SpeakOrEnqueue(
     mojom::TtsUtterancePtr mojo_utterance,
     mojo::PendingRemote<mojom::TtsUtteranceClient> utterance_client) {
-  std::unique_ptr<content::TtsUtterance> utterance =
-      tts_crosapi_util::FromMojo(mojo_utterance);
-  utterance->SetEventDelegate(new LacrosUtteranceEventDelegate(
-      utterance->GetId(), mojo_utterance->utterance_id,
+  std::unique_ptr<content::TtsUtterance> lacros_utterance =
+      tts_crosapi_util::CreateUtteranceFromMojo(
+          mojo_utterance, /*should_always_be_spoken=*/true);
+  lacros_utterance->SetEventDelegate(new LacrosUtteranceEventDelegate(
+      lacros_utterance->GetId(), mojo_utterance->utterance_id,
       std::move(utterance_client)));
 
-  content::TtsController::GetInstance()->SpeakOrEnqueue(std::move(utterance));
+  content::TtsController::GetInstance()->SpeakOrEnqueue(
+      std::move(lacros_utterance));
 }
 
 void TtsAsh::SpeakWithLacrosVoice(content::TtsUtterance* utterance,
@@ -190,32 +237,54 @@
     return;
 
   DCHECK(voice.from_remote_tts_engine);
+  auto mojo_voice = tts_crosapi_util::ToMojo(voice);
+  auto mojo_utterance = tts_crosapi_util::ToMojo(utterance);
+  // TODO(crbug.com/1251979): Add secondary profile Tts support for lacros.
+  base::UnguessableToken browser_context_id =
+      GetPrimaryProfileBrowserContextId();
+  mojo_utterance->browser_context_id = browser_context_id;
+  auto item = tts_clients_.find(browser_context_id);
+  DCHECK(item != tts_clients_.end());
+  auto& tts_client = item->second;
+  // Note: TtsUtterance::ShouldAlwaysBeSpoken() is a misleading name. It should
+  // be renamed as TtsUtterance::FromExternalPlatform(), which indicates whether
+  // the utterance is originated from an external platform(Lacros) or not (Ash).
+  // TODO(crbug/1227543): Rename TtsUtterance::ShouldAlwaysBeSpoken().
   if (utterance->ShouldAlwaysBeSpoken()) {
     // Speak Lacros utterance.
-    auto mojo_voice = tts_crosapi_util::ToMojo(voice);
-    auto mojo_utterance = tts_crosapi_util::ToMojo(utterance);
     mojo_utterance->utterance_id = GetRemoteUtteranceId(utterance);
 
     // Don't need to pass utterance text back to Lacros via crosapi, since its
     // associated TtsUtterance object living in Lacros already has it.
     mojo_utterance->text = "";
 
-    // TODO(crbug.com/1251979): Support secondary profile of Lacros.
-    base::UnguessableToken browser_context_id =
-        GetPrimaryProfileBrowserContextId();
-    mojo_utterance->browser_context_id = browser_context_id;
-    auto item = tts_clients_.find(browser_context_id);
-    DCHECK(item != tts_clients_.end());
-    item->second->SpeakWithLacrosVoice(std::move(mojo_utterance),
-                                       std::move(mojo_voice),
-                                       /*ash_utterance_client=*/{});
+    tts_client->SpeakWithLacrosVoice(std::move(mojo_utterance),
+                                     std::move(mojo_voice),
+                                     /*ash_utterance_client=*/{});
   } else {
-    // TODO(crbug.com/1227543): Implement speaking Ash utterance with Lacros
-    // voice. Speak Ash utterance.
+    // Speak Ash utterance.
+    int utterance_id = utterance->GetId();
+    auto pending_utterance_client =
+        std::make_unique<TtsUtteranceClient>(this, utterance_id);
+    tts_client->SpeakWithLacrosVoice(
+        std::move(mojo_utterance), std::move(mojo_voice),
+        pending_utterance_client->BindTtsUtteranceClient());
+    DCHECK_EQ(pending_ash_utterance_clients_.size(), 0u);
+    pending_ash_utterance_clients_.emplace(utterance_id,
+                                           std::move(pending_utterance_client));
   }
 }
 
 void TtsAsh::StopRemoteEngine(content::TtsUtterance* utterance) {
+  if (!utterance->ShouldAlwaysBeSpoken()) {
+    // When an Ash utterance being spoken by a remote speech engine (in Lacros)
+    // should be stopped due to tts.Stop or its associated WebContents being
+    // destroyed, the TtsUtterance instance owned by Ash's TtsController will be
+    // deleted. The pending utterance client should also be deleted, which will
+    // trigger its disconnect handler in Lacros to notify that the utterance
+    // has become invalid in Ash.
+    DeletePendingAshUtteranceClient(utterance->GetId());
+  }
   auto item = tts_clients_.find(GetPrimaryProfileBrowserContextId());
   DCHECK(item != tts_clients_.end());
   item->second->Stop(utterance->GetEngineId());
@@ -232,6 +301,11 @@
   }
 }
 
+void TtsAsh::DeletePendingAshUtteranceClient(int utterance_id) {
+  pending_ash_utterance_clients_.erase(utterance_id);
+  DCHECK(pending_ash_utterance_clients_.empty());
+}
+
 void TtsAsh::OnVoicesChanged() {
   if (!HasTtsClient())
     return;
diff --git a/chrome/browser/speech/tts_ash.h b/chrome/browser/speech/tts_ash.h
index beeac527..9e6863cfd 100644
--- a/chrome/browser/speech/tts_ash.h
+++ b/chrome/browser/speech/tts_ash.h
@@ -54,6 +54,8 @@
   // |utterance|.
   void StopRemoteEngine(content::TtsUtterance* utterance);
 
+  void DeletePendingAshUtteranceClient(int utterance_id);
+
   // crosapi::mojom::Tts:
   void RegisterTtsClient(mojo::PendingRemote<mojom::TtsClient> client,
                          const base::UnguessableToken& browser_context_id,
@@ -65,6 +67,7 @@
       mojo::PendingRemote<mojom::TtsUtteranceClient> utterance_client) override;
 
  private:
+  class TtsUtteranceClient;
   // content::VoicesChangedDelegate:
   void OnVoicesChanged() override;
 
@@ -90,6 +93,14 @@
 
   base::UnguessableToken primary_profile_browser_context_id_;
 
+  // Pending Ash Utterance clients (for the Ash uttenrances to be spoken by
+  // Lacros speech engine) by utterance id.
+  // Note: The size of |pending_ash_utterance_clients_| should not be greater
+  // that one, since Ash TtsController process the utterances one at a time in
+  // sequence and  will not send more than 1 utterance to Lacros to be spoken.
+  std::map<int, std::unique_ptr<TtsUtteranceClient>>
+      pending_ash_utterance_clients_;
+
   base::ScopedObservation<content::TtsController,
                           content::VoicesChangedDelegate>
       voices_changed_observation_{this};
diff --git a/chrome/browser/speech/tts_client_lacros.cc b/chrome/browser/speech/tts_client_lacros.cc
index 01bfb981..f0d9698 100644
--- a/chrome/browser/speech/tts_client_lacros.cc
+++ b/chrome/browser/speech/tts_client_lacros.cc
@@ -40,6 +40,65 @@
 
 }  // namespace
 
+// This class is used as the UtteranceEventDelegate for the Ash utterance
+// sent to Lacros to be spoken with Lacros speech engine.
+// The lifetime of instance of this class is bound to the lifetime of the
+// associated TtsUtterance.
+class TtsClientLacros::AshUtteranceEventDelegate
+    : public content::UtteranceEventDelegate {
+ public:
+  AshUtteranceEventDelegate(
+      TtsClientLacros* owner,
+      int utterance_id,
+      mojo::PendingRemote<crosapi::mojom::TtsUtteranceClient> client)
+      : owner_(owner), utterance_id_(utterance_id), client_(std::move(client)) {
+    client_.set_disconnect_handler(base::BindOnce(
+        &AshUtteranceEventDelegate::OnTtsUtteranceClientDisconnected,
+        weak_ptr_factory_.GetWeakPtr()));
+  }
+
+  AshUtteranceEventDelegate(const AshUtteranceEventDelegate&) = delete;
+  AshUtteranceEventDelegate& operator=(const AshUtteranceEventDelegate&) =
+      delete;
+  ~AshUtteranceEventDelegate() override = default;
+
+  // content::UtteranceEventDelegate:
+  void OnTtsEvent(content::TtsUtterance* utterance,
+                  content::TtsEventType event_type,
+                  int char_index,
+                  int char_length,
+                  const std::string& error_message) override {
+    DCHECK_EQ(utterance->GetId(), utterance_id_);
+    // Forward the Tts event to Ash.
+    // Note: If |client_| is disconnected, this will be a no-op.
+    client_->OnTtsEvent(tts_crosapi_util::ToMojo(event_type), char_index,
+                        char_length, error_message);
+
+    if (utterance->IsFinished()) {
+      owner_->OnAshUtteranceFinished(utterance->GetId());
+      // |this| is deleted at this point.
+    }
+  }
+
+ private:
+  void OnTtsUtteranceClientDisconnected() {
+    // This will be triggered when the web contents associated with the ash
+    // utterance destroyed in ash.
+    owner_->OnAshUtteranceBecameInvalid(utterance_id_);
+    // |this| is deleted at this point.
+  }
+
+  const raw_ptr<TtsClientLacros> owner_;  // not owned
+  // Id of the TtsUtterance created in Lacros for the ash utterance.
+  int utterance_id_;
+
+  // Used to forward the Tts events back to Ash. Its disconnect handler will
+  // be invoked when its original utterance instance in Ash becomes invalid.
+  mojo::Remote<crosapi::mojom::TtsUtteranceClient> client_;
+
+  base::WeakPtrFactory<AshUtteranceEventDelegate> weak_ptr_factory_{this};
+};
+
 // This class implements crosapi::mojom::TtsUtteranceClient.
 // It is used to create a remote pending utterance client for a Lacros
 // utterance sent to Ash's TtsController.
@@ -184,6 +243,24 @@
       content::TtsController::GetInstance()->GetTtsEngineDelegate()->Speak(
           current_utterance_to_speak, voice);
     }
+  } else {
+    // Speaking an Ash utterance.
+    // There should NOT be an active pending ash utterance, since Ash
+    // TtsController won't process the next utterance in the utterance queue
+    // until the current one is finished.
+    DCHECK(!pending_ash_utterance_ && !ash_utterance_event_delegate_);
+    // Create a TtsUtterance in Lacros for the Ash utterance to be
+    // spoken with Lacros speech engine.
+    pending_ash_utterance_ = tts_crosapi_util::CreateUtteranceFromMojo(
+        mojo_utterance, /*should_always_be_spoken=*/false);
+    ash_utterance_event_delegate_.reset(
+        new AshUtteranceEventDelegate(this, pending_ash_utterance_->GetId(),
+                                      std::move(ash_pending_utterance_client)));
+    pending_ash_utterance_->SetEventDelegate(
+        ash_utterance_event_delegate_.get());
+    // Request Lacros Tts engine to speak the Ash utterance.
+    content::TtsController::GetInstance()->GetTtsEngineDelegate()->Speak(
+        pending_ash_utterance_.get(), voice);
   }
 }
 
@@ -324,9 +401,27 @@
     // Lacros utterance.
     item->second->OnLacrosSpeechEngineTtsEvent(
         utterance_id, event_type, char_index, length, error_message);
+  } else if (pending_ash_utterance_) {
+    // Ash utterance.
+    DCHECK_EQ(utterance_id, pending_ash_utterance_->GetId());
+    pending_ash_utterance_->OnTtsEvent(event_type, char_index, length,
+                                       error_message);
   }
 }
 
 void TtsClientLacros::DeletePendingUtteranceClient(int utterance_id) {
   pending_utterance_clients_.erase(utterance_id);
 }
+
+void TtsClientLacros::OnAshUtteranceFinished(int utterance_id) {
+  DCHECK(pending_ash_utterance_);
+  DCHECK_EQ(pending_ash_utterance_->GetId(), utterance_id);
+  pending_ash_utterance_.reset();
+  ash_utterance_event_delegate_.reset();
+}
+
+void TtsClientLacros::OnAshUtteranceBecameInvalid(int utterance_id) {
+  DCHECK(pending_ash_utterance_);
+  pending_ash_utterance_->Finish();
+  OnAshUtteranceFinished(utterance_id);
+}
diff --git a/chrome/browser/speech/tts_client_lacros.h b/chrome/browser/speech/tts_client_lacros.h
index f4abab1..ffca4ee 100644
--- a/chrome/browser/speech/tts_client_lacros.h
+++ b/chrome/browser/speech/tts_client_lacros.h
@@ -63,6 +63,8 @@
                                     int char_index,
                                     int length,
                                     const std::string& error_message);
+  void OnAshUtteranceFinished(int utterance_id);
+  void OnAshUtteranceBecameInvalid(int utterance_id);
 
   void DeletePendingUtteranceClient(int utterance_id);
 
@@ -73,6 +75,7 @@
 
  private:
   class TtsUtteraneClient;
+  class AshUtteranceEventDelegate;
   friend class extensions::BrowserContextKeyedAPIFactory<TtsClientLacros>;
 
   // net::NetworkChangeNotifier::NetworkChangeObserver:
@@ -104,6 +107,10 @@
   // Pending Lacros Tts Utterance clients by by utterance id.
   std::map<int, std::unique_ptr<TtsUtteraneClient>> pending_utterance_clients_;
 
+  // Pending Ash utterance to be spoken with Lacros speech engine.
+  std::unique_ptr<content::TtsUtterance> pending_ash_utterance_;
+  std::unique_ptr<AshUtteranceEventDelegate> ash_utterance_event_delegate_;
+
   base::WeakPtrFactory<TtsClientLacros> weak_ptr_factory_{this};
 };
 
diff --git a/chrome/browser/speech/tts_crosapi_util.cc b/chrome/browser/speech/tts_crosapi_util.cc
index 2abde62..5d160f0 100644
--- a/chrome/browser/speech/tts_crosapi_util.cc
+++ b/chrome/browser/speech/tts_crosapi_util.cc
@@ -138,14 +138,14 @@
   return mojo_utterance;
 }
 
-std::unique_ptr<content::TtsUtterance> FromMojo(
-    crosapi::mojom::TtsUtterancePtr& mojo_utterance) {
+std::unique_ptr<content::TtsUtterance> CreateUtteranceFromMojo(
+    crosapi::mojom::TtsUtterancePtr& mojo_utterance,
+    bool should_always_be_spoken) {
   // Construct TtsUtterance object.
   content::BrowserContext* browser_context =
       ProfileManager::GetPrimaryUserProfile();
   std::unique_ptr<content::TtsUtterance> utterance =
-      content::TtsUtterance::Create(browser_context,
-                                    /*should_always_be_spoken=*/true);
+      content::TtsUtterance::Create(browser_context, should_always_be_spoken);
 
   utterance->SetText(mojo_utterance->text);
   utterance->SetLang(mojo_utterance->lang);
diff --git a/chrome/browser/speech/tts_crosapi_util.h b/chrome/browser/speech/tts_crosapi_util.h
index 8e8c8a4..ba468ef 100644
--- a/chrome/browser/speech/tts_crosapi_util.h
+++ b/chrome/browser/speech/tts_crosapi_util.h
@@ -18,9 +18,16 @@
 content::VoiceData FromMojo(const crosapi::mojom::TtsVoicePtr& mojo_voice);
 crosapi::mojom::TtsVoicePtr ToMojo(const content::VoiceData& voice);
 crosapi::mojom::TtsUtterancePtr ToMojo(content::TtsUtterance* utterance);
-std::unique_ptr<content::TtsUtterance> FromMojo(
-    crosapi::mojom::TtsUtterancePtr& mojo_utterance);
 
+// Creates TtsUtterane from the mojo Utterance data.
+// |should_always_be_spoken| should be set to true if the TtsUtterance is
+// created for a Lacros utterance; otherwise, it should be set to false if the
+// TtsUtterance is created for an Ash utterance. This is used by Ash's
+// TtsController to differentiate whether an utterances is originated from Ash
+// or Lacros.
+std::unique_ptr<content::TtsUtterance> CreateUtteranceFromMojo(
+    crosapi::mojom::TtsUtterancePtr& mojo_utterance,
+    bool should_always_be_spoken);
 bool ShouldEnableLacrosTtsSupport();
 
 // Functions for testing use only.
diff --git a/chrome/browser/speech/tts_crosapi_util_unittest.cc b/chrome/browser/speech/tts_crosapi_util_unittest.cc
index b6e3ae65..f37b288 100644
--- a/chrome/browser/speech/tts_crosapi_util_unittest.cc
+++ b/chrome/browser/speech/tts_crosapi_util_unittest.cc
@@ -111,27 +111,58 @@
   // Round trip conversion to and from mojom utterance.
   auto mojo_utterance = tts_crosapi_util::ToMojo(in_utterance.get());
   mojo_utterance->browser_context_id = kBrowerContextId;
-  std::unique_ptr<content::TtsUtterance> out_utterance =
-      tts_crosapi_util::FromMojo(mojo_utterance);
 
-  ASSERT_EQ(out_utterance->GetText(), kText);
-  ASSERT_EQ(out_utterance->GetVoiceName(), kVoiceName);
-  ASSERT_EQ(out_utterance->GetLang(), kLang);
-  ASSERT_EQ(out_utterance->GetSrcId(), kSrcId);
-  ASSERT_EQ(out_utterance->GetSrcUrl(), GURL(kSrcUrl));
-  ASSERT_EQ(out_utterance->GetEngineId(), kEngineId);
-  auto continuouse_params = out_utterance->GetContinuousParameters();
-  ASSERT_EQ(continuouse_params.rate, kRate);
-  ASSERT_EQ(continuouse_params.pitch, kPitch);
-  ASSERT_EQ(continuouse_params.volume, kVolume);
-  ASSERT_TRUE(out_utterance->GetShouldClearQueue());
+  {
+    // Create TtsUtterance for a Lacros Utterance.
+    std::unique_ptr<content::TtsUtterance> out_utterance =
+        tts_crosapi_util::CreateUtteranceFromMojo(
+            mojo_utterance, /*should_always_be_spoken=*/true);
 
-  ASSERT_TRUE(EventTypesMatches(in_utterance->GetRequiredEventTypes(),
-                                out_utterance->GetRequiredEventTypes()));
-  ASSERT_TRUE(EventTypesMatches(in_utterance->GetDesiredEventTypes(),
-                                out_utterance->GetDesiredEventTypes()));
+    ASSERT_EQ(out_utterance->GetText(), kText);
+    ASSERT_EQ(out_utterance->GetVoiceName(), kVoiceName);
+    ASSERT_EQ(out_utterance->GetLang(), kLang);
+    ASSERT_EQ(out_utterance->GetSrcId(), kSrcId);
+    ASSERT_EQ(out_utterance->GetSrcUrl(), GURL(kSrcUrl));
+    ASSERT_EQ(out_utterance->GetEngineId(), kEngineId);
+    auto continuouse_params = out_utterance->GetContinuousParameters();
+    ASSERT_EQ(continuouse_params.rate, kRate);
+    ASSERT_EQ(continuouse_params.pitch, kPitch);
+    ASSERT_EQ(continuouse_params.volume, kVolume);
+    ASSERT_TRUE(out_utterance->GetShouldClearQueue());
 
-  ASSERT_TRUE(out_utterance->ShouldAlwaysBeSpoken());
+    ASSERT_TRUE(EventTypesMatches(in_utterance->GetRequiredEventTypes(),
+                                  out_utterance->GetRequiredEventTypes()));
+    ASSERT_TRUE(EventTypesMatches(in_utterance->GetDesiredEventTypes(),
+                                  out_utterance->GetDesiredEventTypes()));
+
+    ASSERT_TRUE(out_utterance->ShouldAlwaysBeSpoken());
+  }
+
+  {
+    // Create TtsUtterance for an Ash Utterance.
+    std::unique_ptr<content::TtsUtterance> out_utterance =
+        tts_crosapi_util::CreateUtteranceFromMojo(
+            mojo_utterance, /*should_always_be_spoken=*/false);
+
+    ASSERT_EQ(out_utterance->GetText(), kText);
+    ASSERT_EQ(out_utterance->GetVoiceName(), kVoiceName);
+    ASSERT_EQ(out_utterance->GetLang(), kLang);
+    ASSERT_EQ(out_utterance->GetSrcId(), kSrcId);
+    ASSERT_EQ(out_utterance->GetSrcUrl(), GURL(kSrcUrl));
+    ASSERT_EQ(out_utterance->GetEngineId(), kEngineId);
+    auto continuouse_params = out_utterance->GetContinuousParameters();
+    ASSERT_EQ(continuouse_params.rate, kRate);
+    ASSERT_EQ(continuouse_params.pitch, kPitch);
+    ASSERT_EQ(continuouse_params.volume, kVolume);
+    ASSERT_TRUE(out_utterance->GetShouldClearQueue());
+
+    ASSERT_TRUE(EventTypesMatches(in_utterance->GetRequiredEventTypes(),
+                                  out_utterance->GetRequiredEventTypes()));
+    ASSERT_TRUE(EventTypesMatches(in_utterance->GetDesiredEventTypes(),
+                                  out_utterance->GetDesiredEventTypes()));
+
+    ASSERT_FALSE(out_utterance->ShouldAlwaysBeSpoken());
+  }
 }
 
 TEST_F(TtsUtteranceMojomTest, RoundTripWithOptions) {
@@ -145,7 +176,8 @@
 
   auto mojo_utterance = tts_crosapi_util::ToMojo(in_utterance.get());
   std::unique_ptr<content::TtsUtterance> out_utterance =
-      tts_crosapi_util::FromMojo(mojo_utterance);
+      tts_crosapi_util::CreateUtteranceFromMojo(
+          mojo_utterance, /*should_always_be_spoken=*/true);
 
   auto* out_options = out_utterance->GetOptions();
 
diff --git a/chrome/browser/sync/glue/extensions_activity_monitor_unittest.cc b/chrome/browser/sync/glue/extensions_activity_monitor_unittest.cc
index ce33e68..aa0bc980 100644
--- a/chrome/browser/sync/glue/extensions_activity_monitor_unittest.cc
+++ b/chrome/browser/sync/glue/extensions_activity_monitor_unittest.cc
@@ -42,10 +42,10 @@
   EXPECT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &path));
   path = path.AppendASCII(name);
 
-  base::DictionaryValue value;
-  value.SetInteger(keys::kManifestVersion, 2);
-  value.SetString(keys::kVersion, "1.0.0.0");
-  value.SetString(keys::kName, name);
+  base::Value::Dict value;
+  value.Set(keys::kManifestVersion, 2);
+  value.Set(keys::kVersion, "1.0.0.0");
+  value.Set(keys::kName, name);
   std::string error;
   scoped_refptr<Extension> extension(Extension::Create(
       path, extensions::mojom::ManifestLocation::kInvalidLocation, value,
diff --git a/chrome/browser/sync/test/integration/password_manager_sync_test.cc b/chrome/browser/sync/test/integration/password_manager_sync_test.cc
index ad861a6..30f5c452 100644
--- a/chrome/browser/sync/test/integration/password_manager_sync_test.cc
+++ b/chrome/browser/sync/test/integration/password_manager_sync_test.cc
@@ -36,8 +36,14 @@
 #include "components/password_manager/core/browser/password_store_interface.h"
 #include "components/password_manager/core/browser/password_sync_util.h"
 #include "components/password_manager/core/common/password_manager_features.h"
+#include "components/policy/core/browser/browser_policy_connector.h"
+#include "components/policy/core/common/mock_configuration_policy_provider.h"
+#include "components/policy/core/common/policy_map.h"
+#include "components/policy/core/common/policy_types.h"
+#include "components/policy/policy_constants.h"
 #include "components/prefs/pref_service.h"
 #include "components/signin/public/identity_manager/account_info.h"
+#include "components/sync/base/model_type.h"
 #include "components/sync/driver/sync_service_impl.h"
 #include "components/sync/test/fake_server_nigori_helper.h"
 #include "content/public/browser/browser_context.h"
@@ -55,6 +61,7 @@
 
 using testing::ElementsAre;
 using testing::IsEmpty;
+using testing::NiceMock;
 using testing::UnorderedElementsAre;
 
 MATCHER_P2(MatchesLogin, username, password, "") {
@@ -72,6 +79,23 @@
 const char kExampleHostname[] = "www.example.com";
 const char kExamplePslHostname[] = "psl.example.com";
 
+class SyncActiveWithoutPasswordsChecker
+    : public SingleClientStatusChangeChecker {
+ public:
+  explicit SyncActiveWithoutPasswordsChecker(syncer::SyncServiceImpl* service)
+      : SingleClientStatusChangeChecker(service) {}
+
+  ~SyncActiveWithoutPasswordsChecker() override = default;
+
+  // StatusChangeChecker implementation.
+  bool IsExitConditionSatisfied(std::ostream* os) override {
+    // DEVICE_INFO is another arbitrary type supported for signed-in users,
+    // just so we rule out no type at all is active.
+    return !service()->GetActiveDataTypes().Has(syncer::PASSWORDS) &&
+           service()->GetActiveDataTypes().Has(syncer::DEVICE_INFO);
+  }
+};
+
 // Note: This helper applies to ChromeOS too, but is currently unused there. So
 // define it out to prevent a compile error due to the unused function.
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
@@ -939,4 +963,49 @@
             kExpectedUsername);
 }
 
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
+class PasswordManagerSyncTestWithPolicy : public PasswordManagerSyncTest {
+ public:
+  void SetUpInProcessBrowserTestFixture() override {
+    PasswordManagerSyncTest::SetUpInProcessBrowserTestFixture();
+    policy_provider_.SetDefaultReturns(
+        /*is_initialization_complete_return=*/true,
+        /*is_first_policy_load_complete_return=*/true);
+    policy::BrowserPolicyConnector::SetPolicyProviderForTesting(
+        &policy_provider_);
+  }
+
+  NiceMock<policy::MockConfigurationPolicyProvider>* policy_provider() {
+    return &policy_provider_;
+  }
+
+ private:
+  NiceMock<policy::MockConfigurationPolicyProvider> policy_provider_;
+};
+
+IN_PROC_BROWSER_TEST_F(PasswordManagerSyncTestWithPolicy,
+                       PRE_SyncTypesListDisabled) {
+  ASSERT_TRUE(SetupClients());
+  SetupSyncTransportWithPasswordAccountStorage();
+}
+
+IN_PROC_BROWSER_TEST_F(PasswordManagerSyncTestWithPolicy,
+                       SyncTypesListDisabled) {
+  // Disable passwords via the kSyncTypesListDisabled policy. The PRE_ test is
+  // required because the policy is only applied on startup.
+  base::Value::List disabled_types;
+  disabled_types.Append("passwords");
+  policy::PolicyMap policies;
+  policies.Set(policy::key::kSyncTypesListDisabled,
+               policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
+               policy::POLICY_SOURCE_CLOUD,
+               base::Value(std::move(disabled_types)), nullptr);
+  policy_provider()->UpdateChromePolicy(policies);
+
+  ASSERT_TRUE(SetupClients());
+
+  SyncActiveWithoutPasswordsChecker(GetSyncService(0)).Wait();
+}
+#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
+
 }  // namespace
diff --git a/chrome/browser/sync/test/integration/single_client_app_list_sync_test.cc b/chrome/browser/sync/test/integration/single_client_app_list_sync_test.cc
index 860d7f6..d006a90 100644
--- a/chrome/browser/sync/test/integration/single_client_app_list_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_app_list_sync_test.cc
@@ -6,6 +6,7 @@
 
 #include "ash/constants/ash_features.h"
 #include "base/run_loop.h"
+#include "chrome/browser/ash/app_list/internal_app/internal_app_metadata.h"
 #include "chrome/browser/sync/sync_service_factory.h"
 #include "chrome/browser/sync/test/integration/apps_helper.h"
 #include "chrome/browser/sync/test/integration/status_change_checker.h"
@@ -16,7 +17,6 @@
 #include "chrome/browser/ui/app_list/app_list_syncable_service.h"
 #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h"
 #include "chrome/browser/ui/app_list/chrome_app_list_item.h"
-#include "chrome/browser/ui/app_list/internal_app/internal_app_metadata.h"
 #include "components/sync/base/user_selectable_type.h"
 #include "components/sync/driver/sync_service.h"
 #include "components/sync/driver/sync_user_settings.h"
diff --git a/chrome/browser/sync/test/integration/sync_test.cc b/chrome/browser/sync/test/integration/sync_test.cc
index c154481..de188f3 100644
--- a/chrome/browser/sync/test/integration/sync_test.cc
+++ b/chrome/browser/sync/test/integration/sync_test.cc
@@ -103,9 +103,9 @@
 #include "ash/constants/ash_features.h"
 #include "ash/constants/ash_switches.h"
 #include "chrome/browser/ash/app_list/arc/arc_app_list_prefs_factory.h"
+#include "chrome/browser/ash/app_list/test/fake_app_list_model_updater.h"
 #include "chrome/browser/sync/test/integration/printers_helper.h"
 #include "chrome/browser/sync/test/integration/sync_arc_package_helper.h"
-#include "chrome/browser/ui/app_list/test/fake_app_list_model_updater.h"
 #include "chromeos/ash/components/account_manager/account_manager_factory.h"
 #include "components/account_manager_core/chromeos/account_manager.h"
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/task_manager/task_manager_browsertest.cc b/chrome/browser/task_manager/task_manager_browsertest.cc
index e26b1e8..e71bd90 100644
--- a/chrome/browser/task_manager/task_manager_browsertest.cc
+++ b/chrome/browser/task_manager/task_manager_browsertest.cc
@@ -1677,6 +1677,7 @@
   // Terminate the prerender task, which should signal the task manager to
   // remove the prerender task entry.
   {
+    base::HistogramTester histogram_tester;
     content::ScopedAllowRendererCrashes scoped_allow_renderer_crashes;
     absl::optional<size_t> trigger_row =
         FindResourceIndex(MatchTab("Title Of Awesomeness"));
@@ -1685,6 +1686,9 @@
     model()->Kill(trigger_row.value());
     ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyTab()));
     ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyPrerender()));
+    histogram_tester.ExpectUniqueSample(
+        "Prerender.Experimental.PrerenderHostFinalStatus.SpeculationRule",
+        /*PrerenderFinalStatus::kRendererProcessKilled=*/14, 1);
   }
 }
 
@@ -1722,6 +1726,7 @@
       WaitForTaskManagerRows(1, MatchPrerender(prerender_gurl.spec())));
   // Main task stays after prerendered task is terminated.
   {
+    base::HistogramTester histogram_tester;
     content::ScopedAllowRendererCrashes scoped_allow_renderer_crashes;
     absl::optional<size_t> prerender_row =
         FindResourceIndex(MatchPrerender(prerender_gurl.spec()));
@@ -1732,12 +1737,17 @@
     ASSERT_NO_FATAL_FAILURE(
         WaitForTaskManagerRows(1, MatchTab("Title Of Awesomeness")));
     ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyPrerender()));
+    histogram_tester.ExpectUniqueSample(
+        "Prerender.Experimental.PrerenderHostFinalStatus.Embedder_"
+        "DirectURLInput",
+        /*PrerenderFinalStatus::kRendererProcessKilled=*/14, 1);
   }
   // Both tasks are deleted after main task is terminated.
   {
     // Use a different URL because re-using the same URL does not trigger new
     // prerendering:
     // https://crsrc.org/c/chrome/browser/predictors/autocomplete_action_predictor.cc;l=208;drc=a08a4e1c3f6862b3b1385b8a040a4fdb524e509d
+    base::HistogramTester histogram_tester;
     const char kNewPrerenderURL[] = "/title3.html";
     const auto new_prerender_gurl =
         embedded_test_server()->GetURL(kNewPrerenderURL);
@@ -1756,6 +1766,10 @@
     model()->Kill(trigger_row.value());
     ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyTab()));
     ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyPrerender()));
+    histogram_tester.ExpectUniqueSample(
+        "Prerender.Experimental.PrerenderHostFinalStatus.Embedder_"
+        "DirectURLInput",
+        /*PrerenderFinalStatus::kRendererProcessKilled=*/14, 1);
   }
 }
 
diff --git a/chrome/browser/themes/browser_theme_pack.cc b/chrome/browser/themes/browser_theme_pack.cc
index 44400d5..31043413e 100644
--- a/chrome/browser/themes/browser_theme_pack.cc
+++ b/chrome/browser/themes/browser_theme_pack.cc
@@ -24,7 +24,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/thread_pool.h"
 #include "base/threading/thread_restrictions.h"
-#include "base/values.h"
 #include "build/build_config.h"
 #include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/ui/color/chrome_color_id.h"
@@ -1240,8 +1239,7 @@
   memcpy(header_->theme_id, id.c_str(), crx_file::id_util::kIdSize);
 }
 
-void BrowserThemePack::SetTintsFromJSON(
-    const base::DictionaryValue* tints_value) {
+void BrowserThemePack::SetTintsFromJSON(const base::Value::Dict* tints_value) {
   DCHECK(tints_);
 
   if (!tints_value)
@@ -1249,11 +1247,11 @@
 
   // Parse the incoming data from |tints_value| into an intermediary structure.
   std::map<int, color_utils::HSL> temp_tints;
-  for (const auto item : tints_value->GetDict()) {
-    if (!item.second.is_list())
+  for (const auto [key, value] : *tints_value) {
+    if (!value.is_list())
       continue;
 
-    const base::Value::List& tint_list = item.second.GetList();
+    const base::Value::List& tint_list = value.GetList();
     if (tint_list.size() != 3)
       continue;
 
@@ -1266,7 +1264,7 @@
     color_utils::HSL hsl = {*h, *s, *l};
     MakeHSLShiftValid(&hsl);
 
-    int id = GetIntForString(item.first, kTintTable, kTintTableLength);
+    int id = GetIntForString(key, kTintTable, kTintTableLength);
     if (id != -1)
       temp_tints[id] = hsl;
   }
@@ -1284,12 +1282,13 @@
   }
 }
 
-void BrowserThemePack::SetColorsFromJSON(const base::Value* colors_value) {
+void BrowserThemePack::SetColorsFromJSON(
+    const base::Value::Dict* colors_value) {
   DCHECK(colors_);
 
   std::map<int, SkColor> temp_colors;
   if (colors_value)
-    ReadColorsFromJSON(colors_value, &temp_colors);
+    ReadColorsFromJSON(*colors_value, &temp_colors);
 
   // Copy data from the intermediary data structure to the array.
   size_t count = 0;
@@ -1301,15 +1300,13 @@
   }
 }
 
-void BrowserThemePack::ReadColorsFromJSON(const base::Value* colors_value,
+void BrowserThemePack::ReadColorsFromJSON(const base::Value::Dict& colors_value,
                                           std::map<int, SkColor>* temp_colors) {
-  DCHECK(colors_value);
-  DCHECK(colors_value->is_dict());
   // Parse the incoming data from |colors_value| into an intermediary structure.
-  for (const auto iter : colors_value->DictItems()) {
-    if (!iter.second.is_list())
+  for (const auto [key, value] : colors_value) {
+    if (!value.is_list())
       continue;
-    const base::Value::List& color_list = iter.second.GetList();
+    const base::Value::List& color_list = value.GetList();
     if (!(color_list.size() == 3 || color_list.size() == 4))
       continue;
 
@@ -1346,14 +1343,14 @@
       color = SkColorSetRGB(*r, *g, *b);
     }
 
-    if (iter.first == "ntp_section") {
+    if (key == "ntp_section") {
       // We no longer use ntp_section, but to support legacy
       // themes we still need to use it as a fallback for
       // ntp_header.
       if (!temp_colors->count(TP::COLOR_NTP_HEADER))
         (*temp_colors)[TP::COLOR_NTP_HEADER] = color;
     } else {
-      int id = GetIntForString(iter.first, kOverwritableColorTable,
+      int id = GetIntForString(key, kOverwritableColorTable,
                                kOverwritableColorTableLength);
       if (id != -1)
         (*temp_colors)[id] = color;
@@ -1362,34 +1359,34 @@
 }
 
 void BrowserThemePack::SetDisplayPropertiesFromJSON(
-    const base::DictionaryValue* display_properties_value) {
+    const base::Value::Dict* display_properties_value) {
   DCHECK(display_properties_);
 
   if (!display_properties_value)
     return;
 
   std::map<int, int> temp_properties;
-  for (const auto item : display_properties_value->GetDict()) {
+  for (const auto [key, value] : *display_properties_value) {
     int property_id =
-        GetIntForString(item.first, kDisplayProperties, kDisplayPropertiesSize);
+        GetIntForString(key, kDisplayProperties, kDisplayPropertiesSize);
     switch (property_id) {
       case TP::NTP_BACKGROUND_ALIGNMENT: {
-        if (item.second.is_string()) {
+        if (value.is_string()) {
           temp_properties[TP::NTP_BACKGROUND_ALIGNMENT] =
-              TP::StringToAlignment(item.second.GetString());
+              TP::StringToAlignment(value.GetString());
         }
         break;
       }
       case TP::NTP_BACKGROUND_TILING: {
-        if (item.second.is_string()) {
+        if (value.is_string()) {
           temp_properties[TP::NTP_BACKGROUND_TILING] =
-              TP::StringToTiling(item.second.GetString());
+              TP::StringToTiling(value.GetString());
         }
         break;
       }
       case TP::NTP_LOGO_ALTERNATE: {
-        if (item.second.is_int())
-          temp_properties[TP::NTP_LOGO_ALTERNATE] = item.second.GetInt();
+        if (value.is_int())
+          temp_properties[TP::NTP_LOGO_ALTERNATE] = value.GetInt();
         break;
       }
     }
@@ -1406,27 +1403,26 @@
 }
 
 void BrowserThemePack::ParseImageNamesFromJSON(
-    const base::DictionaryValue* images_value,
+    const base::Value::Dict* images_value,
     const base::FilePath& images_path,
     FilePathMap* file_paths) const {
   if (!images_value)
     return;
 
-  for (const auto item : images_value->GetDict()) {
-    if (item.second.is_dict()) {
-      for (const auto inner_item : item.second.GetDict()) {
+  for (const auto [key, value] : *images_value) {
+    if (value.is_dict()) {
+      for (const auto [inner_key, inner_value] : value.GetDict()) {
         ui::ResourceScaleFactor scale_factor = ui::kScaleFactorNone;
-        if (GetScaleFactorFromManifestKey(inner_item.first, &scale_factor) &&
-            inner_item.second.is_string()) {
-          AddFileAtScaleToMap(
-              item.first, scale_factor,
-              images_path.AppendASCII(inner_item.second.GetString()),
-              file_paths);
+        if (GetScaleFactorFromManifestKey(inner_key, &scale_factor) &&
+            inner_value.is_string()) {
+          AddFileAtScaleToMap(key, scale_factor,
+                              images_path.AppendASCII(inner_value.GetString()),
+                              file_paths);
         }
       }
-    } else if (item.second.is_string()) {
-      AddFileAtScaleToMap(item.first, ui::k100Percent,
-                          images_path.AppendASCII(item.second.GetString()),
+    } else if (value.is_string()) {
+      AddFileAtScaleToMap(key, ui::k100Percent,
+                          images_path.AppendASCII(value.GetString()),
                           file_paths);
     }
   }
diff --git a/chrome/browser/themes/browser_theme_pack.h b/chrome/browser/themes/browser_theme_pack.h
index dbbec9e..671b2d6 100644
--- a/chrome/browser/themes/browser_theme_pack.h
+++ b/chrome/browser/themes/browser_theme_pack.h
@@ -15,6 +15,7 @@
 #include "base/containers/flat_map.h"
 #include "base/memory/raw_ptr.h"
 #include "base/task/sequenced_task_runner_helpers.h"
+#include "base/values.h"
 #include "chrome/browser/themes/custom_theme_supplier.h"
 #include "chrome/common/themes/autogenerated_theme_util.h"
 #include "extensions/common/extension.h"
@@ -23,10 +24,9 @@
 #include "ui/gfx/color_utils.h"
 
 namespace base {
-class DictionaryValue;
 class FilePath;
 class RefCountedMemory;
-}
+}  // namespace base
 
 namespace gfx {
 class Image;
@@ -178,22 +178,25 @@
   void SetHeaderId(const extensions::Extension* extension);
 
   // Transforms the JSON tint values into their final versions in the |tints_|
-  // array.
-  void SetTintsFromJSON(const base::DictionaryValue* tints_value);
+  // array. Does nothing if |tints_value| is nullptr.
+  void SetTintsFromJSON(const base::Value::Dict* tints_value);
 
   // Transforms the JSON color values into their final versions in the
   // |colors_| array and also fills in unspecified colors based on tint values.
-  void SetColorsFromJSON(const base::Value* color_value);
+  // Does nothing if |color_value| is nullptr.
+  void SetColorsFromJSON(const base::Value::Dict* color_value);
 
   // Implementation details of BuildColorsFromJSON().
-  void ReadColorsFromJSON(const base::Value* colors_value,
+  void ReadColorsFromJSON(const base::Value::Dict& colors_value,
                           std::map<int, SkColor>* temp_colors);
 
-  // Transforms the JSON display properties into |display_properties_|.
-  void SetDisplayPropertiesFromJSON(const base::DictionaryValue* display_value);
+  // Transforms the JSON display properties into |display_properties_|. Does
+  // nothing if |display_value| is nullptr.
+  void SetDisplayPropertiesFromJSON(const base::Value::Dict* display_value);
 
-  // Parses the image names out of an extension.
-  void ParseImageNamesFromJSON(const base::DictionaryValue* images_value,
+  // Parses the image names out of an extension. Does nothing if |images_value|
+  // is nullptr.
+  void ParseImageNamesFromJSON(const base::Value::Dict* images_value,
                                const base::FilePath& images_path,
                                FilePathMap* file_paths) const;
 
diff --git a/chrome/browser/themes/browser_theme_pack_unittest.cc b/chrome/browser/themes/browser_theme_pack_unittest.cc
index 1f0fbb3..688ed72 100644
--- a/chrome/browser/themes/browser_theme_pack_unittest.cc
+++ b/chrome/browser/themes/browser_theme_pack_unittest.cc
@@ -61,14 +61,14 @@
 
   void VerifyColorMap(const std::map<int, SkColor>& color_map);
   void LoadColorJSON(const std::string& json);
-  void LoadColorDictionary(base::DictionaryValue* value);
+  void LoadColorDictionary(const base::Value::Dict* value);
   void LoadTintJSON(const std::string& json);
-  void LoadTintDictionary(base::DictionaryValue* value);
+  void LoadTintDictionary(const base::Value::Dict* value);
   void LoadDisplayPropertiesJSON(const std::string& json);
-  void LoadDisplayPropertiesDictionary(base::DictionaryValue* value);
+  void LoadDisplayPropertiesDictionary(const base::Value::Dict* value);
   void ParseImageNamesJSON(const std::string& json,
                            TestFilePathMap* out_file_paths);
-  void ParseImageNamesDictionary(base::DictionaryValue* value,
+  void ParseImageNamesDictionary(const base::Value::Dict* value,
                                  TestFilePathMap* out_file_paths);
   bool LoadRawBitmapsTo(const TestFilePathMap& out_file_paths);
 
@@ -180,49 +180,40 @@
 }
 
 void BrowserThemePackTest::LoadColorJSON(const std::string& json) {
-  std::unique_ptr<base::Value> value = base::JSONReader::ReadDeprecated(json);
-  ASSERT_TRUE(value->is_dict());
-  LoadColorDictionary(static_cast<base::DictionaryValue*>(value.get()));
+  LoadColorDictionary(&base::JSONReader::Read(json)->GetDict());
 }
 
-void BrowserThemePackTest::LoadColorDictionary(base::DictionaryValue* value) {
+void BrowserThemePackTest::LoadColorDictionary(const base::Value::Dict* value) {
   theme_pack_->SetColorsFromJSON(value);
   theme_pack_->GenerateFrameColorsFromTints();
 }
 
 void BrowserThemePackTest::LoadTintJSON(const std::string& json) {
-  std::unique_ptr<base::Value> value = base::JSONReader::ReadDeprecated(json);
-  ASSERT_TRUE(value->is_dict());
-  LoadTintDictionary(static_cast<base::DictionaryValue*>(value.get()));
+  LoadTintDictionary(&base::JSONReader::Read(json)->GetDict());
 }
 
-void BrowserThemePackTest::LoadTintDictionary(base::DictionaryValue* value) {
+void BrowserThemePackTest::LoadTintDictionary(const base::Value::Dict* value) {
   theme_pack_->SetTintsFromJSON(value);
 }
 
 void BrowserThemePackTest::LoadDisplayPropertiesJSON(const std::string& json) {
-  std::unique_ptr<base::Value> value = base::JSONReader::ReadDeprecated(json);
-  ASSERT_TRUE(value->is_dict());
-  LoadDisplayPropertiesDictionary(
-      static_cast<base::DictionaryValue*>(value.get()));
+  LoadDisplayPropertiesDictionary(&base::JSONReader::Read(json)->GetDict());
 }
 
 void BrowserThemePackTest::LoadDisplayPropertiesDictionary(
-    base::DictionaryValue* value) {
+    const base::Value::Dict* value) {
   theme_pack_->SetDisplayPropertiesFromJSON(value);
 }
 
 void BrowserThemePackTest::ParseImageNamesJSON(
     const std::string& json,
     TestFilePathMap* out_file_paths) {
-  std::unique_ptr<base::Value> value = base::JSONReader::ReadDeprecated(json);
-  ASSERT_TRUE(value->is_dict());
-  ParseImageNamesDictionary(static_cast<base::DictionaryValue*>(value.get()),
+  ParseImageNamesDictionary(&base::JSONReader::Read(json)->GetDict(),
                             out_file_paths);
 }
 
 void BrowserThemePackTest::ParseImageNamesDictionary(
-    base::DictionaryValue* value,
+    const base::Value::Dict* value,
     TestFilePathMap* out_file_paths) {
   theme_pack_->ParseImageNamesFromJSON(value, base::FilePath(), out_file_paths);
 
@@ -242,13 +233,13 @@
   base::FilePath manifest_path = extension_path.AppendASCII("manifest.json");
   std::string error;
   JSONFileValueDeserializer deserializer(manifest_path);
-  std::unique_ptr<base::DictionaryValue> valid_value =
-      base::DictionaryValue::From(deserializer.Deserialize(nullptr, &error));
+  std::unique_ptr<base::Value> valid_value =
+      deserializer.Deserialize(nullptr, &error);
   EXPECT_EQ("", error);
-  ASSERT_TRUE(valid_value.get());
+  ASSERT_TRUE(valid_value.get() && valid_value->is_dict());
   scoped_refptr<Extension> extension(Extension::Create(
       extension_path, extensions::mojom::ManifestLocation::kInvalidLocation,
-      *valid_value, Extension::NO_FLAGS, &error));
+      valid_value->GetDict(), Extension::NO_FLAGS, &error));
   ASSERT_TRUE(extension.get());
   ASSERT_EQ("", error);
   BrowserThemePack::BuildFromExtension(extension.get(), pack);
@@ -716,7 +707,7 @@
       theme_pack().GetDisplayProperty(TP::NTP_BACKGROUND_ALIGNMENT, &out_val));
 }
 
-// These three tests should just not cause a segmentation fault.
+// These four tests should just not cause a segmentation fault.
 TEST_F(BrowserThemePackTest, NullPaths) {
   TestFilePathMap out_file_paths;
   ParseImageNamesDictionary(nullptr, &out_file_paths);
diff --git a/chrome/browser/themes/theme_syncable_service_unittest.cc b/chrome/browser/themes/theme_syncable_service_unittest.cc
index d7adb9d..f3d7219 100644
--- a/chrome/browser/themes/theme_syncable_service_unittest.cc
+++ b/chrome/browser/themes/theme_syncable_service_unittest.cc
@@ -185,12 +185,11 @@
     const string& name,
     extensions::mojom::ManifestLocation location,
     const string& update_url) {
-  base::DictionaryValue source;
-  source.SetString(extensions::manifest_keys::kName, name);
-  source.Set(extensions::manifest_keys::kTheme,
-             std::make_unique<base::DictionaryValue>());
-  source.SetString(extensions::manifest_keys::kUpdateURL, update_url);
-  source.SetString(extensions::manifest_keys::kVersion, "0.0.0.0");
+  base::Value::Dict source;
+  source.Set(extensions::manifest_keys::kName, name);
+  source.Set(extensions::manifest_keys::kTheme, base::Value::Dict());
+  source.Set(extensions::manifest_keys::kUpdateURL, update_url);
+  source.Set(extensions::manifest_keys::kVersion, "0.0.0.0");
   string error;
   scoped_refptr<extensions::Extension> extension =
       extensions::Extension::Create(
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index de8d7b5..cdb153f 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -497,6 +497,7 @@
     "//components/history_clusters/history_clusters_internals/webui",
     "//components/history_clusters/history_clusters_internals/webui:mojo_bindings",
     "//components/image_fetcher/core",
+    "//components/image_service",
     "//components/infobars/content",
     "//components/infobars/core",
     "//components/invalidation/impl",
@@ -1992,6 +1993,118 @@
       "../ash/app_list/arc/arc_vpn_provider_manager_factory.h",
       "../ash/app_list/arc/intent.cc",
       "../ash/app_list/arc/intent.h",
+      "../ash/app_list/internal_app/internal_app_metadata.cc",
+      "../ash/app_list/internal_app/internal_app_metadata.h",
+      "../ash/app_list/reorder/app_list_reorder_core.cc",
+      "../ash/app_list/reorder/app_list_reorder_core.h",
+      "../ash/app_list/reorder/app_list_reorder_delegate.h",
+      "../ash/app_list/reorder/app_list_reorder_util.cc",
+      "../ash/app_list/reorder/app_list_reorder_util.h",
+      "../ash/app_list/search/arc/arc_app_shortcut_search_result.cc",
+      "../ash/app_list/search/arc/arc_app_shortcut_search_result.h",
+      "../ash/app_list/search/arc/arc_app_shortcuts_search_provider.cc",
+      "../ash/app_list/search/arc/arc_app_shortcuts_search_provider.h",
+      "../ash/app_list/search/arc/arc_playstore_search_provider.cc",
+      "../ash/app_list/search/arc/arc_playstore_search_provider.h",
+      "../ash/app_list/search/arc/arc_playstore_search_result.cc",
+      "../ash/app_list/search/arc/arc_playstore_search_result.h",
+      "../ash/app_list/search/arc/fake_recommend_apps_fetcher_delegate.cc",
+      "../ash/app_list/search/arc/fake_recommend_apps_fetcher_delegate.h",
+      "../ash/app_list/search/arc/recommend_apps_fetcher.cc",
+      "../ash/app_list/search/arc/recommend_apps_fetcher.h",
+      "../ash/app_list/search/arc/recommend_apps_fetcher_delegate.h",
+      "../ash/app_list/search/arc/recommend_apps_fetcher_impl.cc",
+      "../ash/app_list/search/arc/recommend_apps_fetcher_impl.h",
+      "../ash/app_list/search/common/icon_constants.cc",
+      "../ash/app_list/search/common/icon_constants.h",
+      "../ash/app_list/search/common/search_result_util.cc",
+      "../ash/app_list/search/common/search_result_util.h",
+      "../ash/app_list/search/common/string_util.cc",
+      "../ash/app_list/search/common/string_util.h",
+      "../ash/app_list/search/common/types_util.cc",
+      "../ash/app_list/search/common/types_util.h",
+      "../ash/app_list/search/cros_action_history/cros_action_recorder.cc",
+      "../ash/app_list/search/cros_action_history/cros_action_recorder.h",
+      "../ash/app_list/search/cros_action_history/cros_action_recorder_tab_tracker.cc",
+      "../ash/app_list/search/cros_action_history/cros_action_recorder_tab_tracker.h",
+      "../ash/app_list/search/files/drive_file_suggestion_provider.cc",
+      "../ash/app_list/search/files/drive_file_suggestion_provider.h",
+      "../ash/app_list/search/files/drive_search_provider.cc",
+      "../ash/app_list/search/files/drive_search_provider.h",
+      "../ash/app_list/search/files/file_result.cc",
+      "../ash/app_list/search/files/file_result.h",
+      "../ash/app_list/search/files/file_search_provider.cc",
+      "../ash/app_list/search/files/file_search_provider.h",
+      "../ash/app_list/search/files/file_suggest_keyed_service.cc",
+      "../ash/app_list/search/files/file_suggest_keyed_service.h",
+      "../ash/app_list/search/files/file_suggest_keyed_service_factory.cc",
+      "../ash/app_list/search/files/file_suggest_keyed_service_factory.h",
+      "../ash/app_list/search/files/file_suggest_util.cc",
+      "../ash/app_list/search/files/file_suggest_util.h",
+      "../ash/app_list/search/files/file_suggestion_provider.cc",
+      "../ash/app_list/search/files/file_suggestion_provider.h",
+      "../ash/app_list/search/files/item_suggest_cache.cc",
+      "../ash/app_list/search/files/item_suggest_cache.h",
+      "../ash/app_list/search/files/justifications.cc",
+      "../ash/app_list/search/files/justifications.h",
+      "../ash/app_list/search/files/local_file_suggestion_provider.cc",
+      "../ash/app_list/search/files/local_file_suggestion_provider.h",
+      "../ash/app_list/search/files/zero_state_drive_provider.cc",
+      "../ash/app_list/search/files/zero_state_drive_provider.h",
+      "../ash/app_list/search/files/zero_state_file_provider.cc",
+      "../ash/app_list/search/files/zero_state_file_provider.h",
+      "../ash/app_list/search/games/game_provider.cc",
+      "../ash/app_list/search/games/game_provider.h",
+      "../ash/app_list/search/games/game_result.cc",
+      "../ash/app_list/search/games/game_result.h",
+      "../ash/app_list/search/omnibox/omnibox_answer_result.cc",
+      "../ash/app_list/search/omnibox/omnibox_answer_result.h",
+      "../ash/app_list/search/omnibox/omnibox_lacros_provider.cc",
+      "../ash/app_list/search/omnibox/omnibox_lacros_provider.h",
+      "../ash/app_list/search/omnibox/omnibox_provider.cc",
+      "../ash/app_list/search/omnibox/omnibox_provider.h",
+      "../ash/app_list/search/omnibox/omnibox_result.cc",
+      "../ash/app_list/search/omnibox/omnibox_result.h",
+      "../ash/app_list/search/omnibox/omnibox_util.cc",
+      "../ash/app_list/search/omnibox/omnibox_util.h",
+      "../ash/app_list/search/omnibox/open_tab_result.cc",
+      "../ash/app_list/search/omnibox/open_tab_result.h",
+      "../ash/app_list/search/ranking/answer_ranker.cc",
+      "../ash/app_list/search/ranking/answer_ranker.h",
+      "../ash/app_list/search/ranking/best_match_ranker.cc",
+      "../ash/app_list/search/ranking/best_match_ranker.h",
+      "../ash/app_list/search/ranking/constants.h",
+      "../ash/app_list/search/ranking/continue_ranker.cc",
+      "../ash/app_list/search/ranking/continue_ranker.h",
+      "../ash/app_list/search/ranking/filtering_ranker.cc",
+      "../ash/app_list/search/ranking/filtering_ranker.h",
+      "../ash/app_list/search/ranking/ftrl_ranker.cc",
+      "../ash/app_list/search/ranking/ftrl_ranker.h",
+      "../ash/app_list/search/ranking/launch_data.cc",
+      "../ash/app_list/search/ranking/launch_data.h",
+      "../ash/app_list/search/ranking/mrfu_ranker.cc",
+      "../ash/app_list/search/ranking/mrfu_ranker.h",
+      "../ash/app_list/search/ranking/query_highlighter.cc",
+      "../ash/app_list/search/ranking/query_highlighter.h",
+      "../ash/app_list/search/ranking/ranker.cc",
+      "../ash/app_list/search/ranking/ranker.h",
+      "../ash/app_list/search/ranking/ranker_manager.cc",
+      "../ash/app_list/search/ranking/ranker_manager.h",
+      "../ash/app_list/search/ranking/removed_results_ranker.cc",
+      "../ash/app_list/search/ranking/removed_results_ranker.h",
+      "../ash/app_list/search/ranking/score_normalizing_ranker.cc",
+      "../ash/app_list/search/ranking/score_normalizing_ranker.h",
+      "../ash/app_list/search/ranking/scoring.cc",
+      "../ash/app_list/search/ranking/scoring.h",
+      "../ash/app_list/search/ranking/util.cc",
+      "../ash/app_list/search/ranking/util.h",
+      "../ash/app_list/search/util/ftrl_optimizer.cc",
+      "../ash/app_list/search/util/ftrl_optimizer.h",
+      "../ash/app_list/search/util/mrfu_cache.cc",
+      "../ash/app_list/search/util/mrfu_cache.h",
+      "../ash/app_list/search/util/persistent_proto.h",
+      "../ash/app_list/search/util/score_normalizer.cc",
+      "../ash/app_list/search/util/score_normalizer.h",
       "app_icon_loader_delegate.h",
       "app_list/app_context_menu.cc",
       "app_list/app_context_menu.h",
@@ -2029,15 +2142,8 @@
       "app_list/chrome_app_list_model_updater.h",
       "app_list/extension_app_utils.cc",
       "app_list/extension_app_utils.h",
-      "app_list/internal_app/internal_app_metadata.cc",
-      "app_list/internal_app/internal_app_metadata.h",
       "app_list/md_icon_normalizer.cc",
       "app_list/md_icon_normalizer.h",
-      "app_list/reorder/app_list_reorder_core.cc",
-      "app_list/reorder/app_list_reorder_core.h",
-      "app_list/reorder/app_list_reorder_delegate.h",
-      "app_list/reorder/app_list_reorder_util.cc",
-      "app_list/reorder/app_list_reorder_util.h",
       "app_list/search/app_result.cc",
       "app_list/search/app_result.h",
       "app_list/search/app_search_data_source.cc",
@@ -2048,69 +2154,12 @@
       "app_list/search/app_service_app_result.h",
       "app_list/search/app_zero_state_provider.cc",
       "app_list/search/app_zero_state_provider.h",
-      "app_list/search/arc/arc_app_shortcut_search_result.cc",
-      "app_list/search/arc/arc_app_shortcut_search_result.h",
-      "app_list/search/arc/arc_app_shortcuts_search_provider.cc",
-      "app_list/search/arc/arc_app_shortcuts_search_provider.h",
-      "app_list/search/arc/arc_playstore_search_provider.cc",
-      "app_list/search/arc/arc_playstore_search_provider.h",
-      "app_list/search/arc/arc_playstore_search_result.cc",
-      "app_list/search/arc/arc_playstore_search_result.h",
-      "app_list/search/arc/fake_recommend_apps_fetcher_delegate.cc",
-      "app_list/search/arc/fake_recommend_apps_fetcher_delegate.h",
-      "app_list/search/arc/recommend_apps_fetcher.cc",
-      "app_list/search/arc/recommend_apps_fetcher.h",
-      "app_list/search/arc/recommend_apps_fetcher_delegate.h",
-      "app_list/search/arc/recommend_apps_fetcher_impl.cc",
-      "app_list/search/arc/recommend_apps_fetcher_impl.h",
       "app_list/search/assistant_text_search_provider.cc",
       "app_list/search/assistant_text_search_provider.h",
       "app_list/search/burnin_controller.cc",
       "app_list/search/burnin_controller.h",
       "app_list/search/chrome_search_result.cc",
       "app_list/search/chrome_search_result.h",
-      "app_list/search/common/icon_constants.cc",
-      "app_list/search/common/icon_constants.h",
-      "app_list/search/common/search_result_util.cc",
-      "app_list/search/common/search_result_util.h",
-      "app_list/search/common/string_util.cc",
-      "app_list/search/common/string_util.h",
-      "app_list/search/common/types_util.cc",
-      "app_list/search/common/types_util.h",
-      "app_list/search/cros_action_history/cros_action_recorder.cc",
-      "app_list/search/cros_action_history/cros_action_recorder.h",
-      "app_list/search/cros_action_history/cros_action_recorder_tab_tracker.cc",
-      "app_list/search/cros_action_history/cros_action_recorder_tab_tracker.h",
-      "app_list/search/files/drive_file_suggestion_provider.cc",
-      "app_list/search/files/drive_file_suggestion_provider.h",
-      "app_list/search/files/drive_search_provider.cc",
-      "app_list/search/files/drive_search_provider.h",
-      "app_list/search/files/file_result.cc",
-      "app_list/search/files/file_result.h",
-      "app_list/search/files/file_search_provider.cc",
-      "app_list/search/files/file_search_provider.h",
-      "app_list/search/files/file_suggest_keyed_service.cc",
-      "app_list/search/files/file_suggest_keyed_service.h",
-      "app_list/search/files/file_suggest_keyed_service_factory.cc",
-      "app_list/search/files/file_suggest_keyed_service_factory.h",
-      "app_list/search/files/file_suggest_util.cc",
-      "app_list/search/files/file_suggest_util.h",
-      "app_list/search/files/file_suggestion_provider.cc",
-      "app_list/search/files/file_suggestion_provider.h",
-      "app_list/search/files/item_suggest_cache.cc",
-      "app_list/search/files/item_suggest_cache.h",
-      "app_list/search/files/justifications.cc",
-      "app_list/search/files/justifications.h",
-      "app_list/search/files/local_file_suggestion_provider.cc",
-      "app_list/search/files/local_file_suggestion_provider.h",
-      "app_list/search/files/zero_state_drive_provider.cc",
-      "app_list/search/files/zero_state_drive_provider.h",
-      "app_list/search/files/zero_state_file_provider.cc",
-      "app_list/search/files/zero_state_file_provider.h",
-      "app_list/search/games/game_provider.cc",
-      "app_list/search/games/game_provider.h",
-      "app_list/search/games/game_result.cc",
-      "app_list/search/games/game_result.h",
       "app_list/search/help_app_provider.cc",
       "app_list/search/help_app_provider.h",
       "app_list/search/help_app_zero_state_provider.cc",
@@ -2121,51 +2170,10 @@
       "app_list/search/keyboard_shortcut_provider.h",
       "app_list/search/keyboard_shortcut_result.cc",
       "app_list/search/keyboard_shortcut_result.h",
-      "app_list/search/omnibox/omnibox_answer_result.cc",
-      "app_list/search/omnibox/omnibox_answer_result.h",
-      "app_list/search/omnibox/omnibox_lacros_provider.cc",
-      "app_list/search/omnibox/omnibox_lacros_provider.h",
-      "app_list/search/omnibox/omnibox_provider.cc",
-      "app_list/search/omnibox/omnibox_provider.h",
-      "app_list/search/omnibox/omnibox_result.cc",
-      "app_list/search/omnibox/omnibox_result.h",
-      "app_list/search/omnibox/omnibox_util.cc",
-      "app_list/search/omnibox/omnibox_util.h",
-      "app_list/search/omnibox/open_tab_result.cc",
-      "app_list/search/omnibox/open_tab_result.h",
       "app_list/search/os_settings_provider.cc",
       "app_list/search/os_settings_provider.h",
       "app_list/search/personalization_provider.cc",
       "app_list/search/personalization_provider.h",
-      "app_list/search/ranking/answer_ranker.cc",
-      "app_list/search/ranking/answer_ranker.h",
-      "app_list/search/ranking/best_match_ranker.cc",
-      "app_list/search/ranking/best_match_ranker.h",
-      "app_list/search/ranking/constants.h",
-      "app_list/search/ranking/continue_ranker.cc",
-      "app_list/search/ranking/continue_ranker.h",
-      "app_list/search/ranking/filtering_ranker.cc",
-      "app_list/search/ranking/filtering_ranker.h",
-      "app_list/search/ranking/ftrl_ranker.cc",
-      "app_list/search/ranking/ftrl_ranker.h",
-      "app_list/search/ranking/launch_data.cc",
-      "app_list/search/ranking/launch_data.h",
-      "app_list/search/ranking/mrfu_ranker.cc",
-      "app_list/search/ranking/mrfu_ranker.h",
-      "app_list/search/ranking/query_highlighter.cc",
-      "app_list/search/ranking/query_highlighter.h",
-      "app_list/search/ranking/ranker.cc",
-      "app_list/search/ranking/ranker.h",
-      "app_list/search/ranking/ranker_manager.cc",
-      "app_list/search/ranking/ranker_manager.h",
-      "app_list/search/ranking/removed_results_ranker.cc",
-      "app_list/search/ranking/removed_results_ranker.h",
-      "app_list/search/ranking/score_normalizing_ranker.cc",
-      "app_list/search/ranking/score_normalizing_ranker.h",
-      "app_list/search/ranking/scoring.cc",
-      "app_list/search/ranking/scoring.h",
-      "app_list/search/ranking/util.cc",
-      "app_list/search/ranking/util.h",
       "app_list/search/search_controller.h",
       "app_list/search/search_controller_factory.cc",
       "app_list/search/search_controller_factory.h",
@@ -2183,13 +2191,6 @@
       "app_list/search/search_session_metrics_manager.h",
       "app_list/search/types.cc",
       "app_list/search/types.h",
-      "app_list/search/util/ftrl_optimizer.cc",
-      "app_list/search/util/ftrl_optimizer.h",
-      "app_list/search/util/mrfu_cache.cc",
-      "app_list/search/util/mrfu_cache.h",
-      "app_list/search/util/persistent_proto.h",
-      "app_list/search/util/score_normalizer.cc",
-      "app_list/search/util/score_normalizer.h",
       "ash/accessibility/accessibility_controller_client.cc",
       "ash/accessibility/accessibility_controller_client.h",
       "ash/ambient/ambient_client_impl.cc",
@@ -3130,6 +3131,9 @@
       "//build:chromeos_buildflags",
       "//chrome/app:generated_resources",
       "//chrome/browser/ash",
+      "//chrome/browser/ash/app_list/search/cros_action_history:cros_action_proto",
+      "//chrome/browser/ash/app_list/search/ranking:proto",
+      "//chrome/browser/ash/app_list/search/util:proto",
       "//chrome/browser/ash/crosapi",
       "//chrome/browser/ash/crostini:crostini_installer_types_mojom",
       "//chrome/browser/ash/login/oobe_quick_start",
@@ -3157,9 +3161,6 @@
       "//chrome/browser/resources:internet_detail_dialog_resources",
       "//chrome/browser/resources/chromeos:multidevice_setup_resources",
       "//chrome/browser/resources/chromeos/cloud_upload:resources",
-      "//chrome/browser/ui/app_list/search/cros_action_history:cros_action_proto",
-      "//chrome/browser/ui/app_list/search/ranking:proto",
-      "//chrome/browser/ui/app_list/search/util:proto",
       "//chrome/browser/ui/quick_answers",
       "//chrome/browser/ui/webui/ash/add_supervision:mojo_bindings",
       "//chrome/browser/ui/webui/ash/audio:mojo_bindings",
@@ -4216,6 +4217,8 @@
       "translate/translate_bubble_test_utils.h",
       "views/accessibility/caption_bubble_context_views.cc",
       "views/accessibility/caption_bubble_context_views.h",
+      "views/accessibility/caption_bubble_session_observer_views.cc",
+      "views/accessibility/caption_bubble_session_observer_views.h",
       "views/accessibility/caret_browsing_dialog_delegate.cc",
       "views/accessibility/caret_browsing_dialog_delegate.h",
       "views/accessibility/non_accessible_image_view.cc",
@@ -5259,6 +5262,7 @@
       "//components/content_settings/browser/ui",
       "//components/fullscreen_control",
       "//components/global_media_controls",
+      "//components/live_caption",
       "//components/live_caption:constants",
       "//components/media_message_center",
       "//components/page_info",
@@ -5959,12 +5963,12 @@
 
   if (is_chromeos_ash) {
     sources += [
-      "app_list/search/files/file_suggest_test_util.cc",
-      "app_list/search/files/file_suggest_test_util.h",
-      "app_list/search/files/mock_file_suggest_keyed_service.cc",
-      "app_list/search/files/mock_file_suggest_keyed_service.h",
-      "app_list/search/files/mock_file_suggest_keyed_service_observer.cc",
-      "app_list/search/files/mock_file_suggest_keyed_service_observer.h",
+      "../ash/app_list/search/files/file_suggest_test_util.cc",
+      "../ash/app_list/search/files/file_suggest_test_util.h",
+      "../ash/app_list/search/files/mock_file_suggest_keyed_service.cc",
+      "../ash/app_list/search/files/mock_file_suggest_keyed_service.h",
+      "../ash/app_list/search/files/mock_file_suggest_keyed_service_observer.cc",
+      "../ash/app_list/search/files/mock_file_suggest_keyed_service_observer.h",
       "ash/ash_test_util.cc",
       "ash/ash_test_util.h",
       "ash/shelf/chrome_shelf_controller_test_util.cc",
diff --git a/chrome/browser/ui/DEPS b/chrome/browser/ui/DEPS
index eabbb5c..70b6b66d 100644
--- a/chrome/browser/ui/DEPS
+++ b/chrome/browser/ui/DEPS
@@ -8,6 +8,7 @@
   "+components/country_codes",
   "+components/enterprise",
   "+components/infobars/android",
+  "+components/image_service",
   "+components/live_caption",
   "+components/omnibox",
   "+components/page_load_metrics/browser",
diff --git a/chrome/browser/ui/app_list/app_context_menu_unittest.cc b/chrome/browser/ui/app_list/app_context_menu_unittest.cc
index a63ef05f..7f06c74 100644
--- a/chrome/browser/ui/app_list/app_context_menu_unittest.cc
+++ b/chrome/browser/ui/app_list/app_context_menu_unittest.cc
@@ -27,6 +27,9 @@
 #include "chrome/browser/ash/app_list/app_service/app_service_context_menu.h"
 #include "chrome/browser/ash/app_list/arc/arc_app_list_prefs.h"
 #include "chrome/browser/ash/app_list/arc/arc_app_test.h"
+#include "chrome/browser/ash/app_list/internal_app/internal_app_metadata.h"
+#include "chrome/browser/ash/app_list/test/fake_app_list_model_updater.h"
+#include "chrome/browser/ash/app_list/test/test_app_list_controller_delegate.h"
 #include "chrome/browser/ash/crosapi/browser_util.h"
 #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
@@ -38,9 +41,6 @@
 #include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
 #include "chrome/browser/ui/app_list/app_list_test_util.h"
 #include "chrome/browser/ui/app_list/chrome_app_list_item.h"
-#include "chrome/browser/ui/app_list/internal_app/internal_app_metadata.h"
-#include "chrome/browser/ui/app_list/test/fake_app_list_model_updater.h"
-#include "chrome/browser/ui/app_list/test/test_app_list_controller_delegate.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/app_constants/constants.h"
@@ -288,8 +288,7 @@
     std::string error;
     return extensions::Extension::Create(
         path.DirName(), extensions::mojom::ManifestLocation::kInternal,
-        base::Value::AsDictionaryValue(manifest),
-        extensions::Extension::NO_FLAGS, app_id, &error);
+        manifest.GetDict(), extensions::Extension::NO_FLAGS, app_id, &error);
   }
 
   void TestExtensionApp(const std::string& app_id,
@@ -332,10 +331,10 @@
 
   scoped_refptr<extensions::Extension> MakeChromeApp() {
     std::string err;
-    base::DictionaryValue value;
-    value.SetStringKey("name", "Chrome App");
-    value.SetStringKey("version", "0.0");
-    value.SetStringPath("app.launch.web_url", "http://google.com");
+    base::Value::Dict value;
+    value.Set("name", "Chrome App");
+    value.Set("version", "0.0");
+    value.SetByDottedPath("app.launch.web_url", "http://google.com");
     scoped_refptr<extensions::Extension> app = extensions::Extension::Create(
         base::FilePath(), extensions::mojom::ManifestLocation::kInternal, value,
         extensions::Extension::WAS_INSTALLED_BY_DEFAULT,
diff --git a/chrome/browser/ui/app_list/app_list_client_impl.cc b/chrome/browser/ui/app_list/app_list_client_impl.cc
index 67520c11a..4c101d6 100644
--- a/chrome/browser/ui/app_list/app_list_client_impl.cc
+++ b/chrome/browser/ui/app_list/app_list_client_impl.cc
@@ -19,6 +19,8 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
 #include "base/strings/strcat.h"
+#include "chrome/browser/ash/app_list/search/cros_action_history/cros_action_recorder.h"
+#include "chrome/browser/ash/app_list/search/ranking/launch_data.h"
 #include "chrome/browser/ash/crosapi/browser_util.h"
 #include "chrome/browser/ash/crosapi/url_handler_ash.h"
 #include "chrome/browser/profiles/profile.h"
@@ -31,8 +33,6 @@
 #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h"
 #include "chrome/browser/ui/app_list/app_sync_ui_state_watcher.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
-#include "chrome/browser/ui/app_list/search/cros_action_history/cros_action_recorder.h"
-#include "chrome/browser/ui/app_list/search/ranking/launch_data.h"
 #include "chrome/browser/ui/app_list/search/search_controller.h"
 #include "chrome/browser/ui/app_list/search/search_controller_factory.h"
 #include "chrome/browser/ui/ash/shelf/app_shortcut_shelf_item_controller.h"
diff --git a/chrome/browser/ui/app_list/app_list_client_impl_browsertest.cc b/chrome/browser/ui/app_list/app_list_client_impl_browsertest.cc
index 7f862a3..3a04e44 100644
--- a/chrome/browser/ui/app_list/app_list_client_impl_browsertest.cc
+++ b/chrome/browser/ui/app_list/app_list_client_impl_browsertest.cc
@@ -27,6 +27,7 @@
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "chrome/browser/apps/app_service/launch_utils.h"
 #include "chrome/browser/apps/platform_apps/app_browsertest_util.h"
+#include "chrome/browser/ash/app_list/test/chrome_app_list_test_support.h"
 #include "chrome/browser/ash/login/demo_mode/demo_session.h"
 #include "chrome/browser/ash/login/login_manager_test.h"
 #include "chrome/browser/ash/login/test/login_manager_mixin.h"
@@ -46,7 +47,6 @@
 #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h"
 #include "chrome/browser/ui/app_list/chrome_app_list_item.h"
 #include "chrome/browser/ui/app_list/search/search_controller.h"
-#include "chrome/browser/ui/app_list/test/chrome_app_list_test_support.h"
 #include "chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
diff --git a/chrome/browser/ui/app_list/app_list_sort_browsertest.cc b/chrome/browser/ui/app_list/app_list_sort_browsertest.cc
index fb0da7b8..0f0d2b28 100644
--- a/chrome/browser/ui/app_list/app_list_sort_browsertest.cc
+++ b/chrome/browser/ui/app_list/app_list_sort_browsertest.cc
@@ -18,6 +18,7 @@
 #include "base/run_loop.h"
 #include "base/strings/safe_sprintf.h"
 #include "base/test/metrics/histogram_tester.h"
+#include "chrome/browser/ash/app_list/test/chrome_app_list_test_support.h"
 #include "chrome/browser/ash/login/login_manager_test.h"
 #include "chrome/browser/ash/login/test/login_manager_mixin.h"
 #include "chrome/browser/ash/login/ui/user_adding_screen.h"
@@ -25,7 +26,6 @@
 #include "chrome/browser/ui/app_list/app_list_client_impl.h"
 #include "chrome/browser/ui/app_list/app_list_model_updater.h"
 #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h"
-#include "chrome/browser/ui/app_list/test/chrome_app_list_test_support.h"
 #include "chrome/common/pref_names.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/test/browser_test.h"
diff --git a/chrome/browser/ui/app_list/app_list_sort_unittest.cc b/chrome/browser/ui/app_list/app_list_sort_unittest.cc
index f33bfbd..caa0f4f5 100644
--- a/chrome/browser/ui/app_list/app_list_sort_unittest.cc
+++ b/chrome/browser/ui/app_list/app_list_sort_unittest.cc
@@ -7,12 +7,12 @@
 #include "ash/app_list/model/app_list_model.h"
 #include "ash/constants/ash_features.h"
 #include "base/containers/cxx20_erase_vector.h"
+#include "chrome/browser/ash/app_list/test/app_list_syncable_service_test_base.h"
+#include "chrome/browser/ash/app_list/test/test_app_list_controller.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/app_list_model_updater.h"
 #include "chrome/browser/ui/app_list/app_list_test_util.h"
 #include "chrome/browser/ui/app_list/chrome_app_list_model_updater.h"
-#include "chrome/browser/ui/app_list/test/app_list_syncable_service_test_base.h"
-#include "chrome/browser/ui/app_list/test/test_app_list_controller.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/crx_file/id_util.h"
diff --git a/chrome/browser/ui/app_list/app_list_syncable_service.cc b/chrome/browser/ui/app_list/app_list_syncable_service.cc
index d7cd4aa3..1113ffa7 100644
--- a/chrome/browser/ui/app_list/app_list_syncable_service.cc
+++ b/chrome/browser/ui/app_list/app_list_syncable_service.cc
@@ -26,6 +26,8 @@
 #include "chrome/browser/ash/app_list/app_service/app_service_app_model_builder.h"
 #include "chrome/browser/ash/app_list/arc/arc_app_list_prefs.h"
 #include "chrome/browser/ash/app_list/arc/arc_app_utils.h"
+#include "chrome/browser/ash/app_list/reorder/app_list_reorder_core.h"
+#include "chrome/browser/ash/app_list/reorder/app_list_reorder_util.h"
 #include "chrome/browser/ash/arc/arc_util.h"
 #include "chrome/browser/ash/crostini/crostini_features.h"
 #include "chrome/browser/ash/crostini/crostini_util.h"
@@ -39,8 +41,6 @@
 #include "chrome/browser/ui/app_list/app_list_util.h"
 #include "chrome/browser/ui/app_list/chrome_app_list_item.h"
 #include "chrome/browser/ui/app_list/chrome_app_list_model_updater.h"
-#include "chrome/browser/ui/app_list/reorder/app_list_reorder_core.h"
-#include "chrome/browser/ui/app_list/reorder/app_list_reorder_util.h"
 #include "chrome/browser/web_applications/web_app_id_constants.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/extension_constants.h"
diff --git a/chrome/browser/ui/app_list/app_list_syncable_service.h b/chrome/browser/ui/app_list/app_list_syncable_service.h
index f553964..6da0b86 100644
--- a/chrome/browser/ui/app_list/app_list_syncable_service.h
+++ b/chrome/browser/ui/app_list/app_list_syncable_service.h
@@ -21,8 +21,8 @@
 #include "base/one_shot_event.h"
 #include "base/scoped_observation_traits.h"
 #include "build/build_config.h"
+#include "chrome/browser/ash/app_list/reorder/app_list_reorder_delegate.h"
 #include "chrome/browser/sync/glue/sync_start_util.h"
-#include "chrome/browser/ui/app_list/reorder/app_list_reorder_delegate.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/sync/model/string_ordinal.h"
 #include "components/sync/model/sync_change.h"
diff --git a/chrome/browser/ui/app_list/app_list_syncable_service_factory.cc b/chrome/browser/ui/app_list/app_list_syncable_service_factory.cc
index 61e997f..d4cce6d8 100644
--- a/chrome/browser/ui/app_list/app_list_syncable_service_factory.cc
+++ b/chrome/browser/ui/app_list/app_list_syncable_service_factory.cc
@@ -9,9 +9,9 @@
 #include "build/build_config.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "chrome/browser/ash/app_list/arc/arc_app_list_prefs_factory.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_keyed_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/app_list_syncable_service.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_factory.h"
 #include "components/prefs/pref_service.h"
 #include "extensions/browser/extension_system_provider.h"
 #include "extensions/browser/extensions_browser_client.h"
diff --git a/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc b/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc
index fcecba0..a982aeb 100644
--- a/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc
+++ b/chrome/browser/ui/app_list/app_list_syncable_service_unittest.cc
@@ -20,6 +20,9 @@
 #include "cc/base/math_util.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
+#include "chrome/browser/ash/app_list/reorder/app_list_reorder_core.h"
+#include "chrome/browser/ash/app_list/test/app_list_syncable_service_test_base.h"
+#include "chrome/browser/ash/app_list/test/fake_app_list_model_updater.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/app_list/app_list_client_impl.h"
@@ -27,9 +30,6 @@
 #include "chrome/browser/ui/app_list/app_list_test_util.h"
 #include "chrome/browser/ui/app_list/chrome_app_list_item.h"
 #include "chrome/browser/ui/app_list/chrome_app_list_model_updater.h"
-#include "chrome/browser/ui/app_list/reorder/app_list_reorder_core.h"
-#include "chrome/browser/ui/app_list/test/app_list_syncable_service_test_base.h"
-#include "chrome/browser/ui/app_list/test/fake_app_list_model_updater.h"
 #include "chrome/browser/ui/settings_window_manager_chromeos.h"
 #include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
 #include "chrome/browser/web_applications/web_app_id_constants.h"
diff --git a/chrome/browser/ui/app_list/app_list_test_util.cc b/chrome/browser/ui/app_list/app_list_test_util.cc
index 7c929ab8..517be4e 100644
--- a/chrome/browser/ui/app_list/app_list_test_util.cc
+++ b/chrome/browser/ui/app_list/app_list_test_util.cc
@@ -90,10 +90,10 @@
     const std::string& id,
     extensions::Extension::InitFromValueFlags flags) {
   std::string err;
-  base::DictionaryValue value;
-  value.SetStringKey("name", name);
-  value.SetStringKey("version", "0.0");
-  value.SetStringPath("app.launch.web_url", "http://google.com");
+  base::Value::Dict value;
+  value.Set("name", name);
+  value.Set("version", "0.0");
+  value.SetByDottedPath("app.launch.web_url", "http://google.com");
   scoped_refptr<extensions::Extension> app = extensions::Extension::Create(
       base::FilePath(), extensions::mojom::ManifestLocation::kInternal, value,
       flags, id, &err);
diff --git a/chrome/browser/ui/app_list/chrome_app_list_item.cc b/chrome/browser/ui/app_list/chrome_app_list_item.cc
index 8fe333f6..a8ffebb 100644
--- a/chrome/browser/ui/app_list/chrome_app_list_item.cc
+++ b/chrome/browser/ui/app_list/chrome_app_list_item.cc
@@ -9,11 +9,11 @@
 #include "ash/public/cpp/tablet_mode.h"
 #include "base/notreached.h"
 #include "build/chromeos_buildflags.h"
+#include "chrome/browser/ash/app_list/reorder/app_list_reorder_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/app_list_client_impl.h"
 #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h"
 #include "chrome/browser/ui/app_list/chrome_app_list_model_updater.h"
-#include "chrome/browser/ui/app_list/reorder/app_list_reorder_util.h"
 #include "chrome/browser/ui/ash/app_icon_color_cache.h"
 #include "extensions/browser/app_sorting.h"
 #include "extensions/browser/extension_system.h"
diff --git a/chrome/browser/ui/app_list/chrome_app_list_item_browsertest.cc b/chrome/browser/ui/app_list/chrome_app_list_item_browsertest.cc
index 2d256ba..0c899ae 100644
--- a/chrome/browser/ui/app_list/chrome_app_list_item_browsertest.cc
+++ b/chrome/browser/ui/app_list/chrome_app_list_item_browsertest.cc
@@ -10,10 +10,10 @@
 #include "ash/public/cpp/accelerators.h"
 #include "ash/public/cpp/test/app_list_test_api.h"
 #include "base/strings/stringprintf.h"
+#include "chrome/browser/ash/app_list/test/chrome_app_list_test_support.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/app_list/app_list_client_impl.h"
 #include "chrome/browser/ui/app_list/app_list_model_updater.h"
-#include "chrome/browser/ui/app_list/test/chrome_app_list_test_support.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "content/public/test/browser_test.h"
 #include "ui/gfx/image/image_skia.h"
diff --git a/chrome/browser/ui/app_list/chrome_app_list_item_manager_unittest.cc b/chrome/browser/ui/app_list/chrome_app_list_item_manager_unittest.cc
index f0b50b4..a15d038 100644
--- a/chrome/browser/ui/app_list/chrome_app_list_item_manager_unittest.cc
+++ b/chrome/browser/ui/app_list/chrome_app_list_item_manager_unittest.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/browser/ui/app_list/chrome_app_list_item_manager.h"
 
-#include "chrome/browser/ui/app_list/test/fake_app_list_model_updater.h"
+#include "chrome/browser/ash/app_list/test/fake_app_list_model_updater.h"
 #include "components/crx_file/id_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc b/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc
index d1f6f6f1..41cdaad 100644
--- a/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc
+++ b/chrome/browser/ui/app_list/chrome_app_list_model_updater.cc
@@ -17,12 +17,12 @@
 #include "ash/public/cpp/tablet_mode.h"
 #include "base/bind.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/ash/app_list/reorder/app_list_reorder_core.h"
+#include "chrome/browser/ash/app_list/reorder/app_list_reorder_delegate.h"
 #include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
 #include "chrome/browser/ui/app_list/app_list_sync_model_sanitizer.h"
 #include "chrome/browser/ui/app_list/chrome_app_list_item.h"
 #include "chrome/browser/ui/app_list/chrome_app_list_item_manager.h"
-#include "chrome/browser/ui/app_list/reorder/app_list_reorder_core.h"
-#include "chrome/browser/ui/app_list/reorder/app_list_reorder_delegate.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
 #include "extensions/common/constants.h"
 #include "ui/base/models/menu_model.h"
diff --git a/chrome/browser/ui/app_list/chrome_app_list_model_updater_browsertest.cc b/chrome/browser/ui/app_list/chrome_app_list_model_updater_browsertest.cc
index c82c724..751eb6e 100644
--- a/chrome/browser/ui/app_list/chrome_app_list_model_updater_browsertest.cc
+++ b/chrome/browser/ui/app_list/chrome_app_list_model_updater_browsertest.cc
@@ -16,6 +16,7 @@
 #include "base/run_loop.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
+#include "chrome/browser/ash/app_list/test/chrome_app_list_test_support.h"
 #include "chrome/browser/ash/login/login_manager_test.h"
 #include "chrome/browser/ash/login/test/login_manager_mixin.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
@@ -26,7 +27,6 @@
 #include "chrome/browser/ui/app_list/app_list_model_updater.h"
 #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h"
 #include "chrome/browser/ui/app_list/chrome_app_list_item.h"
-#include "chrome/browser/ui/app_list/test/chrome_app_list_test_support.h"
 #include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
 #include "chrome/browser/web_applications/web_app_id_constants.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
diff --git a/chrome/browser/ui/app_list/search/DEPS b/chrome/browser/ui/app_list/search/DEPS
index 98c13e7..b9d912a 100644
--- a/chrome/browser/ui/app_list/search/DEPS
+++ b/chrome/browser/ui/app_list/search/DEPS
@@ -1,3 +1,6 @@
+# TODO(https://crbug.com/1164001): When this file is edited, same file in
+# //chrome/browser/ash/app_list/search should be updated as well. We need
+# to sync both files until the migration is done.
 include_rules = [
   "+ash/accelerators",
   "+ash/assistant/model",
diff --git a/chrome/browser/ui/app_list/search/OWNERS b/chrome/browser/ui/app_list/search/OWNERS
index eb3513f..054371b6 100644
--- a/chrome/browser/ui/app_list/search/OWNERS
+++ b/chrome/browser/ui/app_list/search/OWNERS
@@ -1,5 +1 @@
-amandadeacon@chromium.org
-chenjih@google.com
-tby@chromium.org
-thanhdng@chromium.org
-wrong@chromium.org
+file://chrome/browser/ash/app_list/search/OWNERS
diff --git a/chrome/browser/ui/app_list/search/app_search_provider_test_base.cc b/chrome/browser/ui/app_list/search/app_search_provider_test_base.cc
index e8f4024e..c7a88233 100644
--- a/chrome/browser/ui/app_list/search/app_search_provider_test_base.cc
+++ b/chrome/browser/ui/app_list/search/app_search_provider_test_base.cc
@@ -21,14 +21,14 @@
 #include "chrome/browser/ash/app_list/arc/arc_app_list_prefs.h"
 #include "chrome/browser/ash/app_list/arc/arc_app_test.h"
 #include "chrome/browser/ash/app_list/arc/arc_default_app_list.h"
+#include "chrome/browser/ash/app_list/search/test/test_search_controller.h"
+#include "chrome/browser/ash/app_list/test/fake_app_list_model_updater.h"
+#include "chrome/browser/ash/app_list/test/test_app_list_controller_delegate.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/ui/app_list/search/app_search_data_source.h"
 #include "chrome/browser/ui/app_list/search/app_search_provider.h"
 #include "chrome/browser/ui/app_list/search/app_zero_state_provider.h"
 #include "chrome/browser/ui/app_list/search/search_provider.h"
-#include "chrome/browser/ui/app_list/search/test/test_search_controller.h"
-#include "chrome/browser/ui/app_list/test/fake_app_list_model_updater.h"
-#include "chrome/browser/ui/app_list/test/test_app_list_controller_delegate.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/sync/model/string_ordinal.h"
 #include "extensions/browser/extension_prefs.h"
diff --git a/chrome/browser/ui/app_list/search/app_service_app_result.cc b/chrome/browser/ui/app_list/search/app_service_app_result.cc
index 4028d00..ac5ccc8 100644
--- a/chrome/browser/ui/app_list/search/app_service_app_result.cc
+++ b/chrome/browser/ui/app_list/search/app_service_app_result.cc
@@ -15,11 +15,11 @@
 #include "chrome/browser/apps/app_service/launch_utils.h"
 #include "chrome/browser/apps/app_service/metrics/app_service_metrics.h"
 #include "chrome/browser/ash/app_list/app_service/app_service_context_menu.h"
+#include "chrome/browser/ash/app_list/internal_app/internal_app_metadata.h"
+#include "chrome/browser/ash/app_list/search/common/icon_constants.h"
 #include "chrome/browser/favicon/large_icon_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/app_list_client_impl.h"
-#include "chrome/browser/ui/app_list/internal_app/internal_app_metadata.h"
-#include "chrome/browser/ui/app_list/search/common/icon_constants.h"
 #include "chrome/browser/ui/ash/shelf/chrome_shelf_controller.h"
 #include "components/favicon/core/large_icon_service.h"
 #include "components/services/app_service/public/cpp/app_launch_util.h"
diff --git a/chrome/browser/ui/app_list/search/assistant_text_search_provider.cc b/chrome/browser/ui/app_list/search/assistant_text_search_provider.cc
index c364d06..0195348 100644
--- a/chrome/browser/ui/app_list/search/assistant_text_search_provider.cc
+++ b/chrome/browser/ui/app_list/search/assistant_text_search_provider.cc
@@ -15,8 +15,8 @@
 #include "ash/public/cpp/assistant/controller/assistant_suggestions_controller.h"
 #include "ash/strings/grit/ash_strings.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/ash/app_list/search/common/icon_constants.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
-#include "chrome/browser/ui/app_list/search/common/icon_constants.h"
 #include "chromeos/ash/services/assistant/public/cpp/assistant_service.h"
 #include "chromeos/ui/vector_icons/vector_icons.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/ui/app_list/search/assistant_text_search_provider_unittest.cc b/chrome/browser/ui/app_list/search/assistant_text_search_provider_unittest.cc
index 407818a4..d1bbdd4 100644
--- a/chrome/browser/ui/app_list/search/assistant_text_search_provider_unittest.cc
+++ b/chrome/browser/ui/app_list/search/assistant_text_search_provider_unittest.cc
@@ -11,9 +11,9 @@
 #include "ash/public/cpp/assistant/test_support/mock_assistant_state.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_feature_list.h"
+#include "chrome/browser/ash/app_list/search/test/test_search_controller.h"
 #include "chrome/browser/ui/app_list/app_list_test_util.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
-#include "chrome/browser/ui/app_list/search/test/test_search_controller.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "url/gurl.h"
 
diff --git a/chrome/browser/ui/app_list/search/help_app_provider.cc b/chrome/browser/ui/app_list/search/help_app_provider.cc
index b8c5fca..d7be18f 100644
--- a/chrome/browser/ui/app_list/search/help_app_provider.cc
+++ b/chrome/browser/ui/app_list/search/help_app_provider.cc
@@ -16,8 +16,8 @@
 #include "base/time/time.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
+#include "chrome/browser/ash/app_list/search/common/icon_constants.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/app_list/search/common/icon_constants.h"
 #include "chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.h"
 #include "chrome/browser/web_applications/web_app_id_constants.h"
 #include "components/services/app_service/public/cpp/app_launch_util.h"
diff --git a/chrome/browser/ui/app_list/search/help_app_provider_unittest.cc b/chrome/browser/ui/app_list/search/help_app_provider_unittest.cc
index d072a841e..833f6d8 100644
--- a/chrome/browser/ui/app_list/search/help_app_provider_unittest.cc
+++ b/chrome/browser/ui/app_list/search/help_app_provider_unittest.cc
@@ -13,10 +13,10 @@
 #include "base/test/scoped_feature_list.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
+#include "chrome/browser/ash/app_list/search/common/icon_constants.h"
+#include "chrome/browser/ash/app_list/search/test/test_search_controller.h"
 #include "chrome/browser/ui/app_list/app_list_test_util.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
-#include "chrome/browser/ui/app_list/search/common/icon_constants.h"
-#include "chrome/browser/ui/app_list/search/test/test_search_controller.h"
 #include "chrome/browser/web_applications/web_app_id_constants.h"
 #include "components/services/app_service/public/cpp/stub_icon_loader.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ui/app_list/search/help_app_search_browsertest.cc b/chrome/browser/ui/app_list/search/help_app_search_browsertest.cc
index 4d44aa5..9eb1a49 100644
--- a/chrome/browser/ui/app_list/search/help_app_search_browsertest.cc
+++ b/chrome/browser/ui/app_list/search/help_app_search_browsertest.cc
@@ -13,10 +13,10 @@
 #include "chrome/browser/apps/app_service/app_launch_params.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
+#include "chrome/browser/ash/app_list/search/test/app_list_search_test_helper.h"
+#include "chrome/browser/ash/app_list/search/test/search_results_changed_waiter.h"
+#include "chrome/browser/ash/app_list/search/test/test_continue_files_search_provider.h"
 #include "chrome/browser/ash/system_web_apps/system_web_app_manager.h"
-#include "chrome/browser/ui/app_list/search/test/app_list_search_test_helper.h"
-#include "chrome/browser/ui/app_list/search/test/search_results_changed_waiter.h"
-#include "chrome/browser/ui/app_list/search/test/test_continue_files_search_provider.h"
 #include "chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
diff --git a/chrome/browser/ui/app_list/search/help_app_zero_state_provider.cc b/chrome/browser/ui/app_list/search/help_app_zero_state_provider.cc
index 8de2760d..81391d5 100644
--- a/chrome/browser/ui/app_list/search/help_app_zero_state_provider.cc
+++ b/chrome/browser/ui/app_list/search/help_app_zero_state_provider.cc
@@ -12,9 +12,9 @@
 #include "base/metrics/user_metrics.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
+#include "chrome/browser/ash/app_list/search/common/icon_constants.h"
 #include "chrome/browser/ash/release_notes/release_notes_storage.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/app_list/search/common/icon_constants.h"
 #include "chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.h"
 #include "chrome/browser/web_applications/web_app_id_constants.h"
 #include "chrome/common/pref_names.h"
diff --git a/chrome/browser/ui/app_list/search/help_app_zero_state_provider_unittest.cc b/chrome/browser/ui/app_list/search/help_app_zero_state_provider_unittest.cc
index acd838c..3870604 100644
--- a/chrome/browser/ui/app_list/search/help_app_zero_state_provider_unittest.cc
+++ b/chrome/browser/ui/app_list/search/help_app_zero_state_provider_unittest.cc
@@ -11,11 +11,11 @@
 #include "ash/public/cpp/app_list/app_list_types.h"
 #include "base/feature_list.h"
 #include "base/test/scoped_feature_list.h"
+#include "chrome/browser/ash/app_list/search/test/test_search_controller.h"
+#include "chrome/browser/ash/app_list/test/test_app_list_controller.h"
 #include "chrome/browser/ui/app_list/app_list_notifier_impl.h"
 #include "chrome/browser/ui/app_list/app_list_test_util.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
-#include "chrome/browser/ui/app_list/search/test/test_search_controller.h"
-#include "chrome/browser/ui/app_list/test/test_app_list_controller.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/strings/grit/chromeos_strings.h"
diff --git a/chrome/browser/ui/app_list/search/keyboard_shortcut_provider_unittest.cc b/chrome/browser/ui/app_list/search/keyboard_shortcut_provider_unittest.cc
index 916dec61..63213e56 100644
--- a/chrome/browser/ui/app_list/search/keyboard_shortcut_provider_unittest.cc
+++ b/chrome/browser/ui/app_list/search/keyboard_shortcut_provider_unittest.cc
@@ -5,8 +5,8 @@
 #include "chrome/browser/ui/app_list/search/keyboard_shortcut_provider.h"
 
 #include "base/test/scoped_feature_list.h"
+#include "chrome/browser/ash/app_list/search/test/test_search_controller.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
-#include "chrome/browser/ui/app_list/search/test/test_search_controller.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/browser/ui/app_list/search/keyboard_shortcut_result.cc b/chrome/browser/ui/app_list/search/keyboard_shortcut_result.cc
index c4f1dcd..9fb0708 100644
--- a/chrome/browser/ui/app_list/search/keyboard_shortcut_result.cc
+++ b/chrome/browser/ui/app_list/search/keyboard_shortcut_result.cc
@@ -16,8 +16,8 @@
 #include "base/strings/string_split.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
-#include "chrome/browser/ui/app_list/search/common/icon_constants.h"
-#include "chrome/browser/ui/app_list/search/common/search_result_util.h"
+#include "chrome/browser/ash/app_list/search/common/icon_constants.h"
+#include "chrome/browser/ash/app_list/search/common/search_result_util.h"
 #include "chrome/grit/generated_resources.h"
 #include "chromeos/ash/components/string_matching/tokenized_string.h"
 #include "chromeos/ash/components/string_matching/tokenized_string_match.h"
diff --git a/chrome/browser/ui/app_list/search/os_settings_provider.cc b/chrome/browser/ui/app_list/search/os_settings_provider.cc
index 502e920..f278286 100644
--- a/chrome/browser/ui/app_list/search/os_settings_provider.cc
+++ b/chrome/browser/ui/app_list/search/os_settings_provider.cc
@@ -12,8 +12,8 @@
 #include "base/containers/flat_set.h"
 #include "base/metrics/histogram_macros.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
+#include "chrome/browser/ash/app_list/search/common/icon_constants.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/app_list/search/common/icon_constants.h"
 #include "chrome/browser/ui/settings_window_manager_chromeos.h"
 #include "chrome/browser/ui/webui/settings/ash/hierarchy.h"
 #include "chrome/browser/ui/webui/settings/ash/search/search_handler.h"
diff --git a/chrome/browser/ui/app_list/search/os_settings_provider_unittest.cc b/chrome/browser/ui/app_list/search/os_settings_provider_unittest.cc
index 477c1fe..073a4ca 100644
--- a/chrome/browser/ui/app_list/search/os_settings_provider_unittest.cc
+++ b/chrome/browser/ui/app_list/search/os_settings_provider_unittest.cc
@@ -7,7 +7,7 @@
 #include <memory>
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
-#include "chrome/browser/ui/app_list/search/test/test_search_controller.h"
+#include "chrome/browser/ash/app_list/search/test/test_search_controller.h"
 #include "chrome/browser/ui/webui/settings/ash/fake_hierarchy.h"
 #include "chrome/browser/ui/webui/settings/ash/fake_os_settings_sections.h"
 #include "chrome/browser/ui/webui/settings/ash/search/search_handler.h"
diff --git a/chrome/browser/ui/app_list/search/personalization_provider.cc b/chrome/browser/ui/app_list/search/personalization_provider.cc
index 2898bad..9854fdcb 100644
--- a/chrome/browser/ui/app_list/search/personalization_provider.cc
+++ b/chrome/browser/ui/app_list/search/personalization_provider.cc
@@ -18,9 +18,9 @@
 #include "base/metrics/histogram_functions.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
+#include "chrome/browser/ash/app_list/search/common/icon_constants.h"
 #include "chrome/browser/ash/web_applications/personalization_app/personalization_app_metrics.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/app_list/search/common/icon_constants.h"
 #include "chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.h"
 #include "chrome/browser/web_applications/web_app_id_constants.h"
 #include "components/services/app_service/public/cpp/app_registry_cache.h"
diff --git a/chrome/browser/ui/app_list/search/personalization_provider_unittest.cc b/chrome/browser/ui/app_list/search/personalization_provider_unittest.cc
index a8cccf3e..c0dbe3e 100644
--- a/chrome/browser/ui/app_list/search/personalization_provider_unittest.cc
+++ b/chrome/browser/ui/app_list/search/personalization_provider_unittest.cc
@@ -9,8 +9,8 @@
 #include "ash/webui/personalization_app/search/search_handler.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
-#include "chrome/browser/ui/app_list/search/common/icon_constants.h"
-#include "chrome/browser/ui/app_list/search/test/test_search_controller.h"
+#include "chrome/browser/ash/app_list/search/common/icon_constants.h"
+#include "chrome/browser/ash/app_list/search/test/test_search_controller.h"
 #include "chrome/browser/web_applications/web_app_id_constants.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
diff --git a/chrome/browser/ui/app_list/search/search_controller.h b/chrome/browser/ui/app_list/search/search_controller.h
index a298dd5..60147ce 100644
--- a/chrome/browser/ui/app_list/search/search_controller.h
+++ b/chrome/browser/ui/app_list/search/search_controller.h
@@ -15,7 +15,7 @@
 #include "base/containers/flat_map.h"
 #include "base/observer_list_types.h"
 #include "base/time/time.h"
-#include "chrome/browser/ui/app_list/search/ranking/launch_data.h"
+#include "chrome/browser/ash/app_list/search/ranking/launch_data.h"
 #include "chrome/browser/ui/app_list/search/types.h"
 
 class ChromeSearchResult;
diff --git a/chrome/browser/ui/app_list/search/search_controller_factory.cc b/chrome/browser/ui/app_list/search/search_controller_factory.cc
index 94b24c8..f40f0ec 100644
--- a/chrome/browser/ui/app_list/search/search_controller_factory.cc
+++ b/chrome/browser/ui/app_list/search/search_controller_factory.cc
@@ -13,6 +13,15 @@
 #include "base/metrics/field_trial_params.h"
 #include "build/build_config.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
+#include "chrome/browser/ash/app_list/search/arc/arc_app_shortcuts_search_provider.h"
+#include "chrome/browser/ash/app_list/search/arc/arc_playstore_search_provider.h"
+#include "chrome/browser/ash/app_list/search/files/drive_search_provider.h"
+#include "chrome/browser/ash/app_list/search/files/file_search_provider.h"
+#include "chrome/browser/ash/app_list/search/files/zero_state_drive_provider.h"
+#include "chrome/browser/ash/app_list/search/files/zero_state_file_provider.h"
+#include "chrome/browser/ash/app_list/search/games/game_provider.h"
+#include "chrome/browser/ash/app_list/search/omnibox/omnibox_lacros_provider.h"
+#include "chrome/browser/ash/app_list/search/omnibox/omnibox_provider.h"
 #include "chrome/browser/ash/arc/arc_util.h"
 #include "chrome/browser/ash/crosapi/browser_util.h"
 #include "chrome/browser/ash/crosapi/crosapi_manager.h"
@@ -23,19 +32,10 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/search/app_search_provider.h"
 #include "chrome/browser/ui/app_list/search/app_zero_state_provider.h"
-#include "chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.h"
-#include "chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider.h"
 #include "chrome/browser/ui/app_list/search/assistant_text_search_provider.h"
-#include "chrome/browser/ui/app_list/search/files/drive_search_provider.h"
-#include "chrome/browser/ui/app_list/search/files/file_search_provider.h"
-#include "chrome/browser/ui/app_list/search/files/zero_state_drive_provider.h"
-#include "chrome/browser/ui/app_list/search/files/zero_state_file_provider.h"
-#include "chrome/browser/ui/app_list/search/games/game_provider.h"
 #include "chrome/browser/ui/app_list/search/help_app_provider.h"
 #include "chrome/browser/ui/app_list/search/help_app_zero_state_provider.h"
 #include "chrome/browser/ui/app_list/search/keyboard_shortcut_provider.h"
-#include "chrome/browser/ui/app_list/search/omnibox/omnibox_lacros_provider.h"
-#include "chrome/browser/ui/app_list/search/omnibox/omnibox_provider.h"
 #include "chrome/browser/ui/app_list/search/os_settings_provider.h"
 #include "chrome/browser/ui/app_list/search/personalization_provider.h"
 #include "chrome/browser/ui/app_list/search/search_controller.h"
diff --git a/chrome/browser/ui/app_list/search/search_controller_impl.cc b/chrome/browser/ui/app_list/search/search_controller_impl.cc
index ba3ac25..40ded5d5 100644
--- a/chrome/browser/ui/app_list/search/search_controller_impl.cc
+++ b/chrome/browser/ui/app_list/search/search_controller_impl.cc
@@ -16,15 +16,15 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/default_clock.h"
 #include "base/time/time.h"
+#include "chrome/browser/ash/app_list/search/common/string_util.h"
+#include "chrome/browser/ash/app_list/search/cros_action_history/cros_action_recorder.h"
+#include "chrome/browser/ash/app_list/search/ranking/ranker_manager.h"
+#include "chrome/browser/ash/app_list/search/ranking/scoring.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
 #include "chrome/browser/ui/app_list/app_list_model_updater.h"
 #include "chrome/browser/ui/app_list/search/app_search_data_source.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
-#include "chrome/browser/ui/app_list/search/common/string_util.h"
-#include "chrome/browser/ui/app_list/search/cros_action_history/cros_action_recorder.h"
-#include "chrome/browser/ui/app_list/search/ranking/ranker_manager.h"
-#include "chrome/browser/ui/app_list/search/ranking/scoring.h"
 #include "chrome/browser/ui/app_list/search/search_metrics_manager.h"
 #include "chrome/browser/ui/app_list/search/search_provider.h"
 #include "chrome/browser/ui/app_list/search/search_session_metrics_manager.h"
diff --git a/chrome/browser/ui/app_list/search/search_controller_impl.h b/chrome/browser/ui/app_list/search/search_controller_impl.h
index 363511f..b35ef5b 100644
--- a/chrome/browser/ui/app_list/search/search_controller_impl.h
+++ b/chrome/browser/ui/app_list/search/search_controller_impl.h
@@ -16,9 +16,9 @@
 #include "base/observer_list.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
+#include "chrome/browser/ash/app_list/search/ranking/launch_data.h"
+#include "chrome/browser/ash/app_list/search/ranking/ranker_manager.h"
 #include "chrome/browser/ui/app_list/search/burnin_controller.h"
-#include "chrome/browser/ui/app_list/search/ranking/launch_data.h"
-#include "chrome/browser/ui/app_list/search/ranking/ranker_manager.h"
 #include "chrome/browser/ui/app_list/search/search_controller.h"
 
 class AppListControllerDelegate;
diff --git a/chrome/browser/ui/app_list/search/search_controller_impl_unittest.cc b/chrome/browser/ui/app_list/search/search_controller_impl_unittest.cc
index b5650e5..eead637 100644
--- a/chrome/browser/ui/app_list/search/search_controller_impl_unittest.cc
+++ b/chrome/browser/ui/app_list/search/search_controller_impl_unittest.cc
@@ -10,16 +10,16 @@
 #include "ash/public/cpp/app_list/app_list_types.h"
 #include "base/test/bind.h"
 #include "base/time/time.h"
+#include "chrome/browser/ash/app_list/search/ranking/launch_data.h"
+#include "chrome/browser/ash/app_list/search/ranking/ranker_manager.h"
+#include "chrome/browser/ash/app_list/search/test/search_controller_test_util.h"
+#include "chrome/browser/ash/app_list/search/test/test_ranker_manager.h"
+#include "chrome/browser/ash/app_list/search/test/test_search_provider.h"
+#include "chrome/browser/ash/app_list/test/fake_app_list_model_updater.h"
+#include "chrome/browser/ash/app_list/test/test_app_list_controller_delegate.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
-#include "chrome/browser/ui/app_list/search/ranking/launch_data.h"
-#include "chrome/browser/ui/app_list/search/ranking/ranker_manager.h"
 #include "chrome/browser/ui/app_list/search/search_controller.h"
 #include "chrome/browser/ui/app_list/search/search_provider.h"
-#include "chrome/browser/ui/app_list/search/test/search_controller_test_util.h"
-#include "chrome/browser/ui/app_list/search/test/test_ranker_manager.h"
-#include "chrome/browser/ui/app_list/search/test/test_search_provider.h"
-#include "chrome/browser/ui/app_list/test/fake_app_list_model_updater.h"
-#include "chrome/browser/ui/app_list/test/test_app_list_controller_delegate.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/browser/ui/ash/app_list/apps_grid_drag_browsertest.cc b/chrome/browser/ui/ash/app_list/apps_grid_drag_browsertest.cc
index a257203..2614e06 100644
--- a/chrome/browser/ui/ash/app_list/apps_grid_drag_browsertest.cc
+++ b/chrome/browser/ui/ash/app_list/apps_grid_drag_browsertest.cc
@@ -8,7 +8,7 @@
 #include "ash/public/cpp/accelerators.h"
 #include "ash/public/cpp/test/app_list_test_api.h"
 #include "ash/root_window_controller.h"
-#include "chrome/browser/ui/app_list/test/chrome_app_list_test_support.h"
+#include "chrome/browser/ash/app_list/test/chrome_app_list_test_support.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/test/base/in_process_browser_test.h"
diff --git a/chrome/browser/ui/ash/cast_config_controller_media_router.cc b/chrome/browser/ui/ash/cast_config_controller_media_router.cc
index e502f890..179f5c0 100644
--- a/chrome/browser/ui/ash/cast_config_controller_media_router.cc
+++ b/chrome/browser/ui/ash/cast_config_controller_media_router.cc
@@ -8,9 +8,12 @@
 #include <utility>
 #include <vector>
 
+#include "ash/constants/ash_switches.h"
 #include "base/callback.h"
 #include "base/callback_helpers.h"
+#include "base/command_line.h"
 #include "base/feature_list.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
@@ -181,6 +184,10 @@
   observers_.RemoveObserver(observer);
 }
 
+bool CastConfigControllerMediaRouter::HasMediaRouterForPrimaryProfile() const {
+  return !!GetMediaRouter();
+}
+
 bool CastConfigControllerMediaRouter::HasSinksAndRoutes() const {
   return !devices_.empty();
 }
@@ -210,6 +217,14 @@
   // update those sinks with activity information.
   devices_.clear();
 
+#if !defined(OFFICIAL_BUILD)
+  // Optionally add fake cast devices for manual UI testing.
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          ash::switches::kQsAddFakeCastDevices)) {
+    AddFakeCastDevices();
+  }
+#endif
+
   for (const media_router::MediaSink& sink : device_cache()->sinks()) {
     ash::SinkAndRoute device;
     device.sink.id = sink.id();
@@ -270,3 +285,17 @@
   device_cache_.reset();
   RequestDeviceRefresh();
 }
+
+#if !defined(OFFICIAL_BUILD)
+void CastConfigControllerMediaRouter::AddFakeCastDevices() {
+  // Add enough devices that the UI menu will scroll.
+  for (int i = 1; i <= 10; i++) {
+    ash::SinkAndRoute device;
+    device.sink.id = "fake_sink_id_" + base::NumberToString(i);
+    device.sink.name = "Fake Sink " + base::NumberToString(i);
+    device.sink.domain = "example.com";
+    device.sink.sink_icon_type = ash::SinkIconType::kCast;
+    devices_.push_back(std::move(device));
+  }
+}
+#endif  // defined(OFFICIAL_BUILD)
diff --git a/chrome/browser/ui/ash/cast_config_controller_media_router.h b/chrome/browser/ui/ash/cast_config_controller_media_router.h
index da2b8ed..74b7b11c 100644
--- a/chrome/browser/ui/ash/cast_config_controller_media_router.h
+++ b/chrome/browser/ui/ash/cast_config_controller_media_router.h
@@ -40,6 +40,7 @@
   // CastConfigController:
   void AddObserver(Observer* observer) override;
   void RemoveObserver(Observer* observer) override;
+  bool HasMediaRouterForPrimaryProfile() const override;
   bool HasSinksAndRoutes() const override;
   bool HasActiveRoute() const override;
   bool AccessCodeCastingEnabled() const override;
@@ -51,6 +52,12 @@
   // session_manager::SessionManagerObserver:
   void OnUserProfileLoaded(const AccountId& account_id) override;
 
+#if !defined(OFFICIAL_BUILD)
+  // Adds fake Cast devices for manual testing of the UI (for example, in the
+  // linux-chromeos emulator).
+  void AddFakeCastDevices();
+#endif
+
   // |device_cache_| stores the current source/route status that we query from.
   // This will return null until the media router is initialized.
   CastDeviceCache* device_cache();
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_client_impl.cc b/chrome/browser/ui/ash/holding_space/holding_space_client_impl.cc
index ecd2e537..b36a1fa9b 100644
--- a/chrome/browser/ui/ash/holding_space/holding_space_client_impl.cc
+++ b/chrome/browser/ui/ash/holding_space/holding_space_client_impl.cc
@@ -15,12 +15,12 @@
 #include "base/notreached.h"
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_keyed_service.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_keyed_service_factory.h"
 #include "chrome/browser/ash/file_manager/app_id.h"
 #include "chrome/browser/ash/file_manager/fileapi_util.h"
 #include "chrome/browser/ash/file_manager/open_util.h"
 #include "chrome/browser/ash/file_manager/path_util.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_factory.h"
 #include "chrome/browser/ui/ash/clipboard_util.h"
 #include "chrome/browser/ui/ash/holding_space/holding_space_keyed_service.h"
 #include "chrome/browser/ui/ash/holding_space/holding_space_keyed_service_factory.h"
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc b/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc
index 9788ca1..6c36bac 100644
--- a/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc
+++ b/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc
@@ -26,6 +26,10 @@
 #include "base/test/test_future.h"
 #include "base/time/time.h"
 #include "base/time/time_override.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_keyed_service_factory.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_test_util.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_util.h"
+#include "chrome/browser/ash/app_list/search/files/mock_file_suggest_keyed_service.h"
 #include "chrome/browser/ash/arc/fileapi/arc_file_system_bridge.h"
 #include "chrome/browser/ash/file_manager/fake_disk_mount_manager.h"
 #include "chrome/browser/ash/file_manager/fileapi_util.h"
@@ -37,10 +41,6 @@
 #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
 #include "chrome/browser/nearby_sharing/common/nearby_share_features.h"
 #include "chrome/browser/prefs/browser_prefs.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_factory.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_test_util.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_util.h"
-#include "chrome/browser/ui/app_list/search/files/mock_file_suggest_keyed_service.h"
 #include "chrome/browser/ui/ash/holding_space/holding_space_keyed_service_factory.h"
 #include "chrome/browser/ui/ash/holding_space/holding_space_persistence_delegate.h"
 #include "chrome/browser/ui/ash/holding_space/holding_space_test_util.h"
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_suggestions_delegate.cc b/chrome/browser/ui/ash/holding_space/holding_space_suggestions_delegate.cc
index a6a152e6..e79b49a48 100644
--- a/chrome/browser/ui/ash/holding_space/holding_space_suggestions_delegate.cc
+++ b/chrome/browser/ui/ash/holding_space/holding_space_suggestions_delegate.cc
@@ -6,8 +6,8 @@
 
 #include "ash/constants/ash_features.h"
 #include "base/containers/adapters.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_keyed_service_factory.h"
 #include "chrome/browser/ash/file_manager/path_util.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_factory.h"
 
 namespace ash {
 namespace {
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_suggestions_delegate.h b/chrome/browser/ui/ash/holding_space/holding_space_suggestions_delegate.h
index 2bbc22c..3e09958c 100644
--- a/chrome/browser/ui/ash/holding_space/holding_space_suggestions_delegate.h
+++ b/chrome/browser/ui/ash/holding_space/holding_space_suggestions_delegate.h
@@ -9,8 +9,8 @@
 
 #include "ash/public/cpp/holding_space/holding_space_item.h"
 #include "base/timer/timer.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_util.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_keyed_service.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_util.h"
 #include "chrome/browser/ui/ash/holding_space/holding_space_keyed_service_delegate.h"
 
 namespace ash {
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_ui_browsertest.cc b/chrome/browser/ui/ash/holding_space/holding_space_ui_browsertest.cc
index 92accc25..25cc4a3 100644
--- a/chrome/browser/ui/ash/holding_space/holding_space_ui_browsertest.cc
+++ b/chrome/browser/ui/ash/holding_space/holding_space_ui_browsertest.cc
@@ -34,6 +34,9 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_locale.h"
 #include "build/build_config.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_keyed_service.h"
+#include "chrome/browser/ash/app_list/search/files/file_suggest_keyed_service_factory.h"
+#include "chrome/browser/ash/app_list/search/files/local_file_suggestion_provider.h"
 #include "chrome/browser/ash/crosapi/crosapi_ash.h"
 #include "chrome/browser/ash/crosapi/crosapi_manager.h"
 #include "chrome/browser/ash/file_manager/file_tasks_observer.h"
@@ -43,9 +46,6 @@
 #include "chrome/browser/download/download_core_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service.h"
-#include "chrome/browser/ui/app_list/search/files/file_suggest_keyed_service_factory.h"
-#include "chrome/browser/ui/app_list/search/files/local_file_suggestion_provider.h"
 #include "chrome/browser/ui/ash/holding_space/holding_space_browsertest_base.h"
 #include "chrome/browser/ui/ash/holding_space/holding_space_downloads_delegate.h"
 #include "chrome/browser/ui/ash/holding_space/holding_space_keyed_service_factory.h"
diff --git a/chrome/browser/ui/ash/shelf/app_shortcut_shelf_item_controller.cc b/chrome/browser/ui/ash/shelf/app_shortcut_shelf_item_controller.cc
index ef598e6..afa49ab 100644
--- a/chrome/browser/ui/ash/shelf/app_shortcut_shelf_item_controller.cc
+++ b/chrome/browser/ui/ash/shelf/app_shortcut_shelf_item_controller.cc
@@ -124,8 +124,8 @@
     DCHECK(profile);
     if (web_app::WebAppProvider* provider =
             web_app::WebAppProvider::GetForLocalAppsUnchecked(profile)) {
-      if (provider->registrar().IsLocallyInstalled(app_id)) {
-        registrar_ = &provider->registrar();
+      if (provider->registrar_unsafe().IsLocallyInstalled(app_id)) {
+        registrar_ = &provider->registrar_unsafe();
       }
     }
     if (!registrar_)
@@ -560,7 +560,7 @@
   if (web_app::WebAppProvider* provider =
           web_app::WebAppProvider::GetForLocalAppsUnchecked(
               ChromeShelfController::instance()->profile())) {
-    web_app::WebAppRegistrar& registrar = provider->registrar();
+    web_app::WebAppRegistrar& registrar = provider->registrar_unsafe();
     if (registrar.IsLocallyInstalled(app_id())) {
       return registrar.GetAppUserDisplayMode(app_id()) !=
              web_app::UserDisplayMode::kBrowser;
diff --git a/chrome/browser/ui/ash/shelf/chrome_shelf_controller_unittest.cc b/chrome/browser/ui/ash/shelf/chrome_shelf_controller_unittest.cc
index 97f6035..0c01d64 100644
--- a/chrome/browser/ui/ash/shelf/chrome_shelf_controller_unittest.cc
+++ b/chrome/browser/ui/ash/shelf/chrome_shelf_controller_unittest.cc
@@ -66,6 +66,7 @@
 #include "chrome/browser/ash/app_list/arc/arc_app_test.h"
 #include "chrome/browser/ash/app_list/arc/arc_app_utils.h"
 #include "chrome/browser/ash/app_list/arc/arc_default_app_list.h"
+#include "chrome/browser/ash/app_list/internal_app/internal_app_metadata.h"
 #include "chrome/browser/ash/arc/arc_util.h"
 #include "chrome/browser/ash/arc/session/arc_session_manager.h"
 #include "chrome/browser/ash/crosapi/browser_util.h"
@@ -89,7 +90,6 @@
 #include "chrome/browser/sync/sync_service_factory.h"
 #include "chrome/browser/ui/app_icon_loader.h"
 #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h"
-#include "chrome/browser/ui/app_list/internal_app/internal_app_metadata.h"
 #include "chrome/browser/ui/apps/chrome_app_delegate.h"
 #include "chrome/browser/ui/ash/multi_user/multi_profile_support.h"
 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
diff --git a/chrome/browser/ui/ash/shelf/shelf_context_menu.cc b/chrome/browser/ui/ash/shelf/shelf_context_menu.cc
index 693a747..b3b5622 100644
--- a/chrome/browser/ui/ash/shelf/shelf_context_menu.cc
+++ b/chrome/browser/ui/ash/shelf/shelf_context_menu.cc
@@ -16,11 +16,11 @@
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "chrome/browser/ash/accessibility/accessibility_manager.h"
 #include "chrome/browser/ash/app_list/arc/arc_app_utils.h"
+#include "chrome/browser/ash/app_list/internal_app/internal_app_metadata.h"
 #include "chrome/browser/ash/app_restore/full_restore_service.h"
 #include "chrome/browser/ash/crostini/crostini_util.h"
 #include "chrome/browser/ash/guest_os/guest_os_shelf_utils.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/app_list/internal_app/internal_app_metadata.h"
 #include "chrome/browser/ui/ash/shelf/app_service/app_service_shelf_context_menu.h"
 #include "chrome/browser/ui/ash/shelf/chrome_shelf_controller.h"
 #include "chrome/browser/ui/ash/shelf/chrome_shelf_controller_util.h"
diff --git a/chrome/browser/ui/ash/shelf/shelf_context_menu_unittest.cc b/chrome/browser/ui/ash/shelf/shelf_context_menu_unittest.cc
index 2d079e20..eb9acef 100644
--- a/chrome/browser/ui/ash/shelf/shelf_context_menu_unittest.cc
+++ b/chrome/browser/ui/ash/shelf/shelf_context_menu_unittest.cc
@@ -26,6 +26,7 @@
 #include "chrome/browser/ash/app_list/arc/arc_app_icon.h"
 #include "chrome/browser/ash/app_list/arc/arc_app_test.h"
 #include "chrome/browser/ash/app_list/arc/arc_app_utils.h"
+#include "chrome/browser/ash/app_list/internal_app/internal_app_metadata.h"
 #include "chrome/browser/ash/crostini/crostini_manager.h"
 #include "chrome/browser/ash/crostini/crostini_test_helper.h"
 #include "chrome/browser/ash/crostini/crostini_util.h"
@@ -37,7 +38,6 @@
 #include "chrome/browser/extensions/test_extension_system.h"
 #include "chrome/browser/prefs/incognito_mode_prefs.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/app_list/internal_app/internal_app_metadata.h"
 #include "chrome/browser/ui/ash/shelf/arc_app_shelf_id.h"
 #include "chrome/browser/ui/ash/shelf/browser_shortcut_shelf_item_controller.h"
 #include "chrome/browser/ui/ash/shelf/chrome_shelf_controller.h"
diff --git a/chrome/browser/ui/ash/shelf/shelf_controller_helper.cc b/chrome/browser/ui/ash/shelf/shelf_controller_helper.cc
index d621c97..c5dd18e 100644
--- a/chrome/browser/ui/ash/shelf/shelf_controller_helper.cc
+++ b/chrome/browser/ui/ash/shelf/shelf_controller_helper.cc
@@ -15,6 +15,7 @@
 #include "chrome/browser/apps/app_service/web_contents_app_id_utils.h"
 #include "chrome/browser/ash/app_list/arc/arc_app_list_prefs.h"
 #include "chrome/browser/ash/app_list/arc/arc_app_utils.h"
+#include "chrome/browser/ash/app_list/internal_app/internal_app_metadata.h"
 #include "chrome/browser/ash/arc/arc_util.h"
 #include "chrome/browser/ash/arc/session/arc_session_manager.h"
 #include "chrome/browser/ash/crostini/crostini_features.h"
@@ -25,7 +26,6 @@
 #include "chrome/browser/extensions/extension_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/ui/app_list/internal_app/internal_app_metadata.h"
 #include "chrome/browser/ui/ash/shelf/arc_app_shelf_id.h"
 #include "chrome/browser/ui/ash/shelf/chrome_shelf_controller_util.h"
 #include "chrome/browser/ui/browser.h"
diff --git a/chrome/browser/ui/cocoa/screentime/history_bridge_unittest.cc b/chrome/browser/ui/cocoa/screentime/history_bridge_unittest.cc
index 8a7208f3..474fe66c 100644
--- a/chrome/browser/ui/cocoa/screentime/history_bridge_unittest.cc
+++ b/chrome/browser/ui/cocoa/screentime/history_bridge_unittest.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/ui/cocoa/screentime/history_deleter.h"
 #include "components/history/core/browser/history_database_params.h"
 #include "components/history/core/browser/history_service.h"
+#include "components/version_info/channel.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -64,8 +65,8 @@
         std::make_unique<HistoryBridge>(service_.get(), std::move(deleter));
 
     CHECK(history_dir_.CreateUniqueTempDir());
-    service_->Init(
-        history::HistoryDatabaseParams(history_dir_.GetPath(), 0, 0));
+    service_->Init(history::HistoryDatabaseParams(
+        history_dir_.GetPath(), 0, 0, version_info::Channel::UNKNOWN));
     service_->SetOnBackendDestroyTask(history_teardown_loop_.QuitClosure());
   }
 
diff --git a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
index d912095d..d6ddb6c 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
@@ -2841,7 +2841,7 @@
     StartupBrowserWebAppProtocolHandlingTest,
     WebAppLaunch_WebAppIsNotLaunchedWithProtocolUrlAndDialogCancel) {
   if (!AreProtocolHandlersSupported())
-    return;
+    GTEST_SKIP() << "Protocol Handlers unsupported";
 
   views::NamedWidgetShownWaiter waiter(views::test::AnyWidgetTestPasskey{},
                                        "ProtocolHandlerLaunchDialogView");
@@ -2868,7 +2868,7 @@
     StartupBrowserWebAppProtocolHandlingTest,
     WebAppLaunch_WebAppIsLaunchedWithProtocolUrlAndDialogAccept) {
   if (!AreProtocolHandlersSupported())
-    return;
+    GTEST_SKIP() << "Protocol Handlers unsupported";
 
   views::NamedWidgetShownWaiter waiter(views::test::AnyWidgetTestPasskey{},
                                        "ProtocolHandlerLaunchDialogView");
@@ -2924,7 +2924,7 @@
     StartupBrowserWebAppProtocolHandlingTest,
     WebAppLaunch_WebAppIsNotTranslatedWithUnhandledProtocolUrl) {
   if (!AreProtocolHandlersSupported())
-    return;
+    GTEST_SKIP() << "Protocol Handlers unsupported";
 
   // Register web app as a protocol handler that should *not* handle the launch.
   apps::ProtocolHandlerInfo protocol_handler;
@@ -2957,7 +2957,7 @@
     StartupBrowserWebAppProtocolHandlingTest,
     WebAppLaunch_WebAppIsLaunchedWithAllowedProtocolUrlPref) {
   if (!AreProtocolHandlersSupported())
-    return;
+    GTEST_SKIP() << "Protocol Handlers unsupported";
 
   views::NamedWidgetShownWaiter waiter(views::test::AnyWidgetTestPasskey{},
                                        "ProtocolHandlerLaunchDialogView");
@@ -3026,7 +3026,7 @@
 IN_PROC_BROWSER_TEST_F(StartupBrowserWebAppProtocolHandlingTest,
                        WebAppLaunch_WebAppIsLaunchedWithAllowedProtocol) {
   if (!AreProtocolHandlersSupported())
-    return;
+    GTEST_SKIP() << "Protocol Handlers unsupported";
 
   // Register web app as a protocol handler that should handle the launch.
   apps::ProtocolHandlerInfo protocol_handler;
@@ -3098,7 +3098,7 @@
     StartupBrowserWebAppProtocolHandlingTest,
     WebAppLaunch_WebAppIsLaunchedWithDiallowedProtocolUrlPref) {
   if (!AreProtocolHandlersSupported())
-    return;
+    GTEST_SKIP() << "Protocol Handlers unsupported";
 
   views::NamedWidgetShownWaiter waiter(views::test::AnyWidgetTestPasskey{},
                                        "ProtocolHandlerLaunchDialogView");
@@ -3136,7 +3136,7 @@
     StartupBrowserWebAppProtocolHandlingTest,
     WebAppLaunch_WebAppIsLaunchedWithDisallowedOnceProtocol) {
   if (!AreProtocolHandlersSupported())
-    return;
+    GTEST_SKIP() << "Protocol Handlers unsupported";
 
   // Register web app as a protocol handler that should handle the launch.
   apps::ProtocolHandlerInfo protocol_handler;
@@ -3191,7 +3191,7 @@
 IN_PROC_BROWSER_TEST_F(StartupBrowserWebAppProtocolAndFileHandlingTest,
                        WebAppLaunch_FileProtocol) {
   if (!AreProtocolHandlersSupported())
-    return;
+    GTEST_SKIP() << "Protocol Handlers unsupported";
 
   // Install an app with protocol handlers and a handler for plain text files.
   apps::ProtocolHandlerInfo protocol_handler;
diff --git a/chrome/browser/ui/startup/web_app_startup_utils.cc b/chrome/browser/ui/startup/web_app_startup_utils.cc
index 21b6d176..0e58b195 100644
--- a/chrome/browser/ui/startup/web_app_startup_utils.cc
+++ b/chrome/browser/ui/startup/web_app_startup_utils.cc
@@ -304,15 +304,15 @@
                        base::WrapRefCounted(this), allowed);
 
     if (remember_user_choice) {
+      WebAppProvider* provider = WebAppProvider::GetForWebApps(profile_);
       if (!protocol_url_.is_empty()) {
-        PersistProtocolHandlersUserChoice(profile_, app_id_, protocol_url_,
-                                          allowed, std::move(persist_callback));
+        provider->scheduler().UpdateProtocolHandlerUserApproval(
+            app_id_, protocol_url_.scheme(), allowed,
+            std::move(persist_callback));
       } else {
         DCHECK(!file_launch_infos_.empty());
-        WebAppProvider::GetForWebApps(profile_)
-            ->scheduler()
-            .PersistFileHandlersUserChoice(app_id_, allowed,
-                                           std::move(persist_callback));
+        provider->scheduler().PersistFileHandlersUserChoice(
+            app_id_, allowed, std::move(persist_callback));
       }
     } else {
       std::move(persist_callback).Run();
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc
index 45f1a38..d1f7fc57 100644
--- a/chrome/browser/ui/tab_helpers.cc
+++ b/chrome/browser/ui/tab_helpers.cc
@@ -191,7 +191,7 @@
 #endif
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-#include "chrome/browser/ui/app_list/search/cros_action_history/cros_action_recorder_tab_tracker.h"
+#include "chrome/browser/ash/app_list/search/cros_action_history/cros_action_recorder_tab_tracker.h"
 #endif
 
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
diff --git a/chrome/browser/ui/thumbnails/thumbnail_tab_helper_interactive_uitest.cc b/chrome/browser/ui/thumbnails/thumbnail_tab_helper_interactive_uitest.cc
index 0caf865..65a376e 100644
--- a/chrome/browser/ui/thumbnails/thumbnail_tab_helper_interactive_uitest.cc
+++ b/chrome/browser/ui/thumbnails/thumbnail_tab_helper_interactive_uitest.cc
@@ -173,8 +173,15 @@
   WaitForAndVerifyThumbnail(browser(), 1);
 }
 
+// TODO(crbug.com/1399402): Times out on MSan bot.
+#if defined(MEMORY_SANITIZER)
+#define MAYBE_TabDiscardPreservesScreenshot \
+  DISABLED_TabDiscardPreservesScreenshot
+#else
+#define MAYBE_TabDiscardPreservesScreenshot TabDiscardPreservesScreenshot
+#endif
 IN_PROC_BROWSER_TEST_F(ThumbnailTabHelperInteractiveTest,
-                       TabDiscardPreservesScreenshot) {
+                       MAYBE_TabDiscardPreservesScreenshot) {
   ui_test_utils::NavigateToURLWithDisposition(
       browser(), url2_, WindowOpenDisposition::NEW_BACKGROUND_TAB,
       ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
diff --git a/chrome/browser/ui/views/accessibility/caption_bubble_context_views.cc b/chrome/browser/ui/views/accessibility/caption_bubble_context_views.cc
index 748be3c1..53341029 100644
--- a/chrome/browser/ui/views/accessibility/caption_bubble_context_views.cc
+++ b/chrome/browser/ui/views/accessibility/caption_bubble_context_views.cc
@@ -9,6 +9,8 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/views/accessibility/caption_bubble_session_observer_views.h"
+#include "content/public/browser/browser_context.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/views/widget/widget.h"
 
@@ -22,7 +24,10 @@
 
 CaptionBubbleContextViews::CaptionBubbleContextViews(
     content::WebContents* web_contents)
-    : CaptionBubbleContextBrowser(web_contents), web_contents_(web_contents) {}
+    : CaptionBubbleContextBrowser(web_contents),
+      web_contents_(web_contents),
+      web_contents_observer_(
+          std::make_unique<CaptionBubbleSessionObserverViews>(web_contents)) {}
 
 CaptionBubbleContextViews::~CaptionBubbleContextViews() = default;
 
@@ -37,6 +42,10 @@
   return context_bounds;
 }
 
+const std::string CaptionBubbleContextViews::GetSessionId() const {
+  return web_contents_->GetBrowserContext()->UniqueId();
+}
+
 void CaptionBubbleContextViews::Activate() {
   if (!web_contents_)
     return;
@@ -63,4 +72,11 @@
   return true;
 }
 
+std::unique_ptr<CaptionBubbleSessionObserver>
+CaptionBubbleContextViews::GetCaptionBubbleSessionObserver() {
+  if (web_contents_observer_)
+    return std::move(web_contents_observer_);
+
+  return nullptr;
+}
 }  // namespace captions
diff --git a/chrome/browser/ui/views/accessibility/caption_bubble_context_views.h b/chrome/browser/ui/views/accessibility/caption_bubble_context_views.h
index 704f94b..fbf53d6 100644
--- a/chrome/browser/ui/views/accessibility/caption_bubble_context_views.h
+++ b/chrome/browser/ui/views/accessibility/caption_bubble_context_views.h
@@ -5,15 +5,20 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_ACCESSIBILITY_CAPTION_BUBBLE_CONTEXT_VIEWS_H_
 #define CHROME_BROWSER_UI_VIEWS_ACCESSIBILITY_CAPTION_BUBBLE_CONTEXT_VIEWS_H_
 
-#include "base/memory/raw_ptr.h"
 #include "chrome/browser/accessibility/caption_bubble_context_browser.h"
 
+#include <string>
+
+#include "base/memory/raw_ptr.h"
+
 namespace content {
 class WebContents;
 }
 
 namespace captions {
 
+class CaptionBubbleSessionObserverViews;
+
 ///////////////////////////////////////////////////////////////////////////////
 // Caption Bubble Context for Views
 //
@@ -29,11 +34,16 @@
 
   // CaptionBubbleContextBrowser:
   absl::optional<gfx::Rect> GetBounds() const override;
+  const std::string GetSessionId() const override;
   void Activate() override;
   bool IsActivatable() const override;
+  std::unique_ptr<CaptionBubbleSessionObserver>
+  GetCaptionBubbleSessionObserver() override;
 
  private:
   raw_ptr<content::WebContents, DanglingUntriaged> web_contents_;
+
+  std::unique_ptr<CaptionBubbleSessionObserver> web_contents_observer_;
 };
 
 }  // namespace captions
diff --git a/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc b/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc
index 49e2ac19..afba739 100644
--- a/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc
+++ b/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc
@@ -844,12 +844,12 @@
   EXPECT_TRUE(IsWidgetVisible());
   EXPECT_EQ("Polar bears are the largest carnivores on land", GetLabelText());
 
-  // Close the bubble. Check that the bubble is still visible with media 1.
+  // Close the bubble. Check that the bubble is still closed.
   ClickButton(GetCloseButton());
   EXPECT_FALSE(IsWidgetVisible());
   OnPartialTranscription("A snail can sleep for two years", media_1.get());
-  EXPECT_TRUE(IsWidgetVisible());
-  EXPECT_EQ("A snail can sleep for two years", GetLabelText());
+  EXPECT_FALSE(IsWidgetVisible());
+  EXPECT_EQ("", GetLabelText());
 
   // Send a transcription from media 0. Check that the bubble is still closed.
   OnPartialTranscription("carnivores on land", media_0);
diff --git a/chrome/browser/ui/views/accessibility/caption_bubble_session_observer_views.cc b/chrome/browser/ui/views/accessibility/caption_bubble_session_observer_views.cc
new file mode 100644
index 0000000..bf53346
--- /dev/null
+++ b/chrome/browser/ui/views/accessibility/caption_bubble_session_observer_views.cc
@@ -0,0 +1,49 @@
+// 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/ui/views/accessibility/caption_bubble_session_observer_views.h"
+
+#include <memory>
+
+#include "components/live_caption/caption_bubble_session_observer.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_observer.h"
+
+namespace captions {
+
+CaptionBubbleSessionObserverViews::CaptionBubbleSessionObserverViews(
+    content::WebContents* web_contents)
+    : CaptionBubbleSessionObserver(),
+      content::WebContentsObserver(web_contents),
+      web_contents_id_(web_contents->GetBrowserContext()->UniqueId()) {}
+
+CaptionBubbleSessionObserverViews::~CaptionBubbleSessionObserverViews() =
+    default;
+
+void CaptionBubbleSessionObserverViews::DidFinishNavigation(
+    content::NavigationHandle* handle) {
+  if (!handle->HasCommitted()) {
+    return;
+  }
+
+  if (end_session_callback_ && handle->IsInPrimaryMainFrame() &&
+      (!handle->IsSameOrigin() ||
+       handle->GetReloadType() != content::ReloadType::NONE)) {
+    end_session_callback_.Run(web_contents_id_);
+  }
+}
+
+void CaptionBubbleSessionObserverViews::WebContentsDestroyed() {
+  if (end_session_callback_)
+    end_session_callback_.Run(web_contents_id_);
+}
+
+void CaptionBubbleSessionObserverViews::SetEndSessionCallback(
+    EndSessionCallback callback) {
+  end_session_callback_ = std::move(callback);
+}
+
+}  // namespace captions
diff --git a/chrome/browser/ui/views/accessibility/caption_bubble_session_observer_views.h b/chrome/browser/ui/views/accessibility/caption_bubble_session_observer_views.h
new file mode 100644
index 0000000..fe4584e
--- /dev/null
+++ b/chrome/browser/ui/views/accessibility/caption_bubble_session_observer_views.h
@@ -0,0 +1,45 @@
+// 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_UI_VIEWS_ACCESSIBILITY_CAPTION_BUBBLE_SESSION_OBSERVER_VIEWS_H_
+#define CHROME_BROWSER_UI_VIEWS_ACCESSIBILITY_CAPTION_BUBBLE_SESSION_OBSERVER_VIEWS_H_
+
+#include "components/live_caption/caption_bubble_session_observer.h"
+
+#include "content/public/browser/web_contents_observer.h"
+
+namespace content {
+class NavigationHandle;
+class WebContents;
+}  // namespace content
+
+namespace captions {
+
+class CaptionBubbleSessionObserverViews : public CaptionBubbleSessionObserver,
+                                          public content::WebContentsObserver {
+ public:
+  explicit CaptionBubbleSessionObserverViews(
+      content::WebContents* web_contents);
+  ~CaptionBubbleSessionObserverViews() override;
+  CaptionBubbleSessionObserverViews(const CaptionBubbleSessionObserverViews&) =
+      delete;
+  CaptionBubbleSessionObserverViews& operator=(
+      const CaptionBubbleSessionObserverViews&) = delete;
+
+  // content::WebContentsObserver:
+  void DidFinishNavigation(
+      content::NavigationHandle* navigation_handle) override;
+  void WebContentsDestroyed() override;
+
+  // CaptionBubbleSessionObserver:
+  void SetEndSessionCallback(EndSessionCallback callback) override;
+
+ private:
+  std::string web_contents_id_;
+  EndSessionCallback end_session_callback_;
+};
+
+}  // namespace captions
+
+#endif  // CHROME_BROWSER_UI_VIEWS_ACCESSIBILITY_CAPTION_BUBBLE_SESSION_OBSERVER_VIEWS_H_
diff --git a/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views.cc b/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views.cc
index ac8c0bce..e17f3dc 100644
--- a/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views.cc
+++ b/chrome/browser/ui/views/autofill/payments/virtual_card_enroll_bubble_views.cc
@@ -167,9 +167,20 @@
       views::BoxLayout::Orientation::kVertical);
   card_identifier_view->SetCrossAxisAlignment(
       views::BoxLayout::CrossAxisAlignment::kStart);
-  card_identifier_view->AddChildView(std::make_unique<views::Label>(
-      card.CardIdentifierStringForAutofillDisplay(),
-      views::style::CONTEXT_DIALOG_BODY_TEXT, views::style::STYLE_PRIMARY));
+  auto* card_name_4digits_view = card_identifier_view->AddChildView(
+      std::make_unique<views::BoxLayoutView>());
+  card_name_4digits_view->SetOrientation(
+      views::BoxLayout::Orientation::kHorizontal);
+  card_name_4digits_view->SetBetweenChildSpacing(
+      provider->GetDistanceMetric(DISTANCE_RELATED_LABEL_HORIZONTAL_LIST));
+  auto* card_name_label =
+      card_name_4digits_view->AddChildView(std::make_unique<views::Label>(
+          card.CardNameForAutofillDisplay(),
+          views::style::CONTEXT_DIALOG_BODY_TEXT, views::style::STYLE_PRIMARY));
+  card_name_4digits_view->SetFlexForView(card_name_label, /*flex=*/1);
+  card_name_4digits_view->AddChildView(std::make_unique<views::Label>(
+      card.ObfuscatedLastFourDigits(), views::style::CONTEXT_DIALOG_BODY_TEXT,
+      views::style::STYLE_PRIMARY));
   card_identifier_view->AddChildView(std::make_unique<views::Label>(
       l10n_util::GetStringUTF16(IDS_AUTOFILL_VIRTUAL_CARD_ENTRY_PREFIX),
       ChromeTextContext::CONTEXT_DIALOG_BODY_TEXT_SMALL,
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc
index 8285fcd..e8ac410 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc
@@ -458,7 +458,7 @@
     GetDragTaskRunner()->PostTask(
         FROM_HERE,
         base::BindOnce(base::IgnoreResult(&ui_controls::SendMouseMove),
-                       target.x(), target.y()));
+                       target.x(), target.y(), ui_controls::kNoWindowHint));
   }
 
   void OnWidgetDragComplete(views::Widget* widget) override {
@@ -522,7 +522,8 @@
         FROM_HERE,
         base::BindOnce(base::IgnoreResult(&ui_controls::SendMouseEvents),
                        ui_controls::LEFT, ui_controls::UP,
-                       ui_controls::kNoAccelerator));
+                       ui_controls::kNoAccelerator,
+                       ui_controls::kNoWindowHint));
   }
 
   // Called after the drag ends; returns the node the test thinks should be the
@@ -917,7 +918,7 @@
     GetDragTaskRunner()->PostTask(
         FROM_HERE,
         base::BindOnce(base::IgnoreResult(&ui_controls::SendMouseMove),
-                       target.x(), target.y()));
+                       target.x(), target.y(), ui_controls::kNoWindowHint));
   }
 
   void OnWidgetDragComplete(views::Widget* widget) override {
@@ -971,7 +972,7 @@
     GetDragTaskRunner()->PostTask(
         FROM_HERE,
         base::BindOnce(base::IgnoreResult(&ui_controls::SendMouseMove),
-                       target.x(), target.y()));
+                       target.x(), target.y(), ui_controls::kNoWindowHint));
   }
 
  protected:
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_drag_drop_views.cc b/chrome/browser/ui/views/bookmarks/bookmark_drag_drop_views.cc
index 12aae17..a4e706e 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_drag_drop_views.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_drag_drop_views.cc
@@ -69,7 +69,9 @@
   static constexpr int kIconSize = 16;
   static constexpr int kTitlePadding = 12;
 
+#if !BUILDFLAG(IS_MAC)
   static constexpr int kCountPadding = 5;
+#endif
   static constexpr int kCountContainerRadius = 12;
 
   static constexpr gfx::Size kBookmarkDragImageSize =
@@ -85,10 +87,52 @@
       : gfx::CanvasImageSource(kBookmarkDragImageSize),
         color_provider_(color_provider),
         title_(title),
-        icon_(icon),
-        count_(count) {}
+        icon_(icon)
+#if !BUILDFLAG(IS_MAC)
+        ,
+        count_(count)
+#endif
+  {
+  }
 
  private:
+#if !BUILDFLAG(IS_MAC)
+  void DrawCountBubble(const gfx::FontList& font_list,
+                       const gfx::RectF& container_rect,
+                       cc::PaintFlags paint_flags,
+                       gfx::Canvas* canvas) {
+    // Draw bookmark count if more than 1 bookmark is dragged.
+    std::u16string count = base::NumberToString16(count_);
+    std::unique_ptr<gfx::RenderText> render_text =
+        gfx::RenderText::CreateRenderText();
+    render_text->SetFontList(font_list);
+    render_text->SetCursorEnabled(false);
+    render_text->SetColor(
+        color_provider_->GetColor(kColorBookmarkDragImageCountForeground));
+    render_text->SetText(count);
+    render_text->SetHorizontalAlignment(gfx::ALIGN_CENTER);
+
+    // We measure the count text size to determine container width, as the
+    // container is a rounded rect behind the text.
+    int count_width = render_text->GetStringSize().width();
+    int count_container_width =
+        std::max(kCountContainerRadius * 2, count_width + 2 * kCountPadding);
+
+    // Draw the count container.
+    gfx::Rect count_container_rect(
+        container_rect.right() - count_container_width, 0,
+        count_container_width, kCountContainerRadius * 2);
+    paint_flags.setColor(
+        color_provider_->GetColor(kColorBookmarkDragImageCountBackground));
+    canvas->DrawRoundRect(gfx::RectF(count_container_rect),
+                          kCountContainerRadius, paint_flags);
+
+    // Draw the count text.
+    render_text->SetDisplayRect(count_container_rect);
+    render_text->Draw(canvas);
+  }
+#endif  // BUILDFLAG(IS_MAC)
+
   // gfx::CanvasImageSource overrides:
   void Draw(gfx::Canvas* canvas) override {
     cc::PaintFlags paint_flags;
@@ -126,44 +170,23 @@
         color_provider_->GetColor(kColorBookmarkDragImageForeground), text_rect,
         gfx::Canvas::TEXT_ALIGN_LEFT);
 
-    if (count_ <= 1)
-      return;
-
-    // Draw bookmark count if more than 1 bookmark is dragged.
-    std::u16string count = base::NumberToString16(count_);
-    std::unique_ptr<gfx::RenderText> render_text =
-        gfx::RenderText::CreateRenderText();
-    render_text->SetFontList(font_list);
-    render_text->SetCursorEnabled(false);
-    render_text->SetColor(
-        color_provider_->GetColor(kColorBookmarkDragImageCountForeground));
-    render_text->SetText(count);
-    render_text->SetHorizontalAlignment(gfx::ALIGN_CENTER);
-
-    // We measure the count text size to determine container width, as the
-    // container is a rounded rect behind the text.
-    int count_width = render_text->GetStringSize().width();
-    int count_container_width =
-        std::max(kCountContainerRadius * 2, count_width + 2 * kCountPadding);
-
-    // Draw the count container.
-    gfx::Rect count_container_rect(
-        container_rect.right() - count_container_width, 0,
-        count_container_width, kCountContainerRadius * 2);
-    paint_flags.setColor(
-        color_provider_->GetColor(kColorBookmarkDragImageCountBackground));
-    canvas->DrawRoundRect(gfx::RectF(count_container_rect),
-                          kCountContainerRadius, paint_flags);
-
-    // Draw the count text.
-    render_text->SetDisplayRect(count_container_rect);
-    render_text->Draw(canvas);
+    // On the Mac, the Chromium drag code passes the bookmarks to macOS as
+    // individual drag items, and macOS will tag the drag image with the (#)
+    // count bubble. To avoid duplicate count tagging, end here on the Mac. On
+    // other platforms, tag the drag image with the count.
+#if !BUILDFLAG(IS_MAC)
+    if (count_ > 1) {
+      DrawCountBubble(font_list, container_rect, paint_flags, canvas);
+    }
+#endif
   }
 
   const raw_ref<const ui::ColorProvider> color_provider_;
   const std::u16string title_;
   const gfx::ImageSkia icon_;
+#if !BUILDFLAG(IS_MAC)
   const int count_;
+#endif
 };
 
 constexpr gfx::Size BookmarkDragImageSource::kBookmarkDragImageSize;
diff --git a/chrome/browser/ui/views/crostini/crostini_uninstaller_view_browsertest.cc b/chrome/browser/ui/views/crostini/crostini_uninstaller_view_browsertest.cc
index 5758d53..a1e4fe1 100644
--- a/chrome/browser/ui/views/crostini/crostini_uninstaller_view_browsertest.cc
+++ b/chrome/browser/ui/views/crostini/crostini_uninstaller_view_browsertest.cc
@@ -8,12 +8,12 @@
 #include "base/metrics/histogram_base.h"
 #include "base/run_loop.h"
 #include "base/test/metrics/histogram_tester.h"
+#include "chrome/browser/ash/app_list/test/chrome_app_list_test_support.h"
 #include "chrome/browser/ash/crostini/crostini_manager.h"
 #include "chrome/browser/ash/crostini/crostini_pref_names.h"
 #include "chrome/browser/ash/crostini/crostini_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/app_list_client_impl.h"
-#include "chrome/browser/ui/app_list/test/chrome_app_list_test_support.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/views/crostini/crostini_dialogue_browser_test_util.h"
 #include "chrome/test/base/in_process_browser_test.h"
diff --git a/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc b/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc
index 34ac0e8..0968c05 100644
--- a/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc
+++ b/chrome/browser/ui/views/download/bubble/download_bubble_row_view.cc
@@ -32,6 +32,7 @@
 #include "ui/compositor/layer.h"
 #include "ui/display/screen.h"
 #include "ui/gfx/geometry/insets.h"
+#include "ui/views/accessibility/view_accessibility.h"
 #include "ui/views/animation/ink_drop.h"
 #include "ui/views/controls/button/image_button.h"
 #include "ui/views/controls/button/image_button_factory.h"
@@ -125,6 +126,16 @@
       (is_paused_ == is_paused)) {
     return false;
   }
+
+  // Announce completion of downloads
+  if (state == download::DownloadItem::COMPLETE && !initial_setup &&
+      state_ != state) {
+    const std::u16string alert_text = l10n_util::GetStringFUTF16(
+        IDS_DOWNLOAD_COMPLETE_ACCESSIBLE_ALERT,
+        model_->GetFileNameToReportUser().LossyDisplayName());
+    GetViewAccessibility().AnnounceText(alert_text);
+  }
+
   mode_ = mode;
   state_ = state;
   is_paused_ = is_paused;
@@ -726,6 +737,13 @@
       views::CreateEmptyBorder(GetLayoutInsets(DOWNLOAD_ICON)));
   quick_action->SetProperty(views::kMarginsKey, kRowInterElementPadding);
   quick_action->SetVisible(false);
+  views::InkDrop::Get(quick_action)
+      ->SetBaseColorCallback(base::BindRepeating(
+          [](views::View* host) {
+            return views::style::GetColor(*host, views::style::CONTEXT_BUTTON,
+                                          views::style::STYLE_SECONDARY);
+          },
+          quick_action));
   return quick_action;
 }
 
diff --git a/chrome/browser/ui/views/dropdown_bar_host.cc b/chrome/browser/ui/views/dropdown_bar_host.cc
index 8d1c065f..cf671ff 100644
--- a/chrome/browser/ui/views/dropdown_bar_host.cc
+++ b/chrome/browser/ui/views/dropdown_bar_host.cc
@@ -53,7 +53,7 @@
   views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL);
   params.delegate = this;
   params.name = "DropdownBarHost";
-  params.parent = browser_view_->GetWidgetForAnchoring()->GetNativeView();
+  params.parent = browser_view_->GetWidget()->GetNativeView();
   params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent;
 #if BUILDFLAG(IS_MAC)
   params.activatable = views::Widget::InitParams::Activatable::kYes;
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index 02008ad..fd0c69ad 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -1269,14 +1269,6 @@
   return 1.f;
 }
 
-views::Widget* BrowserView::GetWidgetForAnchoring() {
-#if BUILDFLAG(IS_MAC)
-  if (UsesImmersiveFullscreenMode())
-    return IsFullscreen() ? overlay_widget_.get() : GetWidget();
-#endif
-  return GetWidget();
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 // BrowserView, BrowserWindow implementation:
 
@@ -3971,9 +3963,10 @@
   // TODO(https://crbug.com/1036519): Remove BrowserViewLayout dependence on
   // Widget and move to the constructor.
   SetLayoutManager(std::make_unique<BrowserViewLayout>(
-      std::make_unique<BrowserViewLayoutDelegateImpl>(this), this,
-      top_container_, tab_strip_region_view_, tabstrip_, toolbar_,
-      infobar_container_, contents_container_, side_search_side_panel_,
+      std::make_unique<BrowserViewLayoutDelegateImpl>(this),
+      GetWidget()->GetNativeView(), this, top_container_,
+      tab_strip_region_view_, tabstrip_, toolbar_, infobar_container_,
+      contents_container_, side_search_side_panel_,
       left_aligned_side_panel_separator_, unified_side_panel_,
       right_aligned_side_panel_separator_, lens_side_panel_,
       immersive_mode_controller_.get(), contents_separator_));
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h
index 97f6f59..79911e54 100644
--- a/chrome/browser/ui/views/frame/browser_view.h
+++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -357,11 +357,6 @@
   // Returns the current shown ratio of the top browser controls.
   float GetTopControlsSlideBehaviorShownRatio() const;
 
-  // Returns the widget for anchoring bubbles and dialogs.
-  // This returns BrowserFrame except on fullscreen macOS where the toolbar is
-  // hosted in an OverlayWidget.
-  views::Widget* GetWidgetForAnchoring();
-
   // See ImmersiveModeController for description.
   ImmersiveModeController* immersive_mode_controller() const {
     return immersive_mode_controller_.get();
diff --git a/chrome/browser/ui/views/frame/browser_view_layout.cc b/chrome/browser/ui/views/frame/browser_view_layout.cc
index 25d99c0b..472db7e 100644
--- a/chrome/browser/ui/views/frame/browser_view_layout.cc
+++ b/chrome/browser/ui/views/frame/browser_view_layout.cc
@@ -37,6 +37,7 @@
 #include "chrome/browser/ui/web_applications/app_browser_controller.h"
 #include "components/web_modal/web_contents_modal_dialog_host.h"
 #include "ui/base/hit_test.h"
+#include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
@@ -123,8 +124,7 @@
 
  private:
   gfx::NativeView GetHostView() const override {
-    return browser_view_layout_->browser_view_->GetWidgetForAnchoring()
-        ->GetNativeView();
+    return browser_view_layout_->host_view_;
   }
 
   // Add/remove observer.
@@ -145,6 +145,7 @@
 
 BrowserViewLayout::BrowserViewLayout(
     std::unique_ptr<BrowserViewLayoutDelegate> delegate,
+    gfx::NativeView host_view,
     BrowserView* browser_view,
     views::View* top_container,
     TabStripRegionView* tab_strip_region_view,
@@ -160,6 +161,7 @@
     ImmersiveModeController* immersive_mode_controller,
     views::View* contents_separator)
     : delegate_(std::move(delegate)),
+      host_view_(host_view),
       browser_view_(browser_view),
       top_container_(top_container),
       tab_strip_region_view_(tab_strip_region_view),
@@ -755,6 +757,18 @@
                   contents_container_->width(), contents_container_->height());
   }
 
+#if BUILDFLAG(IS_CHROMEOS)
+  // Immersive top container might overlap with the blue border in fullscreen
+  // mode - see crbug.com/1392733. By insetting the bounds rectangle we ensure
+  // that the blue border is always placed below the top container.
+  if (immersive_mode_controller_->IsRevealed()) {
+    int delta = top_container_->bounds().bottom() - rect.y();
+    if (delta > 0) {
+      rect.Inset(gfx::Insets().set_top(delta));
+    }
+  }
+#endif
+
   contents_border_widget_->SetBounds(rect);
 }
 
diff --git a/chrome/browser/ui/views/frame/browser_view_layout.h b/chrome/browser/ui/views/frame/browser_view_layout.h
index 54ac0917..980cb72 100644
--- a/chrome/browser/ui/views/frame/browser_view_layout.h
+++ b/chrome/browser/ui/views/frame/browser_view_layout.h
@@ -50,6 +50,7 @@
 
   // |browser_view| may be null in tests.
   BrowserViewLayout(std::unique_ptr<BrowserViewLayoutDelegate> delegate,
+                    gfx::NativeView host_view,
                     BrowserView* browser_view,
                     views::View* top_container,
                     TabStripRegionView* tab_strip_region_view,
@@ -164,6 +165,9 @@
   // The delegate interface. May be a mock in tests.
   const std::unique_ptr<BrowserViewLayoutDelegate> delegate_;
 
+  // The view against which the web dialog is positioned and parented.
+  gfx::NativeView const host_view_;
+
   // The owning browser view.
   const raw_ptr<BrowserView, DanglingUntriaged> browser_view_;
 
diff --git a/chrome/browser/ui/views/frame/browser_view_layout_unittest.cc b/chrome/browser/ui/views/frame/browser_view_layout_unittest.cc
index 441a2e1..0390c50 100644
--- a/chrome/browser/ui/views/frame/browser_view_layout_unittest.cc
+++ b/chrome/browser/ui/views/frame/browser_view_layout_unittest.cc
@@ -213,6 +213,7 @@
     delegate_ = delegate.get();
     auto layout = std::make_unique<BrowserViewLayout>(
         std::move(delegate),
+        /*host_view=*/nullptr,
         /*browser_view=*/nullptr, top_container_, tab_strip_region_view,
         tab_strip_, toolbar_, infobar_container_, contents_container_,
         /*left_aligned_side_panel=*/nullptr,
diff --git a/chrome/browser/ui/views/intent_picker_bubble_view.cc b/chrome/browser/ui/views/intent_picker_bubble_view.cc
index 83c3bf2..b54406b 100644
--- a/chrome/browser/ui/views/intent_picker_bubble_view.cc
+++ b/chrome/browser/ui/views/intent_picker_bubble_view.cc
@@ -83,6 +83,8 @@
 constexpr int kGridItemBorderRadius = 4;
 constexpr int kGridItemGroupId = 1;
 
+bool g_auto_accept_intent_picker_bubble_for_testing = false;
+
 bool IsKeyboardCodeArrow(ui::KeyboardCode key_code) {
   return key_code == ui::VKEY_UP || key_code == ui::VKEY_DOWN ||
          key_code == ui::VKEY_RIGHT || key_code == ui::VKEY_LEFT;
@@ -528,10 +530,20 @@
   intent_picker_bubble_->ShowForReason(DisplayReason::USER_GESTURE);
 
   intent_picker_bubble_->SelectDefaultItem();
+  if (g_auto_accept_intent_picker_bubble_for_testing) {
+    intent_picker_bubble_->AcceptDialog();
+  }
   return widget;
 }
 
 // static
+base::AutoReset<bool>
+IntentPickerBubbleView::SetAutoAcceptIntentPickerBubbleForTesting() {
+  return base::AutoReset<bool>(&g_auto_accept_intent_picker_bubble_for_testing,
+                               true);
+}
+
+// static
 void IntentPickerBubbleView::CloseCurrentBubble() {
   if (intent_picker_bubble_)
     intent_picker_bubble_->CloseBubble();
diff --git a/chrome/browser/ui/views/intent_picker_bubble_view.h b/chrome/browser/ui/views/intent_picker_bubble_view.h
index be88669..8a675ef 100644
--- a/chrome/browser/ui/views/intent_picker_bubble_view.h
+++ b/chrome/browser/ui/views/intent_picker_bubble_view.h
@@ -9,6 +9,7 @@
 #include <string>
 #include <vector>
 
+#include "base/auto_reset.h"
 #include "base/gtest_prod_util.h"
 #include "base/memory/raw_ptr.h"
 #include "chrome/browser/apps/intent_helper/apps_navigation_types.h"
@@ -96,6 +97,9 @@
   static IntentPickerBubbleView* intent_picker_bubble() {
     return intent_picker_bubble_;
   }
+
+  static base::AutoReset<bool> SetAutoAcceptIntentPickerBubbleForTesting();
+
   static void CloseCurrentBubble();
 
   // LocationBarBubbleDelegateView overrides:
diff --git a/chrome/browser/ui/views/menu_view_drag_and_drop_test.cc b/chrome/browser/ui/views/menu_view_drag_and_drop_test.cc
index 7ebc593..d2cfa63c 100644
--- a/chrome/browser/ui/views/menu_view_drag_and_drop_test.cc
+++ b/chrome/browser/ui/views/menu_view_drag_and_drop_test.cc
@@ -13,6 +13,7 @@
 #include "ui/base/dragdrop/drag_drop_types.h"
 #include "ui/base/dragdrop/mojom/drag_drop_types.mojom.h"
 #include "ui/base/dragdrop/os_exchange_data.h"
+#include "ui/gfx/native_widget_types.h"
 #include "ui/views/controls/menu/menu_controller.h"
 #include "ui/views/controls/menu/menu_item_view.h"
 #include "ui/views/controls/menu/menu_runner.h"
@@ -264,7 +265,7 @@
       FROM_HERE,
       base::BindOnce(base::IgnoreResult(&ui_controls::SendMouseEvents),
                      ui_controls::LEFT, ui_controls::UP,
-                     ui_controls::kNoAccelerator));
+                     ui_controls::kNoAccelerator, ui_controls::kNoWindowHint));
 }
 
 bool MenuViewDragAndDropTest::GetDropFormats(
@@ -350,8 +351,9 @@
   const gfx::Point target =
       ui_test_utils::GetCenterInScreenCoordinates(drop_target_view);
   GetDragTaskRunner()->PostTask(
-      FROM_HERE, base::BindOnce(base::IgnoreResult(&ui_controls::SendMouseMove),
-                                target.x(), target.y()));
+      FROM_HERE,
+      base::BindOnce(base::IgnoreResult(&ui_controls::SendMouseMove),
+                     target.x(), target.y(), ui_controls::kNoWindowHint));
 }
 
 void MenuViewDragAndDropTestTestInMenuDrag::OnWidgetDragComplete(
@@ -430,8 +432,9 @@
   const gfx::Point target =
       ui_test_utils::GetCenterInScreenCoordinates(drop_target_view);
   GetDragTaskRunner()->PostTask(
-      FROM_HERE, base::BindOnce(base::IgnoreResult(&ui_controls::SendMouseMove),
-                                target.x(), target.y()));
+      FROM_HERE,
+      base::BindOnce(base::IgnoreResult(&ui_controls::SendMouseMove),
+                     target.x(), target.y(), ui_controls::kNoWindowHint));
 }
 
 void MenuViewDragAndDropTestNestedDrag::OnWidgetDragComplete(
diff --git a/chrome/browser/ui/views/permissions/permission_prompt_bubble_view.cc b/chrome/browser/ui/views/permissions/permission_prompt_bubble_view.cc
index d1132d6..2ec1fb6 100644
--- a/chrome/browser/ui/views/permissions/permission_prompt_bubble_view.cc
+++ b/chrome/browser/ui/views/permissions/permission_prompt_bubble_view.cc
@@ -330,6 +330,8 @@
 
   // Set |parent_window| because some valid anchors can become hidden.
   DCHECK(browser_->window());
+  set_parent_window(
+      platform_util::GetViewForWindow(browser_->window()->GetNativeWindow()));
   UpdateAnchorPosition();
 
   views::Widget* widget = views::BubbleDialogDelegateView::CreateBubble(this);
@@ -372,18 +374,12 @@
 }
 
 void PermissionPromptBubbleView::UpdateAnchorPosition() {
+  DCHECK_EQ(browser_->window()->GetNativeWindow(), parent_window());
+
   bubble_anchor_util::AnchorConfiguration configuration =
       bubble_anchor_util::GetPermissionPromptBubbleAnchorConfiguration(
           browser_);
   SetAnchorView(configuration.anchor_view);
-  // In fullscreen, `anchor_view` may be nullptr because the toolbar is hidden,
-  // therefore anchor to the browser window instead.
-  if (configuration.anchor_view) {
-    set_parent_window(configuration.anchor_view->GetWidget()->GetNativeView());
-  } else {
-    set_parent_window(
-        platform_util::GetViewForWindow(browser_->window()->GetNativeWindow()));
-  }
   SetHighlightedButton(configuration.highlighted_button);
   if (!configuration.anchor_view)
     SetAnchorRect(bubble_anchor_util::GetPageInfoAnchorRect(browser_));
diff --git a/chrome/browser/ui/views/side_panel/read_anything/read_anything_model.cc b/chrome/browser/ui/views/side_panel/read_anything/read_anything_model.cc
index f0ef6dd6..339782b8 100644
--- a/chrome/browser/ui/views/side_panel/read_anything/read_anything_model.cc
+++ b/chrome/browser/ui/views/side_panel/read_anything/read_anything_model.cc
@@ -268,10 +268,15 @@
                              ui::kColorReadAnythingForegroundYellow,
                              ui::kColorReadAnythingBackgroundYellow};
 
+  ColorInfo kBlueColors = {u"Blue", IDS_READ_ANYTHING_BLUE_PNG,
+                           ui::kColorReadAnythingForegroundBlue,
+                           ui::kColorReadAnythingBackgroundBlue};
+
   colors_choices_.emplace_back(kDefaultColors);
   colors_choices_.emplace_back(kLightColors);
   colors_choices_.emplace_back(kDarkColors);
   colors_choices_.emplace_back(kYellowColors);
+  colors_choices_.emplace_back(kBlueColors);
   colors_choices_.shrink_to_fit();
 }
 bool ReadAnythingColorsModel::IsValidColorsIndex(size_t index) {
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac.cc b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac.cc
index 793b10c4..4a944de1 100644
--- a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac.cc
@@ -429,639 +429,5 @@
   helper_.CheckWindowNotCreated();
 }
 
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerWindowed_120FileHandlerOneFooFileAllowAskAgain_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerWindowed_120FileHandlerMultipleFooFilesAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
-  helper_.LaunchFileExpectDialog(
-      Site::kFileHandler, FilesOptions::kMultipleFooFiles,
-      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerWindowed_120FileHandlerOneBarFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneBarFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerWindowed_120FileHandlerMultipleBarFilesAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
-  helper_.LaunchFileExpectDialog(
-      Site::kFileHandler, FilesOptions::kMultipleBarFiles,
-      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerWindowed_120FileHandlerOneFooFileAllowRemember_121FileHandlerOneFooFile) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kRemember);
-  helper_.LaunchFileExpectNoDialog(Site::kFileHandler,
-                                   FilesOptions::kOneFooFile);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerWindowed_120FileHandlerOneFooFileDenyAskAgain_127_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kAskAgain);
-  helper_.CheckWindowNotCreated();
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerWindowed_120FileHandlerOneFooFileDenyRemember_127) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kRemember);
-  helper_.CheckWindowNotCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerBrowser_120FileHandlerOneFooFileAllowAskAgain_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerBrowser_120FileHandlerMultipleFooFilesAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser);
-  helper_.LaunchFileExpectDialog(
-      Site::kFileHandler, FilesOptions::kMultipleFooFiles,
-      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerBrowser_120FileHandlerOneBarFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneBarFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerBrowser_120FileHandlerMultipleBarFilesAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser);
-  helper_.LaunchFileExpectDialog(
-      Site::kFileHandler, FilesOptions::kMultipleBarFiles,
-      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerBrowser_120FileHandlerOneFooFileAllowRemember_121FileHandlerOneFooFile) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kRemember);
-  helper_.LaunchFileExpectNoDialog(Site::kFileHandler,
-                                   FilesOptions::kOneFooFile);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerBrowser_120FileHandlerOneFooFileDenyAskAgain_127_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kAskAgain);
-  helper_.CheckWindowNotCreated();
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerBrowser_120FileHandlerOneFooFileDenyRemember_127) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kRemember);
-  helper_.CheckWindowNotCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutWindowedWebApp_120FileHandlerOneFooFileAllowAskAgain_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutWindowedWebApp_120FileHandlerMultipleFooFilesAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.LaunchFileExpectDialog(
-      Site::kFileHandler, FilesOptions::kMultipleFooFiles,
-      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutWindowedWebApp_120FileHandlerOneBarFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneBarFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutWindowedWebApp_120FileHandlerMultipleBarFilesAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.LaunchFileExpectDialog(
-      Site::kFileHandler, FilesOptions::kMultipleBarFiles,
-      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutWindowedWebApp_120FileHandlerOneFooFileAllowRemember_121FileHandlerOneFooFile) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kRemember);
-  helper_.LaunchFileExpectNoDialog(Site::kFileHandler,
-                                   FilesOptions::kOneFooFile);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutWindowedWebApp_120FileHandlerOneFooFileDenyAskAgain_127_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kAskAgain);
-  helper_.CheckWindowNotCreated();
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutWindowedWebApp_120FileHandlerOneFooFileDenyRemember_127) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kRemember);
-  helper_.CheckWindowNotCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutBrowserWebApp_120FileHandlerOneFooFileAllowAskAgain_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutBrowserWebApp_120FileHandlerMultipleFooFilesAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.LaunchFileExpectDialog(
-      Site::kFileHandler, FilesOptions::kMultipleFooFiles,
-      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutBrowserWebApp_120FileHandlerOneBarFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneBarFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutBrowserWebApp_120FileHandlerMultipleBarFilesAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.LaunchFileExpectDialog(
-      Site::kFileHandler, FilesOptions::kMultipleBarFiles,
-      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutBrowserWebApp_120FileHandlerOneFooFileAllowRemember_121FileHandlerOneFooFile) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kRemember);
-  helper_.LaunchFileExpectNoDialog(Site::kFileHandler,
-                                   FilesOptions::kOneFooFile);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutBrowserWebApp_120FileHandlerOneFooFileDenyAskAgain_127_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kAskAgain);
-  helper_.CheckWindowNotCreated();
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutBrowserWebApp_120FileHandlerOneFooFileDenyRemember_127) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kRemember);
-  helper_.CheckWindowNotCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutWindowedWebApp_120FileHandlerOneFooFileAllowAskAgain_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutWindowedWebApp_120FileHandlerMultipleFooFilesAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.LaunchFileExpectDialog(
-      Site::kFileHandler, FilesOptions::kMultipleFooFiles,
-      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutWindowedWebApp_120FileHandlerOneBarFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneBarFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutWindowedWebApp_120FileHandlerMultipleBarFilesAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.LaunchFileExpectDialog(
-      Site::kFileHandler, FilesOptions::kMultipleBarFiles,
-      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutWindowedWebApp_120FileHandlerOneFooFileAllowRemember_121FileHandlerOneFooFile) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kRemember);
-  helper_.LaunchFileExpectNoDialog(Site::kFileHandler,
-                                   FilesOptions::kOneFooFile);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutWindowedWebApp_120FileHandlerOneFooFileDenyAskAgain_127_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kAskAgain);
-  helper_.CheckWindowNotCreated();
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutWindowedWebApp_120FileHandlerOneFooFileDenyRemember_127) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kRemember);
-  helper_.CheckWindowNotCreated();
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutBrowserWebApp_120FileHandlerOneFooFileAllowAskAgain_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutBrowserWebApp_120FileHandlerMultipleFooFilesAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.LaunchFileExpectDialog(
-      Site::kFileHandler, FilesOptions::kMultipleFooFiles,
-      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutBrowserWebApp_120FileHandlerOneBarFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneBarFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutBrowserWebApp_120FileHandlerMultipleBarFilesAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.LaunchFileExpectDialog(
-      Site::kFileHandler, FilesOptions::kMultipleBarFiles,
-      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutBrowserWebApp_120FileHandlerOneFooFileAllowRemember_121FileHandlerOneFooFile) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kRemember);
-  helper_.LaunchFileExpectNoDialog(Site::kFileHandler,
-                                   FilesOptions::kOneFooFile);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutBrowserWebApp_120FileHandlerOneFooFileDenyAskAgain_127_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kAskAgain);
-  helper_.CheckWindowNotCreated();
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutBrowserWebApp_120FileHandlerOneFooFileDenyRemember_127) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kRemember);
-  helper_.CheckWindowNotCreated();
-}
-
 }  // namespace
 }  // namespace web_app::integration_tests
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac_win_linux.cc b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac_win_linux.cc
index cc4fbf4..7197875 100644
--- a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac_win_linux.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_mac_win_linux.cc
@@ -1577,6 +1577,18 @@
 
 IN_PROC_BROWSER_TEST_F(
     WebAppIntegration,
+    WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar) {
+  // Test contents are generated by script. Please do not modify!
+  // See `docs/webapps/why-is-this-test-failing.md` or
+  // `docs/webapps/integration-testing-framework` for more info.
+  // Sheriffs: Disabling this test is supported.
+  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
+  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    WebAppIntegration,
     WAI_32StandaloneNoShortcutWindowedWebApp_12Standalone_101Standalone_111Standalone) {
   // Test contents are generated by script. Please do not modify!
   // See `docs/webapps/why-is-this-test-failing.md` or
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_win_linux.cc b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_win_linux.cc
index 95dea42..b7e2cfb 100644
--- a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_win_linux.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest_win_linux.cc
@@ -319,747 +319,5 @@
   helper_.CheckWindowCreated();
 }
 
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleFooFilesAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(
-      Site::kFileHandler, FilesOptions::kMultipleFooFiles,
-      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneBarFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneBarFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleBarFilesAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(
-      Site::kFileHandler, FilesOptions::kMultipleBarFiles,
-      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowRemember_121FileHandlerOneFooFile) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kRemember);
-  helper_.LaunchFileExpectNoDialog(Site::kFileHandler,
-                                   FilesOptions::kOneFooFile);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyAskAgain_127_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kAskAgain);
-  helper_.CheckWindowNotCreated();
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerWindowed_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyRemember_127_122FileHandlerFoo_122FileHandlerBar) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kWindowed);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kRemember);
-  helper_.CheckWindowNotCreated();
-  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kBar);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerBrowser_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerBrowser_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleFooFilesAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(
-      Site::kFileHandler, FilesOptions::kMultipleFooFiles,
-      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerBrowser_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneBarFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneBarFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerBrowser_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleBarFilesAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(
-      Site::kFileHandler, FilesOptions::kMultipleBarFiles,
-      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerBrowser_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowRemember_121FileHandlerOneFooFile) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kRemember);
-  helper_.LaunchFileExpectNoDialog(Site::kFileHandler,
-                                   FilesOptions::kOneFooFile);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerBrowser_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyAskAgain_127_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kAskAgain);
-  helper_.CheckWindowNotCreated();
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_29FileHandlerBrowser_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyRemember_127_122FileHandlerFoo_122FileHandlerBar) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.CreateShortcut(Site::kFileHandler, WindowOptions::kBrowser);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kRemember);
-  helper_.CheckWindowNotCreated();
-  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kBar);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleFooFilesAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(
-      Site::kFileHandler, FilesOptions::kMultipleFooFiles,
-      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneBarFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneBarFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleBarFilesAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(
-      Site::kFileHandler, FilesOptions::kMultipleBarFiles,
-      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowRemember_121FileHandlerOneFooFile) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kRemember);
-  helper_.LaunchFileExpectNoDialog(Site::kFileHandler,
-                                   FilesOptions::kOneFooFile);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyAskAgain_127_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kAskAgain);
-  helper_.CheckWindowNotCreated();
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyRemember_127_122FileHandlerFoo_122FileHandlerBar) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kRemember);
-  helper_.CheckWindowNotCreated();
-  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kBar);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleFooFilesAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(
-      Site::kFileHandler, FilesOptions::kMultipleFooFiles,
-      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneBarFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneBarFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleBarFilesAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(
-      Site::kFileHandler, FilesOptions::kMultipleBarFiles,
-      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowRemember_121FileHandlerOneFooFile) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kRemember);
-  helper_.LaunchFileExpectNoDialog(Site::kFileHandler,
-                                   FilesOptions::kOneFooFile);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyAskAgain_127_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kAskAgain);
-  helper_.CheckWindowNotCreated();
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerWithShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyRemember_127_122FileHandlerFoo_122FileHandlerBar) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kWithShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kRemember);
-  helper_.CheckWindowNotCreated();
-  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kBar);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleFooFilesAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(
-      Site::kFileHandler, FilesOptions::kMultipleFooFiles,
-      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneBarFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneBarFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleBarFilesAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(
-      Site::kFileHandler, FilesOptions::kMultipleBarFiles,
-      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowRemember_121FileHandlerOneFooFile) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kRemember);
-  helper_.LaunchFileExpectNoDialog(Site::kFileHandler,
-                                   FilesOptions::kOneFooFile);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyAskAgain_127_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kAskAgain);
-  helper_.CheckWindowNotCreated();
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutWindowedWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyRemember_127_122FileHandlerFoo_122FileHandlerBar) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kWindowed, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kRemember);
-  helper_.CheckWindowNotCreated();
-  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kBar);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleFooFilesAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(
-      Site::kFileHandler, FilesOptions::kMultipleFooFiles,
-      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneBarFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneBarFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerMultipleBarFilesAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(
-      Site::kFileHandler, FilesOptions::kMultipleBarFiles,
-      AllowDenyOptions::kAllow, AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowRemember_121FileHandlerOneFooFile) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kRemember);
-  helper_.LaunchFileExpectNoDialog(Site::kFileHandler,
-                                   FilesOptions::kOneFooFile);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyAskAgain_127_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileAllowAskAgain) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kAskAgain);
-  helper_.CheckWindowNotCreated();
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kAllow,
-                                 AskAgainOptions::kAskAgain);
-}
-
-IN_PROC_BROWSER_TEST_F(
-    WebAppIntegration,
-    WAI_32FileHandlerNoShortcutBrowserWebApp_118FileHandlerFoo_118FileHandlerBar_120FileHandlerOneFooFileDenyRemember_127_122FileHandlerFoo_122FileHandlerBar) {
-  // Test contents are generated by script. Please do not modify!
-  // See `docs/webapps/why-is-this-test-failing.md` or
-  // `docs/webapps/integration-testing-framework` for more info.
-  // Sheriffs: Disabling this test is supported.
-  helper_.InstallPolicyApp(Site::kFileHandler, ShortcutOptions::kNoShortcut,
-                           WindowOptions::kBrowser, InstallMode::kWebApp);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteHandlesFile(Site::kFileHandler, FileExtension::kBar);
-  helper_.LaunchFileExpectDialog(Site::kFileHandler, FilesOptions::kOneFooFile,
-                                 AllowDenyOptions::kDeny,
-                                 AskAgainOptions::kRemember);
-  helper_.CheckWindowNotCreated();
-  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kFoo);
-  helper_.CheckSiteNotHandlesFile(Site::kFileHandler, FileExtension::kBar);
-}
-
 }  // namespace
 }  // namespace web_app::integration_tests
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 6540fb7..a75b3c0 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
@@ -47,6 +47,7 @@
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/frame/browser_view_layout.h"
 #include "chrome/browser/ui/views/frame/toolbar_button_provider.h"
+#include "chrome/browser/ui/views/intent_picker_bubble_view.h"
 #include "chrome/browser/ui/views/location_bar/custom_tab_bar_view.h"
 #include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
 #include "chrome/browser/ui/views/page_info/page_info_bubble_view.h"
@@ -1273,6 +1274,8 @@
 void WebAppIntegrationTestDriver::LaunchFromLaunchIcon(Site site) {
   if (!BeforeStateChangeAction(__FUNCTION__))
     return;
+  base::AutoReset<bool> intent_picker_bubble_scope =
+      IntentPickerBubbleView::SetAutoAcceptIntentPickerBubbleForTesting();
   AppId app_id = GetAppIdBySiteMode(site);
   ASSERT_TRUE(provider()->registrar().GetAppById(app_id))
       << "No app installed for site: " << static_cast<int>(site);
@@ -1280,22 +1283,20 @@
   NavigateTabbedBrowserToSite(GetInScopeURL(site), NavigationMode::kNewTab);
 
   ASSERT_TRUE(intent_picker_view()->GetVisible());
-
   BrowserAddedWaiter browser_added_waiter;
 
-  if (!IntentPickerBubbleView::intent_picker_bubble()) {
+  if (IntentPickerBubbleView::intent_picker_bubble()) {
+    // This means that the intent_picker_bubble has shown up before the scoped
+    // response was provided. Manually accept the bubble.
+    IntentPickerBubbleView::intent_picker_bubble()->AcceptDialog();
+  } else {
     views::NamedWidgetShownWaiter waiter(
         views::test::AnyWidgetTestPasskey{},
         IntentPickerBubbleView::kViewClassName);
-    EXPECT_FALSE(IntentPickerBubbleView::intent_picker_bubble());
     intent_picker_view()->ExecuteForTesting();
     waiter.WaitIfNeededAndGet();
   }
 
-  ASSERT_TRUE(IntentPickerBubbleView::intent_picker_bubble());
-  EXPECT_TRUE(IntentPickerBubbleView::intent_picker_bubble()->GetVisible());
-
-  IntentPickerBubbleView::intent_picker_bubble()->AcceptDialog();
   browser_added_waiter.Wait();
   app_browser_ = browser_added_waiter.browser_added();
   ActivateBrowserAndWait(app_browser_);
diff --git a/chrome/browser/ui/web_applications/lacros_web_app_shelf_browsertest.cc b/chrome/browser/ui/web_applications/lacros_web_app_shelf_browsertest.cc
index c1dd734..7bc33e3f 100644
--- a/chrome/browser/ui/web_applications/lacros_web_app_shelf_browsertest.cc
+++ b/chrome/browser/ui/web_applications/lacros_web_app_shelf_browsertest.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
@@ -111,6 +112,8 @@
   ASSERT_TRUE(browser_test_util::WaitForShelfItemState(
       app1_id, static_cast<uint32_t>(ShelfItemState::kActive)));
 
+  ASSERT_TRUE(AddTabAtIndex(/*index=*/1, app1_url, ui::PAGE_TRANSITION_TYPED));
+
   AppReadinessWaiter(profile(), app2_id).Await();
   LaunchWebAppBrowser(profile(), app2_id);
   ASSERT_TRUE(browser_test_util::WaitForShelfItemState(
@@ -119,6 +122,8 @@
       app1_id, static_cast<uint32_t>(ShelfItemState::kRunning)));
 
   CloseAndWait(app_browser1);
+  // A tab open at app1_url is not sufficient for the app to be considered
+  // running.
   ASSERT_TRUE(browser_test_util::WaitForShelfItemState(
       app1_id, static_cast<uint32_t>(ShelfItemState::kNormal)));
 
@@ -131,6 +136,58 @@
   test::UninstallWebApp(profile(), app1_id);
 }
 
+// Navigating out of scope in an app window does not affect which app is
+// considered running.
+IN_PROC_BROWSER_TEST_F(LacrosWebAppShelfBrowserTest, Navigation) {
+  if (!IsServiceAvailable())
+    GTEST_SKIP();
+
+  const GURL app1_url =
+      https_server().GetURL(kFirstAppUrlHost, "/web_apps/basic.html");
+  const AppId app1_id =
+      InstallWebAppFromPageAndCloseAppBrowser(browser(), app1_url);
+
+  const GURL app2_url = https_server().GetURL(
+      kSecondAppUrlHost, "/web_app_shortcuts/shortcuts.html");
+  const AppId app2_id =
+      InstallWebAppFromPageAndCloseAppBrowser(browser(), app2_url);
+
+  GURL out_of_scope_url = https_server().GetURL("/empty.html");
+
+  Browser* app_browser1 = LaunchWebAppBrowser(profile(), app1_id);
+  {
+    NavigateParams params(app_browser1, out_of_scope_url,
+                          ui::PAGE_TRANSITION_LINK);
+    params.tabstrip_index = app_browser1->tab_strip_model()->active_index();
+    params.disposition = WindowOpenDisposition::CURRENT_TAB;
+    Navigate(&params);
+    ASSERT_TRUE(
+        content::WaitForLoadStop(params.navigated_or_inserted_contents));
+    EXPECT_EQ(app_browser1->tab_strip_model()->count(), 1);
+    EXPECT_EQ(app_browser1->tab_strip_model()
+                  ->GetActiveWebContents()
+                  ->GetLastCommittedURL(),
+              out_of_scope_url);
+  }
+  ASSERT_TRUE(browser_test_util::WaitForShelfItemState(
+      app1_id, static_cast<uint32_t>(ShelfItemState::kActive)));
+
+  LaunchWebAppBrowser(profile(), app2_id);
+  ASSERT_TRUE(browser_test_util::WaitForShelfItemState(
+      app2_id, static_cast<uint32_t>(ShelfItemState::kActive)));
+  ASSERT_TRUE(browser_test_util::WaitForShelfItemState(
+      app1_id, static_cast<uint32_t>(ShelfItemState::kRunning)));
+
+  app_browser1->window()->Activate();
+  ASSERT_TRUE(browser_test_util::WaitForShelfItemState(
+      app1_id, static_cast<uint32_t>(ShelfItemState::kActive)));
+  ASSERT_TRUE(browser_test_util::WaitForShelfItemState(
+      app2_id, static_cast<uint32_t>(ShelfItemState::kRunning)));
+
+  test::UninstallWebApp(profile(), app1_id);
+  test::UninstallWebApp(profile(), app2_id);
+}
+
 IN_PROC_BROWSER_TEST_F(LacrosWebAppShelfBrowserTest, BadgeShown) {
   if (!IsServiceAvailable())
     GTEST_SKIP();
@@ -233,6 +290,29 @@
       app_constants::kLacrosAppId,
       static_cast<uint32_t>(ShelfItemState::kRunning)));
 
+  tab_strip_model->CloseWebContentsAt(tab_strip_model->active_index(),
+                                      TabCloseTypes::CLOSE_NONE);
+  ASSERT_TRUE(AddTabAtIndex(/*index=*/1, app2_url, ui::PAGE_TRANSITION_TYPED));
+  ASSERT_TRUE(browser_test_util::WaitForShelfItemState(
+      app1_id, static_cast<uint32_t>(ShelfItemState::kNormal)));
+  ASSERT_TRUE(browser_test_util::WaitForShelfItemState(
+      app2_id, static_cast<uint32_t>(ShelfItemState::kActive)));
+
+  // Navigation is sufficient to change which app is considered running.
+  {
+    NavigateParams params(browser(), app1_url, ui::PAGE_TRANSITION_TYPED);
+    params.tabstrip_index = tab_strip_model->active_index();
+    params.disposition = WindowOpenDisposition::CURRENT_TAB;
+    Navigate(&params);
+    ASSERT_TRUE(
+        content::WaitForLoadStop(params.navigated_or_inserted_contents));
+  }
+
+  ASSERT_TRUE(browser_test_util::WaitForShelfItemState(
+      app2_id, static_cast<uint32_t>(ShelfItemState::kNormal)));
+  ASSERT_TRUE(browser_test_util::WaitForShelfItemState(
+      app1_id, static_cast<uint32_t>(ShelfItemState::kActive)));
+
   test::UninstallWebApp(profile(), app1_id);
   test::UninstallWebApp(profile(), app2_id);
 }
diff --git a/chrome/browser/ui/web_applications/web_app_ui_manager_impl_browsertest.cc b/chrome/browser/ui/web_applications/web_app_ui_manager_impl_browsertest.cc
index a329183..675e96f 100644
--- a/chrome/browser/ui/web_applications/web_app_ui_manager_impl_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_ui_manager_impl_browsertest.cc
@@ -31,10 +31,10 @@
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/public/cpp/app_list/internal_app_id_constants.h"
+#include "chrome/browser/ash/app_list/test/chrome_app_list_test_support.h"
 #include "chrome/browser/ui/app_list/app_list_model_updater.h"
 #include "chrome/browser/ui/app_list/app_list_syncable_service.h"
 #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h"
-#include "chrome/browser/ui/app_list/test/chrome_app_list_test_support.h"
 #endif
 
 namespace web_app {
diff --git a/chrome/browser/ui/webui/access_code_cast/access_code_cast_ui.cc b/chrome/browser/ui/webui/access_code_cast/access_code_cast_ui.cc
index fd734eee6..03dc697 100644
--- a/chrome/browser/ui/webui/access_code_cast/access_code_cast_ui.cc
+++ b/chrome/browser/ui/webui/access_code_cast/access_code_cast_ui.cc
@@ -31,7 +31,6 @@
       source.get(),
       base::make_span(kAccessCodeCastResources, kAccessCodeCastResourcesSize),
       IDR_ACCESS_CODE_CAST_INDEX_HTML);
-  webui::EnableTrustedTypesCSP(source.get());
 
   static constexpr webui::LocalizedString kStrings[] = {
       {"accessCodeMessage", IDS_ACCESS_CODE_CAST_ACCESS_CODE_MESSAGE},
diff --git a/chrome/browser/ui/webui/app_home/app_home.mojom b/chrome/browser/ui/webui/app_home/app_home.mojom
index f3395193..e55572f 100644
--- a/chrome/browser/ui/webui/app_home/app_home.mojom
+++ b/chrome/browser/ui/webui/app_home/app_home.mojom
@@ -67,6 +67,8 @@
   LaunchApp(string app_id, int32 source, ClickEvent? click_event);
   // Used to set the Run On OS Login Modes from the frontend of an app.
   SetRunOnOsLoginMode(string app_id, RunOnOsLoginMode run_on_os_login_mode);
+  // Open the deprecated apps dialog.
+  LaunchDeprecatedAppDialog();
 };
 
 // The `Page` interface is used for sending mojom action messsage
diff --git a/chrome/browser/ui/webui/app_home/app_home_page_handler.cc b/chrome/browser/ui/webui/app_home/app_home_page_handler.cc
index 651bc9b..0a0fc938 100644
--- a/chrome/browser/ui/webui/app_home/app_home_page_handler.cc
+++ b/chrome/browser/ui/webui/app_home/app_home_page_handler.cc
@@ -23,9 +23,11 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/extensions/extension_enable_flow.h"
+#include "chrome/browser/ui/tab_dialogs.h"
 #include "chrome/browser/ui/web_applications/web_app_dialog_manager.h"
 #include "chrome/browser/ui/web_applications/web_app_ui_manager_impl.h"
 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
+#include "chrome/browser/web_applications/extension_status_utils.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_command_scheduler.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
@@ -202,9 +204,23 @@
                                                ExtensionRegistry::DISABLED |
                                                ExtensionRegistry::TERMINATED);
   for (const auto& extension : *extension_apps) {
-    if (extensions::ui_util::ShouldDisplayInNewTabPage(extension.get(),
-                                                       profile_))
-      result->emplace_back(CreateAppInfoPtrFromExtension(extension.get()));
+    if (!extensions::ui_util::ShouldDisplayInNewTabPage(extension.get(),
+                                                        profile_)) {
+      continue;
+    }
+
+    bool is_deprecated_app = false;
+    auto* context = extension_service_->GetBrowserContext();
+#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \
+    BUILDFLAG(IS_FUCHSIA)
+    is_deprecated_app = extensions::IsExtensionUnsupportedDeprecatedApp(
+        context, extension->id());
+#endif
+    if (is_deprecated_app && !extensions::IsExtensionForceInstalled(
+                                 context, extension->id(), nullptr)) {
+      deprecated_app_ids_.insert(extension->id());
+    }
+    result->emplace_back(CreateAppInfoPtrFromExtension(extension.get()));
   }
 }
 
@@ -278,6 +294,19 @@
       extensions::UNINSTALL_SOURCE_CHROME_APPS_PAGE);
 }
 
+void AppHomePageHandler::ExtensionRemoved(const Extension* extension) {
+  if (deprecated_app_ids_.find(extension->id()) != deprecated_app_ids_.end())
+    deprecated_app_ids_.erase(extension->id());
+
+  if (!extension->is_app() ||
+      !extensions::ui_util::ShouldDisplayInNewTabPage(extension, profile_))
+    return;
+
+  auto app_info = app_home::mojom::AppInfo::New();
+  app_info->id = extension->id();
+  page_->RemoveApp(std::move(app_info));
+}
+
 void AppHomePageHandler::OnWebAppWillBeUninstalled(
     const web_app::AppId& app_id) {
   auto app_info = app_home::mojom::AppInfo::New();
@@ -299,13 +328,18 @@
   page_->AddApp(CreateAppInfoPtrFromExtension(extension));
 }
 
+void AppHomePageHandler::OnExtensionUnloaded(
+    content::BrowserContext* browser_context,
+    const Extension* extension,
+    extensions::UnloadedExtensionReason reason) {
+  ExtensionRemoved(extension);
+}
+
 void AppHomePageHandler::OnExtensionUninstalled(
     content::BrowserContext* browser_context,
     const Extension* extension,
     extensions::UninstallReason reason) {
-  auto app_info = app_home::mojom::AppInfo::New();
-  app_info->id = extension->id();
-  page_->RemoveApp(std::move(app_info));
+  ExtensionRemoved(extension);
 }
 
 void AppHomePageHandler::PromptToEnableExtensionApp(
@@ -528,4 +562,10 @@
       app_id, run_on_os_login_mode, base::DoNothing());
 }
 
+void AppHomePageHandler::LaunchDeprecatedAppDialog() {
+  TabDialogs::FromWebContents(web_ui_->GetWebContents())
+      ->ShowDeprecatedAppsDialog(extensions::ExtensionId(), deprecated_app_ids_,
+                                 web_ui_->GetWebContents(), base::DoNothing());
+}
+
 }  // namespace webapps
diff --git a/chrome/browser/ui/webui/app_home/app_home_page_handler.h b/chrome/browser/ui/webui/app_home/app_home_page_handler.h
index b9001ad..6f9eb128 100644
--- a/chrome/browser/ui/webui/app_home/app_home_page_handler.h
+++ b/chrome/browser/ui/webui/app_home/app_home_page_handler.h
@@ -67,6 +67,9 @@
   void OnExtensionUninstalled(content::BrowserContext* browser_context,
                               const extensions::Extension* extension,
                               extensions::UninstallReason reason) override;
+  void OnExtensionUnloaded(content::BrowserContext* browser_context,
+                           const extensions::Extension* extension,
+                           extensions::UnloadedExtensionReason reason) override;
 
   // web_app::AppRegistrarObserver:
   void OnWebAppRunOnOsLoginModeChanged(
@@ -86,6 +89,7 @@
   void SetRunOnOsLoginMode(
       const std::string& app_id,
       web_app::RunOnOsLoginMode run_on_os_login_mode) override;
+  void LaunchDeprecatedAppDialog() override;
 
  private:
   Browser* GetCurrentBrowser();
@@ -100,6 +104,8 @@
   // Reset some instance flags we use to track the currently prompting app.
   void ResetExtensionDialogState();
 
+  void ExtensionRemoved(const extensions::Extension* extension);
+
   // ExtensionUninstallDialog::Delegate:
   void OnExtensionUninstallDialogClosed(bool did_start_uninstall,
                                         const std::u16string& error) override;
@@ -153,6 +159,8 @@
 
   // Used to show confirmation UI for enabling extensions.
   std::unique_ptr<ExtensionEnableFlow> extension_enable_flow_;
+  // Set of deprecated app ids for showing on dialog.
+  std::set<extensions::ExtensionId> deprecated_app_ids_;
 
   // Used for passing callbacks.
   base::WeakPtrFactory<AppHomePageHandler> weak_ptr_factory_{this};
diff --git a/chrome/browser/ui/webui/app_home/app_home_page_handler_browsertest.cc b/chrome/browser/ui/webui/app_home/app_home_page_handler_browsertest.cc
index 796b08d..d6d5ba9 100644
--- a/chrome/browser/ui/webui/app_home/app_home_page_handler_browsertest.cc
+++ b/chrome/browser/ui/webui/app_home/app_home_page_handler_browsertest.cc
@@ -25,6 +25,7 @@
 #include "content/public/test/test_web_ui.h"
 #include "extensions/browser/extension_dialog_auto_confirm.h"
 #include "extensions/common/extension_builder.h"
+#include "extensions/common/manifest_constants.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "ui/views/test/dialog_test.h"
 #include "ui/views/widget/any_widget_observer.h"
@@ -195,8 +196,19 @@
   }
 
   scoped_refptr<const extensions::Extension> InstallTestExtensionApp() {
-    scoped_refptr<const extensions::Extension> extension =
-        extensions::ExtensionBuilder(kTestAppName).Build();
+    base::DictionaryValue manifest;
+    manifest.SetString(extensions::manifest_keys::kName, kTestAppName);
+    manifest.SetString(extensions::manifest_keys::kVersion, "0.0.0.0");
+    manifest.SetString(extensions::manifest_keys::kApp, "true");
+    manifest.SetString(extensions::manifest_keys::kPlatformAppBackgroundPage,
+                       std::string());
+
+    std::string error;
+    scoped_refptr<extensions::Extension> extension =
+        extensions::Extension::Create(
+            base::FilePath(), extensions::mojom::ManifestLocation::kUnpacked,
+            manifest, 0, &error);
+
     extension_service()->AddExtension(extension.get());
     return extension;
   }
diff --git a/chrome/browser/ui/webui/app_home/app_home_ui.cc b/chrome/browser/ui/webui/app_home/app_home_ui.cc
index 655aeac..013deee 100644
--- a/chrome/browser/ui/webui/app_home/app_home_ui.cc
+++ b/chrome/browser/ui/webui/app_home/app_home_ui.cc
@@ -20,7 +20,6 @@
   webui::SetupWebUIDataSource(
       source, base::make_span(kAppHomeResources, kAppHomeResourcesSize),
       IDR_APP_HOME_APP_HOME_HTML);
-  webui::EnableTrustedTypesCSP(source);
   Profile* profile = Profile::FromWebUI(web_ui);
   content::WebUIDataSource::Add(profile, source);
 }
diff --git a/chrome/browser/ui/webui/app_service_internals/app_service_internals_ui.cc b/chrome/browser/ui/webui/app_service_internals/app_service_internals_ui.cc
index b7654ac1..2e41c75 100644
--- a/chrome/browser/ui/webui/app_service_internals/app_service_internals_ui.cc
+++ b/chrome/browser/ui/webui/app_service_internals/app_service_internals_ui.cc
@@ -25,7 +25,6 @@
       base::make_span(kAppServiceInternalsResources,
                       kAppServiceInternalsResourcesSize),
       IDR_APP_SERVICE_INTERNALS_INDEX_HTML);
-  webui::EnableTrustedTypesCSP(source);
 
   content::WebUIDataSource::Add(profile_, source);
 }
diff --git a/chrome/browser/ui/webui/app_settings/web_app_settings_ui.cc b/chrome/browser/ui/webui/app_settings/web_app_settings_ui.cc
index 6252efc..baf0fff4 100644
--- a/chrome/browser/ui/webui/app_settings/web_app_settings_ui.cc
+++ b/chrome/browser/ui/webui/app_settings/web_app_settings_ui.cc
@@ -89,7 +89,6 @@
       html_source,
       base::make_span(kAppSettingsResources, kAppSettingsResourcesSize),
       IDR_APP_SETTINGS_WEB_APP_SETTINGS_HTML);
-  webui::EnableTrustedTypesCSP(html_source);
 
   Profile* profile = Profile::FromWebUI(web_ui);
   content::WebUIDataSource::Add(profile, html_source);
diff --git a/chrome/browser/ui/webui/ash/emoji/emoji_page_handler.cc b/chrome/browser/ui/webui/ash/emoji/emoji_page_handler.cc
index 48b782f..e7e4b31 100644
--- a/chrome/browser/ui/webui/ash/emoji/emoji_page_handler.cc
+++ b/chrome/browser/ui/webui/ash/emoji/emoji_page_handler.cc
@@ -159,6 +159,11 @@
     enabled_features.push_back(
         emoji_picker::mojom::Feature::EMOJI_PICKER_SEARCH_EXTENSION);
   }
+  if (base::FeatureList::IsEnabled(features::kImeSystemEmojiPickerGIFSupport)) {
+    enabled_features.push_back(
+        emoji_picker::mojom::Feature::EMOJI_PICKER_GIF_SUPPORT);
+  }
+
   std::move(callback).Run(enabled_features);
 }
 
diff --git a/chrome/browser/ui/webui/ash/emoji/emoji_picker.mojom b/chrome/browser/ui/webui/ash/emoji/emoji_picker.mojom
index cbac059..dfbf5896 100644
--- a/chrome/browser/ui/webui/ash/emoji/emoji_picker.mojom
+++ b/chrome/browser/ui/webui/ash/emoji/emoji_picker.mojom
@@ -12,6 +12,9 @@
   // Extends the search functionality of emoji picker by implementing multi word
   // prefix search across all categories.
   EMOJI_PICKER_SEARCH_EXTENSION = 1,
+  // Extends the emoji picker to include gifs as an insertable option for the
+  // user.
+  EMOJI_PICKER_GIF_SUPPORT = 2,
 };
 
 // Used by the WebUI page to bootstrap bidirectional communication.
diff --git a/chrome/browser/ui/webui/ash/launcher_internals/launcher_internals_handler.cc b/chrome/browser/ui/webui/ash/launcher_internals/launcher_internals_handler.cc
index e0c46260..7ab8618 100644
--- a/chrome/browser/ui/webui/ash/launcher_internals/launcher_internals_handler.cc
+++ b/chrome/browser/ui/webui/ash/launcher_internals/launcher_internals_handler.cc
@@ -5,8 +5,8 @@
 #include "chrome/browser/ui/webui/ash/launcher_internals/launcher_internals_handler.h"
 
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/ash/app_list/search/common/types_util.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
-#include "chrome/browser/ui/app_list/search/common/types_util.h"
 
 namespace ash {
 
diff --git a/chrome/browser/ui/webui/bookmarks/bookmarks_ui.cc b/chrome/browser/ui/webui/bookmarks/bookmarks_ui.cc
index 6bd71ecf..4babca9 100644
--- a/chrome/browser/ui/webui/bookmarks/bookmarks_ui.cc
+++ b/chrome/browser/ui/webui/bookmarks/bookmarks_ui.cc
@@ -49,7 +49,6 @@
   webui::SetupWebUIDataSource(
       source, base::make_span(kBookmarksResources, kBookmarksResourcesSize),
       IDR_BOOKMARKS_BOOKMARKS_HTML);
-  webui::EnableTrustedTypesCSP(source);
 
   // Build an Accelerator to describe undo shortcut
   // NOTE: the undo shortcut is also defined in bookmarks/command_manager.js
diff --git a/chrome/browser/ui/webui/browser_switch/browser_switch_ui.cc b/chrome/browser/ui/webui/browser_switch/browser_switch_ui.cc
index ff76de5..cb2bdb2 100644
--- a/chrome/browser/ui/webui/browser_switch/browser_switch_ui.cc
+++ b/chrome/browser/ui/webui/browser_switch/browser_switch_ui.cc
@@ -195,7 +195,6 @@
       source,
       base::make_span(kBrowserSwitchResources, kBrowserSwitchResourcesSize),
       IDR_BROWSER_SWITCH_BROWSER_SWITCH_HTML);
-  webui::EnableTrustedTypesCSP(source);
 
   // Setup chrome://browser-switch/internals debug UI.
   source->AddResourcePath(
diff --git a/chrome/browser/ui/webui/browsing_topics/browsing_topics_internals_ui.cc b/chrome/browser/ui/webui/browsing_topics/browsing_topics_internals_ui.cc
index bfe2dfd..52af0b6 100644
--- a/chrome/browser/ui/webui/browsing_topics/browsing_topics_internals_ui.cc
+++ b/chrome/browser/ui/webui/browsing_topics/browsing_topics_internals_ui.cc
@@ -25,7 +25,6 @@
       base::make_span(kBrowsingTopicsInternalsResources,
                       kBrowsingTopicsInternalsResourcesSize),
       IDR_BROWSING_TOPICS_INTERNALS_BROWSING_TOPICS_INTERNALS_HTML);
-  webui::EnableTrustedTypesCSP(source);
 
   content::WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(),
                                 source);
diff --git a/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc b/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc
index 6a0d76d..ba155c55 100644
--- a/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc
+++ b/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc
@@ -31,6 +31,7 @@
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
 #include "media/base/media_switches.h"
+#include "ui/accessibility/accessibility_features.h"
 
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
 #include "chrome/browser/signin/signin_features.h"
@@ -156,10 +157,13 @@
  public:
   ChromeURLDataManagerWebUITrustedTypesTest() {
     std::vector<base::test::FeatureRef> enabled_features;
+    enabled_features.push_back(features::kChromeWhatsNewUI);
     enabled_features.push_back(features::kSidePanelJourneys);
     enabled_features.push_back(features::kSupportTool);
     enabled_features.push_back(
         password_manager::features::kPasswordManagerRedesign);
+    enabled_features.push_back(features::kReadAnything);
+
 #if !BUILDFLAG(IS_CHROMEOS)
     if (GetParam() == std::string("chrome://welcome"))
       enabled_features.push_back(welcome::kForceEnabled);
@@ -273,6 +277,8 @@
     "chrome://connection-monitoring-detected",
     "chrome://crashes",
     "chrome://credits",
+    // TODO(crbug/1396866): Enable when bug is fixed.
+    // "chrome://customize-chrome-side-panel.top-chrome",
     "chrome://device-log",
     // "chrome://dino",
     // TODO(crbug.com/1113446): Test failure due to excessive output.
@@ -322,6 +328,8 @@
     "chrome://privacy-sandbox-dialog/?debug",
     "chrome://process-internals",
     "chrome://quota-internals",
+    "chrome://read-anything-side-panel.top-chrome",
+    "chrome://read-later.top-chrome",
     "chrome://reset-password",
     "chrome://safe-browsing",
     "chrome://serviceworker-internals",
@@ -347,11 +355,18 @@
     "chrome://ukm",
     "chrome://usb-internals",
     "chrome://user-actions",
+    "chrome://user-notes-side-panel.top-chrome",
     "chrome://version",
     "chrome://web-app-internals",
     "chrome://webrtc-internals",
     "chrome://webrtc-logs",
     "chrome://webui-gallery",
+    "chrome://whats-new",
+
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
+    "chrome://cast-feedback",
+#endif
+
 #if BUILDFLAG(IS_ANDROID)
     "chrome://explore-sites-internals",
     "chrome://internals/notifications",
@@ -360,6 +375,7 @@
     "chrome://snippets-internals",
     "chrome://webapks",
 #endif
+
 #if BUILDFLAG(IS_CHROMEOS_ASH)
     // "chrome://account-manager-error",
     // "chrome://account-migration-welcome",
@@ -397,6 +413,7 @@
 #if !BUILDFLAG(IS_CHROMEOS)
     "chrome://apps",
     "chrome://browser-switch",
+    "chrome://browser-switch/internals",
     "chrome://profile-picker",
     "chrome://welcome",
 #endif
diff --git a/chrome/browser/ui/webui/commander/commander_ui.cc b/chrome/browser/ui/webui/commander/commander_ui.cc
index 1ebb496..e3669155d 100644
--- a/chrome/browser/ui/webui/commander/commander_ui.cc
+++ b/chrome/browser/ui/webui/commander/commander_ui.cc
@@ -34,7 +34,6 @@
   webui::SetupWebUIDataSource(
       source, base::make_span(kCommanderResources, kCommanderResourcesSize),
       IDR_COMMANDER_COMMANDER_HTML);
-  webui::EnableTrustedTypesCSP(source);
 
   Profile* profile = Profile::FromWebUI(web_ui);
   content::WebUIDataSource::Add(profile, source);
diff --git a/chrome/browser/ui/webui/device_log_ui.cc b/chrome/browser/ui/webui/device_log_ui.cc
index 205a9cfd..95d5668 100644
--- a/chrome/browser/ui/webui/device_log_ui.cc
+++ b/chrome/browser/ui/webui/device_log_ui.cc
@@ -92,6 +92,7 @@
       {"logTypeFidoText", IDS_DEVICE_LOG_TYPE_FIDO},
       {"logTypeSerialText", IDS_DEVICE_LOG_TYPE_SERIAL},
       {"logTypeCameraText", IDS_DEVICE_LOG_TYPE_CAMERA},
+      {"logTypeGeolocationText", IDS_DEVICE_LOG_TYPE_GEOLOCATION},
       {"logEntryFormat", IDS_DEVICE_LOG_ENTRY},
   };
   html->AddLocalizedStrings(kStrings);
diff --git a/chrome/browser/ui/webui/discards/discards.mojom b/chrome/browser/ui/webui/discards/discards.mojom
index 67639ae..92c3b4e 100644
--- a/chrome/browser/ui/webui/discards/discards.mojom
+++ b/chrome/browser/ui/webui/discards/discards.mojom
@@ -52,11 +52,6 @@
   // This can be manipulated by the chrome://discards UI, or via the discards
   // extension API.
   bool is_auto_discardable;
-  // True if a reactivation score is calculated for the tab. Reactivation score
-  // can be predicted only for background tabs.
-  bool has_reactivation_score;
-  // Tab Ranker reactivation score, if |has_reactivation_score| is true.
-  double reactivation_score;
   // Site engagement score.
   double site_engagement_score;
   // Whether or not the tab has input focus.
diff --git a/chrome/browser/ui/webui/discards/discards_ui.cc b/chrome/browser/ui/webui/discards/discards_ui.cc
index 1d2666f5..bbf5d43 100644
--- a/chrome/browser/ui/webui/discards/discards_ui.cc
+++ b/chrome/browser/ui/webui/discards/discards_ui.cc
@@ -18,7 +18,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/resource_coordinator/lifecycle_unit.h"
 #include "chrome/browser/resource_coordinator/lifecycle_unit_state.mojom.h"
-#include "chrome/browser/resource_coordinator/tab_activity_watcher.h"
 #include "chrome/browser/resource_coordinator/tab_lifecycle_unit_external.h"
 #include "chrome/browser/resource_coordinator/tab_manager.h"
 #include "chrome/browser/resource_coordinator/time.h"
@@ -154,12 +153,6 @@
       info->is_auto_discardable =
           tab_lifecycle_unit_external->IsAutoDiscardable();
       info->id = lifecycle_unit->GetID();
-      absl::optional<float> reactivation_score =
-          resource_coordinator::TabActivityWatcher::GetInstance()
-              ->CalculateReactivationScore(contents);
-      info->has_reactivation_score = reactivation_score.has_value();
-      if (info->has_reactivation_score)
-        info->reactivation_score = reactivation_score.value();
       info->site_engagement_score = GetSiteEngagementScore(contents);
       info->state_change_time =
           lifecycle_unit->GetStateChangeTime() - base::TimeTicks::UnixEpoch();
@@ -255,7 +248,6 @@
   webui::SetupWebUIDataSource(
       source.get(), base::make_span(kDiscardsResources, kDiscardsResourcesSize),
       IDR_DISCARDS_DISCARDS_HTML);
-  webui::EnableTrustedTypesCSP(source.get());
 
   Profile* profile = Profile::FromWebUI(web_ui);
   content::WebUIDataSource::Add(profile, source.release());
diff --git a/chrome/browser/ui/webui/downloads/downloads_ui.cc b/chrome/browser/ui/webui/downloads/downloads_ui.cc
index f96d0d0..ff71b606 100644
--- a/chrome/browser/ui/webui/downloads/downloads_ui.cc
+++ b/chrome/browser/ui/webui/downloads/downloads_ui.cc
@@ -62,7 +62,6 @@
   webui::SetupWebUIDataSource(
       source, base::make_span(kDownloadsResources, kDownloadsResourcesSize),
       IDR_DOWNLOADS_DOWNLOADS_HTML);
-  webui::EnableTrustedTypesCSP(source);
 
   bool requests_ap_verdicts =
       safe_browsing::AdvancedProtectionStatusManagerFactory::GetForProfile(
diff --git a/chrome/browser/ui/webui/extensions/extensions_internals_source.cc b/chrome/browser/ui/webui/extensions/extensions_internals_source.cc
index 8c914e24..3003389 100644
--- a/chrome/browser/ui/webui/extensions/extensions_internals_source.cc
+++ b/chrome/browser/ui/webui/extensions/extensions_internals_source.cc
@@ -423,7 +423,7 @@
       listener_data.Set(kIsLazyKey, listener_entry->IsLazy());
       listener_data.Set(kListenerUrlKey, listener_entry->listener_url().spec());
       // Add the filter if one exists.
-      base::Value* const filter = listener_entry->filter();
+      base::Value::Dict* const filter = listener_entry->filter();
       if (filter) {
         listener_data.Set(kFilterKey, filter->Clone());
       }
diff --git a/chrome/browser/ui/webui/extensions/extensions_ui.cc b/chrome/browser/ui/webui/extensions/extensions_ui.cc
index fda9e4d..1179c4a 100644
--- a/chrome/browser/ui/webui/extensions/extensions_ui.cc
+++ b/chrome/browser/ui/webui/extensions/extensions_ui.cc
@@ -74,7 +74,6 @@
   webui::SetupWebUIDataSource(
       source, base::make_span(kExtensionsResources, kExtensionsResourcesSize),
       IDR_EXTENSIONS_EXTENSIONS_HTML);
-  webui::EnableTrustedTypesCSP(source);
 
   static constexpr webui::LocalizedString kLocalizedStrings[] = {
     // Add common strings.
diff --git a/chrome/browser/ui/webui/feed/feed_ui.cc b/chrome/browser/ui/webui/feed/feed_ui.cc
index 14e07474..ba4679b 100644
--- a/chrome/browser/ui/webui/feed/feed_ui.cc
+++ b/chrome/browser/ui/webui/feed/feed_ui.cc
@@ -31,7 +31,6 @@
   webui::SetupWebUIDataSource(
       source, base::make_span(kFeedResources, kFeedResourcesSize),
       IDR_FEED_FEED_HTML);
-  webui::EnableTrustedTypesCSP(source);
 
   if (kWebUiDisableContentSecurityPolicy.Get()) {
     source->DisableContentSecurityPolicy();
diff --git a/chrome/browser/ui/webui/history/history_ui.cc b/chrome/browser/ui/webui/history/history_ui.cc
index d1b8413..b4cd6b1 100644
--- a/chrome/browser/ui/webui/history/history_ui.cc
+++ b/chrome/browser/ui/webui/history/history_ui.cc
@@ -130,7 +130,6 @@
   webui::SetupWebUIDataSource(
       source, base::make_span(kHistoryResources, kHistoryResourcesSize),
       IDR_HISTORY_HISTORY_HTML);
-  webui::EnableTrustedTypesCSP(source);
 
   content::URLDataSource::Add(
       profile, std::make_unique<FaviconSource>(
diff --git a/chrome/browser/ui/webui/history_clusters/history_clusters_handler.cc b/chrome/browser/ui/webui/history_clusters/history_clusters_handler.cc
index 8d9c027..f4aeef9 100644
--- a/chrome/browser/ui/webui/history_clusters/history_clusters_handler.cc
+++ b/chrome/browser/ui/webui/history_clusters/history_clusters_handler.cc
@@ -19,7 +19,6 @@
 #include "base/time/time_to_iso8601.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/history/history_service_factory.h"
-#include "chrome/browser/history_clusters/entity_image_service.h"
 #include "chrome/browser/history_clusters/history_clusters_metrics_logger.h"
 #include "chrome/browser/history_clusters/history_clusters_service_factory.h"
 #include "chrome/browser/image_service/image_service_factory.h"
@@ -38,6 +37,7 @@
 #include "components/history_clusters/core/features.h"
 #include "components/history_clusters/core/history_clusters_prefs.h"
 #include "components/history_clusters/core/query_clusters_state.h"
+#include "components/image_service/image_service.h"
 #include "components/keyed_service/core/service_access_type.h"
 #include "components/prefs/pref_service.h"
 #include "components/search_engines/template_url.h"
@@ -521,8 +521,10 @@
   // ImageService, have HistoryClustersService pass a pointer to it in the
   // constructor, so `QueryClustersState` can do this for itself.
   if (auto* image_service =
-          image_service::ImageServiceFactory::GetForBrowserContext(
-              GetProfile())) {
+          GetConfig().images
+              ? image_service::ImageServiceFactory::GetForBrowserContext(
+                    GetProfile())
+              : nullptr) {
     image_service->PopulateEntityImagesFor(
         std::move(clusters_batch),
         base::BindOnce(&HistoryClustersHandler::SendClustersToPage,
diff --git a/chrome/browser/ui/webui/intro/intro_ui.cc b/chrome/browser/ui/webui/intro/intro_ui.cc
index 41768ae3..7b4f596 100644
--- a/chrome/browser/ui/webui/intro/intro_ui.cc
+++ b/chrome/browser/ui/webui/intro/intro_ui.cc
@@ -54,7 +54,6 @@
   webui::SetupWebUIDataSource(
       source, base::make_span(kIntroResources, kIntroResourcesSize),
       IDR_INTRO_INTRO_HTML);
-  webui::EnableTrustedTypesCSP(source);
 
   AddStrings(source);
 
diff --git a/chrome/browser/ui/webui/lens/lens_ui.cc b/chrome/browser/ui/webui/lens/lens_ui.cc
index 2edccdc..7c3c474 100644
--- a/chrome/browser/ui/webui/lens/lens_ui.cc
+++ b/chrome/browser/ui/webui/lens/lens_ui.cc
@@ -21,7 +21,6 @@
   webui::SetupWebUIDataSource(
       html_source, base::make_span(kLensResources, kLensResourcesSize),
       IDR_LENS_REGION_SEARCH_HTML);
-  webui::EnableTrustedTypesCSP(html_source);
 
   // Set up Content Security Policy (CSP) for chrome-untrusted://lens iframe.
   web_ui->AddRequestableScheme(content::kChromeUIUntrustedScheme);
diff --git a/chrome/browser/ui/webui/lens/lens_untrusted_ui.cc b/chrome/browser/ui/webui/lens/lens_untrusted_ui.cc
index 18b8bcc8..0afb7a91 100644
--- a/chrome/browser/ui/webui/lens/lens_untrusted_ui.cc
+++ b/chrome/browser/ui/webui/lens/lens_untrusted_ui.cc
@@ -40,7 +40,6 @@
       html_source,
       base::make_span(kLensUntrustedResources, kLensUntrustedResourcesSize),
       IDR_LENS_UNTRUSTED_REGION_SEARCH_UNTRUSTED_HTML);
-  webui::EnableTrustedTypesCSP(html_source);
   html_source->AddFrameAncestor(GURL(chrome::kChromeUILensURL));
   // Allows chrome:://lens to load this page in an iframe.
   html_source->OverrideCrossOriginOpenerPolicy("same-origin");
diff --git a/chrome/browser/ui/webui/management/management_ui.cc b/chrome/browser/ui/webui/management/management_ui.cc
index ed4a46c1..0895b3f4 100644
--- a/chrome/browser/ui/webui/management/management_ui.cc
+++ b/chrome/browser/ui/webui/management/management_ui.cc
@@ -173,7 +173,6 @@
   webui::SetupWebUIDataSource(
       source, base::make_span(kManagementResources, kManagementResourcesSize),
       IDR_MANAGEMENT_MANAGEMENT_HTML);
-  webui::EnableTrustedTypesCSP(source);
   return source;
 }
 
diff --git a/chrome/browser/ui/webui/management/management_ui_handler_unittest.cc b/chrome/browser/ui/webui/management/management_ui_handler_unittest.cc
index 235266e..870773d 100644
--- a/chrome/browser/ui/webui/management/management_ui_handler_unittest.cc
+++ b/chrome/browser/ui/webui/management/management_ui_handler_unittest.cc
@@ -389,9 +389,9 @@
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   void SetUp() override {
-    DeviceSettingsTestBase::SetUp();
     install_attributes_ = std::make_unique<ash::ScopedStubInstallAttributes>(
         ash::StubInstallAttributes::CreateUnset());
+    DeviceSettingsTestBase::SetUp();
 
     crostini_features_ = std::make_unique<crostini::FakeCrostiniFeatures>();
     SetUpConnectManager();
diff --git a/chrome/browser/ui/webui/media_router/cast_feedback_ui.cc b/chrome/browser/ui/webui/media_router/cast_feedback_ui.cc
index 628e814..907d0d3 100644
--- a/chrome/browser/ui/webui/media_router/cast_feedback_ui.cc
+++ b/chrome/browser/ui/webui/media_router/cast_feedback_ui.cc
@@ -172,7 +172,6 @@
       base::make_span(kMediaRouterFeedbackResources,
                       kMediaRouterFeedbackResourcesSize),
       IDR_MEDIA_ROUTER_FEEDBACK_FEEDBACK_HTML);
-  webui::EnableTrustedTypesCSP(source);
 
   content::WebUIDataSource::Add(profile_, source);
 
diff --git a/chrome/browser/ui/webui/metrics_internals/metrics_internals_ui.cc b/chrome/browser/ui/webui/metrics_internals/metrics_internals_ui.cc
index 34ef89f1..45fa057 100644
--- a/chrome/browser/ui/webui/metrics_internals/metrics_internals_ui.cc
+++ b/chrome/browser/ui/webui/metrics_internals/metrics_internals_ui.cc
@@ -26,7 +26,6 @@
                               base::make_span(kMetricsInternalsResources,
                                               kMetricsInternalsResourcesSize),
                               IDR_METRICS_INTERNALS_METRICS_INTERNALS_HTML);
-  webui::EnableTrustedTypesCSP(source);
 
   web_ui->AddMessageHandler(std::make_unique<MetricsInternalsHandler>());
 }
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc
index d78869b..8a75a45 100644
--- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc
+++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc
@@ -519,7 +519,6 @@
   webui::SetupWebUIDataSource(
       source, base::make_span(kNewTabPageResources, kNewTabPageResourcesSize),
       IDR_NEW_TAB_PAGE_NEW_TAB_PAGE_HTML);
-  webui::EnableTrustedTypesCSP(source);
 
   // Allow embedding of iframes for the doodle and
   // chrome-untrusted://new-tab-page for other external content and resources.
diff --git a/chrome/browser/ui/webui/new_tab_page_third_party/new_tab_page_third_party_ui.cc b/chrome/browser/ui/webui/new_tab_page_third_party/new_tab_page_third_party_ui.cc
index ef230583..7897215 100644
--- a/chrome/browser/ui/webui/new_tab_page_third_party/new_tab_page_third_party_ui.cc
+++ b/chrome/browser/ui/webui/new_tab_page_third_party/new_tab_page_third_party_ui.cc
@@ -125,7 +125,6 @@
       base::make_span(kNewTabPageThirdPartyResources,
                       kNewTabPageThirdPartyResourcesSize),
       IDR_NEW_TAB_PAGE_THIRD_PARTY_NEW_TAB_PAGE_THIRD_PARTY_HTML);
-  webui::EnableTrustedTypesCSP(source);
 
   return source;
 }
diff --git a/chrome/browser/ui/webui/password_manager/password_manager_ui.cc b/chrome/browser/ui/webui/password_manager/password_manager_ui.cc
index 82a1db6..0978a501 100644
--- a/chrome/browser/ui/webui/password_manager/password_manager_ui.cc
+++ b/chrome/browser/ui/webui/password_manager/password_manager_ui.cc
@@ -42,7 +42,6 @@
       source,
       base::make_span(kPasswordManagerResources, kPasswordManagerResourcesSize),
       IDR_PASSWORD_MANAGER_PASSWORD_MANAGER_HTML);
-  webui::EnableTrustedTypesCSP(source);
 
   static constexpr webui::LocalizedString kStrings[] = {
       {"usernameCopiedToClipboard",
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
index 50ba956..3d036e4 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
@@ -372,7 +372,6 @@
       source,
       base::make_span(kPrintPreviewResources, kPrintPreviewResourcesSize),
       IDR_PRINT_PREVIEW_PRINT_PREVIEW_HTML);
-  webui::EnableTrustedTypesCSP(source);
   AddPrintPreviewStrings(source);
   SetupPrintPreviewPlugin(source);
   AddPrintPreviewFlags(source, profile);
diff --git a/chrome/browser/ui/webui/privacy_sandbox/privacy_sandbox_dialog_ui.cc b/chrome/browser/ui/webui/privacy_sandbox/privacy_sandbox_dialog_ui.cc
index 4a454046..91352e0 100644
--- a/chrome/browser/ui/webui/privacy_sandbox/privacy_sandbox_dialog_ui.cc
+++ b/chrome/browser/ui/webui/privacy_sandbox/privacy_sandbox_dialog_ui.cc
@@ -32,7 +32,6 @@
       source,
       base::make_span(kPrivacySandboxResources, kPrivacySandboxResourcesSize),
       IDR_PRIVACY_SANDBOX_PRIVACY_SANDBOX_DIALOG_HTML);
-  webui::EnableTrustedTypesCSP(source);
 
   source->AddResourcePath(
       chrome::kChromeUIPrivacySandboxDialogCombinedPath,
diff --git a/chrome/browser/ui/webui/segmentation_internals/segmentation_internals_ui.cc b/chrome/browser/ui/webui/segmentation_internals/segmentation_internals_ui.cc
index 657fe03..813a189 100644
--- a/chrome/browser/ui/webui/segmentation_internals/segmentation_internals_ui.cc
+++ b/chrome/browser/ui/webui/segmentation_internals/segmentation_internals_ui.cc
@@ -24,7 +24,6 @@
       base::make_span(kSegmentationInternalsResources,
                       kSegmentationInternalsResourcesSize),
       IDR_SEGMENTATION_INTERNALS_SEGMENTATION_INTERNALS_HTML);
-  webui::EnableTrustedTypesCSP(source.get());
 
   content::BrowserContext* browser_context =
       web_ui->GetWebContents()->GetBrowserContext();
diff --git a/chrome/browser/ui/webui/settings/settings_ui.cc b/chrome/browser/ui/webui/settings/settings_ui.cc
index 061aeae..0cb3166 100644
--- a/chrome/browser/ui/webui/settings/settings_ui.cc
+++ b/chrome/browser/ui/webui/settings/settings_ui.cc
@@ -407,7 +407,6 @@
   webui::SetupWebUIDataSource(
       html_source, base::make_span(kSettingsResources, kSettingsResourcesSize),
       IDR_SETTINGS_SETTINGS_HTML);
-  webui::EnableTrustedTypesCSP(html_source);
 
   AddLocalizedStrings(html_source, profile, web_ui->GetWebContents());
 
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 eed9f69..9ae8d9fb 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
@@ -104,7 +104,6 @@
   webui::SetupWebUIDataSource(
       source, base::make_span(kSidePanelResources, kSidePanelResourcesSize),
       resource);
-  webui::EnableTrustedTypesCSP(source);
 
   // Add a handler to provide pluralized strings.
   auto plural_string_handler = std::make_unique<PluralStringHandler>();
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_ui.cc b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_ui.cc
index 41315b4..5e71aed 100644
--- a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_ui.cc
+++ b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_ui.cc
@@ -46,7 +46,6 @@
       base::make_span(kSidePanelCustomizeChromeResources,
                       kSidePanelCustomizeChromeResourcesSize),
       IDR_SIDE_PANEL_CUSTOMIZE_CHROME_CUSTOMIZE_CHROME_HTML);
-  webui::EnableTrustedTypesCSP(source);
 
   content::WebUIDataSource::Add(profile_, source);
 }
diff --git a/chrome/browser/ui/webui/side_panel/history_clusters/history_clusters_side_panel_ui.cc b/chrome/browser/ui/webui/side_panel/history_clusters/history_clusters_side_panel_ui.cc
index d3bc8921..f58a4d0 100644
--- a/chrome/browser/ui/webui/side_panel/history_clusters/history_clusters_side_panel_ui.cc
+++ b/chrome/browser/ui/webui/side_panel/history_clusters/history_clusters_side_panel_ui.cc
@@ -46,7 +46,6 @@
   webui::SetupWebUIDataSource(
       source, kHistoryClustersResources,
       IDR_SIDE_PANEL_HISTORY_CLUSTERS_HISTORY_CLUSTERS_HTML);
-  webui::EnableTrustedTypesCSP(source);
   content::WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(),
                                 source);
 }
diff --git a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_ui.cc b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_ui.cc
index 0ba6bb8b..cb115d1 100644
--- a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_ui.cc
+++ b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_ui.cc
@@ -35,7 +35,6 @@
   webui::SetupWebUIDataSource(
       source, base::make_span(kSidePanelResources, kSidePanelResourcesSize),
       IDR_SIDE_PANEL_READ_ANYTHING_READ_ANYTHING_HTML);
-  webui::EnableTrustedTypesCSP(source);
   content::WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(),
                                 source);
 }
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 c725c6c..b88812e 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
@@ -140,7 +140,6 @@
   webui::SetupWebUIDataSource(
       source, base::make_span(kSidePanelResources, kSidePanelResourcesSize),
       resource);
-  webui::EnableTrustedTypesCSP(source);
   content::WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(),
                                 source);
   content::URLDataSource::Add(profile,
diff --git a/chrome/browser/ui/webui/side_panel/user_notes/user_notes_side_panel_ui.cc b/chrome/browser/ui/webui/side_panel/user_notes/user_notes_side_panel_ui.cc
index 0248e86..a921d9c 100644
--- a/chrome/browser/ui/webui/side_panel/user_notes/user_notes_side_panel_ui.cc
+++ b/chrome/browser/ui/webui/side_panel/user_notes/user_notes_side_panel_ui.cc
@@ -25,7 +25,6 @@
   webui::SetupWebUIDataSource(
       source, base::make_span(kSidePanelResources, kSidePanelResourcesSize),
       resource);
-  webui::EnableTrustedTypesCSP(source);
   content::WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(),
                                 source);
 }
diff --git a/chrome/browser/ui/webui/signin/enterprise_profile_welcome_ui.cc b/chrome/browser/ui/webui/signin/enterprise_profile_welcome_ui.cc
index 320fa5a..273df317 100644
--- a/chrome/browser/ui/webui/signin/enterprise_profile_welcome_ui.cc
+++ b/chrome/browser/ui/webui/signin/enterprise_profile_welcome_ui.cc
@@ -45,7 +45,6 @@
   webui::SetupWebUIDataSource(
       source, base::make_span(kResources),
       IDR_SIGNIN_ENTERPRISE_PROFILE_WELCOME_ENTERPRISE_PROFILE_WELCOME_HTML);
-  webui::EnableTrustedTypesCSP(source);
 
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
   source->AddResourcePath(
diff --git a/chrome/browser/ui/webui/signin/inline_login_ui.cc b/chrome/browser/ui/webui/signin/inline_login_ui.cc
index 1ab94a1..fde641a8 100644
--- a/chrome/browser/ui/webui/signin/inline_login_ui.cc
+++ b/chrome/browser/ui/webui/signin/inline_login_ui.cc
@@ -117,7 +117,6 @@
       source,
       base::make_span(kGaiaAuthHostResources, kGaiaAuthHostResourcesSize),
       IDR_INLINE_LOGIN_INLINE_LOGIN_HTML);
-  webui::EnableTrustedTypesCSP(source);
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   source->AddResourcePaths(base::make_span(kArcAccountPickerResources,
diff --git a/chrome/browser/ui/webui/signin/profile_customization_ui.cc b/chrome/browser/ui/webui/signin/profile_customization_ui.cc
index 899c135..de9f262f 100644
--- a/chrome/browser/ui/webui/signin/profile_customization_ui.cc
+++ b/chrome/browser/ui/webui/signin/profile_customization_ui.cc
@@ -55,7 +55,6 @@
   webui::SetupWebUIDataSource(
       source, base::make_span(kResources),
       IDR_SIGNIN_PROFILE_CUSTOMIZATION_PROFILE_CUSTOMIZATION_HTML);
-  webui::EnableTrustedTypesCSP(source);
 
   // Localized strings.
   static constexpr webui::LocalizedString kLocalizedStrings[] = {
diff --git a/chrome/browser/ui/webui/signin/profile_picker_ui.cc b/chrome/browser/ui/webui/signin/profile_picker_ui.cc
index 1bf7646..84719da 100644
--- a/chrome/browser/ui/webui/signin/profile_picker_ui.cc
+++ b/chrome/browser/ui/webui/signin/profile_picker_ui.cc
@@ -284,7 +284,6 @@
       html_source,
       base::make_span(kProfilePickerResources, kProfilePickerResourcesSize),
       IDR_PROFILE_PICKER_PROFILE_PICKER_HTML);
-  webui::EnableTrustedTypesCSP(html_source);
   content::WebUIDataSource::Add(profile, html_source);
 }
 
diff --git a/chrome/browser/ui/webui/signin/signin_reauth_ui.cc b/chrome/browser/ui/webui/signin/signin_reauth_ui.cc
index 6d0049d4..80762b7 100644
--- a/chrome/browser/ui/webui/signin/signin_reauth_ui.cc
+++ b/chrome/browser/ui/webui/signin/signin_reauth_ui.cc
@@ -112,7 +112,6 @@
 
   webui::SetupWebUIDataSource(source, base::make_span(kResources),
                               IDR_SIGNIN_SIGNIN_REAUTH_SIGNIN_REAUTH_HTML);
-  webui::EnableTrustedTypesCSP(source);
 
   source->AddString("accountImageUrl", GetAccountImageURL(profile));
 
diff --git a/chrome/browser/ui/webui/support_tool/support_tool_ui.cc b/chrome/browser/ui/webui/support_tool/support_tool_ui.cc
index baf1899..b30dea7 100644
--- a/chrome/browser/ui/webui/support_tool/support_tool_ui.cc
+++ b/chrome/browser/ui/webui/support_tool/support_tool_ui.cc
@@ -54,7 +54,6 @@
   webui::SetupWebUIDataSource(
       source, base::make_span(kSupportToolResources, kSupportToolResourcesSize),
       IDR_SUPPORT_TOOL_SUPPORT_TOOL_CONTAINER_HTML);
-  webui::EnableTrustedTypesCSP(source);
 
   source->AddResourcePath("url-generator",
                           IDR_SUPPORT_TOOL_URL_GENERATOR_CONTAINER_HTML);
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_ui.cc b/chrome/browser/ui/webui/tab_search/tab_search_ui.cc
index 36719034..a31b127 100644
--- a/chrome/browser/ui/webui/tab_search/tab_search_ui.cc
+++ b/chrome/browser/ui/webui/tab_search/tab_search_ui.cc
@@ -102,7 +102,6 @@
   webui::SetupWebUIDataSource(
       source, base::make_span(kTabSearchResources, kTabSearchResourcesSize),
       IDR_TAB_SEARCH_TAB_SEARCH_HTML);
-  webui::EnableTrustedTypesCSP(source);
   content::WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(),
                                 source);
 
diff --git a/chrome/browser/ui/webui/tab_strip/tab_strip_ui.cc b/chrome/browser/ui/webui/tab_strip/tab_strip_ui.cc
index 6e38e23..68c207fb 100644
--- a/chrome/browser/ui/webui/tab_strip/tab_strip_ui.cc
+++ b/chrome/browser/ui/webui/tab_strip/tab_strip_ui.cc
@@ -52,7 +52,6 @@
   webui::SetupWebUIDataSource(
       html_source, base::make_span(kTabStripResources, kTabStripResourcesSize),
       IDR_TAB_STRIP_TAB_STRIP_HTML);
-  webui::EnableTrustedTypesCSP(html_source);
 
   html_source->AddString("tabIdDataType", kWebUITabIdDataType);
   html_source->AddString("tabGroupIdDataType", kWebUITabGroupIdDataType);
diff --git a/chrome/browser/ui/webui/usb_internals/usb_internals_ui.cc b/chrome/browser/ui/webui/usb_internals/usb_internals_ui.cc
index c9615df..ae3abe7 100644
--- a/chrome/browser/ui/webui/usb_internals/usb_internals_ui.cc
+++ b/chrome/browser/ui/webui/usb_internals/usb_internals_ui.cc
@@ -32,7 +32,6 @@
       source,
       base::make_span(kUsbInternalsResources, kUsbInternalsResourcesSize),
       IDR_USB_INTERNALS_USB_INTERNALS_HTML);
-  webui::EnableTrustedTypesCSP(source);
 
   content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), source);
 }
diff --git a/chrome/browser/ui/webui/webui_gallery/webui_gallery_ui.cc b/chrome/browser/ui/webui/webui_gallery/webui_gallery_ui.cc
index e3f0cf9..19547ea 100644
--- a/chrome/browser/ui/webui/webui_gallery/webui_gallery_ui.cc
+++ b/chrome/browser/ui/webui/webui_gallery/webui_gallery_ui.cc
@@ -23,7 +23,6 @@
       source,
       base::make_span(kWebuiGalleryResources, kWebuiGalleryResourcesSize),
       IDR_WEBUI_GALLERY_WEBUI_GALLERY_HTML);
-  webui::EnableTrustedTypesCSP(source);
 
   source->OverrideContentSecurityPolicy(
       network::mojom::CSPDirectiveName::FrameSrc, "frame-src 'self';");
diff --git a/chrome/browser/ui/webui/webui_js_error/webui_js_error_ui.cc b/chrome/browser/ui/webui/webui_js_error/webui_js_error_ui.cc
index 3e1a031c..e018d93 100644
--- a/chrome/browser/ui/webui/webui_js_error/webui_js_error_ui.cc
+++ b/chrome/browser/ui/webui/webui_js_error/webui_js_error_ui.cc
@@ -40,7 +40,6 @@
       source,
       base::make_span(kWebuiJsErrorResources, kWebuiJsErrorResourcesSize),
       IDR_WEBUI_JS_ERROR_WEBUI_JS_ERROR_HTML);
-  webui::EnableTrustedTypesCSP(source);
   Profile* profile = Profile::FromWebUI(web_ui);
   content::WebUIDataSource::Add(profile, source);
 }
diff --git a/chrome/browser/ui/webui/whats_new/whats_new_ui.cc b/chrome/browser/ui/webui/whats_new/whats_new_ui.cc
index 40f556d..0da20011 100644
--- a/chrome/browser/ui/webui/whats_new/whats_new_ui.cc
+++ b/chrome/browser/ui/webui/whats_new/whats_new_ui.cc
@@ -38,7 +38,6 @@
   webui::SetupWebUIDataSource(
       source, base::make_span(kWhatsNewResources, kWhatsNewResourcesSize),
       IDR_WHATS_NEW_WHATS_NEW_HTML);
-  webui::EnableTrustedTypesCSP(source);
 
   static constexpr webui::LocalizedString kStrings[] = {
       {"title", IDS_WHATS_NEW_TITLE},
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn
index d90a35a..d1907e58 100644
--- a/chrome/browser/web_applications/BUILD.gn
+++ b/chrome/browser/web_applications/BUILD.gn
@@ -34,6 +34,8 @@
     "commands/sub_app_install_command.h",
     "commands/update_file_handler_command.cc",
     "commands/update_file_handler_command.h",
+    "commands/update_protocol_handler_approval_command.cc",
+    "commands/update_protocol_handler_approval_command.h",
     "commands/web_app_command.cc",
     "commands/web_app_command.h",
     "commands/web_app_uninstall_command.cc",
@@ -729,6 +731,7 @@
     "commands/install_from_info_command_browsertest.cc",
     "commands/install_from_sync_command_browsertest.cc",
     "commands/install_isolated_web_app_command_browsertest.cc",
+    "commands/update_protocol_handler_approval_command_browsertest.cc",
     "externally_installed_web_app_prefs_browsertest.cc",
     "externally_managed_app_manager_impl_browsertest.cc",
     "isolated_web_apps/install_isolated_web_app_from_command_line_browsertest.cc",
diff --git a/chrome/browser/web_applications/app_service/lacros_web_apps_controller.cc b/chrome/browser/web_applications/app_service/lacros_web_apps_controller.cc
index 05e03d4..88046b0 100644
--- a/chrome/browser/web_applications/app_service/lacros_web_apps_controller.cc
+++ b/chrome/browser/web_applications/app_service/lacros_web_apps_controller.cc
@@ -110,7 +110,7 @@
 }
 
 WebAppRegistrar& LacrosWebAppsController::registrar() const {
-  return provider_->registrar();
+  return provider_->registrar_unsafe();
 }
 
 void LacrosWebAppsController::SetPublisherForTesting(
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 34a89f9..d3448f5 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
@@ -507,7 +507,7 @@
   const GURL app_url =
       embedded_test_server()->GetURL("/web_apps/file_handler_index.html");
   AppId app_id = InstallWebAppFromManifest(browser(), app_url);
-  EXPECT_EQ(provider().registrar().GetAppStartUrl(app_id), app_url);
+  EXPECT_EQ(provider().registrar_unsafe().GetAppStartUrl(app_id), app_url);
 
   MockAppPublisher mock_app_publisher;
   LacrosWebAppsController lacros_web_apps_controller(profile());
@@ -1021,8 +1021,9 @@
   EXPECT_TRUE(HasFileViewFilters(
       mock_app_publisher.get_deltas().back()->intent_filters));
 
-  EXPECT_EQ(ApiApprovalState::kRequiresPrompt,
-            provider().registrar().GetAppFileHandlerApprovalState(app_id));
+  EXPECT_EQ(
+      ApiApprovalState::kRequiresPrompt,
+      provider().registrar_unsafe().GetAppFileHandlerApprovalState(app_id));
   provider().sync_bridge().SetAppFileHandlerApprovalState(
       app_id, ApiApprovalState::kDisallowed);
 
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 399375d..dd4b228 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
@@ -727,16 +727,16 @@
 
   auto app = apps::AppPublisher::MakeApp(
       app_type(), web_app->app_id(), readiness,
-      provider_->registrar().GetAppShortName(web_app->app_id()),
+      provider_->registrar_unsafe().GetAppShortName(web_app->app_id()),
       apps::ConvertMojomInstallReasonToInstallReason(
           GetHighestPriorityInstallReason(web_app)),
       apps::ConvertMojomInstallSourceToInstallSource(
           ConvertInstallSourceToMojom(
-              provider_->registrar().GetAppInstallSourceForMetrics(
+              provider_->registrar_unsafe().GetAppInstallSourceForMetrics(
                   web_app->app_id()))));
 
   app->description =
-      provider_->registrar().GetAppDescription(web_app->app_id());
+      provider_->registrar_unsafe().GetAppDescription(web_app->app_id());
   app->additional_search_terms = web_app->additional_search_terms();
 
   // Web App's publisher_id the start url.
@@ -1403,7 +1403,7 @@
 }
 
 WebAppRegistrar& WebAppPublisherHelper::registrar() const {
-  return provider_->registrar();
+  return provider_->registrar_unsafe();
 }
 
 WebAppInstallManager& WebAppPublisherHelper::install_manager() const {
@@ -1969,7 +1969,8 @@
                      weak_ptr_factory_.GetWeakPtr(), app_id, std::move(params),
                      std::move(callback));
 
-  switch (provider_->registrar().GetAppFileHandlerApprovalState(app_id)) {
+  switch (
+      provider_->registrar_unsafe().GetAppFileHandlerApprovalState(app_id)) {
     case ApiApprovalState::kRequiresPrompt:
       chrome::ShowWebAppFileLaunchDialog(file_paths, profile(), app_id,
                                          std::move(launch_callback));
diff --git a/chrome/browser/web_applications/app_service/web_app_publisher_helper_browsertest.cc b/chrome/browser/web_applications/app_service/web_app_publisher_helper_browsertest.cc
index 07c8fa2..583a945 100644
--- a/chrome/browser/web_applications/app_service/web_app_publisher_helper_browsertest.cc
+++ b/chrome/browser/web_applications/app_service/web_app_publisher_helper_browsertest.cc
@@ -135,8 +135,8 @@
     const web_app::AppId app_id =
         web_app::InstallWebAppFromManifest(browser(), app_url);
     filters = WebAppPublisherHelper::CreateIntentFiltersForWebApp(
-        app_id, provider.registrar().GetAppScope(app_id),
-        provider.registrar().GetAppShareTarget(app_id),
+        app_id, provider.registrar_unsafe().GetAppScope(app_id),
+        provider.registrar_unsafe().GetAppShareTarget(app_id),
         provider.os_integration_manager().GetEnabledFileHandlers(app_id));
   }
 
@@ -168,8 +168,8 @@
     const web_app::AppId app_id =
         web_app::InstallWebAppFromManifest(browser(), app_url);
     filters = WebAppPublisherHelper::CreateIntentFiltersForWebApp(
-        app_id, provider.registrar().GetAppScope(app_id),
-        provider.registrar().GetAppShareTarget(app_id),
+        app_id, provider.registrar_unsafe().GetAppScope(app_id),
+        provider.registrar_unsafe().GetAppShareTarget(app_id),
         provider.os_integration_manager().GetEnabledFileHandlers(app_id));
   }
 
@@ -199,8 +199,8 @@
     const web_app::AppId app_id =
         web_app::InstallWebAppFromManifest(browser(), app_url);
     filters = WebAppPublisherHelper::CreateIntentFiltersForWebApp(
-        app_id, provider.registrar().GetAppScope(app_id),
-        provider.registrar().GetAppShareTarget(app_id),
+        app_id, provider.registrar_unsafe().GetAppScope(app_id),
+        provider.registrar_unsafe().GetAppShareTarget(app_id),
         provider.os_integration_manager().GetEnabledFileHandlers(app_id));
   }
 
diff --git a/chrome/browser/web_applications/app_service/web_app_publisher_helper_unittest.cc b/chrome/browser/web_applications/app_service/web_app_publisher_helper_unittest.cc
index a61e7e5..7a0c2a10 100644
--- a/chrome/browser/web_applications/app_service/web_app_publisher_helper_unittest.cc
+++ b/chrome/browser/web_applications/app_service/web_app_publisher_helper_unittest.cc
@@ -110,7 +110,7 @@
   info->start_url = start_url;
 
   AppId app_id = test::InstallWebApp(profile(), std::move(info));
-  const WebApp* web_app = provider_->registrar().GetAppById(app_id);
+  const WebApp* web_app = provider_->registrar_unsafe().GetAppById(app_id);
   apps::AppPtr app = publisher_->CreateWebApp(web_app);
 
   EXPECT_EQ(app->app_id, app_id);
@@ -165,7 +165,7 @@
   info->note_taking_new_note_url = new_note_url;
 
   AppId app_id = test::InstallWebApp(profile(), std::move(info));
-  const WebApp* web_app = provider_->registrar().GetAppById(app_id);
+  const WebApp* web_app = provider_->registrar_unsafe().GetAppById(app_id);
   apps::AppPtr app = publisher_->CreateWebApp(web_app);
 
   EXPECT_TRUE(HandlesIntent(app, apps_util::CreateCreateNoteIntent()));
@@ -186,7 +186,7 @@
   info->lock_screen_start_url = lock_screen_url;
 
   AppId app_id = test::InstallWebApp(profile(), std::move(info));
-  const WebApp* web_app = provider_->registrar().GetAppById(app_id);
+  const WebApp* web_app = provider_->registrar_unsafe().GetAppById(app_id);
   apps::AppPtr app = publisher_->CreateWebApp(web_app);
 
   EXPECT_FALSE(HandlesIntent(app, apps_util::CreateStartOnLockScreenIntent()));
@@ -312,7 +312,7 @@
   info->lock_screen_start_url = lock_screen_url;
 
   AppId app_id = test::InstallWebApp(profile(), std::move(info));
-  const WebApp* web_app = provider_->registrar().GetAppById(app_id);
+  const WebApp* web_app = provider_->registrar_unsafe().GetAppById(app_id);
   apps::AppPtr app = publisher_->CreateWebApp(web_app);
 
   EXPECT_TRUE(HandlesIntent(app, apps_util::CreateStartOnLockScreenIntent()));
diff --git a/chrome/browser/web_applications/app_service/web_apps.cc b/chrome/browser/web_applications/app_service/web_apps.cc
index 7d72071..fead2625f 100644
--- a/chrome/browser/web_applications/app_service/web_apps.cc
+++ b/chrome/browser/web_applications/app_service/web_apps.cc
@@ -71,7 +71,7 @@
 
 const WebApp* WebApps::GetWebApp(const AppId& app_id) const {
   DCHECK(provider_);
-  return provider_->registrar().GetAppById(app_id);
+  return provider_->registrar_unsafe().GetAppById(app_id);
 }
 
 void WebApps::Initialize(
@@ -355,7 +355,7 @@
   DCHECK(provider_);
 
   std::vector<apps::AppPtr> apps;
-  for (const WebApp& web_app : provider_->registrar().GetApps()) {
+  for (const WebApp& web_app : provider_->registrar_unsafe().GetApps()) {
     apps.push_back(publisher_helper().CreateWebApp(&web_app));
   }
   return apps;
@@ -367,7 +367,7 @@
     return;
   }
 
-  for (const WebApp& web_app : provider_->registrar().GetApps()) {
+  for (const WebApp& web_app : provider_->registrar_unsafe().GetApps()) {
     apps_out->push_back(publisher_helper().ConvertWebApp(&web_app));
   }
 }
diff --git a/chrome/browser/web_applications/app_service/web_apps_browsertest.cc b/chrome/browser/web_applications/app_service/web_apps_browsertest.cc
index 4ba69eb6..832c62f3 100644
--- a/chrome/browser/web_applications/app_service/web_apps_browsertest.cc
+++ b/chrome/browser/web_applications/app_service/web_apps_browsertest.cc
@@ -116,7 +116,7 @@
   // Install file handling web app.
   const AppId app_id = InstallWebAppFromManifest(browser(), app_url);
   const WebAppRegistrar& registrar =
-      WebAppProvider::GetForTest(browser()->profile())->registrar();
+      WebAppProvider::GetForTest(browser()->profile())->registrar_unsafe();
   const WebApp* web_app = registrar.GetAppById(app_id);
   ASSERT_TRUE(web_app);
 
diff --git a/chrome/browser/web_applications/commands/update_protocol_handler_approval_command.cc b/chrome/browser/web_applications/commands/update_protocol_handler_approval_command.cc
new file mode 100644
index 0000000..da025484
--- /dev/null
+++ b/chrome/browser/web_applications/commands/update_protocol_handler_approval_command.cc
@@ -0,0 +1,127 @@
+// 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/web_applications/commands/update_protocol_handler_approval_command.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/containers/contains.h"
+#include "base/functional/bind.h"
+#include "base/functional/callback.h"
+#include "base/memory/ptr_util.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/web_applications/locks/app_lock.h"
+#include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
+#include "chrome/browser/web_applications/web_app_constants.h"
+#include "chrome/browser/web_applications/web_app_id.h"
+#include "chrome/browser/web_applications/web_app_registrar.h"
+#include "chrome/browser/web_applications/web_app_registry_update.h"
+#include "chrome/browser/web_applications/web_app_sync_bridge.h"
+
+namespace web_app {
+
+UpdateProtocolHandlerApprovalCommand::UpdateProtocolHandlerApprovalCommand(
+    const AppId& app_id,
+    const std::string& protocol_scheme,
+    bool allowed,
+    base::OnceClosure callback)
+    : WebAppCommandTemplate<AppLock>("UpdateProtocolHandlerApprovalCommand"),
+      lock_description_(
+          std::make_unique<AppLockDescription, base::flat_set<AppId>>(
+              {app_id})),
+      app_id_(app_id),
+      protocol_scheme_(protocol_scheme),
+      allowed_(allowed),
+      callback_(std::move(callback)) {
+  debug_info_.Set("name", "UpdateProtocolHandlerApprovalCommand");
+  debug_info_.Set("app_id", app_id_);
+  debug_info_.Set("allowed", allowed);
+  debug_info_.Set("protocol_scheme", protocol_scheme);
+  DCHECK(!protocol_scheme.empty());
+}
+
+UpdateProtocolHandlerApprovalCommand::~UpdateProtocolHandlerApprovalCommand() =
+    default;
+
+void UpdateProtocolHandlerApprovalCommand::StartWithLock(
+    std::unique_ptr<AppLock> lock) {
+  lock_ = std::move(lock);
+
+  OsIntegrationManager& os_integration_manager =
+      lock_->os_integration_manager();
+  const std::vector<custom_handlers::ProtocolHandler>
+      original_protocol_handlers =
+          os_integration_manager.GetAppProtocolHandlers(app_id_);
+
+  // Use a scope here, so that the web app registry is updated when
+  // `update` goes out of scope. If it doesn't then observers will
+  // examine stale data.
+  {
+    ScopedRegistryUpdate update(&lock_->sync_bridge());
+    WebApp* app_to_update = update->UpdateApp(app_id_);
+
+    base::flat_set<std::string> allowed_protocols(
+        app_to_update->allowed_launch_protocols());
+    base::flat_set<std::string> disallowed_protocols(
+        app_to_update->disallowed_launch_protocols());
+
+    if (allowed_) {
+      DCHECK(!base::Contains(allowed_protocols, protocol_scheme_));
+      allowed_protocols.insert(protocol_scheme_);
+      disallowed_protocols.erase(protocol_scheme_);
+    } else {
+      DCHECK(!base::Contains(disallowed_protocols, protocol_scheme_));
+      allowed_protocols.erase(protocol_scheme_);
+      disallowed_protocols.insert(protocol_scheme_);
+    }
+    app_to_update->SetAllowedLaunchProtocols(std::move(allowed_protocols));
+    app_to_update->SetDisallowedLaunchProtocols(
+        std::move(disallowed_protocols));
+  }
+  // Notify observers that the list of allowed or disallowed protocols was
+  // updated.
+  lock_->registrar().NotifyWebAppProtocolSettingsChanged();
+
+  // OS protocol registration does not need to be updated.
+  if (original_protocol_handlers ==
+      os_integration_manager.GetAppProtocolHandlers(app_id_)) {
+    debug_info_.Set("was_update_required", false);
+    SignalCompletionAndSelfDestruct(CommandResult::kSuccess,
+                                    std::move(callback_));
+    return;
+  }
+  debug_info_.Set("was_update_required", true);
+
+  // TODO(https://crbug.com/1251062): Can we avoid the delay of startup, if the
+  // action as allowed?
+  lock_->os_integration_manager().UpdateProtocolHandlers(
+      app_id_, /*force_shortcut_updates_if_needed=*/true,
+      base::BindOnce(
+          &UpdateProtocolHandlerApprovalCommand::OnProtocolHandlersUpdated,
+          weak_factory_.GetWeakPtr()));
+}
+
+LockDescription& UpdateProtocolHandlerApprovalCommand::lock_description()
+    const {
+  return *lock_description_;
+}
+
+base::Value UpdateProtocolHandlerApprovalCommand::ToDebugValue() const {
+  return base::Value(debug_info_.Clone());
+}
+
+void UpdateProtocolHandlerApprovalCommand::OnProtocolHandlersUpdated() {
+  SignalCompletionAndSelfDestruct(CommandResult::kSuccess,
+                                  std::move(callback_));
+}
+
+void UpdateProtocolHandlerApprovalCommand::OnSyncSourceRemoved() {}
+
+void UpdateProtocolHandlerApprovalCommand::OnShutdown() {
+  SignalCompletionAndSelfDestruct(CommandResult::kShutdown,
+                                  std::move(callback_));
+}
+
+}  // namespace web_app
diff --git a/chrome/browser/web_applications/commands/update_protocol_handler_approval_command.h b/chrome/browser/web_applications/commands/update_protocol_handler_approval_command.h
new file mode 100644
index 0000000..2a01a59
--- /dev/null
+++ b/chrome/browser/web_applications/commands/update_protocol_handler_approval_command.h
@@ -0,0 +1,63 @@
+// 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_WEB_APPLICATIONS_COMMANDS_UPDATE_PROTOCOL_HANDLER_APPROVAL_COMMAND_H_
+#define CHROME_BROWSER_WEB_APPLICATIONS_COMMANDS_UPDATE_PROTOCOL_HANDLER_APPROVAL_COMMAND_H_
+
+#include <memory>
+#include <string>
+
+#include "base/functional/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "base/values.h"
+#include "chrome/browser/web_applications/commands/web_app_command.h"
+#include "chrome/browser/web_applications/web_app_id.h"
+
+namespace web_app {
+
+class AppLock;
+class AppLockDescription;
+class LockDescription;
+
+// Updates the approved or disallowed protocol list for the given app. If
+// necessary, it also updates the protocol registration with the OS.
+class UpdateProtocolHandlerApprovalCommand
+    : public WebAppCommandTemplate<AppLock> {
+ public:
+  UpdateProtocolHandlerApprovalCommand(const AppId& app_id,
+                                       const std::string& protocol_scheme,
+                                       bool allowed,
+                                       base::OnceClosure callback);
+
+  ~UpdateProtocolHandlerApprovalCommand() override;
+
+  void StartWithLock(std::unique_ptr<AppLock> lock) override;
+
+  LockDescription& lock_description() const override;
+
+  base::Value ToDebugValue() const override;
+
+  void OnSyncSourceRemoved() override;
+  void OnShutdown() override;
+
+ private:
+  void OnProtocolHandlersUpdated();
+
+  std::unique_ptr<AppLockDescription> lock_description_;
+  std::unique_ptr<AppLock> lock_;
+
+  const AppId app_id_;
+  std::string protocol_scheme_;
+  bool allowed_;
+  base::OnceClosure callback_;
+
+  base::Value::Dict debug_info_;
+
+  base::WeakPtrFactory<UpdateProtocolHandlerApprovalCommand> weak_factory_{
+      this};
+};
+
+}  // namespace web_app
+
+#endif  // CHROME_BROWSER_WEB_APPLICATIONS_COMMANDS_UPDATE_PROTOCOL_HANDLER_APPROVAL_COMMAND_H_
diff --git a/chrome/browser/web_applications/commands/update_protocol_handler_approval_command_browsertest.cc b/chrome/browser/web_applications/commands/update_protocol_handler_approval_command_browsertest.cc
new file mode 100644
index 0000000..5f2f1d3
--- /dev/null
+++ b/chrome/browser/web_applications/commands/update_protocol_handler_approval_command_browsertest.cc
@@ -0,0 +1,302 @@
+// 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 "base/containers/contains.h"
+#include "base/files/file_util.h"
+#include "base/test/test_future.h"
+#include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
+#include "chrome/browser/ui/web_applications/web_app_controller_browsertest.h"
+#include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
+#include "chrome/browser/web_applications/web_app_command_scheduler.h"
+#include "chrome/browser/web_applications/web_app_constants.h"
+#include "chrome/browser/web_applications/web_app_provider.h"
+#include "components/webapps/browser/installable/installable_metrics.h"
+#include "content/public/test/browser_test.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+#if BUILDFLAG(IS_MAC)
+#include "chrome/browser/web_applications/app_shim_registry_mac.h"
+#endif
+
+namespace web_app {
+namespace {
+const char16_t kAppName[] = u"Test App";
+
+class UpdateProtocolHandlerApprovalCommandTest
+    : public WebAppControllerBrowserTest {
+ public:
+  const GURL kTestAppUrl = GURL("https://example.com");
+
+  UpdateProtocolHandlerApprovalCommandTest() = default;
+  ~UpdateProtocolHandlerApprovalCommandTest() override = default;
+
+  void SetUpOnMainThread() override {
+    os_hooks_suppress_.reset();
+    {
+      base::ScopedAllowBlockingForTesting allow_blocking;
+      shortcut_override_ =
+          ShortcutOverrideForTesting::OverrideForTesting(base::GetHomeDir());
+    }
+    WebAppControllerBrowserTest::SetUpOnMainThread();
+  }
+
+  void TearDownOnMainThread() override {
+    // Uninstallation of all apps is required for the shortcut override
+    // destruction.
+    EXPECT_TRUE(test::UninstallAllWebApps(profile()));
+    {
+      // Blocking required due to file operations in the shortcut override
+      // destructor.
+      base::ScopedAllowBlockingForTesting allow_blocking;
+      shortcut_override_.reset();
+    }
+    WebAppControllerBrowserTest::TearDownOnMainThread();
+  }
+
+  web_app::AppId InstallWebAppWithProtocolHandlers(
+      const std::vector<apps::ProtocolHandlerInfo>& protocol_handlers) {
+    std::unique_ptr<WebAppInstallInfo> info =
+        std::make_unique<WebAppInstallInfo>();
+    info->start_url = GURL(kTestAppUrl);
+    info->title = kAppName;
+    info->user_display_mode = web_app::UserDisplayMode::kStandalone;
+    info->protocol_handlers = protocol_handlers;
+    base::test::TestFuture<const AppId&, webapps::InstallResultCode> result;
+    // InstallFromInfoWithParams is used instead of InstallFromInfo, because
+    // InstallFromInfo doesn't register OS integration.
+    provider().scheduler().InstallFromInfoWithParams(
+        std::move(info), /*overwrite_existing_manifest_fields=*/true,
+        webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON,
+        result.GetCallback(), WebAppInstallParams());
+    bool success = result.Wait();
+    EXPECT_TRUE(success);
+    if (!success)
+      return AppId();
+    EXPECT_EQ(result.Get<webapps::InstallResultCode>(),
+              webapps::InstallResultCode::kSuccessNewInstall);
+    return result.Get<AppId>();
+  }
+
+#if BUILDFLAG(IS_MAC)
+  std::vector<std::string> GetAppShimRegisteredProtocolHandlers(
+      const AppId& app_id) {
+    std::vector<std::string> protocol_schemes;
+    for (const auto& [file_path, handler] :
+         AppShimRegistry::Get()->GetHandlersForApp(app_id)) {
+      protocol_schemes.insert(protocol_schemes.end(),
+                              handler.protocol_handlers.begin(),
+                              handler.protocol_handlers.end());
+    }
+    return protocol_schemes;
+  }
+#endif  // BUILDFLAG(IS_MAC)
+
+  bool AreProtocolsRegisteredWithOs() {
+#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+    return false;
+#else
+    return true;
+#endif
+  }
+
+ private:
+  std::unique_ptr<ShortcutOverrideForTesting::BlockingRegistration>
+      shortcut_override_;
+};
+
+IN_PROC_BROWSER_TEST_F(UpdateProtocolHandlerApprovalCommandTest, Install) {
+  apps::ProtocolHandlerInfo protocol_handler;
+  const std::string handler_url =
+      std::string(kTestAppUrl.spec()) + "/testing=%s";
+  protocol_handler.url = GURL(handler_url);
+  protocol_handler.protocol = "web+test";
+  web_app::AppId app_id = InstallWebAppWithProtocolHandlers({protocol_handler});
+
+  EXPECT_THAT(provider().registrar().IsAllowedLaunchProtocol(
+                  app_id, protocol_handler.protocol),
+              testing::IsFalse());
+  EXPECT_THAT(provider().registrar().IsDisallowedLaunchProtocol(
+                  app_id, protocol_handler.protocol),
+              testing::IsFalse());
+
+#if BUILDFLAG(IS_MAC)
+  EXPECT_THAT(GetAppShimRegisteredProtocolHandlers(app_id),
+              testing::ElementsAre(protocol_handler.protocol));
+#endif
+
+  if (AreProtocolsRegisteredWithOs()) {
+    // Installation registers the protocol handlers.
+    EXPECT_THAT(GetShortcutOverrideForTesting()->protocol_scheme_registrations,
+                testing::ElementsAre(std::make_tuple(
+                    app_id, std::vector({protocol_handler.protocol}))));
+  }
+}
+
+IN_PROC_BROWSER_TEST_F(UpdateProtocolHandlerApprovalCommandTest,
+                       ProtocolHandlersRegisteredAndAllowed) {
+  apps::ProtocolHandlerInfo protocol_handler;
+  const std::string handler_url =
+      std::string(kTestAppUrl.spec()) + "/testing=%s";
+  protocol_handler.url = GURL(handler_url);
+  protocol_handler.protocol = "web+test";
+  web_app::AppId app_id = InstallWebAppWithProtocolHandlers({protocol_handler});
+
+  base::test::TestFuture<void> future;
+  provider().scheduler().UpdateProtocolHandlerUserApproval(
+      app_id, protocol_handler.protocol, /*allowed=*/true,
+      future.GetCallback());
+  EXPECT_TRUE(future.Wait());
+
+  EXPECT_THAT(provider().registrar().IsAllowedLaunchProtocol(
+                  app_id, protocol_handler.protocol),
+              testing::IsTrue());
+  EXPECT_THAT(provider().registrar().IsDisallowedLaunchProtocol(
+                  app_id, protocol_handler.protocol),
+              testing::IsFalse());
+
+#if BUILDFLAG(IS_MAC)
+  EXPECT_THAT(GetAppShimRegisteredProtocolHandlers(app_id),
+              testing::ElementsAre(protocol_handler.protocol));
+#endif
+
+  if (AreProtocolsRegisteredWithOs()) {
+    // Since they were already registered, no work needed to register them
+    // again.
+    EXPECT_THAT(GetShortcutOverrideForTesting()->protocol_scheme_registrations,
+                testing::ElementsAre(std::make_tuple(
+                    app_id, std::vector({protocol_handler.protocol}))));
+  }
+}
+
+IN_PROC_BROWSER_TEST_F(UpdateProtocolHandlerApprovalCommandTest,
+                       ProtocolHandlersDisallowed) {
+  apps::ProtocolHandlerInfo protocol_handler;
+  const std::string handler_url =
+      std::string(kTestAppUrl.spec()) + "/testing=%s";
+  protocol_handler.url = GURL(handler_url);
+  protocol_handler.protocol = "web+test";
+  web_app::AppId app_id = InstallWebAppWithProtocolHandlers({protocol_handler});
+
+  base::test::TestFuture<void> future;
+  provider().scheduler().UpdateProtocolHandlerUserApproval(
+      app_id, protocol_handler.protocol, /*allowed=*/false,
+      future.GetCallback());
+  EXPECT_TRUE(future.Wait());
+
+  EXPECT_THAT(provider().registrar().IsAllowedLaunchProtocol(
+                  app_id, protocol_handler.protocol),
+              testing::IsFalse());
+  EXPECT_THAT(provider().registrar().IsDisallowedLaunchProtocol(
+                  app_id, protocol_handler.protocol),
+              testing::IsTrue());
+
+#if BUILDFLAG(IS_MAC)
+  EXPECT_THAT(GetAppShimRegisteredProtocolHandlers(app_id), testing::IsEmpty());
+#endif
+
+  if (AreProtocolsRegisteredWithOs()) {
+    // They should be registered on first install, then removed on disallow.
+    EXPECT_THAT(
+        GetShortcutOverrideForTesting()->protocol_scheme_registrations,
+        testing::ElementsAre(
+            std::make_tuple(app_id, std::vector({protocol_handler.protocol})),
+            std::make_tuple(app_id, std::vector<std::string>())));
+  }
+}
+
+IN_PROC_BROWSER_TEST_F(UpdateProtocolHandlerApprovalCommandTest,
+                       ProtocolHandlersAllowedThenDisallowed) {
+  apps::ProtocolHandlerInfo protocol_handler;
+  const std::string handler_url =
+      std::string(kTestAppUrl.spec()) + "/testing=%s";
+  protocol_handler.url = GURL(handler_url);
+  protocol_handler.protocol = "web+test";
+  web_app::AppId app_id = InstallWebAppWithProtocolHandlers({protocol_handler});
+
+  {
+    base::test::TestFuture<void> future;
+    provider().scheduler().UpdateProtocolHandlerUserApproval(
+        app_id, protocol_handler.protocol, /*allowed=*/true,
+        future.GetCallback());
+    EXPECT_TRUE(future.Wait());
+  }
+  {
+    base::test::TestFuture<void> future;
+    provider().scheduler().UpdateProtocolHandlerUserApproval(
+        app_id, protocol_handler.protocol, /*allowed=*/false,
+        future.GetCallback());
+    EXPECT_TRUE(future.Wait());
+  }
+  EXPECT_THAT(provider().registrar().IsAllowedLaunchProtocol(
+                  app_id, protocol_handler.protocol),
+              testing::IsFalse());
+  EXPECT_THAT(provider().registrar().IsDisallowedLaunchProtocol(
+                  app_id, protocol_handler.protocol),
+              testing::IsTrue());
+
+#if BUILDFLAG(IS_MAC)
+  EXPECT_THAT(GetAppShimRegisteredProtocolHandlers(app_id), testing::IsEmpty());
+#endif
+
+  if (AreProtocolsRegisteredWithOs()) {
+    // They should be registered on first install, then removed on disallow.
+    EXPECT_THAT(
+        GetShortcutOverrideForTesting()->protocol_scheme_registrations,
+        testing::ElementsAre(
+            std::make_tuple(app_id, std::vector({protocol_handler.protocol})),
+            std::make_tuple(app_id, std::vector<std::string>())));
+  }
+}
+
+IN_PROC_BROWSER_TEST_F(UpdateProtocolHandlerApprovalCommandTest,
+                       ProtocolHandlersDisallowedThenAllowed) {
+  apps::ProtocolHandlerInfo protocol_handler;
+  const std::string handler_url =
+      std::string(kTestAppUrl.spec()) + "/testing=%s";
+  protocol_handler.url = GURL(handler_url);
+  protocol_handler.protocol = "web+test";
+  web_app::AppId app_id = InstallWebAppWithProtocolHandlers({protocol_handler});
+
+  {
+    base::test::TestFuture<void> future;
+    provider().scheduler().UpdateProtocolHandlerUserApproval(
+        app_id, protocol_handler.protocol, /*allowed=*/false,
+        future.GetCallback());
+    EXPECT_TRUE(future.Wait());
+  }
+
+  {
+    base::test::TestFuture<void> future;
+    provider().scheduler().UpdateProtocolHandlerUserApproval(
+        app_id, protocol_handler.protocol, /*allowed=*/true,
+        future.GetCallback());
+    EXPECT_TRUE(future.Wait());
+  }
+  EXPECT_THAT(provider().registrar().IsAllowedLaunchProtocol(
+                  app_id, protocol_handler.protocol),
+              testing::IsTrue());
+  EXPECT_THAT(provider().registrar().IsDisallowedLaunchProtocol(
+                  app_id, protocol_handler.protocol),
+              testing::IsFalse());
+
+#if BUILDFLAG(IS_MAC)
+  EXPECT_THAT(GetAppShimRegisteredProtocolHandlers(app_id),
+              testing::ElementsAre(protocol_handler.protocol));
+#endif
+
+  if (AreProtocolsRegisteredWithOs()) {
+    EXPECT_THAT(
+        GetShortcutOverrideForTesting()->protocol_scheme_registrations,
+        testing::ElementsAre(
+            std::make_tuple(app_id, std::vector({protocol_handler.protocol})),
+            std::make_tuple(app_id, std::vector<std::string>()),
+            std::make_tuple(app_id, std::vector({protocol_handler.protocol}))));
+  }
+}
+
+}  // namespace
+}  // namespace web_app
diff --git a/chrome/browser/web_applications/commands/web_app_uninstall_command.cc b/chrome/browser/web_applications/commands/web_app_uninstall_command.cc
index c5dd12f..79d86fad 100644
--- a/chrome/browser/web_applications/commands/web_app_uninstall_command.cc
+++ b/chrome/browser/web_applications/commands/web_app_uninstall_command.cc
@@ -42,7 +42,8 @@
          uninstall_source == webapps::WebappUninstallSource::kAppList ||
          uninstall_source == webapps::WebappUninstallSource::kShelf ||
          uninstall_source == webapps::WebappUninstallSource::kSync ||
-         uninstall_source == webapps::WebappUninstallSource::kStartupCleanup;
+         uninstall_source == webapps::WebappUninstallSource::kStartupCleanup ||
+         uninstall_source == webapps::WebappUninstallSource::kTestCleanup;
 }
 
 auto StreamableToString = [](const auto& value) {
diff --git a/chrome/browser/web_applications/os_integration/web_app_protocol_handler_manager.cc b/chrome/browser/web_applications/os_integration/web_app_protocol_handler_manager.cc
index 9fcb183ed..d3407d2 100644
--- a/chrome/browser/web_applications/os_integration/web_app_protocol_handler_manager.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_protocol_handler_manager.cc
@@ -135,10 +135,6 @@
   }
   const std::vector<apps::ProtocolHandlerInfo> handlers =
       GetAppProtocolHandlerInfos(app_id);
-  if (handlers.empty()) {
-    std::move(callback).Run(Result::kOk);
-    return;
-  }
   RegisterProtocolHandlersWithOs(app_id,
                                  app_registrar_->GetAppShortName(app_id),
                                  profile_, handlers, std::move(callback));
diff --git a/chrome/browser/web_applications/os_integration/web_app_protocol_handler_registration_win.cc b/chrome/browser/web_applications/os_integration/web_app_protocol_handler_registration_win.cc
index 8a65a0f..ff1699b 100644
--- a/chrome/browser/web_applications/os_integration/web_app_protocol_handler_registration_win.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_protocol_handler_registration_win.cc
@@ -31,6 +31,7 @@
 #include "chrome/installer/util/shell_util.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/scoped_user_pref_update.h"
+#include "components/services/app_service/public/cpp/protocol_handler_info.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -46,6 +47,19 @@
     std::vector<apps::ProtocolHandlerInfo> protocol_handlers,
     const std::wstring& app_name_extension) {
   base::AssertLongCPUWorkAllowed();
+
+  if (web_app::GetShortcutOverrideForTesting()) {  // IN-TEST
+    // Instead of modifying the registry, add them to the testing data.
+    std::vector<std::string> protocols_registered;
+    for (apps::ProtocolHandlerInfo& info : protocol_handlers) {
+      protocols_registered.push_back(info.protocol);
+    }
+    web_app::GetShortcutOverrideForTesting()
+        ->protocol_scheme_registrations.emplace_back(
+            app_id, std::move(protocols_registered));
+    return;
+  }
+
   base::FilePath web_app_path =
       web_app::GetOsIntegrationResourcesDirectoryForApp(profile_path, app_id,
                                                         GURL());
@@ -87,6 +101,14 @@
     const web_app::AppId& app_id,
     const base::FilePath& profile_path) {
   base::AssertLongCPUWorkAllowed();
+
+  if (web_app::GetShortcutOverrideForTesting()) {  // IN-TEST
+    // The unregistration is not tested due to complication in the
+    // implementation of other OS's. Instead, we check if the updated
+    // registrations are empty / don't have the offending protocol.
+    return;
+  }
+
   // Need to delete the app-specific-launcher file, since uninstall may not
   // remove the web application directory. This must be done before cleaning up
   // the registry, since the app-specific-launcher path is retrieved from the
@@ -117,8 +139,15 @@
     Profile* profile,
     std::vector<apps::ProtocolHandlerInfo> protocol_handlers,
     ResultCallback callback) {
-  if (protocol_handlers.empty())
+  if (protocol_handlers.empty()) {
+    if (web_app::GetShortcutOverrideForTesting()) {  // IN-TEST
+      web_app::GetShortcutOverrideForTesting()
+          ->protocol_scheme_registrations.emplace_back(
+              app_id, std::vector<std::string>());
+    }
+    std::move(callback).Run(Result::kOk);
     return;
+  }
 
   std::wstring app_name_extension =
       GetAppNameExtensionForNextInstall(app_id, profile->GetPath());
diff --git a/chrome/browser/web_applications/os_integration/web_app_shortcut.h b/chrome/browser/web_applications/os_integration/web_app_shortcut.h
index f897ff66..1882b7e8 100644
--- a/chrome/browser/web_applications/os_integration/web_app_shortcut.h
+++ b/chrome/browser/web_applications/os_integration/web_app_shortcut.h
@@ -8,6 +8,7 @@
 #include <memory>
 #include <set>
 #include <string>
+#include <vector>
 
 #include "base/callback_forward.h"
 #include "base/callback_helpers.h"
@@ -18,6 +19,7 @@
 #include "base/sequence_checker.h"
 #include "build/build_config.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
+#include "chrome/browser/web_applications/web_app_id.h"
 #include "ui/gfx/image/image_family.h"
 #include "url/gurl.h"
 
@@ -97,6 +99,12 @@
   // std::string mime_types_file_contents;
 #endif
 
+  // Records all registration events for a given app id & protocol list. Due to
+  // simplification on the OS-side, unregistrations are not recorded, and
+  // instead this list can be checked for an empty registration.
+  std::vector<std::tuple<AppId, std::vector<std::string>>>
+      protocol_scheme_registrations;
+
  private:
   friend class base::RefCountedThreadSafe<ShortcutOverrideForTesting>;
 
diff --git a/chrome/browser/web_applications/os_integration/web_app_shortcut_linux.cc b/chrome/browser/web_applications/os_integration/web_app_shortcut_linux.cc
index 6a21a31..78f8963a 100644
--- a/chrome/browser/web_applications/os_integration/web_app_shortcut_linux.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_shortcut_linux.cc
@@ -437,7 +437,6 @@
       DeleteShortcutOnDesktop(shortcut_filename);
 
     if (create_shortcut_in_startup)
-      // if (creation_locations.in_startup)
       DeleteShortcutInAutoStart(env, shortcut_filename);
 
     if (applications_menu_location != APP_MENU_LOCATION_NONE) {
@@ -487,6 +486,14 @@
         CreateShortcutInAutoStart(env, shortcut_filename, contents) && success;
   }
 
+  if (shortcut_override) {  // IN-TEST
+    std::vector<std::string> protocol_handler(
+        shortcut_info.protocol_handlers.begin(),
+        shortcut_info.protocol_handlers.end());
+    shortcut_override->protocol_scheme_registrations.emplace_back(
+        shortcut_info.extension_id, std::move(protocol_handler));
+  }
+
   if (applications_menu_location == APP_MENU_LOCATION_NONE) {
     return success;
   }
diff --git a/chrome/browser/web_applications/os_integration/web_app_shortcut_mac.mm b/chrome/browser/web_applications/os_integration/web_app_shortcut_mac.mm
index 9e6069f..49893606 100644
--- a/chrome/browser/web_applications/os_integration/web_app_shortcut_mac.mm
+++ b/chrome/browser/web_applications/os_integration/web_app_shortcut_mac.mm
@@ -50,6 +50,7 @@
 #import "chrome/browser/mac/dock.h"
 #include "chrome/browser/shell_integration.h"
 #include "chrome/browser/web_applications/os_integration/icns_encoder.h"
+#include "chrome/browser/web_applications/os_integration/web_app_shortcut.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/common/channel_info.h"
 #include "chrome/common/chrome_constants.h"
@@ -1215,6 +1216,15 @@
       app_mode::kCFBundleURLSchemesKey : handlers
     } ];
   }
+  if (GetShortcutOverrideForTesting()) {  // IN-TEST
+    std::vector<std::string> protocol_handlers_vec;
+    protocol_handlers_vec.insert(protocol_handlers_vec.end(),
+                                 protocol_handlers.begin(),
+                                 protocol_handlers.end());
+    GetShortcutOverrideForTesting()  // IN-TEST
+        ->protocol_scheme_registrations.emplace_back(
+            info_->extension_id, std::move(protocol_handlers_vec));
+  }
 
   // TODO(crbug.com/1273526): If we decide to rename app bundles on app title
   // changes, instead of relying on localization, then this will need to change
diff --git a/chrome/browser/web_applications/test/web_app_install_test_utils.cc b/chrome/browser/web_applications/test/web_app_install_test_utils.cc
index 7335be2..dcbfdc4 100644
--- a/chrome/browser/web_applications/test/web_app_install_test_utils.cc
+++ b/chrome/browser/web_applications/test/web_app_install_test_utils.cc
@@ -5,27 +5,37 @@
 #include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
 
 #include "base/command_line.h"
+#include "base/containers/enum_set.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/bind.h"
+#include "base/test/test_future.h"
 #include "build/build_config.h"
 #include "chrome/browser/web_applications/test/fake_web_app_provider.h"
 #include "chrome/browser/web_applications/user_display_mode.h"
 #include "chrome/browser/web_applications/web_app_command_scheduler.h"
+#include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
 #include "chrome/browser/web_applications/web_app_install_finalizer.h"
 #include "chrome/browser/web_applications/web_app_install_info.h"
 #include "chrome/browser/web_applications/web_app_install_utils.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
+#include "chrome/browser/web_applications/web_app_sources.h"
 #include "chrome/common/buildflags.h"
 #include "chrome/common/chrome_switches.h"
 #include "components/webapps/browser/install_result_code.h"
+#include "components/webapps/browser/installable/installable_metrics.h"
 #include "components/webapps/browser/uninstall_result_code.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
 namespace web_app {
 namespace test {
+namespace {
+using WebAppSourcesSet = base::EnumSet<WebAppManagement::Type,
+                                       WebAppManagement::kMinValue,
+                                       WebAppManagement::kMaxValue>;
+}
 
 void WaitUntilReady(WebAppProvider* provider) {
   if (provider->on_registry_ready().is_signaled())
@@ -117,5 +127,49 @@
   base::RunLoop().RunUntilIdle();
 }
 
+bool UninstallAllWebApps(Profile* profile) {
+  bool success = true;
+  auto* provider = WebAppProvider::GetForTest(profile);
+  if (!provider)
+    return false;
+  std::vector<AppId> app_ids = provider->registrar().GetAppIds();
+  for (auto& app_id : app_ids) {
+    const WebApp* app = provider->registrar().GetAppById(app_id);
+    WebAppSourcesSet sources =
+        WebAppSourcesSet::FromEnumBitmask(app->GetSources().to_ullong());
+
+    // Non-user installs first, as they block user uninstalls.
+    for (WebAppManagement::Type source : sources) {
+      if (source == WebAppManagement::kSync)
+        continue;
+      base::test::TestFuture<webapps::UninstallResultCode> result;
+      provider->install_finalizer().UninstallExternalWebApp(
+          app_id, source, webapps::WebappUninstallSource::kTestCleanup,
+          result.GetCallback());
+      if (!result.Wait() ||
+          result.Get() == webapps::UninstallResultCode::kError) {
+        LOG(ERROR) << "Error uninstalling " << app_id;
+        success = false;
+      }
+    }
+
+    // User uninstalls now, which should be unblocked now.
+    for (WebAppManagement::Type source : sources) {
+      if (source != WebAppManagement::kSync)
+        continue;
+      base::test::TestFuture<webapps::UninstallResultCode> result;
+      provider->install_finalizer().UninstallWebApp(
+          app_id, webapps::WebappUninstallSource::kTestCleanup,
+          result.GetCallback());
+      if (!result.Wait() ||
+          result.Get() == webapps::UninstallResultCode::kError) {
+        LOG(ERROR) << "Error uninstalling " << app_id;
+        success = false;
+      }
+    }
+  }
+  return success;
+}
+
 }  // namespace test
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/test/web_app_install_test_utils.h b/chrome/browser/web_applications/test/web_app_install_test_utils.h
index c71d0765..afb8410 100644
--- a/chrome/browser/web_applications/test/web_app_install_test_utils.h
+++ b/chrome/browser/web_applications/test/web_app_install_test_utils.h
@@ -56,6 +56,10 @@
 // tests.
 void UninstallWebApp(Profile* profile, const AppId& app_id);
 
+// Synchronously uninstall all web apps for the given profile. May be used in
+// unit tests and browser tests. Returns `false` if there was a failure.
+bool UninstallAllWebApps(Profile* profile);
+
 }  // namespace test
 }  // namespace web_app
 
diff --git a/chrome/browser/web_applications/web_app_command_scheduler.cc b/chrome/browser/web_applications/web_app_command_scheduler.cc
index b10a467d..4d5692d 100644
--- a/chrome/browser/web_applications/web_app_command_scheduler.cc
+++ b/chrome/browser/web_applications/web_app_command_scheduler.cc
@@ -25,6 +25,7 @@
 #include "chrome/browser/web_applications/commands/manifest_update_finalize_command.h"
 #include "chrome/browser/web_applications/commands/run_on_os_login_command.h"
 #include "chrome/browser/web_applications/commands/update_file_handler_command.h"
+#include "chrome/browser/web_applications/commands/update_protocol_handler_approval_command.h"
 #include "chrome/browser/web_applications/commands/web_app_uninstall_command.h"
 #include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_info.h"
 #include "chrome/browser/web_applications/isolation_data.h"
@@ -320,6 +321,22 @@
       RunOnOsLoginCommand::CreateForSyncLoginMode(app_id, std::move(callback)));
 }
 
+void WebAppCommandScheduler::UpdateProtocolHandlerUserApproval(
+    const AppId& app_id,
+    const std::string& protocol_scheme,
+    bool allowed,
+    base::OnceClosure callback) {
+  if (IsShuttingDown()) {
+    base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+                                                     std::move(callback));
+    return;
+  }
+
+  provider_->command_manager().ScheduleCommand(
+      std::make_unique<UpdateProtocolHandlerApprovalCommand>(
+          app_id, protocol_scheme, allowed, std::move(callback)));
+}
+
 void WebAppCommandScheduler::ClearWebAppBrowsingData(
     const base::Time& begin_time,
     const base::Time& end_time,
diff --git a/chrome/browser/web_applications/web_app_command_scheduler.h b/chrome/browser/web_applications/web_app_command_scheduler.h
index 1e61eb2..2c3019c 100644
--- a/chrome/browser/web_applications/web_app_command_scheduler.h
+++ b/chrome/browser/web_applications/web_app_command_scheduler.h
@@ -146,6 +146,13 @@
   // OS.
   void SyncRunOnOsLoginMode(const AppId& app_id, base::OnceClosure callback);
 
+  // Updates the approved or disallowed protocol list for the given app. If
+  // necessary, it also updates the protocol registration with the OS.
+  void UpdateProtocolHandlerUserApproval(const AppId& app_id,
+                                         const std::string& protocol_scheme,
+                                         bool allowed,
+                                         base::OnceClosure callback);
+
   // Set app to disabled, This is Chrome OS specific and no-op on other
   // platforms.
   void SetAppIsDisabled(const AppId& app_id,
diff --git a/chrome/browser/web_applications/web_app_constants.cc b/chrome/browser/web_applications/web_app_constants.cc
index c37434e..42f9c74 100644
--- a/chrome/browser/web_applications/web_app_constants.cc
+++ b/chrome/browser/web_applications/web_app_constants.cc
@@ -87,6 +87,8 @@
       return "Parent App Uninstalled";
     case webapps::WebappUninstallSource::kExternalLockScreen:
       return "External Lock Screen";
+    case webapps::WebappUninstallSource::kTestCleanup:
+      return "Test cleanup";
   }
 }
 
diff --git a/chrome/browser/web_applications/web_app_registrar_unittest.cc b/chrome/browser/web_applications/web_app_registrar_unittest.cc
index 5aec09b0..74c0e77 100644
--- a/chrome/browser/web_applications/web_app_registrar_unittest.cc
+++ b/chrome/browser/web_applications/web_app_registrar_unittest.cc
@@ -1060,92 +1060,6 @@
   EXPECT_EQ(false, registrar().GetWindowControlsOverlayEnabled(app_id));
 }
 
-TEST_F(WebAppRegistrarTest, AllowedLaunchProtocols) {
-  InitSyncBridge();
-
-  auto web_app = test::CreateWebApp(GURL("https://example.com/path"));
-  const AppId app_id1 = web_app->app_id();
-  const std::string protocol_scheme1 = "test";
-  RegisterApp(std::move(web_app));
-
-  auto web_app2 = test::CreateWebApp(GURL("https://example.com/path2"));
-  const AppId app_id2 = web_app2->app_id();
-  const std::string protocol_scheme2 = "test2";
-  RegisterApp(std::move(web_app2));
-
-  // Test we can add and remove allowed protocols.
-  EXPECT_EQ(false,
-            registrar().IsAllowedLaunchProtocol(app_id1, protocol_scheme1));
-
-  sync_bridge().AddAllowedLaunchProtocol(app_id1, protocol_scheme1);
-  EXPECT_EQ(true,
-            registrar().IsAllowedLaunchProtocol(app_id1, protocol_scheme1));
-
-  sync_bridge().RemoveAllowedLaunchProtocol(app_id1, protocol_scheme1);
-  EXPECT_EQ(false,
-            registrar().IsAllowedLaunchProtocol(app_id1, protocol_scheme1));
-
-  // Test that we can get allowed protocols from multiple web apps.
-  sync_bridge().AddAllowedLaunchProtocol(app_id1, protocol_scheme1);
-  sync_bridge().AddAllowedLaunchProtocol(app_id2, protocol_scheme2);
-
-  {
-    auto allowed_protocols = registrar().GetAllAllowedLaunchProtocols();
-    EXPECT_TRUE(base::Contains(allowed_protocols, protocol_scheme1));
-    EXPECT_TRUE(base::Contains(allowed_protocols, protocol_scheme2));
-
-    sync_bridge().RemoveAllowedLaunchProtocol(app_id2, protocol_scheme2);
-  }
-  {
-    auto allowed_protocols = registrar().GetAllAllowedLaunchProtocols();
-    EXPECT_TRUE(base::Contains(allowed_protocols, protocol_scheme1));
-    EXPECT_FALSE(base::Contains(allowed_protocols, protocol_scheme2));
-  }
-}
-
-TEST_F(WebAppRegistrarTest, DisallowedLaunchProtocols) {
-  InitSyncBridge();
-
-  auto web_app = test::CreateWebApp(GURL("https://example.com/path"));
-  const AppId app_id1 = web_app->app_id();
-  const std::string protocol_scheme1 = "test";
-  RegisterApp(std::move(web_app));
-
-  auto web_app2 = test::CreateWebApp(GURL("https://example.com/path2"));
-  const AppId app_id2 = web_app2->app_id();
-  const std::string protocol_scheme2 = "test2";
-  RegisterApp(std::move(web_app2));
-
-  // Test we can add and remove diallowed protocols.
-  EXPECT_EQ(false,
-            registrar().IsDisallowedLaunchProtocol(app_id1, protocol_scheme1));
-
-  sync_bridge().AddDisallowedLaunchProtocol(app_id1, protocol_scheme1);
-  EXPECT_EQ(true,
-            registrar().IsDisallowedLaunchProtocol(app_id1, protocol_scheme1));
-
-  sync_bridge().RemoveDisallowedLaunchProtocol(app_id1, protocol_scheme1);
-  EXPECT_EQ(false,
-            registrar().IsDisallowedLaunchProtocol(app_id1, protocol_scheme1));
-
-  // Test that we can get disallowed protocols from multiple web apps.
-  sync_bridge().AddDisallowedLaunchProtocol(app_id1, protocol_scheme1);
-  sync_bridge().AddDisallowedLaunchProtocol(app_id2, protocol_scheme2);
-
-  {
-    auto disallowed_protocols = registrar().GetAllDisallowedLaunchProtocols();
-    EXPECT_TRUE(base::Contains(disallowed_protocols, protocol_scheme1));
-    EXPECT_TRUE(base::Contains(disallowed_protocols, protocol_scheme2));
-
-    sync_bridge().RemoveDisallowedLaunchProtocol(app_id2, protocol_scheme2);
-  }
-  {
-    auto disallowed_protocols = registrar().GetAllDisallowedLaunchProtocols();
-    EXPECT_TRUE(base::Contains(disallowed_protocols, protocol_scheme1));
-    EXPECT_FALSE(base::Contains(disallowed_protocols, protocol_scheme2));
-  }
-}
-
 TEST_F(WebAppRegistrarTest, IsRegisteredLaunchProtocol) {
   InitSyncBridge();
 
diff --git a/chrome/browser/web_applications/web_app_sync_bridge.cc b/chrome/browser/web_applications/web_app_sync_bridge.cc
index f8a7ef3..9328fdd1 100644
--- a/chrome/browser/web_applications/web_app_sync_bridge.cc
+++ b/chrome/browser/web_applications/web_app_sync_bridge.cc
@@ -347,26 +347,6 @@
     web_app->SetUserLaunchOrdinal(std::move(launch_ordinal));
 }
 
-void WebAppSyncBridge::AddAllowedLaunchProtocol(
-    const AppId& app_id,
-    const std::string& protocol_scheme) {
-  // Use a scope here, so that the web app registry is updated when
-  // `update` goes out of scope. If it doesn't then observers will
-  // examine stale data.
-  {
-    ScopedRegistryUpdate update(this);
-    WebApp* app_to_update = update->UpdateApp(app_id);
-    base::flat_set<std::string> protocol_handlers(
-        app_to_update->allowed_launch_protocols());
-
-    DCHECK(!base::Contains(protocol_handlers, protocol_scheme));
-    protocol_handlers.insert(protocol_scheme);
-    app_to_update->SetAllowedLaunchProtocols(std::move(protocol_handlers));
-  }
-  // Notify observers that the list of allowed protocols was updated.
-  registrar_->NotifyWebAppProtocolSettingsChanged();
-}
-
 void WebAppSyncBridge::RemoveAllowedLaunchProtocol(
     const AppId& app_id,
     const std::string& protocol_scheme) {
@@ -385,26 +365,6 @@
   registrar_->NotifyWebAppProtocolSettingsChanged();
 }
 
-void WebAppSyncBridge::AddDisallowedLaunchProtocol(
-    const AppId& app_id,
-    const std::string& protocol_scheme) {
-  // Use a scope here, so that the web app registry is updated when
-  // `update` goes out of scope. If it doesn't then observers will
-  // examine stale data.
-  {
-    ScopedRegistryUpdate update(this);
-    WebApp* app_to_update = update->UpdateApp(app_id);
-    base::flat_set<std::string> protocol_handlers(
-        app_to_update->disallowed_launch_protocols());
-
-    DCHECK(!base::Contains(protocol_handlers, protocol_scheme));
-    protocol_handlers.insert(protocol_scheme);
-    app_to_update->SetDisallowedLaunchProtocols(std::move(protocol_handlers));
-  }
-  // Notify observers that the list of disallowed protocols was updated.
-  registrar_->NotifyWebAppProtocolSettingsChanged();
-}
-
 void WebAppSyncBridge::RemoveDisallowedLaunchProtocol(
     const AppId& app_id,
     const std::string& protocol_scheme) {
diff --git a/chrome/browser/web_applications/web_app_sync_bridge.h b/chrome/browser/web_applications/web_app_sync_bridge.h
index db024420..18858014 100644
--- a/chrome/browser/web_applications/web_app_sync_bridge.h
+++ b/chrome/browser/web_applications/web_app_sync_bridge.h
@@ -117,12 +117,10 @@
   void SetUserLaunchOrdinal(const AppId& app_id,
                             syncer::StringOrdinal user_launch_ordinal);
 
-  // These methods are used by web apps to add or remove allowed
-  // protocol schemes based on user approval or withdrawal of that approval.
-  // Allowed protocol schemes will allow web apps to handle launches from
-  // urls that start with that scheme without asking the user.
-  void AddAllowedLaunchProtocol(const AppId& app_id,
-                                const std::string& protocol_scheme);
+  // This method is used by web apps to remove allowed protocol schemes based
+  // on user withdrawal of that approval. Allowed protocol schemes will allow
+  // web apps to handle launches from urls that start with that scheme without
+  // asking the user.
   void RemoveAllowedLaunchProtocol(const AppId& app_id,
                                    const std::string& protocol_scheme);
 
@@ -130,12 +128,10 @@
   void SetAppFileHandlerApprovalState(const AppId& app_id,
                                       ApiApprovalState state);
 
-  // These methods are used by web apps to add or remove disallowed
-  // protocol schemes based on user preference or withdrawal of that preference.
-  // Disallowed protocol schemes will never allow web apps to handle launches
-  // from urls that start with that scheme.
-  void AddDisallowedLaunchProtocol(const AppId& app_id,
-                                   const std::string& protocol_scheme);
+  // This method are used by web apps to remove disallowed protocol schemes
+  // based on user withdrawal of that preference. Disallowed protocol schemes
+  // will never allow web apps to handle launches from urls that start with that
+  // scheme.
   void RemoveDisallowedLaunchProtocol(const AppId& app_id,
                                       const std::string& protocol_scheme);
 
diff --git a/chrome/browser/web_applications/web_app_utils.cc b/chrome/browser/web_applications/web_app_utils.cc
index df79e33..d1da5ad6 100644
--- a/chrome/browser/web_applications/web_app_utils.cc
+++ b/chrome/browser/web_applications/web_app_utils.cc
@@ -556,43 +556,6 @@
 }
 #endif
 
-void PersistProtocolHandlersUserChoice(
-    Profile* profile,
-    const AppId& app_id,
-    const GURL& protocol_url,
-    bool allowed,
-    base::OnceClosure update_finished_callback) {
-  WebAppProvider* const provider = WebAppProvider::GetForWebApps(profile);
-  DCHECK(provider);
-
-  OsIntegrationManager& os_integration_manager =
-      provider->os_integration_manager();
-  const std::vector<custom_handlers::ProtocolHandler>
-      original_protocol_handlers =
-          os_integration_manager.GetAppProtocolHandlers(app_id);
-
-  if (allowed) {
-    provider->sync_bridge().AddAllowedLaunchProtocol(app_id,
-                                                     protocol_url.scheme());
-  } else {
-    provider->sync_bridge().AddDisallowedLaunchProtocol(app_id,
-                                                        protocol_url.scheme());
-  }
-
-  // OS protocol registration does not need to be updated.
-  if (original_protocol_handlers ==
-      os_integration_manager.GetAppProtocolHandlers(app_id)) {
-    std::move(update_finished_callback).Run();
-    return;
-  }
-
-  // TODO(https://crbug.com/1251062): Can we avoid the delay of startup, if the
-  // action as allowed?
-  provider->os_integration_manager().UpdateProtocolHandlers(
-      app_id, /*force_shortcut_updates_if_needed=*/true,
-      std::move(update_finished_callback));
-}
-
 bool HasAnySpecifiedSourcesAndNoOtherSources(WebAppSources sources,
                                              WebAppSources specified_sources) {
   bool has_any_specified_sources = (sources & specified_sources).any();
diff --git a/chrome/browser/web_applications/web_app_utils.h b/chrome/browser/web_applications/web_app_utils.h
index c4a52f52..5cfd4314 100644
--- a/chrome/browser/web_applications/web_app_utils.h
+++ b/chrome/browser/web_applications/web_app_utils.h
@@ -120,15 +120,6 @@
 std::vector<std::u16string> TransformFileExtensionsForDisplay(
     const std::set<std::string>& extensions);
 
-// Updates the approved or disallowed protocol list for the given app. If
-// necessary, it also updates the protocol registration with the OS.
-void PersistProtocolHandlersUserChoice(
-    Profile* profile,
-    const AppId& app_id,
-    const GURL& protocol_url,
-    bool allowed,
-    base::OnceClosure update_finished_callback);
-
 // Check if only |specified_sources| exist in the |sources|
 bool HasAnySpecifiedSourcesAndNoOtherSources(WebAppSources sources,
                                              WebAppSources specified_sources);
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 2e69cd9..9209ebc 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1670435862-7780b371fc93f7fd45782e575379025c019e8c51.profdata
+chrome-linux-main-1670478704-2ba112ed1db0339d2ab233a7fe0d0a8448697bbe.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index dd21636..64887dd 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1670413999-26ba32cb550175378d42f67fb35bb5796b709578.profdata
+chrome-mac-arm-main-1670478704-fb00ec2ac1c3c6a065e85949fea49cde986d46f8.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 63c3543..decb39c 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1670435862-96ba8bfbcdc61be6ca4340ec99312b1240066f9a.profdata
+chrome-mac-main-1670478704-9e0da5494a66c74832b1dbe8f873da353c661795.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 276423ec..84a6870e 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1670435862-12456f82f8f8e2f82890190f9b9b7c4abfa8d0b4.profdata
+chrome-win32-main-1670478704-c7c88de6f7675ea75164c615b7cbbf78706ff6b6.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 49c3187..f99e6fc51 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1670424874-3fcfc790dcba77f96b99526fa3bd9ad8a308db2f.profdata
+chrome-win64-main-1670478704-80427e0d663fc83bb275d5e7955d140b1c9299ca.profdata
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index 7d9126a5f..640eb6f7 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -638,6 +638,11 @@
 // Sets whether the HTTPS-Only Mode setting is displayed in the settings UI.
 BASE_FEATURE(kHttpsOnlyMode, "HttpsOnlyMode", base::FEATURE_ENABLED_BY_DEFAULT);
 
+// Enables automatically upgrading main frame navigations to HTTPS.
+BASE_FEATURE(kHttpsUpgrades,
+             "HttpsUpgrades",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 #if BUILDFLAG(IS_MAC)
 BASE_FEATURE(kImmersiveFullscreen,
              "ImmersiveFullscreen",
@@ -1075,11 +1080,6 @@
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if !BUILDFLAG(IS_ANDROID)
-// Enables logging UKMs for background tab activity by TabActivityWatcher.
-BASE_FEATURE(kTabMetricsLogging,
-             "TabMetricsLogging",
-             base::FEATURE_ENABLED_BY_DEFAULT);
-
 // Enables the demo version of the Support Tool. The tool will be available in
 // chrome://support-tool. See go/support-tool-v1-design for more details.
 BASE_FEATURE(kSupportTool, "SupportTool", base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h
index 0f4034a..9cb8249 100644
--- a/chrome/common/chrome_features.h
+++ b/chrome/common/chrome_features.h
@@ -374,6 +374,7 @@
 COMPONENT_EXPORT(CHROME_FEATURES) BASE_DECLARE_FEATURE(kHideWebAppOriginText);
 
 COMPONENT_EXPORT(CHROME_FEATURES) BASE_DECLARE_FEATURE(kHttpsOnlyMode);
+COMPONENT_EXPORT(CHROME_FEATURES) BASE_DECLARE_FEATURE(kHttpsUpgrades);
 
 #if BUILDFLAG(IS_MAC)
 COMPONENT_EXPORT(CHROME_FEATURES) BASE_DECLARE_FEATURE(kImmersiveFullscreen);
@@ -598,8 +599,6 @@
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 #if !BUILDFLAG(IS_ANDROID)
-COMPONENT_EXPORT(CHROME_FEATURES) BASE_DECLARE_FEATURE(kTabMetricsLogging);
-
 COMPONENT_EXPORT(CHROME_FEATURES) BASE_DECLARE_FEATURE(kSupportTool);
 
 COMPONENT_EXPORT(CHROME_FEATURES) BASE_DECLARE_FEATURE(kSupportToolScreenshot);
diff --git a/chrome/common/extensions/chrome_extensions_client.cc b/chrome/common/extensions/chrome_extensions_client.cc
index a97676a..493161c 100644
--- a/chrome/common/extensions/chrome_extensions_client.cc
+++ b/chrome/common/extensions/chrome_extensions_client.cc
@@ -185,12 +185,11 @@
       ExtensionsClient::GetBrowserImagePaths(extension);
 
   // Theme images
-  const base::DictionaryValue* theme_images = ThemeInfo::GetImages(extension);
+  const base::Value::Dict* theme_images = ThemeInfo::GetImages(extension);
   if (theme_images) {
-    for (const auto item : theme_images->GetDict()) {
-      if (item.second.is_string())
-        image_paths.insert(
-            base::FilePath::FromUTF8Unsafe(item.second.GetString()));
+    for (const auto [key, value] : *theme_images) {
+      if (value.is_string())
+        image_paths.insert(base::FilePath::FromUTF8Unsafe(value.GetString()));
     }
   }
 
diff --git a/chrome/common/extensions/manifest_handlers/theme_handler.cc b/chrome/common/extensions/manifest_handlers/theme_handler.cc
index cf49ef22..e4bf40e 100644
--- a/chrome/common/extensions/manifest_handlers/theme_handler.cc
+++ b/chrome/common/extensions/manifest_handlers/theme_handler.cc
@@ -27,24 +27,23 @@
   if (const base::Value::Dict* images_dict =
           theme_dict.FindDict(keys::kThemeImages)) {
     // Validate that the images are all strings.
-    for (const auto item : *images_dict) {
+    for (const auto [key, value] : *images_dict) {
       // The value may be a dictionary of scales and files paths.
       // Or the value may be a file path, in which case a scale
       // of 100% is assumed.
-      if (item.second.is_dict()) {
-        for (const auto inner_item : item.second.GetDict()) {
-          if (!inner_item.second.is_string()) {
+      if (value.is_dict()) {
+        for (const auto [inner_key, inner_value] : value.GetDict()) {
+          if (!inner_value.is_string()) {
             *error = errors::kInvalidThemeImages;
             return false;
           }
         }
-      } else if (!item.second.is_string()) {
+      } else if (!value.is_string()) {
         *error = errors::kInvalidThemeImages;
         return false;
       }
     }
-    theme_info->theme_images_ = base::DictionaryValue::From(
-        base::Value::ToUniquePtrValue(base::Value(images_dict->Clone())));
+    theme_info->theme_images_ = images_dict->Clone();
   }
   return true;
 }
@@ -55,12 +54,12 @@
   if (const base::Value::Dict* colors_value =
           theme_dict.FindDict(keys::kThemeColors)) {
     // Validate that the colors are RGB or RGBA lists.
-    for (const auto it : *colors_value) {
-      if (!it.second.is_list()) {
+    for (const auto [key, value] : *colors_value) {
+      if (!value.is_list()) {
         *error = errors::kInvalidThemeColors;
         return false;
       }
-      const base::Value::List& color_list = it.second.GetList();
+      const base::Value::List& color_list = value.GetList();
 
       // There must be either 3 items (RGB), or 4 (RGBA).
       if (!(color_list.size() == 3 || color_list.size() == 4)) {
@@ -83,8 +82,7 @@
       }
     }
 
-    theme_info->theme_colors_ =
-        base::Value::ToUniquePtrValue(base::Value(colors_value->Clone()));
+    theme_info->theme_colors_ = colors_value->Clone();
   }
   return true;
 }
@@ -97,13 +95,13 @@
     return true;
 
   // Validate that the tints are all reals.
-  for (const auto item : *tints_dict) {
-    if (!item.second.is_list()) {
+  for (const auto [key, value] : *tints_dict) {
+    if (!value.is_list()) {
       *error = errors::kInvalidThemeTints;
       return false;
     }
 
-    const base::Value::List& tint_list = item.second.GetList();
+    const base::Value::List& tint_list = value.GetList();
     if (tint_list.size() != 3) {
       *error = errors::kInvalidThemeTints;
       return false;
@@ -116,8 +114,7 @@
     }
   }
 
-  theme_info->theme_tints_ = base::DictionaryValue::From(
-      base::Value::ToUniquePtrValue(base::Value(tints_dict->Clone())));
+  theme_info->theme_tints_ = tints_dict->Clone();
   return true;
 }
 
@@ -126,9 +123,7 @@
                            ThemeInfo* theme_info) {
   if (const base::Value::Dict* display_properties_value =
           theme_dict.FindDict(keys::kThemeDisplayProperties)) {
-    theme_info->theme_display_properties_ =
-        base::DictionaryValue::From(base::Value::ToUniquePtrValue(
-            base::Value(display_properties_value->Clone())));
+    theme_info->theme_display_properties_ = display_properties_value->Clone();
   }
   return true;
 }
@@ -146,28 +141,28 @@
 }
 
 // static
-const base::DictionaryValue* ThemeInfo::GetImages(const Extension* extension) {
+const base::Value::Dict* ThemeInfo::GetImages(const Extension* extension) {
   const ThemeInfo* theme_info = GetInfo(extension);
-  return theme_info ? theme_info->theme_images_.get() : nullptr;
+  return theme_info ? &theme_info->theme_images_ : nullptr;
 }
 
 // static
-const base::Value* ThemeInfo::GetColors(const Extension* extension) {
+const base::Value::Dict* ThemeInfo::GetColors(const Extension* extension) {
   const ThemeInfo* theme_info = GetInfo(extension);
-  return theme_info ? theme_info->theme_colors_.get() : nullptr;
+  return theme_info ? &theme_info->theme_colors_ : nullptr;
 }
 
 // static
-const base::DictionaryValue* ThemeInfo::GetTints(const Extension* extension) {
+const base::Value::Dict* ThemeInfo::GetTints(const Extension* extension) {
   const ThemeInfo* theme_info = GetInfo(extension);
-  return theme_info ? theme_info->theme_tints_.get() : nullptr;
+  return theme_info ? &theme_info->theme_tints_ : nullptr;
 }
 
 // static
-const base::DictionaryValue* ThemeInfo::GetDisplayProperties(
+const base::Value::Dict* ThemeInfo::GetDisplayProperties(
     const Extension* extension) {
   const ThemeInfo* theme_info = GetInfo(extension);
-  return theme_info ? theme_info->theme_display_properties_.get() : nullptr;
+  return theme_info ? &theme_info->theme_display_properties_ : nullptr;
 }
 
 ThemeHandler::ThemeHandler() {
@@ -202,11 +197,11 @@
                             std::vector<InstallWarning>* warnings) const {
   // Validate that theme images exist.
   if (extension->is_theme()) {
-    const base::DictionaryValue* images_value =
+    const base::Value::Dict* images_value =
         extensions::ThemeInfo::GetImages(extension);
     if (images_value) {
-      for (const auto item : images_value->GetDict()) {
-        const std::string* val = item.second.GetIfString();
+      for (const auto [key, value] : *images_value) {
+        const std::string* val = value.GetIfString();
         if (val) {
           base::FilePath image_path =
               extension->path().Append(base::FilePath::FromUTF8Unsafe(*val));
diff --git a/chrome/common/extensions/manifest_handlers/theme_handler.h b/chrome/common/extensions/manifest_handlers/theme_handler.h
index 80a43c8..cda94ba 100644
--- a/chrome/common/extensions/manifest_handlers/theme_handler.h
+++ b/chrome/common/extensions/manifest_handlers/theme_handler.h
@@ -7,13 +7,10 @@
 
 #include <memory>
 
+#include "base/values.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/manifest_handler.h"
 
-namespace base {
-class DictionaryValue;
-}
-
 namespace extensions {
 
 // A structure to hold the parsed theme data.
@@ -22,23 +19,23 @@
   ThemeInfo();
   ~ThemeInfo() override;
 
-  static const base::DictionaryValue* GetImages(const Extension* extension);
-  static const base::Value* GetColors(const Extension* extension);
-  static const base::DictionaryValue* GetTints(const Extension* extension);
-  static const base::DictionaryValue* GetDisplayProperties(
+  static const base::Value::Dict* GetImages(const Extension* extension);
+  static const base::Value::Dict* GetColors(const Extension* extension);
+  static const base::Value::Dict* GetTints(const Extension* extension);
+  static const base::Value::Dict* GetDisplayProperties(
       const Extension* extension);
 
   // A map of resource id's to relative file paths.
-  std::unique_ptr<base::DictionaryValue> theme_images_;
+  base::Value::Dict theme_images_;
 
   // A map of color names to colors.
-  std::unique_ptr<base::Value> theme_colors_;
+  base::Value::Dict theme_colors_;
 
   // A map of color names to colors.
-  std::unique_ptr<base::DictionaryValue> theme_tints_;
+  base::Value::Dict theme_tints_;
 
   // A map of display properties.
-  std::unique_ptr<base::DictionaryValue> theme_display_properties_;
+  base::Value::Dict theme_display_properties_;
 };
 
 // Parses the "theme" manifest key.
diff --git a/chrome/common/net/net_error_page_support.mojom b/chrome/common/net/net_error_page_support.mojom
index 61b5198..fc8c8193 100644
--- a/chrome/common/net/net_error_page_support.mojom
+++ b/chrome/common/net/net_error_page_support.mojom
@@ -14,4 +14,8 @@
   // Called to indicate if download button is being shown in the error page.
   [EnableIf=enable_offline_pages]
   SetIsShowingDownloadButtonInErrorPage(bool showing_download_button);
+
+  // Called to show the captive portal signin page.
+  [EnableIf=is_chromeos]
+  ShowPortalSignin();
 };
diff --git a/chrome/renderer/net/net_error_helper.cc b/chrome/renderer/net/net_error_helper.cc
index 2e8898b..b62f6d7 100644
--- a/chrome/renderer/net/net_error_helper.cc
+++ b/chrome/renderer/net/net_error_helper.cc
@@ -339,6 +339,12 @@
   GetRemoteNetworkDiagnostics()->RunNetworkDiagnostics(page_url);
 }
 
+void NetErrorHelper::PortalSignin() {
+#if BUILDFLAG(IS_CHROMEOS)
+  GetRemoteNetErrorPageSupport()->ShowPortalSignin();
+#endif
+}
+
 void NetErrorHelper::DownloadPageLater() {
 #if BUILDFLAG(ENABLE_OFFLINE_PAGES)
   GetRemoteNetErrorPageSupport()->DownloadPageLater();
diff --git a/chrome/renderer/net/net_error_helper.h b/chrome/renderer/net/net_error_helper.h
index 2f3b7a0..3be1fb1 100644
--- a/chrome/renderer/net/net_error_helper.h
+++ b/chrome/renderer/net/net_error_helper.h
@@ -101,6 +101,7 @@
   void RequestEasterEggHighScore() override;
   void ReloadFrame() override;
   void DiagnoseError(const GURL& page_url) override;
+  void PortalSignin() override;
   void DownloadPageLater() override;
   void SetIsShowingDownloadButton(bool show) override;
   void OfflineContentAvailable(
diff --git a/chrome/renderer/net/net_error_helper_core.cc b/chrome/renderer/net/net_error_helper_core.cc
index 21f7129..9c513538 100644
--- a/chrome/renderer/net/net_error_helper_core.cc
+++ b/chrome/renderer/net/net_error_helper_core.cc
@@ -305,6 +305,10 @@
       RecordEvent(error_page::NETWORK_ERROR_DIAGNOSE_BUTTON_CLICKED);
       delegate_->DiagnoseError(committed_error_page_info_->error.url());
       return;
+    case PORTAL_SIGNIN:
+      RecordEvent(error_page::NETWORK_ERROR_PORTAL_SIGNIN_BUTTON_CLICKED);
+      delegate_->PortalSignin();
+      return;
     case DOWNLOAD_BUTTON:
       RecordEvent(error_page::NETWORK_ERROR_PAGE_DOWNLOAD_BUTTON_CLICKED);
       delegate_->DownloadPageLater();
diff --git a/chrome/renderer/net/net_error_helper_core.h b/chrome/renderer/net/net_error_helper_core.h
index 25cb322b..d893b2c 100644
--- a/chrome/renderer/net/net_error_helper_core.h
+++ b/chrome/renderer/net/net_error_helper_core.h
@@ -48,6 +48,7 @@
     MORE_BUTTON,
     EASTER_EGG,
     DIAGNOSE_ERROR,
+    PORTAL_SIGNIN,
     DOWNLOAD_BUTTON,  // "Download page later" experiment.
   };
 
@@ -93,6 +94,9 @@
     // Run the platform diagnostics too for the specified URL.
     virtual void DiagnoseError(const GURL& page_url) = 0;
 
+    // Show the captive portal signin page.
+    virtual void PortalSignin() = 0;
+
     // Schedule to download the page at a later time.
     virtual void DownloadPageLater() = 0;
 
diff --git a/chrome/renderer/net/net_error_helper_core_unittest.cc b/chrome/renderer/net/net_error_helper_core_unittest.cc
index ccc5f9d..2f97ae1a 100644
--- a/chrome/renderer/net/net_error_helper_core_unittest.cc
+++ b/chrome/renderer/net/net_error_helper_core_unittest.cc
@@ -255,6 +255,8 @@
     diagnose_error_url_ = page_url;
   }
 
+  void PortalSignin() override {}
+
   void DownloadPageLater() override { download_count_++; }
 
   void SetIsShowingDownloadButton(bool show) override {}
diff --git a/chrome/renderer/net/net_error_page_controller.cc b/chrome/renderer/net/net_error_page_controller.cc
index 6424315..045be86 100644
--- a/chrome/renderer/net/net_error_page_controller.cc
+++ b/chrome/renderer/net/net_error_page_controller.cc
@@ -78,6 +78,10 @@
   return ButtonClick(NetErrorHelperCore::DIAGNOSE_ERROR);
 }
 
+bool NetErrorPageController::PortalSigninButtonClick() {
+  return ButtonClick(NetErrorHelperCore::PORTAL_SIGNIN);
+}
+
 bool NetErrorPageController::ButtonClick(NetErrorHelperCore::Button button) {
   if (delegate_)
     delegate_->ButtonPressed(button);
@@ -132,6 +136,8 @@
                  &NetErrorPageController::DetailsButtonClick)
       .SetMethod("diagnoseErrorsButtonClick",
                  &NetErrorPageController::DiagnoseErrorsButtonClick)
+      .SetMethod("portalSigninButtonClick",
+                 &NetErrorPageController::PortalSigninButtonClick)
       .SetMethod("trackEasterEgg", &NetErrorPageController::TrackEasterEgg)
       .SetMethod("updateEasterEggHighScore",
                  &NetErrorPageController::UpdateEasterEggHighScore)
diff --git a/chrome/renderer/net/net_error_page_controller.h b/chrome/renderer/net/net_error_page_controller.h
index fcbc44e6..f69f601 100644
--- a/chrome/renderer/net/net_error_page_controller.h
+++ b/chrome/renderer/net/net_error_page_controller.h
@@ -98,6 +98,9 @@
   // Execute a "Diagnose Errors" button click.
   bool DiagnoseErrorsButtonClick();
 
+  // Execute a "Sign in to network" button click.
+  bool PortalSigninButtonClick();
+
   // Used internally by other button click methods.
   bool ButtonClick(NetErrorHelperCore::Button button);
 
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 0ad4767..54d17d31 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -505,6 +505,8 @@
       "../browser/apps/app_service/metrics/app_platform_metrics_service_test_base.h",
       "../browser/ash/accessibility/speech_monitor.cc",
       "../browser/ash/accessibility/speech_monitor.h",
+      "../browser/ash/app_list/search/test/test_result.cc",
+      "../browser/ash/app_list/search/test/test_result.h",
       "../browser/ash/arc/tracing/arc_app_performance_tracing_test_helper.cc",
       "../browser/ash/arc/tracing/arc_app_performance_tracing_test_helper.h",
       "../browser/ash/child_accounts/child_account_test_utils.cc",
@@ -559,8 +561,6 @@
       "../browser/nearby_sharing/fake_nearby_connection.h",
       "../browser/nearby_sharing/fake_nearby_connections_manager.cc",
       "../browser/nearby_sharing/fake_nearby_connections_manager.h",
-      "../browser/ui/app_list/search/test/test_result.cc",
-      "../browser/ui/app_list/search/test/test_result.h",
       "../browser/ui/ash/accessibility/fake_accessibility_controller.cc",
       "../browser/ui/ash/accessibility/fake_accessibility_controller.h",
       "../browser/ui/ash/clipboard_history_test_util.cc",
@@ -2066,7 +2066,6 @@
       "../browser/resource_coordinator/discard_before_unload_helper.cc",
       "../browser/resource_coordinator/discard_before_unload_helper.h",
       "../browser/resource_coordinator/discard_before_unload_helper_browsertest.cc",
-      "../browser/resource_coordinator/tab_activity_watcher_browsertest.cc",
       "../browser/resource_coordinator/tab_helper_browsertest.cc",
       "../browser/resource_coordinator/tab_manager_browsertest.cc",
       "../browser/safe_browsing/client_side_detection_service_browsertest.cc",
@@ -3632,6 +3631,7 @@
         "../browser/ash/accessibility/accessibility_manager_browsertest.cc",
         "../browser/ash/accessibility/accessibility_test_utils.cc",
         "../browser/ash/accessibility/accessibility_test_utils.h",
+        "../browser/ash/accessibility/autoclick_browsertest.cc",
         "../browser/ash/accessibility/dictation_browsertest.cc",
         "../browser/ash/accessibility/dictation_bubble_test_helper.cc",
         "../browser/ash/accessibility/dictation_bubble_test_helper.h",
@@ -3651,6 +3651,14 @@
         "../browser/ash/app_list/app_service/app_service_app_item_browsertest.cc",
         "../browser/ash/app_list/app_service/app_service_context_menu_browsertest.cc",
         "../browser/ash/app_list/arc/arc_usb_host_permission_browsertest.cc",
+        "../browser/ash/app_list/search/files/drive_search_browsertest.cc",
+        "../browser/ash/app_list/search/files/file_suggest_keyed_service_browsertest.cc",
+        "../browser/ash/app_list/search/test/app_list_search_test_helper.cc",
+        "../browser/ash/app_list/search/test/app_list_search_test_helper.h",
+        "../browser/ash/app_list/search/test/search_results_changed_waiter.cc",
+        "../browser/ash/app_list/search/test/search_results_changed_waiter.h",
+        "../browser/ash/app_list/search/test/test_continue_files_search_provider.cc",
+        "../browser/ash/app_list/search/test/test_continue_files_search_provider.h",
         "../browser/ash/app_mode/arc/arc_kiosk_app_manager_browsertest.cc",
         "../browser/ash/app_mode/kiosk_app_manager_browsertest.cc",
         "../browser/ash/app_mode/kiosk_app_update_service_browsertest.cc",
@@ -4049,15 +4057,7 @@
         "../browser/ui/app_list/app_list_sort_browsertest.cc",
         "../browser/ui/app_list/chrome_app_list_item_browsertest.cc",
         "../browser/ui/app_list/chrome_app_list_model_updater_browsertest.cc",
-        "../browser/ui/app_list/search/files/drive_search_browsertest.cc",
-        "../browser/ui/app_list/search/files/file_suggest_keyed_service_browsertest.cc",
         "../browser/ui/app_list/search/help_app_search_browsertest.cc",
-        "../browser/ui/app_list/search/test/app_list_search_test_helper.cc",
-        "../browser/ui/app_list/search/test/app_list_search_test_helper.h",
-        "../browser/ui/app_list/search/test/search_results_changed_waiter.cc",
-        "../browser/ui/app_list/search/test/search_results_changed_waiter.h",
-        "../browser/ui/app_list/search/test/test_continue_files_search_provider.cc",
-        "../browser/ui/app_list/search/test/test_continue_files_search_provider.h",
         "../browser/ui/ash/accelerator_commands_browsertest.cc",
         "../browser/ui/ash/app_list/app_list_with_recent_apps_browsertest.cc",
         "../browser/ui/ash/app_list/apps_grid_drag_browsertest.cc",
@@ -6767,7 +6767,6 @@
       "../browser/resource_coordinator/lifecycle_unit_base_unittest.cc",
       "../browser/resource_coordinator/lifecycle_unit_unittest.cc",
       "../browser/resource_coordinator/session_restore_policy_unittest.cc",
-      "../browser/resource_coordinator/tab_activity_watcher_unittest.cc",
       "../browser/resource_coordinator/tab_lifecycle_unit_source_unittest.cc",
       "../browser/resource_coordinator/tab_lifecycle_unit_unittest.cc",
       "../browser/resource_coordinator/tab_manager_unittest.cc",
@@ -7332,6 +7331,56 @@
       "../browser/ash/app_list/arc/intent_unittest.cc",
       "../browser/ash/app_list/arc/mock_arc_app_list_prefs_observer.cc",
       "../browser/ash/app_list/arc/mock_arc_app_list_prefs_observer.h",
+      "../browser/ash/app_list/reorder/app_list_reorder_core_unittest.cc",
+      "../browser/ash/app_list/reorder/app_list_reorder_util_unittest.cc",
+      "../browser/ash/app_list/search/arc/arc_app_shortcuts_search_provider_unittest.cc",
+      "../browser/ash/app_list/search/arc/arc_playstore_search_provider_unittest.cc",
+      "../browser/ash/app_list/search/arc/recommend_apps_fetcher_impl_unittest.cc",
+      "../browser/ash/app_list/search/common/string_util_unittest.cc",
+      "../browser/ash/app_list/search/cros_action_history/cros_action_recorder_tab_tracker_unittest.cc",
+      "../browser/ash/app_list/search/cros_action_history/cros_action_recorder_unittest.cc",
+      "../browser/ash/app_list/search/files/file_result_unittest.cc",
+      "../browser/ash/app_list/search/files/file_search_provider_unittest.cc",
+      "../browser/ash/app_list/search/files/file_suggest_keyed_service_unittest.cc",
+      "../browser/ash/app_list/search/files/item_suggest_cache_unittest.cc",
+      "../browser/ash/app_list/search/files/justifications_unittest.cc",
+      "../browser/ash/app_list/search/files/local_file_suggestion_provider_unittest.cc",
+      "../browser/ash/app_list/search/files/zero_state_drive_provider_unittest.cc",
+      "../browser/ash/app_list/search/files/zero_state_file_provider_unittest.cc",
+      "../browser/ash/app_list/search/games/game_provider_unittest.cc",
+      "../browser/ash/app_list/search/games/game_result_unittest.cc",
+      "../browser/ash/app_list/search/omnibox/omnibox_answer_result_unittest.cc",
+      "../browser/ash/app_list/search/omnibox/omnibox_lacros_provider_unittest.cc",
+      "../browser/ash/app_list/search/omnibox/omnibox_provider_unittest.cc",
+      "../browser/ash/app_list/search/omnibox/omnibox_result_unittest.cc",
+      "../browser/ash/app_list/search/omnibox/open_tab_result_unittest.cc",
+      "../browser/ash/app_list/search/ranking/answer_ranker_unittest.cc",
+      "../browser/ash/app_list/search/ranking/best_match_ranker_unittest.cc",
+      "../browser/ash/app_list/search/ranking/filtering_ranker_unittest.cc",
+      "../browser/ash/app_list/search/ranking/ftrl_ranker_unittest.cc",
+      "../browser/ash/app_list/search/ranking/mrfu_ranker_unittest.cc",
+      "../browser/ash/app_list/search/ranking/query_highlighter_unittest.cc",
+      "../browser/ash/app_list/search/ranking/removed_results_proto_unittest.cc",
+      "../browser/ash/app_list/search/ranking/removed_results_ranker_unittest.cc",
+      "../browser/ash/app_list/search/ranking/score_normalizing_ranker_unittest.cc",
+      "../browser/ash/app_list/search/test/ranking_test_util.cc",
+      "../browser/ash/app_list/search/test/ranking_test_util.h",
+      "../browser/ash/app_list/search/test/search_controller_test_util.cc",
+      "../browser/ash/app_list/search/test/search_controller_test_util.h",
+      "../browser/ash/app_list/search/test/test_ranker_manager.cc",
+      "../browser/ash/app_list/search/test/test_ranker_manager.h",
+      "../browser/ash/app_list/search/test/test_search_controller.cc",
+      "../browser/ash/app_list/search/test/test_search_controller.h",
+      "../browser/ash/app_list/search/test/test_search_provider.cc",
+      "../browser/ash/app_list/search/test/test_search_provider.h",
+      "../browser/ash/app_list/search/util/ftrl_optimizer_unittest.cc",
+      "../browser/ash/app_list/search/util/mrfu_cache_unittest.cc",
+      "../browser/ash/app_list/search/util/persistent_proto_unittest.cc",
+      "../browser/ash/app_list/search/util/score_normalizer_unittest.cc",
+      "../browser/ash/app_list/test/app_list_syncable_service_test_base.cc",
+      "../browser/ash/app_list/test/app_list_syncable_service_test_base.h",
+      "../browser/ash/app_list/test/fake_app_list_model_updater.cc",
+      "../browser/ash/app_list/test/fake_app_list_model_updater.h",
       "../browser/ash/attestation/attestation_policy_unittest.cc",
       "../browser/ash/dbus/chrome_features_service_provider_unittest.cc",
       "../browser/ash/login/screens/reset_screen_unittest.cc",
@@ -7422,70 +7471,20 @@
       "../browser/ui/app_list/app_list_test_util.h",
       "../browser/ui/app_list/chrome_app_list_item_manager_unittest.cc",
       "../browser/ui/app_list/md_icon_normalizer_unittest.cc",
-      "../browser/ui/app_list/reorder/app_list_reorder_core_unittest.cc",
-      "../browser/ui/app_list/reorder/app_list_reorder_util_unittest.cc",
       "../browser/ui/app_list/search/app_search_provider_test_base.cc",
       "../browser/ui/app_list/search/app_search_provider_test_base.h",
       "../browser/ui/app_list/search/app_search_provider_unittest.cc",
       "../browser/ui/app_list/search/app_zero_state_provider_unittest.cc",
-      "../browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider_unittest.cc",
-      "../browser/ui/app_list/search/arc/arc_playstore_search_provider_unittest.cc",
-      "../browser/ui/app_list/search/arc/recommend_apps_fetcher_impl_unittest.cc",
       "../browser/ui/app_list/search/assistant_text_search_provider_unittest.cc",
       "../browser/ui/app_list/search/chrome_search_result_unittest.cc",
-      "../browser/ui/app_list/search/common/string_util_unittest.cc",
-      "../browser/ui/app_list/search/cros_action_history/cros_action_recorder_tab_tracker_unittest.cc",
-      "../browser/ui/app_list/search/cros_action_history/cros_action_recorder_unittest.cc",
-      "../browser/ui/app_list/search/files/file_result_unittest.cc",
-      "../browser/ui/app_list/search/files/file_search_provider_unittest.cc",
-      "../browser/ui/app_list/search/files/file_suggest_keyed_service_unittest.cc",
-      "../browser/ui/app_list/search/files/item_suggest_cache_unittest.cc",
-      "../browser/ui/app_list/search/files/justifications_unittest.cc",
-      "../browser/ui/app_list/search/files/local_file_suggestion_provider_unittest.cc",
-      "../browser/ui/app_list/search/files/zero_state_drive_provider_unittest.cc",
-      "../browser/ui/app_list/search/files/zero_state_file_provider_unittest.cc",
-      "../browser/ui/app_list/search/games/game_provider_unittest.cc",
-      "../browser/ui/app_list/search/games/game_result_unittest.cc",
       "../browser/ui/app_list/search/help_app_provider_unittest.cc",
       "../browser/ui/app_list/search/help_app_zero_state_provider_unittest.cc",
       "../browser/ui/app_list/search/keyboard_shortcut_provider_unittest.cc",
       "../browser/ui/app_list/search/keyboard_shortcut_result_unittest.cc",
-      "../browser/ui/app_list/search/omnibox/omnibox_answer_result_unittest.cc",
-      "../browser/ui/app_list/search/omnibox/omnibox_lacros_provider_unittest.cc",
-      "../browser/ui/app_list/search/omnibox/omnibox_provider_unittest.cc",
-      "../browser/ui/app_list/search/omnibox/omnibox_result_unittest.cc",
-      "../browser/ui/app_list/search/omnibox/open_tab_result_unittest.cc",
       "../browser/ui/app_list/search/os_settings_provider_unittest.cc",
       "../browser/ui/app_list/search/personalization_provider_unittest.cc",
-      "../browser/ui/app_list/search/ranking/answer_ranker_unittest.cc",
-      "../browser/ui/app_list/search/ranking/best_match_ranker_unittest.cc",
-      "../browser/ui/app_list/search/ranking/filtering_ranker_unittest.cc",
-      "../browser/ui/app_list/search/ranking/ftrl_ranker_unittest.cc",
-      "../browser/ui/app_list/search/ranking/mrfu_ranker_unittest.cc",
-      "../browser/ui/app_list/search/ranking/query_highlighter_unittest.cc",
-      "../browser/ui/app_list/search/ranking/removed_results_proto_unittest.cc",
-      "../browser/ui/app_list/search/ranking/removed_results_ranker_unittest.cc",
-      "../browser/ui/app_list/search/ranking/score_normalizing_ranker_unittest.cc",
       "../browser/ui/app_list/search/search_controller_impl_unittest.cc",
       "../browser/ui/app_list/search/search_metrics_manager_unittest.cc",
-      "../browser/ui/app_list/search/test/ranking_test_util.cc",
-      "../browser/ui/app_list/search/test/ranking_test_util.h",
-      "../browser/ui/app_list/search/test/search_controller_test_util.cc",
-      "../browser/ui/app_list/search/test/search_controller_test_util.h",
-      "../browser/ui/app_list/search/test/test_ranker_manager.cc",
-      "../browser/ui/app_list/search/test/test_ranker_manager.h",
-      "../browser/ui/app_list/search/test/test_search_controller.cc",
-      "../browser/ui/app_list/search/test/test_search_controller.h",
-      "../browser/ui/app_list/search/test/test_search_provider.cc",
-      "../browser/ui/app_list/search/test/test_search_provider.h",
-      "../browser/ui/app_list/search/util/ftrl_optimizer_unittest.cc",
-      "../browser/ui/app_list/search/util/mrfu_cache_unittest.cc",
-      "../browser/ui/app_list/search/util/persistent_proto_unittest.cc",
-      "../browser/ui/app_list/search/util/score_normalizer_unittest.cc",
-      "../browser/ui/app_list/test/app_list_syncable_service_test_base.cc",
-      "../browser/ui/app_list/test/app_list_syncable_service_test_base.h",
-      "../browser/ui/app_list/test/fake_app_list_model_updater.cc",
-      "../browser/ui/app_list/test/fake_app_list_model_updater.h",
       "../browser/ui/ash/accessibility/accessibility_controller_client_unittest.cc",
       "../browser/ui/ash/accessibility/ax_tree_source_aura_unittest.cc",
       "../browser/ui/ash/ambient/ambient_client_impl_unittest.cc",
@@ -7568,6 +7567,8 @@
       "//chrome/browser/ash:arc_test_support",
       "//chrome/browser/ash:test_support",
       "//chrome/browser/ash:unit_tests",
+      "//chrome/browser/ash/app_list/search/ranking:proto",
+      "//chrome/browser/ash/app_list/search/util:proto",
       "//chrome/browser/ash/crosapi",
       "//chrome/browser/ash/crosapi:test_support",
       "//chrome/browser/ash/crosapi:unit_tests",
@@ -7597,8 +7598,6 @@
       "//chrome/browser/nearby_sharing/scheduling:unit_tests",
       "//chrome/browser/policy:onc",
       "//chrome/browser/policy:unit_tests",
-      "//chrome/browser/ui/app_list/search/ranking:proto",
-      "//chrome/browser/ui/app_list/search/util:proto",
       "//chrome/browser/ui/ash/holding_space:test_support",
       "//chrome/browser/ui/quick_answers",
       "//chrome/browser/ui/webui/nearby_share:mojom",
@@ -10367,6 +10366,8 @@
   }
   if (is_chromeos_ash) {
     sources += [
+      "../browser/ash/app_list/test/fake_app_list_model_updater.cc",
+      "../browser/ash/app_list/test/fake_app_list_model_updater.h",
       "../browser/sync/test/integration/printers_helper.cc",
       "../browser/sync/test/integration/printers_helper.h",
       "../browser/sync/test/integration/sync_app_list_helper.cc",
@@ -10375,8 +10376,6 @@
       "../browser/sync/test/integration/sync_arc_package_helper.h",
       "../browser/sync/test/integration/workspace_desk_helper.cc",
       "../browser/sync/test/integration/workspace_desk_helper.h",
-      "../browser/ui/app_list/test/fake_app_list_model_updater.cc",
-      "../browser/ui/app_list/test/fake_app_list_model_updater.h",
     ]
     deps += [
       "//ash/app_list:test_support",
diff --git a/chrome/test/chromedriver/session.cc b/chrome/test/chromedriver/session.cc
index 7d1f911..b1a369d 100644
--- a/chrome/test/chromedriver/session.cc
+++ b/chrome/test/chromedriver/session.cc
@@ -230,7 +230,11 @@
   }
 
   std::string message;
-  if (!base::JSONWriter::Write(payload, &message)) {
+  // `OPTIONS_OMIT_DOUBLE_TYPE_PRESERVATION` is needed to keep the BiDi format.
+  // crbug.com/chromedriver/4297.
+  if (!base::JSONWriter::WriteWithOptions(
+          payload, base::JSONWriter::OPTIONS_OMIT_DOUBLE_TYPE_PRESERVATION,
+          &message)) {
     return Status{kUnknownError, "unable to serialize a BiDi response"};
   }
 
diff --git a/chrome/test/chromedriver/session_unittest.cc b/chrome/test/chromedriver/session_unittest.cc
index 15d6d16..8951238 100644
--- a/chrome/test/chromedriver/session_unittest.cc
+++ b/chrome/test/chromedriver/session_unittest.cc
@@ -317,6 +317,24 @@
   EXPECT_THAT(data_parsed->GetDict().FindString("data"), Pointee(Eq("ok")));
 }
 
+TEST(Session, OnBidiResponseFormat) {
+  std::unique_ptr<Chrome> chrome(new MockChrome());
+  Session session("1", std::move(chrome));
+  std::string received;
+  session.AddBidiConnection(512, base::BindRepeating(&SaveTo, &received),
+                            base::BindRepeating([] {}));
+  base::Value::Dict payload;
+  payload.Set("channel", std::string("abc/512") + Session::kChannelSuffix);
+  payload.Set("string_field", "some_String");
+  payload.Set("integer_field", 1);
+  payload.Set("float_field", 1.234);
+  EXPECT_TRUE(StatusOk(session.OnBidiResponse(std::move(payload))));
+  EXPECT_EQ(
+      "{\"channel\":\"abc\",\"float_field\":1.234,\"integer_field\":1,\"string_"
+      "field\":\"some_String\"}",
+      received);
+}
+
 TEST(Session, OnBlockingChannelResponseWhileAwaiting) {
   std::string good_blocking_channels[] = {
       std::string("x/7") + Session::kChannelSuffix +
diff --git a/chrome/test/data/extensions/api_test/tts_engine/lacros_tts_support/register_lacros_tts_engine/manifest.json b/chrome/test/data/extensions/api_test/tts_engine/lacros_tts_support/register_lacros_tts_engine/manifest.json
new file mode 100644
index 0000000..28ea169
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/tts_engine/lacros_tts_support/register_lacros_tts_engine/manifest.json
@@ -0,0 +1,30 @@
+{
+  "name": "chrome.ttsEngine",
+  "version": "0.1",
+  "manifest_version": 2,
+  "description": "browser test for chrome.ttsEngine API",
+  "background": {
+    "page": "test.html"
+  },
+  "tts_engine": {
+    "voices": [{
+        "voice_name": "Alice",
+        "lang": "en-US",
+        "gender": "female",
+        "event_types": ["end"]
+      },
+      {
+        "voice_name": "Alex",
+        "lang": "en-US",
+        "event_types": ["end"]
+      },
+      {
+        "voice_name": "Amanda",
+        "lang": "en-US",
+        "gender": "feline",
+        "event_types": ["end"]
+      }
+    ]
+  },
+  "permissions": ["tts", "ttsEngine"]
+}
diff --git a/chrome/test/data/extensions/api_test/tts_engine/lacros_tts_support/register_lacros_tts_engine/test.html b/chrome/test/data/extensions/api_test/tts_engine/lacros_tts_support/register_lacros_tts_engine/test.html
new file mode 100644
index 0000000..5a5ee3d
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/tts_engine/lacros_tts_support/register_lacros_tts_engine/test.html
@@ -0,0 +1,6 @@
+<!--
+ * Copyright 2022 The Chromium Authors. All rights reserved.  Use of this
+ * source code is governed by a BSD-style license that can be found in the
+ * LICENSE file.
+-->
+<script src="test.js"></script>
diff --git a/chrome/test/data/extensions/api_test/tts_engine/lacros_tts_support/register_lacros_tts_engine/test.js b/chrome/test/data/extensions/api_test/tts_engine/lacros_tts_support/register_lacros_tts_engine/test.js
new file mode 100644
index 0000000..190cb58
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/tts_engine/lacros_tts_support/register_lacros_tts_engine/test.js
@@ -0,0 +1,30 @@
+// 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.
+
+// TTS api test running from Lacros with Ash.
+// build/lacros/test_runner.py test
+//     {path_to_lacros_build}/lacros_chrome_browsertests_run_in_series
+//     --gtest_filter=LacrosTtsApiTest.SpeakAshUtteranceWithLacrosSpeechEngine
+//     --ash-chrome-path {path_to_ash_build}/test_ash_chrome
+
+chrome.test.runTests([
+  // Test speaking an Lacros utterance with a voice provided by a speech engine
+  // extension registered from ash.
+  function testSpeakLacrosUtteranceWithAshTtsEngine() {
+    // Register listeners for speech functions, enabling this extension
+    // to be a TTS engine.
+    var speakListener = function (utterance, options, sendTtsEvent) {
+      chrome.test.assertNoLastError();
+      chrome.test.assertEq('Hello from Ash', utterance);
+      sendTtsEvent({
+        'type': 'end',
+        'charIndex': utterance.length
+      });
+    };
+    var stopListener = function () {};
+    chrome.ttsEngine.onSpeak.addListener(speakListener);
+    chrome.ttsEngine.onStop.addListener(stopListener);
+    chrome.test.succeed();
+  }
+]);
diff --git a/chrome/test/data/extensions/auto_picture_in_picture/main.html b/chrome/test/data/extensions/auto_picture_in_picture/main.html
deleted file mode 100644
index b519a30..0000000
--- a/chrome/test/data/extensions/auto_picture_in_picture/main.html
+++ /dev/null
@@ -1,76 +0,0 @@
-<!--
-Copyright 2019 The Chromium Authors
-Use of this source code is governed by a BSD-style license that can be
-found in the LICENSE file.
--->
-<!DOCTYPE html>
-<html>
-<body>
-  <video id="video" preload=auto src="/media/bigbuck.webm"></video>
-  <video id="secondVideo" preload=auto src="/media/bigbuck.webm"></video>
-  <script>
-    video.addEventListener('enterpictureinpicture', () => {
-      document.title = 'video.enterpictureinpicture';
-    });
-
-    video.addEventListener('leavepictureinpicture', () => {
-      document.title = 'video.leavepictureinpicture';
-    });
-
-    secondVideo.addEventListener('enterpictureinpicture', () => {
-      document.title = 'secondVideo.enterpictureinpicture';
-    });
-
-    secondVideo.addEventListener('leavepictureinpicture', () => {
-      document.title = 'secondVideo.leavepictureinpicture';
-    });
-
-    document.addEventListener('visibilitychange', () => {
-      document.title = document.visibilityState;
-    });
-
-    async function enterPictureInPicture() {
-      await video.requestPictureInPicture();
-      return true;
-    }
-
-    function isInPictureInPicture() {
-      return document.pictureInPictureElement == video;
-    }
-
-    async function changeVideoSrcToNoAudioTrackVideo() {
-      video.src = '/media/engagement/engagement_no_audio_track.webm';
-      await video.play();
-      return true;
-    }
-
-    function isPaused() {
-      return video.paused;
-    }
-
-    async function playVideo() {
-      await video.play();
-      return true;
-    }
-
-    async function playSecondVideo() {
-      await secondVideo.play();
-      return true;
-    }
-
-    async function addHtmlVideoWithAutoPictureInPicture() {
-      document.body.insertAdjacentHTML('beforeend',
-        '<video id="htmlVideo" autopictureinpicture></video>');
-      htmlVideo.src = '/media/bigbuck.webm';
-
-      await htmlVideo.play();
-
-      htmlVideo.addEventListener('enterpictureinpicture', () => {
-        document.title = 'htmlVideo.enterpictureinpicture';
-      });
-
-      return true;
-    }
-  </script>
-</body>
-</html>
diff --git a/chrome/test/data/webapps_integration/file_handler/bar_handler.html b/chrome/test/data/webapps_integration/file_handler/image_handler.html
similarity index 100%
rename from chrome/test/data/webapps_integration/file_handler/bar_handler.html
rename to chrome/test/data/webapps_integration/file_handler/image_handler.html
diff --git a/chrome/test/data/webapps_integration/file_handler/foo_handler.html b/chrome/test/data/webapps_integration/file_handler/text_handler.html
similarity index 100%
rename from chrome/test/data/webapps_integration/file_handler/foo_handler.html
rename to chrome/test/data/webapps_integration/file_handler/text_handler.html
diff --git a/chrome/test/data/webui/app_home/app_list_test.ts b/chrome/test/data/webui/app_home/app_list_test.ts
index 7958cc4..52220d0c 100644
--- a/chrome/test/data/webui/app_home/app_list_test.ts
+++ b/chrome/test/data/webui/app_home/app_list_test.ts
@@ -4,6 +4,7 @@
 
 import 'chrome://webui-test/mojo_webui_test_support.js';
 import 'chrome://apps/app_list.js';
+import 'chrome://apps/app_item.js';
 
 import {AppInfo, PageRemote} from 'chrome://apps/app_home.mojom-webui.js';
 import {AppListElement} from 'chrome://apps/app_list.js';
@@ -79,13 +80,8 @@
   test('app list present', () => {
     assertTrue(!!appListElement);
 
-    assertTrue(!!appListElement.shadowRoot!.querySelector('.icon-image'));
-
-    assertTrue(!!appListElement.shadowRoot!.querySelector('.text-container'));
-
     const elementLength =
-        appListElement.shadowRoot!.querySelectorAll('.element-container')
-            .length;
+        appListElement.shadowRoot!.querySelectorAll('app-item').length;
     assertEquals(apps.appList.length, elementLength);
   });
 
@@ -94,18 +90,22 @@
     callbackRouterRemote.addApp(testAppInfo);
     await callbackRouterRemote.$.flushForTesting();
     flush();
-    let appNameList = Array.from(
-        appListElement.shadowRoot!.querySelectorAll('.text-container'));
-    assertTrue(!!appNameList.find(
-        appName => appName.textContent === testAppInfo.name));
+    let appItemList =
+        Array.from(appListElement.shadowRoot!.querySelectorAll('app-item'));
+    assertTrue(!!appItemList.find(
+        appItem => appItem.shadowRoot!.querySelector(
+                                          '.text-container')!.textContent ===
+            testAppInfo.name));
 
     // Test removing an app
     callbackRouterRemote.removeApp(testAppInfo);
     await callbackRouterRemote.$.flushForTesting();
     flush();
-    appNameList = Array.from(
-        appListElement.shadowRoot!.querySelectorAll('.text-container'));
-    assertFalse(!!appNameList.find(
-        appName => appName.textContent === testAppInfo.name));
+    appItemList =
+        Array.from(appListElement.shadowRoot!.querySelectorAll('app-item'));
+    assertFalse(!!appItemList.find(
+        appItem => appItem.shadowRoot!.querySelector(
+                                          '.text-container')!.textContent ===
+            testAppInfo.name));
   });
 });
diff --git a/chrome/test/data/webui/app_home/test_app_home_browser_proxy.ts b/chrome/test/data/webui/app_home/test_app_home_browser_proxy.ts
index f87e4d6..793ed74 100644
--- a/chrome/test/data/webui/app_home/test_app_home_browser_proxy.ts
+++ b/chrome/test/data/webui/app_home/test_app_home_browser_proxy.ts
@@ -30,6 +30,8 @@
   launchApp(_appId: string, _source: number, _clickEvent: ClickEvent) {}
 
   setRunOnOsLoginMode(_appId: string, _runOnOsLoginMode: RunOnOsLoginMode) {}
+
+  launchDeprecatedAppDialog() {}
 }
 
 export class TestAppHomeBrowserProxy implements BrowserProxy {
diff --git a/chrome/test/data/webui/chromeos/personalization_app/dynamic_color_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/dynamic_color_element_test.ts
index 7518c38..ddb8a59 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/dynamic_color_element_test.ts
+++ b/chrome/test/data/webui/chromeos/personalization_app/dynamic_color_element_test.ts
@@ -7,15 +7,20 @@
 import 'chrome://personalization/strings.m.js';
 import 'chrome://webui-test/mojo_webui_test_support.js';
 
-import {DynamicColorElement} from 'chrome://personalization/js/personalization_app.js';
+import {DynamicColorElement, SetColorSchemePrefAction, SetStaticColorPrefAction, ThemeActionName} from 'chrome://personalization/js/personalization_app.js';
+import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.js';
 import {CrToggleElement} from 'chrome://resources/cr_elements/cr_toggle/cr_toggle.js';
 import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
 import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
 
-import {dispatchKeydown, getActiveElement, initElement, teardownElement, waitForActiveElement} from './personalization_app_test_utils.js';
+import {baseSetup, dispatchKeydown, getActiveElement, initElement, teardownElement, waitForActiveElement} from './personalization_app_test_utils.js';
+import {TestPersonalizationStore} from './test_personalization_store.js';
+import {TestThemeProvider} from './test_theme_interface_provider.js';
 
 suite('DynamicColorElementTest', function() {
   let dynamicColorElement: DynamicColorElement|null;
+  let personalizationStore: TestPersonalizationStore;
+  let themeProvider: TestThemeProvider;
 
   function getToggleButton(): CrToggleElement {
     return dynamicColorElement!.shadowRoot!.querySelector('cr-toggle')!;
@@ -31,15 +36,35 @@
         'staticColorSelector')!;
   }
 
-  function getColorSchemeButtons(): NodeListOf<Element> {
+  function getColorSchemeButtons(): NodeListOf<CrButtonElement> {
     return getColorSchemeSelector().querySelectorAll('cr-button')!;
   }
 
-  function getStaticColorButtons(): NodeListOf<Element> {
+  function getStaticColorButtons(): NodeListOf<CrButtonElement> {
     return getStaticColorSelector().querySelectorAll('cr-button')!;
   }
 
+  function showStaticColorButtons() {
+    const toggleButton = getToggleButton();
+    if (toggleButton.checked) {
+      toggleButton.click();
+    }
+    assertFalse(getStaticColorSelector().hidden);
+  }
+
+  function showColorSchemeButtons() {
+    const toggleButton = getToggleButton();
+    if (!toggleButton.checked) {
+      toggleButton.click();
+    }
+    assertFalse(getColorSchemeSelector().hidden);
+  }
+
   setup(async () => {
+    const mocks = baseSetup();
+    personalizationStore = mocks.personalizationStore;
+    themeProvider = mocks.themeProvider;
+
     dynamicColorElement = initElement(DynamicColorElement)!;
     await waitAfterNextRender(dynamicColorElement);
   });
@@ -90,7 +115,7 @@
 
   test('keypress navigates color scheme buttons', async () => {
     assertTrue(!!dynamicColorElement);
-    assertTrue(getToggleButton().checked, 'toggle button should be on');
+    showColorSchemeButtons();
     const colorSchemeButtons = getColorSchemeButtons();
     (colorSchemeButtons[0] as HTMLElement)!.focus();
 
@@ -113,11 +138,7 @@
 
   test('keypress navigates static color buttons', async () => {
     assertTrue(!!dynamicColorElement);
-    const toggleButton = getToggleButton();
-    toggleButton!.click();
-    assertFalse(
-        toggleButton!.checked,
-        'toggle button should be off to show the static color buttons');
+    showStaticColorButtons();
     const staticColorButtons = getStaticColorButtons();
     (staticColorButtons![0] as HTMLElement)!.focus();
 
@@ -138,4 +159,30 @@
           'iron-selected', getActiveElement(dynamicColorElement).className);
     }
   });
+
+  test('sets color scheme', async () => {
+    personalizationStore.expectAction(ThemeActionName.SET_COLOR_SCHEME);
+    showColorSchemeButtons();
+
+    getColorSchemeButtons()[1]!.click();
+    await themeProvider.whenCalled('setColorScheme');
+
+    const action =
+        await personalizationStore.waitForAction(
+            ThemeActionName.SET_COLOR_SCHEME) as SetColorSchemePrefAction;
+    assertTrue(!!action.colorScheme);
+  });
+
+  test('set static color', async () => {
+    personalizationStore.expectAction(ThemeActionName.SET_STATIC_COLOR);
+    showStaticColorButtons();
+
+    getStaticColorButtons()[1]!.click();
+    await themeProvider.whenCalled('setStaticColor');
+
+    const action =
+        await personalizationStore.waitForAction(
+            ThemeActionName.SET_STATIC_COLOR) as SetStaticColorPrefAction;
+    assertTrue(!!action.staticColor);
+  });
 });
diff --git a/chrome/test/data/webui/chromeos/personalization_app/test_theme_interface_provider.ts b/chrome/test/data/webui/chromeos/personalization_app/test_theme_interface_provider.ts
index 161ef1c..253f709 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/test_theme_interface_provider.ts
+++ b/chrome/test/data/webui/chromeos/personalization_app/test_theme_interface_provider.ts
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {ThemeObserverInterface, ThemeObserverRemote, ThemeProviderInterface} from 'chrome://personalization/js/personalization_app.js';
+import {ColorScheme, ThemeObserverInterface, ThemeObserverRemote, ThemeProviderInterface} from 'chrome://personalization/js/personalization_app.js';
+import {SkColor} from 'chrome://resources/mojo/skia/public/mojom/skcolor.mojom-webui.js';
 import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js';
 
 export class TestThemeProvider extends TestBrowserProxy implements
@@ -12,6 +13,8 @@
       'setThemeObserver',
       'setColorModePref',
       'setColorModeAutoScheduleEnabled',
+      'setColorScheme',
+      'setStaticColor',
       'isDarkModeEnabled',
       'isColorModeAutoScheduleEnabled',
     ]);
@@ -38,6 +41,14 @@
     this.methodCalled('setColorModeAutoScheduleEnabled', enabled);
   }
 
+  setColorScheme(colorScheme: ColorScheme) {
+    this.methodCalled('setColorScheme', colorScheme);
+  }
+
+  setStaticColor(color: SkColor) {
+    this.methodCalled('setStaticColor', color);
+  }
+
   isDarkModeEnabled() {
     this.methodCalled('isDarkModeEnabled');
     return Promise.resolve({darkModeEnabled: this.isDarkModeEnabledResponse});
diff --git a/chrome/test/data/webui/extensions/site_permissions_edit_permissions_dialog_test.ts b/chrome/test/data/webui/extensions/site_permissions_edit_permissions_dialog_test.ts
index a7e2742..8000deca 100644
--- a/chrome/test/data/webui/extensions/site_permissions_edit_permissions_dialog_test.ts
+++ b/chrome/test/data/webui/extensions/site_permissions_edit_permissions_dialog_test.ts
@@ -45,6 +45,13 @@
     {id: 'test_2', siteAccess: HostAccess.ON_SPECIFIC_SITES},
   ];
 
+  const changeHostAccess =
+      (select: HTMLSelectElement,
+       access: chrome.developerPrivate.HostAccess) => {
+        select.value = access;
+        select.dispatchEvent(new CustomEvent('change'));
+      };
+
   setup(function() {
     delegate = new TestService();
     delegate.matchingExtensionsInfo = matchingExtensionsInfo;
@@ -118,9 +125,7 @@
         assertEquals(2, extensionSiteAccessRows.length);
 
         const whenClosed = eventToPromise('close', element);
-        const submit = element.$.submit;
-
-        submit.click();
+        element.$.submit.click();
         const [siteSet, sites] =
             await delegate.whenCalled('removeUserSpecifiedSites');
         assertEquals(SiteSet.USER_PERMITTED, siteSet);
@@ -143,7 +148,7 @@
         assertTrue(!!extensionSpecifiedRadioButton);
         extensionSpecifiedRadioButton.click();
         const site = await delegate.whenCalled('getMatchingExtensionsForSite');
-        assertEquals('http://example.com', site);
+        assertEquals('http://example.com/', site);
 
         flush();
         assertTrue(
@@ -166,7 +171,7 @@
         assertTrue(!!extensionSpecifiedRadioButton);
         extensionSpecifiedRadioButton.click();
         let site = await delegate.whenCalled('getMatchingExtensionsForSite');
-        assertEquals('http://example.com', site);
+        assertEquals('http://example.com/', site);
 
         flush();
 
@@ -196,7 +201,7 @@
         // Test that changing `element.extensions` causes a call to
         // getMatchingExtensionsForSite.
         site = await delegate.whenCalled('getMatchingExtensionsForSite');
-        assertEquals('http://example.com', site);
+        assertEquals('http://example.com/', site);
         flush();
 
         extensionSiteAccessSelects =
@@ -208,4 +213,141 @@
         assertEquals(
             HostAccess.ON_ALL_SITES, extensionSiteAccessSelects[0]!.value);
       });
+
+  test('editing extension site access', async function() {
+    element.site = 'example.com';
+    delegate.matchingExtensionsInfo = [
+      ...matchingExtensionsInfo,
+      {id: 'test_3', siteAccess: HostAccess.ON_ALL_SITES},
+    ];
+
+    flush();
+    const extensionSpecifiedRadioButton =
+        element.shadowRoot!.querySelector<HTMLElement>(
+            `cr-radio-button[name=${SiteSet.EXTENSION_SPECIFIED}]`);
+    assertTrue(!!extensionSpecifiedRadioButton);
+    extensionSpecifiedRadioButton.click();
+
+    const site = await delegate.whenCalled('getMatchingExtensionsForSite');
+    assertEquals('*://example.com/', site);
+    flush();
+
+    const extensionSiteAccessRows =
+        element.shadowRoot!.querySelectorAll<HTMLElement>('.extension-row');
+    assertEquals(3, extensionSiteAccessRows.length);
+
+    const siteAccessSelectMenus =
+        element.shadowRoot!.querySelectorAll<HTMLSelectElement>(
+            '.extension-host-access');
+    assertEquals(3, siteAccessSelectMenus.length);
+
+    // Edit the site access values for the first two extensions.
+    changeHostAccess(siteAccessSelectMenus[0]!, HostAccess.ON_SPECIFIC_SITES);
+    changeHostAccess(siteAccessSelectMenus[1]!, HostAccess.ON_ALL_SITES);
+
+    // Edit the site access for the third extension once, then change it
+    // back to the original value.
+    changeHostAccess(siteAccessSelectMenus[2]!, HostAccess.ON_CLICK);
+    changeHostAccess(siteAccessSelectMenus[2]!, HostAccess.ON_ALL_SITES);
+
+    const whenClosed = eventToPromise('close', element);
+    element.$.submit.click();
+    await delegate.whenCalled('removeUserSpecifiedSites');
+
+    const [siteToUpdate, siteAccessUpdates] =
+        await delegate.whenCalled('updateSiteAccess');
+    // For updating the extensions' site access, check that a wildcard
+    // host is used if the site was a host only.
+    assertEquals('*://example.com/', siteToUpdate);
+
+    // Since the site access for extension "test_3" was ultimately not
+    // changed through the select menu, it should not be included in
+    // `siteAccessUpdates`.
+    assertDeepEquals(
+        [
+          {id: 'test_1', siteAccess: HostAccess.ON_SPECIFIC_SITES},
+          {id: 'test_2', siteAccess: HostAccess.ON_ALL_SITES},
+        ],
+        siteAccessUpdates);
+
+    await whenClosed;
+    assertFalse(element.$.dialog.open);
+  });
+
+  test(
+      'updateSiteAccess arguments are updated in response to extension updates',
+      async function() {
+        element.site = 'http://example.com';
+        delegate.matchingExtensionsInfo = [
+          ...matchingExtensionsInfo,
+          {id: 'test_3', siteAccess: HostAccess.ON_ALL_SITES},
+        ];
+
+        flush();
+        const extensionSpecifiedRadioButton =
+            element.shadowRoot!.querySelector<HTMLElement>(
+                `cr-radio-button[name=${SiteSet.EXTENSION_SPECIFIED}]`);
+        assertTrue(!!extensionSpecifiedRadioButton);
+        extensionSpecifiedRadioButton.click();
+
+        let site = await delegate.whenCalled('getMatchingExtensionsForSite');
+        assertEquals('http://example.com/', site);
+        flush();
+
+        const siteAccessSelectMenus =
+            element.shadowRoot!.querySelectorAll<HTMLSelectElement>(
+                '.extension-host-access');
+        assertEquals(3, siteAccessSelectMenus.length);
+
+        // Edit the site access values for all three extensions.
+        changeHostAccess(
+            siteAccessSelectMenus[0]!, HostAccess.ON_SPECIFIC_SITES);
+        changeHostAccess(siteAccessSelectMenus[1]!, HostAccess.ON_ALL_SITES);
+        changeHostAccess(siteAccessSelectMenus[2]!, HostAccess.ON_CLICK);
+
+        // Simulate an update event happening. Note that the new site access for
+        // `test_1` is now the same as what was edited and `test_3` no longer
+        // exists.
+        delegate.matchingExtensionsInfo = [
+          {id: 'test_1', siteAccess: HostAccess.ON_SPECIFIC_SITES},
+          {id: 'test_2', siteAccess: HostAccess.ON_SPECIFIC_SITES},
+        ];
+
+        element.extensions = [
+          createExtensionInfo({
+            id: 'test_1',
+            name: 'test_1',
+            iconUrl: 'icon_url',
+          }),
+          createExtensionInfo({
+            id: 'test_2',
+            name: 'test_2',
+            iconUrl: 'icon_url',
+          }),
+        ];
+
+        // Changing `element.extensions` causes a call to
+        // getMatchingExtensionsForSite.
+        site = await delegate.whenCalled('getMatchingExtensionsForSite');
+        assertEquals('http://example.com/', site);
+        flush();
+
+        const whenClosed = eventToPromise('close', element);
+        element.$.submit.click();
+        await delegate.whenCalled('removeUserSpecifiedSites');
+
+        const [siteToUpdate, siteAccessUpdates] =
+            await delegate.whenCalled('updateSiteAccess');
+        assertEquals('http://example.com/', siteToUpdate);
+
+        // Only the site access update for `test_2` should be included, as after
+        // the update, there's no change for site access for `test_1` and
+        // `test_3` no longer exists.
+        assertDeepEquals(
+            [{id: 'test_2', siteAccess: HostAccess.ON_ALL_SITES}],
+            siteAccessUpdates);
+
+        await whenClosed;
+        assertFalse(element.$.dialog.open);
+      });
 });
diff --git a/chrome/test/data/webui/extensions/test_service.ts b/chrome/test/data/webui/extensions/test_service.ts
index 0d3e352..b0ee42fd 100644
--- a/chrome/test/data/webui/extensions/test_service.ts
+++ b/chrome/test/data/webui/extensions/test_service.ts
@@ -70,6 +70,7 @@
       'updateAllExtensions',
       'updateExtensionCommandKeybinding',
       'updateExtensionCommandScope',
+      'updateSiteAccess',
     ]);
   }
 
@@ -356,4 +357,11 @@
     this.methodCalled('getMatchingExtensionsForSite', site);
     return Promise.resolve(this.matchingExtensionsInfo!);
   }
+
+  updateSiteAccess(
+      site: string,
+      updates: chrome.developerPrivate.ExtensionSiteAccessUpdate[]) {
+    this.methodCalled('updateSiteAccess', site, updates);
+    return Promise.resolve();
+  }
 }
diff --git a/chrome/test/data/webui/js/custom_element_test.ts b/chrome/test/data/webui/js/custom_element_test.ts
index d7a9bc9..18f424a 100644
--- a/chrome/test/data/webui/js/custom_element_test.ts
+++ b/chrome/test/data/webui/js/custom_element_test.ts
@@ -3,12 +3,12 @@
 // found in the LICENSE file.
 
 import {CustomElement} from 'chrome://resources/js/custom_element.js';
-
+import {getTrustedHTML} from 'chrome://resources/js/static_types.js';
 import {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
 
 class TestElement extends CustomElement {
   static override get template() {
-    return '<div id="content"></div>';
+    return getTrustedHTML`<div id="content"></div>`;
   }
 }
 
@@ -18,12 +18,14 @@
 
 suite('CustomElementTest', function() {
   setup(function() {
+    document.body.innerHTML = window.trustedTypes!.emptyHTML;
     testElement = document.createElement('test-element') as TestElement;
     document.body.appendChild(testElement);
   });
 
   test('Template', function() {
-    assertEquals(TestElement.template, testElement.shadowRoot!.innerHTML);
+    assertEquals(
+        TestElement.template.toString(), testElement.shadowRoot!.innerHTML);
   });
 
   test('Test $()', function() {
diff --git a/chrome/test/data/webui/text_defaults_test.ts b/chrome/test/data/webui/text_defaults_test.ts
index 9b9cde90..f8ff8ad 100644
--- a/chrome/test/data/webui/text_defaults_test.ts
+++ b/chrome/test/data/webui/text_defaults_test.ts
@@ -2,16 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {assertEquals, assertNotEquals, assertTrue} from './chai_assert.js';
-
-/**
- * @param html Text, possibly with HTML &entities; in it.
- */
-function decodeHtmlEntities(html: string): string {
-  const element = document.createElement('div');
-  element.innerHTML = html;
-  return element.textContent!;
-}
+import {assertNotEquals, assertTrue} from './chai_assert.js';
 
 suite('TextDefaults', function() {
   test('text_defaults.css', function(done) {
@@ -23,7 +14,6 @@
       const fontFamily = (link.sheet.rules[1] as CSSStyleRule)
                              .style.getPropertyValue('font-family');
       assertNotEquals('', fontFamily);
-      assertEquals(decodeHtmlEntities(fontFamily), fontFamily);
       done();
     };
     document.body.appendChild(link);
@@ -38,7 +28,6 @@
       const fontFamily = (link.sheet.rules[2] as CSSStyleRule)
                              .style.getPropertyValue('font-family');
       assertNotEquals('', fontFamily);
-      assertEquals(decodeHtmlEntities(fontFamily), fontFamily);
       done();
     };
     document.body.appendChild(link);
diff --git a/chrome/test/media_router/access_code_cast/access_code_cast_integration_browsertest.cc b/chrome/test/media_router/access_code_cast/access_code_cast_integration_browsertest.cc
index 17c56c01..d123968 100644
--- a/chrome/test/media_router/access_code_cast/access_code_cast_integration_browsertest.cc
+++ b/chrome/test/media_router/access_code_cast/access_code_cast_integration_browsertest.cc
@@ -4,15 +4,13 @@
 
 #include "chrome/test/media_router/access_code_cast/access_code_cast_integration_browsertest.h"
 
-#include <map>
-
 #include "base/auto_reset.h"
 #include "base/memory/ptr_util.h"
-#include "base/no_destructor.h"
 #include "base/ranges/algorithm.h"
 #include "base/strings/string_util.h"
 #include "base/task/thread_pool/thread_pool_instance.h"
 #include "base/test/gmock_callback_support.h"
+#include "base/test/gtest_tags.h"
 #include "base/test/mock_callback.h"
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
@@ -574,10 +572,7 @@
 
 void AccessCodeCastIntegrationBrowserTest::AddScreenplayTag(
     const std::string& screenplay_tag) {
-  static base::NoDestructor<std::map<std::string, std::string>> tag;
-  tag->insert(
-      std::pair<std::string, std::string>("feature_id", screenplay_tag));
-  RecordPropertyFromMap(*tag);
+  base::AddTagToTestResult("feature_id", screenplay_tag);
 }
 
 }  // namespace media_router
diff --git a/chrome/test/webapps/coverage/coverage_linux.tsv b/chrome/test/webapps/coverage/coverage_linux.tsv
index 10e9698..564e7282 100644
--- a/chrome/test/webapps/coverage/coverage_linux.tsv
+++ b/chrome/test/webapps/coverage/coverage_linux.tsv
@@ -1,5 +1,5 @@
 # This is a generated file.
-# Full coverage: 66%, with partial coverage: 89%
+# Full coverage: 62%, with partial coverage: 85%
 create_shortcut_Standalone_Windowed🌕	launch_from_menu_option_Standalone🌕	check_app_title_Standalone_StandaloneOriginal🌑
 create_shortcut_Standalone_Windowed🌕	launch_from_launch_icon_Standalone🌕	check_app_title_Standalone_StandaloneOriginal🌑
 create_shortcut_Standalone_Windowed🌕	launch_from_chrome_apps_Standalone🌓	check_app_title_Standalone_StandaloneOriginal🌑
@@ -1168,136 +1168,136 @@
 install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
 install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
 install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
 create_shortcut_FileHandler_Windowed🌕	add_file_handling_policy_approval_FileHandler🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
 create_shortcut_FileHandler_Browser🌕	add_file_handling_policy_approval_FileHandler🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
 install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	add_file_handling_policy_approval_FileHandler🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
diff --git a/chrome/test/webapps/coverage/coverage_mac.tsv b/chrome/test/webapps/coverage/coverage_mac.tsv
index 383f9e9e..b38e486 100644
--- a/chrome/test/webapps/coverage/coverage_mac.tsv
+++ b/chrome/test/webapps/coverage/coverage_mac.tsv
@@ -1,5 +1,5 @@
 # This is a generated file.
-# Full coverage: 60%, with partial coverage: 80%
+# Full coverage: 57%, with partial coverage: 77%
 create_shortcut_Standalone_Windowed🌕	launch_from_menu_option_Standalone🌕	check_app_title_Standalone_StandaloneOriginal🌑
 create_shortcut_Standalone_Windowed🌕	launch_from_launch_icon_Standalone🌕	check_app_title_Standalone_StandaloneOriginal🌑
 create_shortcut_Standalone_Windowed🌕	launch_from_chrome_apps_Standalone🌓	check_app_title_Standalone_StandaloneOriginal🌑
@@ -1161,146 +1161,146 @@
 install_menu_option_Wco🌕	manifest_update_display_Wco_Standalone🌕	await_manifest_update_Wco🌕	launch_from_launch_icon_Wco🌕	check_window_controls_overlay_Wco_Off🌕
 install_menu_option_Wco🌕	manifest_update_display_Wco_Standalone🌕	await_manifest_update_Wco🌕	launch_from_chrome_apps_Wco🌓	check_window_controls_overlay_Wco_Off🌕
 install_menu_option_Wco🌕	manifest_update_display_Wco_Standalone🌕	await_manifest_update_Wco🌕	launch_from_platform_shortcut_Wco🌓	check_window_controls_overlay_Wco_Off🌕
-create_shortcut_FileHandler_Windowed🌕	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
-create_shortcut_FileHandler_Browser🌕	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+create_shortcut_FileHandler_Windowed🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+create_shortcut_FileHandler_Browser🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
 create_shortcut_FileHandler_Windowed🌕	add_file_handling_policy_approval_FileHandler🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
 create_shortcut_FileHandler_Browser🌕	add_file_handling_policy_approval_FileHandler🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
 install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	add_file_handling_policy_approval_FileHandler🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
diff --git a/chrome/test/webapps/coverage/coverage_win.tsv b/chrome/test/webapps/coverage/coverage_win.tsv
index 2e83db7..eb76fe2 100644
--- a/chrome/test/webapps/coverage/coverage_win.tsv
+++ b/chrome/test/webapps/coverage/coverage_win.tsv
@@ -1,5 +1,5 @@
 # This is a generated file.
-# Full coverage: 68%, with partial coverage: 91%
+# Full coverage: 63%, with partial coverage: 87%
 create_shortcut_Standalone_Windowed🌕	launch_from_menu_option_Standalone🌕	check_app_title_Standalone_StandaloneOriginal🌑
 create_shortcut_Standalone_Windowed🌕	launch_from_launch_icon_Standalone🌕	check_app_title_Standalone_StandaloneOriginal🌑
 create_shortcut_Standalone_Windowed🌕	launch_from_chrome_apps_Standalone🌓	check_app_title_Standalone_StandaloneOriginal🌑
@@ -1168,136 +1168,136 @@
 install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
 install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
 install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌕	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌕	launch_file_expect_no_dialog_FileHandler_OneFooFile🌕	check_pwa_window_created_FileHandler_One🌑
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	check_window_not_created🌕	check_site_handles_file_FileHandler_Foo🌕	check_site_handles_file_FileHandler_Bar🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌕
-create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
-install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌕	check_window_not_created🌕	check_site_not_handles_file_FileHandler_Foo🌕	check_site_not_handles_file_FileHandler_Bar🌕
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneFooFile🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleFooFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_MultipleFooFiles🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneBarFile_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_One🌑	check_files_loaded_in_site_FileHandler_OneBarFile🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_MultipleBarFiles_Allow_AskAgain🌑	check_pwa_window_created_FileHandler_Two🌑	check_files_loaded_in_site_FileHandler_MultipleBarFiles🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_Remember🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	check_window_not_created🌑	check_site_handles_file_FileHandler_Foo🌑	check_site_handles_file_FileHandler_Bar🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_AskAgain🌑	launch_file_expect_dialog_FileHandler_OneFooFile_Allow_AskAgain🌑
+create_shortcut_FileHandler_Windowed🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+create_shortcut_FileHandler_Browser🌕	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Windowed_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_WithShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
+install_policy_app_FileHandler_NoShortcut_Browser_WebApp🌓	launch_file_expect_dialog_FileHandler_OneFooFile_Deny_Remember🌑	check_window_not_created🌑	check_site_not_handles_file_FileHandler_Foo🌑	check_site_not_handles_file_FileHandler_Bar🌑
 create_shortcut_FileHandler_Windowed🌕	add_file_handling_policy_approval_FileHandler🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
 create_shortcut_FileHandler_Browser🌕	add_file_handling_policy_approval_FileHandler🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
 install_policy_app_FileHandler_WithShortcut_Windowed_WebApp🌓	add_file_handling_policy_approval_FileHandler🌑	launch_file_expect_no_dialog_FileHandler_OneFooFile🌑	check_pwa_window_created_FileHandler_One🌑
diff --git a/chrome/test/webapps/data/framework_supported_actions.csv b/chrome/test/webapps/data/framework_supported_actions.csv
index ed9fc6ce..f35e27e9 100644
--- a/chrome/test/webapps/data/framework_supported_actions.csv
+++ b/chrome/test/webapps/data/framework_supported_actions.csv
@@ -15,8 +15,8 @@
 check_app_navigation_is_start_url,                     🌕, 🌕,  🌕,   🌕,
 check_no_toolbar,                                      🌕, 🌕,  🌕,   🌕,
 check_platform_shortcut_and_icon,                      🌕, 🌓,  🌓,   🌓,
-check_site_handles_file,                               🌑, 🌕,  🌕,   🌑,
-check_site_not_handles_file,                           🌑, 🌕,  🌕,   🌑,
+check_site_handles_file,                               🌕, 🌕,  🌕,   🌑,
+check_site_not_handles_file,                           🌕, 🌕,  🌕,   🌑,
 check_tab_created,                                     🌕, 🌕,  🌕,   🌕,
 check_tab_not_created,                                 🌕, 🌕,  🌕,   🌕,
 check_window_closed,                                   🌕, 🌕,  🌕,   🌕,
@@ -37,8 +37,6 @@
 install_menu_option,                                   🌕, 🌕,  🌕,   🌕,
 install_omnibox_icon,                                  🌕, 🌕,  🌕,   🌕,
 install_policy_app,                                    🌓, 🌓,  🌓,   🌓,
-launch_file_expect_dialog,                             🌕, 🌕,  🌕,   🌑,
-launch_file_expect_no_dialog,                          🌕, 🌕,  🌕,   🌑,
 launch_from_chrome_apps,                               🌓, 🌓,  🌓,   🌓,
 launch_from_launch_icon,                               🌕, 🌕,  🌕,   🌕,
 launch_from_menu_option,                               🌕, 🌕,  🌕,   🌕,
diff --git a/chrome/updater/BUILD.gn b/chrome/updater/BUILD.gn
index e1a9ae33..b1bcb6c6 100644
--- a/chrome/updater/BUILD.gn
+++ b/chrome/updater/BUILD.gn
@@ -323,6 +323,8 @@
 
     if (is_posix) {
       sources += [
+        "app/server/posix/app_server_posix.cc",
+        "app/server/posix/app_server_posix.h",
         "app/server/posix/update_service_internal_stub.cc",
         "app/server/posix/update_service_internal_stub.h",
         "ipc/ipc_support.cc",
@@ -346,6 +348,7 @@
         "app/server/linux/update_service_stub.h",
         "app/server/posix/update_service_internal_stub_linux.cc",
         "device_management/dm_storage_linux.cc",
+        "installer_linux.cc",
         "linux/setup/setup.cc",
         "net/network_fetcher_linux.cc",
         "prefs_linux.cc",
@@ -898,6 +901,7 @@
       ]
 
       deps += [ "//chrome/updater/app/server/posix/mojom" ]
+      data_deps = [ "//chrome/updater/linux:updater_test" ]
     }
   }
 
@@ -953,6 +957,9 @@
         "//third_party/updater:old_updater",
       ]
     }
+    if (is_linux) {
+      data_deps = [ "//chrome/updater/linux:updater_test" ]
+    }
   }
 
   test("updater_tests_system") {
@@ -987,6 +994,9 @@
         "//third_party/updater:old_updater",
       ]
     }
+    if (is_linux) {
+      data_deps += [ "//chrome/updater/linux:updater_test" ]
+    }
   }
 
   if (is_win) {
diff --git a/chrome/updater/activity_impl_util_linux.cc b/chrome/updater/activity_impl_util_linux.cc
index 7089dc4..1252494 100644
--- a/chrome/updater/activity_impl_util_linux.cc
+++ b/chrome/updater/activity_impl_util_linux.cc
@@ -8,19 +8,36 @@
 #include <vector>
 
 #include "base/files/file_path.h"
+#include "base/files/file_util.h"
 #include "base/notreached.h"
+#include "chrome/updater/updater_branding.h"
 #include "chrome/updater/updater_scope.h"
 
 namespace updater {
 std::vector<base::FilePath> GetHomeDirPaths(UpdaterScope scope) {
-  NOTREACHED();
+  switch (scope) {
+    case UpdaterScope::kUser: {
+      const base::FilePath path = base::GetHomeDir();
+      if (path.empty()) {
+        return {};
+      }
+      return {path};
+    }
+    case UpdaterScope::kSystem: {
+      // TODO(crbug.com/c/1384968): Implement activity bits for system-scope.
+      NOTIMPLEMENTED();
+      return {};
+    }
+  }
   return {};
 }
 
 base::FilePath GetActiveFile(const base::FilePath& home_dir,
                              const std::string& id) {
-  NOTREACHED();
-  return base::FilePath();
+  return home_dir.AppendASCII(".local")
+      .AppendASCII(COMPANY_SHORTNAME_STRING)
+      .AppendASCII(PRODUCT_FULLNAME_STRING)
+      .AppendASCII("Actives")
+      .AppendASCII(id);
 }
-
 }  // namespace updater
diff --git a/chrome/updater/app/server/linux/rpc_unittests.cc b/chrome/updater/app/server/linux/rpc_unittests.cc
index 5ade204..00d5794 100644
--- a/chrome/updater/app/server/linux/rpc_unittests.cc
+++ b/chrome/updater/app/server/linux/rpc_unittests.cc
@@ -327,8 +327,8 @@
             std::move(callback).Run(UpdateService::Result::kInstallFailed);
           });
 
-  auto service_stub =
-      std::make_unique<UpdateServiceStub>(mock_service, UpdaterScope::kUser);
+  auto service_stub = std::make_unique<UpdateServiceStub>(
+      mock_service, UpdaterScope::kUser, base::DoNothing(), base::DoNothing());
 
   base::Process child_process = base::SpawnMultiProcessTestChild(
       kClientProcessName, base::GetMultiProcessTestChildBaseCommandLine(),
diff --git a/chrome/updater/app/server/linux/server.cc b/chrome/updater/app/server/linux/server.cc
index 44106e52..6b47c37 100644
--- a/chrome/updater/app/server/linux/server.cc
+++ b/chrome/updater/app/server/linux/server.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include <utility>
 
+#include "base/functional/bind.h"
 #include "base/functional/callback_helpers.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/notreached.h"
@@ -25,14 +26,17 @@
 
 void AppServerLinux::ActiveDuty(scoped_refptr<UpdateService> update_service) {
   active_duty_stub_ = std::make_unique<UpdateServiceStub>(
-      std::move(update_service), updater_scope());
+      std::move(update_service), updater_scope(),
+      base::BindRepeating(&AppServerLinux::TaskStarted, this),
+      base::BindRepeating(&AppServerLinux::TaskCompleted, this));
 }
 
 void AppServerLinux::ActiveDutyInternal(
     scoped_refptr<UpdateServiceInternal> update_service_internal) {
   active_duty_internal_stub_ = std::make_unique<UpdateServiceInternalStub>(
-      std::move(update_service_internal), updater_scope(), base::DoNothing(),
-      base::DoNothing());
+      std::move(update_service_internal), updater_scope(),
+      base::BindRepeating(&AppServerLinux::TaskStarted, this),
+      base::BindRepeating(&AppServerLinux::TaskCompleted, this));
 }
 
 bool AppServerLinux::SwapInNewVersion() {
diff --git a/chrome/updater/app/server/linux/server.h b/chrome/updater/app/server/linux/server.h
index 56089e1..ac30fbae 100644
--- a/chrome/updater/app/server/linux/server.h
+++ b/chrome/updater/app/server/linux/server.h
@@ -7,8 +7,7 @@
 
 #include <memory>
 
-#include "base/memory/scoped_refptr.h"
-#include "chrome/updater/app/app_server.h"
+#include "chrome/updater/app/server/posix/app_server_posix.h"
 #include "mojo/public/cpp/system/message_pipe.h"
 
 namespace updater {
@@ -17,9 +16,8 @@
 class UpdateService;
 class UpdateServiceInternal;
 class UpdateServiceStub;
-class UpdateServiceInternalStub;
 
-class AppServerLinux : public AppServer {
+class AppServerLinux : public AppServerPosix {
  public:
   AppServerLinux();
 
@@ -41,7 +39,6 @@
   void UninstallSelf() override;
 
   std::unique_ptr<UpdateServiceStub> active_duty_stub_;
-  std::unique_ptr<UpdateServiceInternalStub> active_duty_internal_stub_;
 };
 
 scoped_refptr<App> MakeAppServer();
diff --git a/chrome/updater/app/server/linux/update_service_stub.cc b/chrome/updater/app/server/linux/update_service_stub.cc
index d10cc7c..807eec9 100644
--- a/chrome/updater/app/server/linux/update_service_stub.cc
+++ b/chrome/updater/app/server/linux/update_service_stub.cc
@@ -10,6 +10,7 @@
 #include "base/check.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
+#include "base/functional/callback_forward.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/process/process_handle.h"
@@ -99,7 +100,9 @@
 }  // namespace
 
 UpdateServiceStub::UpdateServiceStub(scoped_refptr<updater::UpdateService> impl,
-                                     UpdaterScope scope)
+                                     UpdaterScope scope,
+                                     base::RepeatingClosure task_start_listener,
+                                     base::RepeatingClosure task_end_listener)
     : server_(
           GetActiveDutySocketPath(scope).MaybeAsASCII(),
           named_mojo_ipc_server::NamedMojoIpcServerBase::kUseIsolatedConnection,
@@ -112,7 +115,9 @@
                 return interface;
               },
               this))),
-      impl_(impl) {
+      impl_(impl),
+      task_start_listener_(task_start_listener),
+      task_end_listener_(task_end_listener) {
   server_.set_disconnect_handler(base::BindRepeating(
       &UpdateServiceStub::OnClientDisconnected, base::Unretained(this)));
   server_.StartServer();
@@ -126,38 +131,50 @@
 }
 
 void UpdateServiceStub::GetVersion(GetVersionCallback callback) {
-  impl_->GetVersion(base::BindOnce(
-      [](GetVersionCallback callback, const base::Version& version) {
-        std::move(callback).Run(version.GetString());
-      },
-      std::move(callback)));
+  task_start_listener_.Run();
+  impl_->GetVersion(
+      base::BindOnce(
+          [](GetVersionCallback callback, const base::Version& version) {
+            std::move(callback).Run(version.GetString());
+          },
+          std::move(callback))
+          .Then(task_end_listener_));
 }
 
 void UpdateServiceStub::FetchPolicies(FetchPoliciesCallback callback) {
-  impl_->FetchPolicies(std::move(callback));
+  task_start_listener_.Run();
+  impl_->FetchPolicies(std::move(callback).Then(task_end_listener_));
 }
 
 void UpdateServiceStub::RegisterApp(mojom::RegistrationRequestPtr request,
                                     RegisterAppCallback callback) {
-  impl_->RegisterApp(MakeRegistrationRequest(request), std::move(callback));
+  task_start_listener_.Run();
+  impl_->RegisterApp(MakeRegistrationRequest(request),
+                     std::move(callback).Then(task_end_listener_));
 }
 
 void UpdateServiceStub::GetAppStates(GetAppStatesCallback callback) {
+  task_start_listener_.Run();
   impl_->GetAppStates(
-      base::BindOnce([](const std::vector<updater::UpdateService::AppState>&
-                            app_states) {
-        std::vector<mojom::AppStatePtr> app_states_mojom;
-        std::transform(app_states.begin(), app_states.end(),
-                       std::back_inserter(app_states_mojom), &MakeMojoAppState);
-        return app_states_mojom;
-      }).Then(std::move(callback)));
+      base::BindOnce(
+          [](const std::vector<updater::UpdateService::AppState>& app_states) {
+            std::vector<mojom::AppStatePtr> app_states_mojom;
+            std::transform(app_states.begin(), app_states.end(),
+                           std::back_inserter(app_states_mojom),
+                           &MakeMojoAppState);
+            return app_states_mojom;
+          })
+          .Then(std::move(callback))
+          .Then(task_end_listener_));
 }
 
 void UpdateServiceStub::RunPeriodicTasks(RunPeriodicTasksCallback callback) {
-  impl_->RunPeriodicTasks(std::move(callback));
+  task_start_listener_.Run();
+  impl_->RunPeriodicTasks(std::move(callback).Then(task_end_listener_));
 }
 
 void UpdateServiceStub::UpdateAll(UpdateAllCallback callback) {
+  task_start_listener_.Run();
   std::unique_ptr<mojo::Remote<mojom::StateChangeObserver>> observer =
       std::make_unique<mojo::Remote<mojom::StateChangeObserver>>();
   std::move(callback).Run(observer->BindNewPipeAndPassReceiver());
@@ -165,7 +182,7 @@
   auto [state_change_callback, on_complete_callback] =
       MakeStateChangeObserverCallbacks(std::move(observer));
   impl_->UpdateAll(std::move(state_change_callback),
-                   std::move(on_complete_callback));
+                   std::move(on_complete_callback).Then(task_end_listener_));
 }
 
 void UpdateServiceStub::Update(
@@ -174,6 +191,7 @@
     UpdateService::Priority priority,
     UpdateService::PolicySameVersionUpdate policy_same_version_update,
     UpdateCallback callback) {
+  task_start_listener_.Run();
   std::unique_ptr<mojo::Remote<mojom::StateChangeObserver>> observer =
       std::make_unique<mojo::Remote<mojom::StateChangeObserver>>();
   std::move(callback).Run(observer->BindNewPipeAndPassReceiver());
@@ -185,7 +203,7 @@
                 static_cast<updater::UpdateService::PolicySameVersionUpdate>(
                     policy_same_version_update),
                 std::move(state_change_callback),
-                std::move(on_complete_callback));
+                std::move(on_complete_callback).Then(task_end_listener_));
 }
 
 void UpdateServiceStub::Install(mojom::RegistrationRequestPtr registration,
@@ -193,6 +211,7 @@
                                 const std::string& install_data_index,
                                 UpdateService::Priority priority,
                                 InstallCallback callback) {
+  task_start_listener_.Run();
   std::unique_ptr<mojo::Remote<mojom::StateChangeObserver>> observer =
       std::make_unique<mojo::Remote<mojom::StateChangeObserver>>();
   std::move(callback).Run(observer->BindNewPipeAndPassReceiver());
@@ -203,11 +222,13 @@
                  install_data_index,
                  static_cast<updater::UpdateService::Priority>(priority),
                  std::move(state_change_callback),
-                 std::move(on_complete_callback));
+                 std::move(on_complete_callback).Then(task_end_listener_));
 }
 
 void UpdateServiceStub::CancelInstalls(const std::string& app_id) {
+  task_start_listener_.Run();
   impl_->CancelInstalls(app_id);
+  task_end_listener_.Run();
 }
 
 void UpdateServiceStub::RunInstaller(const std::string& app_id,
@@ -216,6 +237,7 @@
                                      const std::string& install_data,
                                      const std::string& install_settings,
                                      RunInstallerCallback callback) {
+  task_start_listener_.Run();
   std::unique_ptr<mojo::Remote<mojom::StateChangeObserver>> observer =
       std::make_unique<mojo::Remote<mojom::StateChangeObserver>>();
   std::move(callback).Run(observer->BindNewPipeAndPassReceiver());
@@ -224,7 +246,7 @@
       MakeStateChangeObserverCallbacks(std::move(observer));
   impl_->RunInstaller(app_id, installer_path, install_args, install_data,
                       install_settings, std::move(state_change_callback),
-                      std::move(on_complete_callback));
+                      std::move(on_complete_callback).Then(task_end_listener_));
 }
 
 }  // namespace updater
diff --git a/chrome/updater/app/server/linux/update_service_stub.h b/chrome/updater/app/server/linux/update_service_stub.h
index d66f9817..b1a3d5f9 100644
--- a/chrome/updater/app/server/linux/update_service_stub.h
+++ b/chrome/updater/app/server/linux/update_service_stub.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_UPDATER_APP_SERVER_LINUX_UPDATE_SERVICE_STUB_H_
 #define CHROME_UPDATER_APP_SERVER_LINUX_UPDATE_SERVICE_STUB_H_
 
+#include "base/functional/callback_forward.h"
 #include "chrome/updater/app/server/posix/mojom/updater_service.mojom.h"
 
 #include "base/memory/scoped_refptr.h"
@@ -25,7 +26,9 @@
   // `NamedMojoIpcServer` which listens on a socket whose name is decided by
   // `scope`.
   UpdateServiceStub(scoped_refptr<updater::UpdateService> impl,
-                    UpdaterScope scope);
+                    UpdaterScope scope,
+                    base::RepeatingClosure task_start_listener,
+                    base::RepeatingClosure task_end_listener);
   UpdateServiceStub(const UpdateServiceStub&) = delete;
   UpdateServiceStub& operator=(const UpdateServiceStub&) = delete;
   ~UpdateServiceStub() override;
@@ -61,6 +64,8 @@
 
   named_mojo_ipc_server::NamedMojoIpcServer<mojom::UpdateService> server_;
   scoped_refptr<updater::UpdateService> impl_;
+  base::RepeatingClosure task_start_listener_;
+  base::RepeatingClosure task_end_listener_;
 };
 
 }  // namespace updater
diff --git a/chrome/updater/app/server/mac/app_server.h b/chrome/updater/app/server/mac/app_server.h
index 91ef228..ae3d7405 100644
--- a/chrome/updater/app/server/mac/app_server.h
+++ b/chrome/updater/app/server/mac/app_server.h
@@ -9,35 +9,28 @@
 
 #include <xpc/xpc.h>
 
-#include <memory>
-
 #include "base/atomic_ref_count.h"
 #include "base/callback_forward.h"
 #include "base/mac/scoped_nsobject.h"
 #include "base/memory/ref_counted.h"
-#include "base/sequence_checker.h"
-#include "chrome/updater/app/app_server.h"
 #include "chrome/updater/app/server/mac/service_delegate.h"
-#include "chrome/updater/app/server/posix/update_service_internal_stub.h"
+#include "chrome/updater/app/server/posix/app_server_posix.h"
 #import "chrome/updater/configurator.h"
 #import "chrome/updater/mac/xpc_service_names.h"
 #include "chrome/updater/update_service_impl.h"
 
 namespace base {
-class SequencedTaskRunner;
 struct RegistrationRequest;
-}
+}  // namespace base
 
 namespace updater {
 
 class UpdateServiceInternal;
 class UpdateService;
 
-class AppServerMac : public AppServer {
+class AppServerMac : public AppServerPosix {
  public:
   AppServerMac();
-  void TaskStarted();
-  void TaskCompleted();
 
  protected:
   // Overrides of App.
@@ -56,21 +49,9 @@
           register_callback) override;
   void UninstallSelf() override;
 
-  void MarkTaskStarted();
-  void AcknowledgeTaskCompletion();
-
-  base::TimeDelta ServerKeepAlive();
-
-  SEQUENCE_CHECKER(sequence_checker_);
-
-  std::unique_ptr<UpdateServiceInternalStub> active_duty_internal_stub_;
   base::scoped_nsobject<CRUUpdateCheckServiceXPCDelegate>
       update_check_delegate_;
   base::scoped_nsobject<NSXPCListener> update_check_listener_;
-
-  // Task runner bound to the main sequence and the update service instance.
-  scoped_refptr<base::SequencedTaskRunner> main_task_runner_;
-  int tasks_running_ = 0;
 };
 
 }  // namespace updater
diff --git a/chrome/updater/app/server/mac/server.mm b/chrome/updater/app/server/mac/server.mm
index a828db4..4b473e9 100644
--- a/chrome/updater/app/server/mac/server.mm
+++ b/chrome/updater/app/server/mac/server.mm
@@ -35,8 +35,7 @@
 
 namespace updater {
 
-AppServerMac::AppServerMac()
-    : main_task_runner_(base::SequencedTaskRunner::GetCurrentDefault()) {}
+AppServerMac::AppServerMac() = default;
 AppServerMac::~AppServerMac() = default;
 
 void AppServerMac::Uninitialize() {
@@ -93,38 +92,6 @@
   return true;
 }
 
-void AppServerMac::TaskStarted() {
-  main_task_runner_->PostTask(FROM_HERE,
-                              BindOnce(&AppServerMac::MarkTaskStarted, this));
-}
-
-void AppServerMac::MarkTaskStarted() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  ++tasks_running_;
-  VLOG(2) << "Starting task, " << tasks_running_ << " tasks running";
-}
-
-base::TimeDelta AppServerMac::ServerKeepAlive() {
-  int seconds = external_constants()->ServerKeepAliveSeconds();
-  VLOG(2) << "ServerKeepAliveSeconds: " << seconds;
-  return base::Seconds(seconds);
-}
-
-void AppServerMac::TaskCompleted() {
-  main_task_runner_->PostDelayedTask(
-      FROM_HERE, base::BindOnce(&AppServerMac::AcknowledgeTaskCompletion, this),
-      ServerKeepAlive());
-}
-
-void AppServerMac::AcknowledgeTaskCompletion() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (--tasks_running_ < 1) {
-    main_task_runner_->PostTask(
-        FROM_HERE, base::BindOnce(&AppServerMac::Shutdown, this, 0));
-  }
-  VLOG(2) << "Completing task, " << tasks_running_ << " tasks running";
-}
-
 scoped_refptr<App> MakeAppServer() {
   return base::MakeRefCounted<AppServerMac>();
 }
diff --git a/chrome/updater/app/server/posix/app_server_posix.cc b/chrome/updater/app/server/posix/app_server_posix.cc
new file mode 100644
index 0000000..6224afc
--- /dev/null
+++ b/chrome/updater/app/server/posix/app_server_posix.cc
@@ -0,0 +1,52 @@
+// 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/updater/app/server/posix/app_server_posix.h"
+
+#include "base/functional/bind.h"
+#include "base/logging.h"
+#include "base/sequence_checker.h"
+#include "base/task/sequenced_task_runner.h"
+#include "base/time/time.h"
+#include "chrome/updater/app/server/posix/update_service_internal_stub.h"
+
+namespace updater {
+
+AppServerPosix::AppServerPosix() = default;
+AppServerPosix::~AppServerPosix() = default;
+
+void AppServerPosix::TaskStarted() {
+  main_task_runner_->PostTask(FROM_HERE,
+                              BindOnce(&AppServerPosix::MarkTaskStarted, this));
+}
+
+void AppServerPosix::MarkTaskStarted() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  ++tasks_running_;
+  VLOG(2) << "Starting task, " << tasks_running_ << " tasks running";
+}
+
+base::TimeDelta AppServerPosix::ServerKeepAlive() {
+  int seconds = external_constants()->ServerKeepAliveSeconds();
+  VLOG(2) << "ServerKeepAliveSeconds: " << seconds;
+  return base::Seconds(seconds);
+}
+
+void AppServerPosix::TaskCompleted() {
+  main_task_runner_->PostDelayedTask(
+      FROM_HERE,
+      base::BindOnce(&AppServerPosix::AcknowledgeTaskCompletion, this),
+      ServerKeepAlive());
+}
+
+void AppServerPosix::AcknowledgeTaskCompletion() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (--tasks_running_ < 1) {
+    main_task_runner_->PostTask(
+        FROM_HERE, base::BindOnce(&AppServerPosix::Shutdown, this, 0));
+  }
+  VLOG(2) << "Completing task, " << tasks_running_ << " tasks running";
+}
+
+}  // namespace updater
diff --git a/chrome/updater/app/server/posix/app_server_posix.h b/chrome/updater/app/server/posix/app_server_posix.h
new file mode 100644
index 0000000..3b8071f
--- /dev/null
+++ b/chrome/updater/app/server/posix/app_server_posix.h
@@ -0,0 +1,47 @@
+// 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_UPDATER_APP_SERVER_POSIX_APP_SERVER_POSIX_H_
+#define CHROME_UPDATER_APP_SERVER_POSIX_APP_SERVER_POSIX_H_
+
+#include <memory>
+
+#include "base/memory/scoped_refptr.h"
+#include "base/sequence_checker.h"
+#include "base/task/sequenced_task_runner.h"
+#include "base/time/time.h"
+#include "chrome/updater/app/app_server.h"
+
+namespace updater {
+
+class UpdateServiceInternalStub;
+
+class AppServerPosix : public AppServer {
+ public:
+  AppServerPosix();
+
+  void TaskStarted();
+  void TaskCompleted();
+
+ protected:
+  ~AppServerPosix() override;
+
+  SEQUENCE_CHECKER(sequence_checker_);
+
+  std::unique_ptr<UpdateServiceInternalStub> active_duty_internal_stub_;
+
+ private:
+  base::TimeDelta ServerKeepAlive();
+  void MarkTaskStarted();
+  void AcknowledgeTaskCompletion();
+
+  int tasks_running_ = 0;
+  // Task runner bound to the main sequence and the update service instance.
+  scoped_refptr<base::SequencedTaskRunner> main_task_runner_ =
+      base::SequencedTaskRunner::GetCurrentDefault();
+};
+
+}  // namespace updater
+
+#endif  // CHROME_UPDATER_APP_SERVER_POSIX_APP_SERVER_POSIX_H_
diff --git a/chrome/updater/installer.cc b/chrome/updater/installer.cc
index a3709ec1..89ff64b 100644
--- a/chrome/updater/installer.cc
+++ b/chrome/updater/installer.cc
@@ -45,8 +45,9 @@
 absl::optional<base::FilePath> GetAppInstallDir(UpdaterScope scope,
                                                 const std::string& app_id) {
   absl::optional<base::FilePath> app_install_dir = GetBaseDataDirectory(scope);
-  if (!app_install_dir)
+  if (!app_install_dir) {
     return absl::nullopt;
+  }
 
   return app_install_dir->AppendASCII(kAppsDir).AppendASCII(app_id);
 }
@@ -116,8 +117,9 @@
   component.app_id = app_id_;
 
   // Query server for install data only when the client does not specify one.
-  if (client_install_data_.empty())
+  if (client_install_data_.empty()) {
     component.install_data_index = install_data_index_;
+  }
 
   component.ap = ap_;
   component.brand = persisted_data_->GetBrandCode(app_id_);
@@ -170,14 +172,16 @@
   // Resolve the path to an installer file, which is included in the CRX, and
   // specified by the |run| attribute in the manifest object of an update
   // response.
-  if (!install_params || install_params->run.empty())
+  if (!install_params || install_params->run.empty()) {
     return Result(kErrorMissingInstallParams);
+  }
 
   // Assume the install params are ASCII for now.
   const auto application_installer =
       unpack_path.AppendASCII(install_params->run);
-  if (!base::PathExists(application_installer))
+  if (!base::PathExists(application_installer)) {
     return Result(kErrorMissingRunableFile);
+  }
 
   // Upon success, when the control flow returns back to the |update_client|,
   // the prefs are updated asynchronously with the new |pv| and |fingerprint|.
@@ -227,12 +231,14 @@
                                  base::FilePath* installed_file) {
   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                 base::BlockingType::WILL_BLOCK);
-  if (pv_ == base::Version(kNullVersion))
+  if (pv_ == base::Version(kNullVersion)) {
     return false;  // No component has been installed yet.
+  }
 
   const auto install_dir = GetCurrentInstallDir();
-  if (!install_dir)
+  if (!install_dir) {
     return false;
+  }
 
   *installed_file = install_dir->AppendASCII(file);
   return true;
@@ -247,24 +253,10 @@
                                                 base::BlockingType::WILL_BLOCK);
   const absl::optional<base::FilePath> path =
       GetAppInstallDir(updater_scope_, app_id_);
-  if (!path)
+  if (!path) {
     return absl::nullopt;
+  }
   return path->AppendASCII(pv_.GetString());
 }
 
-#if BUILDFLAG(IS_LINUX)
-
-AppInstallerResult RunApplicationInstaller(
-    const AppInfo& /*app_info*/,
-    const base::FilePath& /*app_installer*/,
-    const std::string& /*arguments*/,
-    const absl::optional<base::FilePath>& /*install_data_file*/,
-    const base::TimeDelta& timeout,
-    InstallProgressCallback /*progress_callback*/) {
-  NOTIMPLEMENTED();
-  return AppInstallerResult(-1);
-}
-
-#endif  // BUILDFLAG(IS_LINUX)
-
 }  // namespace updater
diff --git a/chrome/updater/installer_linux.cc b/chrome/updater/installer_linux.cc
new file mode 100644
index 0000000..4436165f
--- /dev/null
+++ b/chrome/updater/installer_linux.cc
@@ -0,0 +1,49 @@
+// 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 "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/process/launch.h"
+#include "base/strings/string_util.h"
+#include "chrome/updater/constants.h"
+#include "chrome/updater/installer.h"
+
+namespace updater {
+
+AppInstallerResult RunApplicationInstaller(
+    const AppInfo& app_info,
+    const base::FilePath& installer_path,
+    const std::string& arguments,
+    const absl::optional<base::FilePath>& install_data_file,
+    const base::TimeDelta& timeout,
+    InstallProgressCallback /*progress_callback*/) {
+  base::LaunchOptions options;
+  if (install_data_file) {
+    options.environment.emplace(base::ToUpperASCII(kInstallerDataSwitch),
+                                install_data_file->value());
+  }
+
+  base::SetPosixFilePermissions(installer_path,
+                                base::FILE_PERMISSION_USER_MASK |
+                                    base::FILE_PERMISSION_GROUP_MASK |
+                                    base::FILE_PERMISSION_READ_BY_OTHERS |
+                                    base::FILE_PERMISSION_EXECUTE_BY_OTHERS);
+
+  base::CommandLine command(installer_path);
+  int exit_code = 0;
+  if (!base::LaunchProcess(command, options)
+           .WaitForExitWithTimeout(timeout, &exit_code)) {
+    LOG(ERROR) << "Could not launch application installer.";
+    return AppInstallerResult(kErrorApplicationInstallerFailed,
+                              kErrorProcessLaunchFailed);
+  }
+  if (exit_code != 0) {
+    LOG(ERROR) << "Installer returned error code " << exit_code;
+    return AppInstallerResult(kErrorApplicationInstallerFailed, exit_code);
+  }
+
+  return AppInstallerResult();
+}
+
+}  // namespace updater
diff --git a/chrome/updater/linux/BUILD.gn b/chrome/updater/linux/BUILD.gn
index 9c735a67..72e74039 100644
--- a/chrome/updater/linux/BUILD.gn
+++ b/chrome/updater/linux/BUILD.gn
@@ -12,15 +12,25 @@
   ]
 }
 
-executable("updater") {
+source_set("updater_executable") {
   sources = [ "main.cc" ]
+  deps = [ "//chrome/updater:base" ]
+}
 
+executable("updater") {
   deps = [
-    "//chrome/updater:base",
+    ":updater_executable",
     "//chrome/updater:constants_prod",
   ]
 }
 
+executable("updater_test") {
+  deps = [
+    ":updater_executable",
+    "//chrome/updater:constants_test",
+  ]
+}
+
 artifact_zip("updater_zip") {
   output = "$root_build_dir/updater.zip"
   inputs = [ "$root_build_dir/qualification_app" ]
diff --git a/chrome/updater/test/integration_tests.cc b/chrome/updater/test/integration_tests.cc
index c52f0bd3..1046cb02 100644
--- a/chrome/updater/test/integration_tests.cc
+++ b/chrome/updater/test/integration_tests.cc
@@ -380,14 +380,7 @@
   Uninstall();
 }
 
-// TODO(crbug.com/1341471): this test is disabled temporarily. Reenable after
-// the build for the current CL is published to CIPD.
-#if BUILDFLAG(IS_WIN)
-#define MAYBE_OverinstallWorking DISABLED_OverinstallWorking
-#else
-#define MAYBE_OverinstallWorking OverinstallWorking
-#endif
-TEST_F(IntegrationTest, MAYBE_OverinstallWorking) {
+TEST_F(IntegrationTest, OverinstallWorking) {
   ASSERT_NO_FATAL_FAILURE(SetupRealUpdaterLowerVersion());
   EXPECT_TRUE(WaitForUpdaterExit());
   ExpectVersionNotActive(kUpdaterVersion);
@@ -401,15 +394,13 @@
   Uninstall();
 }
 
-#if BUILDFLAG(IS_WIN)
-// TODO(crbug.com/1395118): Breaks on Win10 Tests x64. Fix this.
-#define MAYBE_OverinstallBroken DISABLED_OverinstallBroken
-#else
-#define MAYBE_OverinstallBroken OverinstallBroken
-#endif
-TEST_F(IntegrationTest, MAYBE_OverinstallBroken) {
+TEST_F(IntegrationTest, OverinstallBroken) {
   ASSERT_NO_FATAL_FAILURE(SetupRealUpdaterLowerVersion());
   EXPECT_TRUE(WaitForUpdaterExit());
+
+  // TODO(crbug.com/1393788) - find a different way to break the CIPD build,
+  // maybe rename the directory then restore it back before uninstalling such
+  // that clean up is successful.
   DeleteUpdaterDirectory();
 
   // Since the old version is not working, the new version should install and
@@ -792,14 +783,7 @@
 
 #if BUILDFLAG(CHROMIUM_BRANDING) || BUILDFLAG(GOOGLE_CHROME_BRANDING)
 #if !defined(COMPONENT_BUILD)
-// TODO(crbug.com/1341471): this test is disabled temporarily. Reenable after
-// the build for the current CL is published to CIPD.
-#if BUILDFLAG(IS_WIN)
-#define MAYBE_SelfUpdateFromOldReal DISABLED_SelfUpdateFromOldReal
-#else
-#define MAYBE_SelfUpdateFromOldReal SelfUpdateFromOldReal
-#endif
-TEST_F(IntegrationTest, MAYBE_SelfUpdateFromOldReal) {
+TEST_F(IntegrationTest, SelfUpdateFromOldReal) {
   ScopedServer test_server(test_commands_);
 
   ASSERT_NO_FATAL_FAILURE(SetupRealUpdaterLowerVersion());
@@ -825,17 +809,12 @@
 
 // Tests that installing and uninstalling an old version of the updater from
 // CIPD is possible.
-#if BUILDFLAG(IS_WIN)
-// TODO(crbug.com/1395118): Breaks on Win10 Tests x64. Fix this.
-#define MAYBE_InstallLowerVersion DISABLED_InstallLowerVersion
-#else
-#define MAYBE_InstallLowerVersion InstallLowerVersion
-#endif
-TEST_F(IntegrationTest, MAYBE_InstallLowerVersion) {
+TEST_F(IntegrationTest, InstallLowerVersion) {
   ASSERT_NO_FATAL_FAILURE(SetupRealUpdaterLowerVersion());
   ExpectVersionNotActive(kUpdaterVersion);
   Uninstall();
 
+  // TODO(crbug.com/1393788) - eliminate this special case of clean up.
 #if BUILDFLAG(IS_WIN)
   // This deletes a tree of empty subdirectories corresponding to the crash
   // handler of the lower version updater installed above. `Uninstall` runs
diff --git a/chrome/updater/win/app_command_runner_unittest.cc b/chrome/updater/win/app_command_runner_unittest.cc
index 502fe56..a4f01fa 100644
--- a/chrome/updater/win/app_command_runner_unittest.cc
+++ b/chrome/updater/win/app_command_runner_unittest.cc
@@ -340,8 +340,7 @@
 
 TEST_F(AppCommandRunnerTest, CheckChromeBrandedName) {
 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
-  EXPECT_EQ(
-  {L"Google Chrome", L"" BROWSER_PRODUCT_NAME_STRING);
+  EXPECT_STREQ("Google Chrome", BROWSER_PRODUCT_NAME_STRING);
 #endif  // BUILDFLAG(GOOGLE_CHROME_BRANDING)
 }
 
diff --git a/chromeos/ash/components/drivefs/drivefs_pin_manager.cc b/chromeos/ash/components/drivefs/drivefs_pin_manager.cc
index 4291d7b..6e1d89d 100644
--- a/chromeos/ash/components/drivefs/drivefs_pin_manager.cc
+++ b/chromeos/ash/components/drivefs/drivefs_pin_manager.cc
@@ -56,6 +56,44 @@
 
 constexpr char kGCacheFolderName[] = "GCache";
 
+DriveFsPinManager::InProgressSyncingItems::InProgressSyncingItems() = default;
+
+DriveFsPinManager::InProgressSyncingItems::~InProgressSyncingItems() = default;
+
+void DriveFsPinManager::InProgressSyncingItems::AddItem(
+    const std::string path) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  // Emplace an item with no progress, these values (i.e. 0,0) will get updated
+  // in the `OnSyncingStatusUpdate`.
+  in_progress_items_.try_emplace(path, /*bytes_transferred=*/0,
+                                 /*bytes_to_transfer=*/0);
+}
+
+void DriveFsPinManager::InProgressSyncingItems::RemoveItem(
+    const std::string path) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  in_progress_items_.erase(path);
+}
+
+void DriveFsPinManager::InProgressSyncingItems::UpdateItem(
+    const std::string path,
+    int64_t bytes_transferred,
+    int64_t bytes_to_transfer) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  auto it = in_progress_items_.find(path);
+  if (it == in_progress_items_.end()) {
+    return;
+  }
+  it->second.first = bytes_transferred;
+  it->second.second = bytes_to_transfer;
+}
+
+size_t DriveFsPinManager::InProgressSyncingItems::GetItemCount() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  VLOG(1) << "Remaining syncing items: " << in_progress_items_.size();
+  return in_progress_items_.size();
+}
+
 DriveFsPinManager::DriveFsPinManager(bool enabled,
                                      const base::FilePath& profile_path,
                                      mojom::DriveFs* drivefs_interface)
@@ -63,7 +101,10 @@
       free_disk_space_(std::make_unique<FreeDiskSpaceImpl>()),
       profile_path_(profile_path),  // The GCache directory is located in the
                                     // users profile path.
-      drivefs_interface_(drivefs_interface) {}
+      drivefs_interface_(drivefs_interface),
+      task_runner_(base::ThreadPool::CreateSequencedTaskRunner({})),
+      syncing_items_(
+          base::SequenceBound<InProgressSyncingItems>{task_runner_}) {}
 
 DriveFsPinManager::DriveFsPinManager(
     bool enabled,
@@ -235,54 +276,48 @@
     drivefs_interface_->SetPinned(
         path, /*pinned=*/true,
         base::BindOnce(&DriveFsPinManager::OnFilePinned,
-                       weak_ptr_factory_.GetWeakPtr(), path));
+                       weak_ptr_factory_.GetWeakPtr(), path.value()));
   }
 }
 
-void DriveFsPinManager::OnFilePinned(const base::FilePath& path,
+void DriveFsPinManager::OnFilePinned(const std::string& path,
                                      drive::FileError status) {
   if (status != drive::FILE_ERROR_OK) {
     LOG(ERROR) << "Failed pinning an item: " << status;
-    VLOG(2) << "Path that failed to pin: " << path.value() << " with error "
+    VLOG(2) << "Path that failed to pin: " << path << " with error "
             << drive::FileErrorToString(status);
     Complete(PinError::kErrorFailedToPinItem);
     return;
   }
 
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  // Emplace an item with no progress, these values (i.e. 0,0) will get updated
-  // in the `OnSyncingStatusUpdate`.
-  in_progress_items_.try_emplace(path.value(), /*bytes_transferred=*/0,
-                                 /*bytes_to_transfer=*/0);
+  syncing_items_.AsyncCall(&InProgressSyncingItems::AddItem).WithArgs(path);
 }
 
 void DriveFsPinManager::OnSyncingStatusUpdate(
     const mojom::SyncingStatus& status) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
   for (const auto& item : status.item_events) {
     auto cloned_item = item.Clone();
-    auto transferred = in_progress_items_.find(cloned_item->path);
-    if (transferred == in_progress_items_.end()) {
-      continue;
-    }
     // 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 (cloned_item->state == mojom::ItemEvent::State::kCompleted) {
-      in_progress_items_.erase(cloned_item->path);
-      VLOG(2) << "Removing completed items from sync map: "
-              << cloned_item->path.c_str();
+      syncing_items_.AsyncCall(&InProgressSyncingItems::RemoveItem)
+          .WithArgs(cloned_item->path);
       continue;
     }
-    transferred->second.first = cloned_item->bytes_transferred;
-    transferred->second.second = cloned_item->bytes_to_transfer;
+    syncing_items_.AsyncCall(&InProgressSyncingItems::UpdateItem)
+        .WithArgs(cloned_item->path, cloned_item->bytes_transferred,
+                  cloned_item->bytes_to_transfer);
   }
 
-  if (in_progress_items_.size() == 0) {
-    VLOG(2) << "Current batch below threshold (" << in_progress_items_.size()
-            << "), starting new batch";
+  syncing_items_.AsyncCall(&InProgressSyncingItems::GetItemCount)
+      .Then(base::BindOnce(&DriveFsPinManager::MaybeStartSearch,
+                           weak_ptr_factory_.GetWeakPtr()));
+}
+
+void DriveFsPinManager::MaybeStartSearch(size_t remaining_items) {
+  if (remaining_items == 0) {
     search_query_->GetNextPage(
         base::BindOnce(&DriveFsPinManager::OnSearchResultsForPinning,
                        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 bdc22692..e5cd0ef 100644
--- a/chromeos/ash/components/drivefs/drivefs_pin_manager.h
+++ b/chromeos/ash/components/drivefs/drivefs_pin_manager.h
@@ -14,6 +14,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/sequence_checker.h"
 #include "base/thread_annotations.h"
+#include "base/threading/sequence_bound.h"
 #include "base/timer/elapsed_timer.h"
 #include "chromeos/ash/components/drivefs/drivefs_host_observer.h"
 #include "chromeos/ash/components/drivefs/mojom/drivefs.mojom.h"
@@ -94,6 +95,42 @@
   void OnSyncingStatusUpdate(const mojom::SyncingStatus& status) override;
 
  private:
+  // A wrapper to maintain sequence-affinity on the `InProgressMap`. The
+  // instance of this is owned by `DriveFsPinManager`, is created and destroyed
+  // on the same task runner.
+  class InProgressSyncingItems {
+   public:
+    InProgressSyncingItems();
+
+    InProgressSyncingItems(const InProgressSyncingItems&) = delete;
+    InProgressSyncingItems& operator=(const InProgressSyncingItems&) = delete;
+
+    ~InProgressSyncingItems();
+
+    // Adds an item to the map.
+    void AddItem(const std::string path);
+
+    // Removes an item from the map, if the item doesn't exist ignores the
+    // removal.
+    void RemoveItem(const std::string path);
+
+    // Update the item keyed at `path` with the new progress bytes.
+    void UpdateItem(const std::string path,
+                    int64_t bytes_transferred,
+                    int64_t bytes_to_transfer);
+
+    // Return the number of items currently being tracked as in progress.
+    size_t GetItemCount();
+
+   private:
+    SEQUENCE_CHECKER(sequence_checker_);
+    // A map that tracks the in progress items by their key to a pair of
+    // `int64_t` with `first` being the number of bytes transferred and `second`
+    // being the `bytes_to_transfer` i.e. the total bytes of the syncing file.
+    using InProgressMap = std::map<std::string, std::pair<int64_t, int64_t>>;
+    InProgressMap in_progress_items_ GUARDED_BY_CONTEXT(sequence_checker_);
+  };
+
   // Invoked on retrieval of available space in the `~/GCache` directory.
   void OnFreeDiskSpaceRetrieved(int64_t free_space);
 
@@ -121,7 +158,10 @@
   // emplaced. Note the file being pinned is just an update in drivefs, not the
   // actually completion of the file being downloaded, that is monitored via
   // `OnSyncingStatusUpdate`.
-  void OnFilePinned(const base::FilePath& path, drive::FileError status);
+  void OnFilePinned(const std::string& path, drive::FileError status);
+
+  // If there are no remaining items left, get the next search query page.
+  void MaybeStartSearch(size_t remaining_items);
 
   bool enabled_ = false;
   int64_t size_required_ = 0;
@@ -134,12 +174,10 @@
   mojo::Remote<mojom::SearchQuery> search_query_;
   base::ElapsedTimer timer_;
 
-  SEQUENCE_CHECKER(sequence_checker_);
-  // A map that tracks the in progress items by their key to a pair of `int64_t`
-  // with `first` being the number of bytes transferred and `second` being the
-  // `bytes_to_transfer` i.e. the total bytes of the syncing file.
-  using InProgressMap = std::map<std::string, std::pair<int64_t, int64_t>>;
-  InProgressMap in_progress_items_ GUARDED_BY_CONTEXT(sequence_checker_);
+  // The in progress syncing items and the task runner which guarantees items
+  // are added / removed / updated in sequence.
+  const scoped_refptr<base::SequencedTaskRunner> task_runner_;
+  base::SequenceBound<InProgressSyncingItems> syncing_items_;
 
   base::WeakPtrFactory<DriveFsPinManager> weak_ptr_factory_{this};
 };
diff --git a/chromeos/ash/components/network/apn_migrator.cc b/chromeos/ash/components/network/apn_migrator.cc
index a8b3e569..a477fd50 100644
--- a/chromeos/ash/components/network/apn_migrator.cc
+++ b/chromeos/ash/components/network/apn_migrator.cc
@@ -60,7 +60,10 @@
   network_state_handler_->GetVisibleNetworkListByType(
       NetworkTypePattern::Cellular(), &network_list);
   for (const NetworkState* network : network_list) {
-    // TODO(b/162365553): Ignore stub cellular networks
+    if (network->IsNonShillCellularNetwork()) {
+      continue;
+    }
+
     if (!managed_cellular_pref_handler_->ContainsApnMigratedIccid(
             network->iccid())) {
       if (!ash::features::IsApnRevampEnabled()) {
diff --git a/chromeos/ash/components/network/apn_migrator_unittest.cc b/chromeos/ash/components/network/apn_migrator_unittest.cc
index 52bec27..ebf4a75 100644
--- a/chromeos/ash/components/network/apn_migrator_unittest.cc
+++ b/chromeos/ash/components/network/apn_migrator_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "chromeos/ash/components/network/device_state.h"
+#include "chromeos/ash/components/network/fake_stub_cellular_networks_provider.h"
 #include "chromeos/ash/components/network/mock_managed_cellular_pref_handler.h"
 #include "chromeos/ash/components/network/mock_managed_network_configuration_handler.h"
 #include "chromeos/ash/components/network/mock_network_metadata_store.h"
@@ -116,11 +117,17 @@
     return cellular_service_path_3_;
   }
 
+  void AddStub(const std::string& stub_iccid, const std::string& eid) {
+    stub_cellular_networks_provider_.AddStub(stub_iccid, eid);
+    network_state_helper_.network_state_handler()->SyncStubCellularNetworks();
+  }
+
  private:
   base::test::SingleThreadTaskEnvironment task_environment_;
   NetworkStateTestHelper network_state_helper_{
       /*use_default_devices_and_services=*/true};
   NetworkHandlerTestHelper handler_test_helper_;
+  FakeStubCellularNetworksProvider stub_cellular_networks_provider_;
 
   std::unique_ptr<MockManagedCellularPrefHandler>
       managed_cellular_pref_handler_;
@@ -148,6 +155,9 @@
   void SetupNetworks() {
     network_state_helper_.manager_test()->AddTechnology(shill::kTypeCellular,
                                                         /*enabled=*/true);
+    network_state_helper_.network_state_handler()
+        ->set_stub_cellular_networks_provider(
+            &stub_cellular_networks_provider_);
 
     AddTestCellularDevice(kCellularName1, kTestCellularPath1,
                           kTestCellularIccid1);
@@ -220,12 +230,17 @@
   TriggerNetworkListChanged();
 }
 
-TEST_F(ApnMigratorTest, ApnRevampFlagEnabled_AllNetworksMigrated) {
+TEST_F(ApnMigratorTest, ApnRevampFlagEnabled_MigratedNetworks) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndEnableFeature(ash::features::kApnRevamp);
 
-  // Every network should be evaluated, pretend that all network have been
-  // migrated.
+  const char kTestStubIccid[] = "test_stub_iccid";
+  const char kTestStubEid[] = "test_stub_eid";
+  AddStub(kTestStubIccid, kTestStubEid);
+
+  // The migrator routine will iterate through cellular networks. Stub networks
+  // must be ignored. For this test, pretend that all non-stub cellular network
+  // have been migrated.
   EXPECT_CALL(*managed_cellular_pref_handler(),
               ContainsApnMigratedIccid(Eq(kTestCellularIccid1)))
       .Times(1)
@@ -238,6 +253,9 @@
               ContainsApnMigratedIccid(Eq(kTestCellularIccid3)))
       .Times(1)
       .WillOnce(Return(true));
+  EXPECT_CALL(*managed_cellular_pref_handler(),
+              ContainsApnMigratedIccid(Eq(kTestStubIccid)))
+      .Times(0);
 
   // Return nullptr and empty list for the first two networks.
   EXPECT_CALL(*network_metadata_store(), GetCustomApnList(kTestCellularGuid1))
diff --git a/chromeos/ash/components/network/hidden_network_handler.cc b/chromeos/ash/components/network/hidden_network_handler.cc
index 6bc8c4b..3c8680f 100644
--- a/chromeos/ash/components/network/hidden_network_handler.cc
+++ b/chromeos/ash/components/network/hidden_network_handler.cc
@@ -8,6 +8,7 @@
 #include "ash/constants/ash_switches.h"
 #include "base/command_line.h"
 #include "base/metrics/histogram_functions.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/timer/timer.h"
 #include "chromeos/ash/components/network/managed_network_configuration_handler.h"
 #include "chromeos/ash/components/network/network_handler.h"
@@ -21,8 +22,8 @@
 constexpr char kRemoveAttemptResultHistogram[] =
     "Network.Ash.WiFi.Hidden.RemovalAttempt.Result";
 
+constexpr base::TimeDelta kDefaultForcedInterval = base::Seconds(5);
 constexpr base::TimeDelta kOneDay = base::Days(1);
-constexpr base::TimeDelta kOneMinute = base::Minutes(1);
 
 void OnRemoveConfigurationSuccess(const std::string guid) {
   base::UmaHistogramBoolean(kRemoveAttemptResultHistogram, true);
@@ -36,9 +37,22 @@
                  << ", error: " << error_name;
 }
 
-bool ShouldForceMigration() {
-  return base::CommandLine::ForCurrentProcess()->HasSwitch(
-      switches::kForceHiddenNetworkMigration);
+base::TimeDelta ComputeMigrationInterval() {
+  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+
+  if (!command_line->HasSwitch(switches::kForceHiddenNetworkMigration)) {
+    return kOneDay;
+  }
+
+  int interval_in_seconds = -1;
+  const std::string ascii =
+      command_line->GetSwitchValueASCII(switches::kForceHiddenNetworkMigration);
+
+  if (ascii.empty() || !base::StringToInt(ascii, &interval_in_seconds) ||
+      interval_in_seconds < 1) {
+    return kDefaultForcedInterval;
+  }
+  return base::Seconds(interval_in_seconds);
 }
 
 }  // namespace
@@ -68,7 +82,7 @@
   CleanHiddenNetworks();
 
   daily_event_timer_.Start(
-      FROM_HERE, ShouldForceMigration() ? kOneMinute : kOneDay,
+      FROM_HERE, ComputeMigrationInterval(),
       base::BindRepeating(&HiddenNetworkHandler::CleanHiddenNetworks,
                           base::Unretained(this)));
 }
@@ -96,8 +110,10 @@
     // existed for more than two weeks.
     if (network_metadata_store_->UpdateAndRetrieveWiFiTimestamp(
             state->guid()) != base::Time::UnixEpoch()) {
-      if (!ShouldForceMigration())
+      if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+              switches::kForceHiddenNetworkMigration)) {
         continue;
+      }
     }
 
     NET_LOG(EVENT) << "Attempting to remove network configuration with GUID: "
diff --git a/chromeos/ash/components/network/hidden_network_handler_unittest.cc b/chromeos/ash/components/network/hidden_network_handler_unittest.cc
index 489bc72..74d8013 100644
--- a/chromeos/ash/components/network/hidden_network_handler_unittest.cc
+++ b/chromeos/ash/components/network/hidden_network_handler_unittest.cc
@@ -35,7 +35,8 @@
 // initialized until the next time the timer fires, e.g. the next day.
 constexpr base::TimeDelta kTwoWeeks = base::Days(15);
 constexpr base::TimeDelta kArbitraryTime = base::Days(11686);
-constexpr base::TimeDelta kForcedMigrationTime = base::Minutes(2);
+constexpr base::TimeDelta kForcedMigrationTime = base::Seconds(20);
+constexpr char kForcedMigrationTimeASCII[] = "10";
 const char* kWiFiGuid1 = "wifi_guid1";
 const char* kWiFiGuid2 = "wifi_guid2";
 const char* kWiFiGuid3 = "wifi_guid3";
@@ -223,8 +224,8 @@
 }
 
 TEST_F(HiddenNetworkHandlerTest, MeetsAllCriteriaToRemoveForcedMigration) {
-  base::CommandLine::ForCurrentProcess()->AppendSwitch(
-      switches::kForceHiddenNetworkMigration);
+  base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+      switches::kForceHiddenNetworkMigration, kForcedMigrationTimeASCII);
 
   MaybeRegisterAndInitializePrefs();
 
diff --git a/chromeos/crosapi/mojom/test_controller.mojom b/chromeos/crosapi/mojom/test_controller.mojom
index fad156c..6e1c1f5 100644
--- a/chromeos/crosapi/mojom/test_controller.mojom
+++ b/chromeos/crosapi/mojom/test_controller.mojom
@@ -162,8 +162,8 @@
 // This interface is implemented by Ash-Chrome.
 // This interface provides tests a mechanism to mutate or query ash.
 // In the future, this interface may merge with an automation or a11y interface.
-// Next version: 24
-// Next method id: 35
+// Next version: 25
+// Next method id: 37
 [Stable, Uuid="1f93f9d7-e466-466c-a675-c21b48cf30d3"]
 interface TestController {
   // Clicks the middle of the views element identified by |element_name|.
@@ -354,4 +354,14 @@
   // been finished already.
   [MinVersion=23]
   AreDesksBeingModified@34()=>(bool are_desks_being_modified);
+
+  // Returns all available voices in ash-chrome.
+  [MinVersion=24]
+  GetTtsVoices@35() => (array<TtsVoice> voices);
+
+  // Requests Tts(text to speech) to speak an utterance from Ash.
+  [MinVersion=24]
+  TtsSpeak@36(TtsUtterance utterance,
+              pending_remote<TtsUtteranceClient> utterance_client);
+
 };
diff --git a/chromeos/crosapi/mojom/tts.mojom b/chromeos/crosapi/mojom/tts.mojom
index 6f3acdf..5c9f767 100644
--- a/chromeos/crosapi/mojom/tts.mojom
+++ b/chromeos/crosapi/mojom/tts.mojom
@@ -158,20 +158,24 @@
   Stop@2(string engine_id);
 };
 
-// This interface serves as a remote client of a TtsUtterance in Ash which is
-// originated from the Lacros. Implemented in lacros-chrome.
-// When Tts extension API or SpeechSynthesis web API is called from Lacros
-// browser to speak an utterance, We will call Tts::SpeakOrEnqueue to send the
-// utterance data to Ash along with a pending_remote<TtsUtteranceClient>
-// object, which allows to perform tasks associated with the utterance.
-// The disconnect handler will be invoked in Ash when the original utterance
-// becomes invalid in Lacros.
+// This interface receives events from an utterance which is being spoken by
+// a remote process.
+// Can be used in either lacros-chrome or ash.
+//
+// For example, when Tts extension API or SpeechSynthesis web API is called from
+// Lacros browser to speak an utterance, We will call Tts::SpeakOrEnqueue to
+// send the utterance to Ash along with a pending_remote<TtsUtteranceClient>
+// object, which can be used to forward the TtsEvent back to Lacros. In
+// addition, its disconnect handler will be invoked in Ash when the original
+// utterance becomes invalid in Lacros.
+// Similarly, it is also passed as argument in TtsClient::SpeakWithLacrosVoice
+// when Ash calls this API to speak an Ash Utterance with a Lacros speech
+// engine.
 [Stable, Uuid="edf0536d-53ea-445c-9519-cb39af32364f"]
 interface TtsUtteranceClient {
-  // Forwards a speech engine event received from an Ash speech engine
-  // to the callback function of the Tts client in Lacros. |error_message|
-  // may contain an error message from the speech engine only if |event_type|
-  // is TtsEventType::kError.
+  // Forwards a Tts event received from the remote speech engine to the callback
+  // function of the TtsUtterance. |error_message| may contain an error message
+  // from the speech engine only if |event_type| is TtsEventType::kError.
   OnTtsEvent@0(TtsEventType event_type, uint32 char_index,
              uint32 length, string error_message);
 };
diff --git a/chromeos/profiles/arm.afdo.newest.txt b/chromeos/profiles/arm.afdo.newest.txt
index 66a1a8e..f1be48e9 100644
--- a/chromeos/profiles/arm.afdo.newest.txt
+++ b/chromeos/profiles/arm.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-arm-none-110-5359.24-1668435223-benchmark-110.0.5447.0-r1-redacted.afdo.xz
+chromeos-chrome-arm-none-110-5447.0-1670239482-benchmark-110.0.5460.0-r1-redacted.afdo.xz
diff --git a/components/about_ui/resources/about_credits.css b/components/about_ui/resources/about_credits.css
index b5438dd7..521f2bd4 100644
--- a/components/about_ui/resources/about_credits.css
+++ b/components/about_ui/resources/about_credits.css
@@ -11,7 +11,7 @@
   --google-grey-800: rgb(60, 64, 67);
   --google-grey-900: rgb(32, 33, 36);
 
-  --interactive-color: var(--google-blue-600);
+  --interactive-color: var(--google-blue-900);
   --primary-color: var(--google-grey-900);
 
   --product-background: var(--google-blue-50);
diff --git a/components/autofill/core/browser/browser_autofill_manager.cc b/components/autofill/core/browser/browser_autofill_manager.cc
index c3170fc..87c2217 100644
--- a/components/autofill/core/browser/browser_autofill_manager.cc
+++ b/components/autofill/core/browser/browser_autofill_manager.cc
@@ -948,7 +948,8 @@
       base::BindOnce(
           &BrowserAutofillManager::DeterminePossibleFieldTypesForUpload,
           std::move(copied_profiles), std::move(copied_credit_cards),
-          last_unlocked_credit_card_cvc_, app_locale_, raw_form),
+          last_unlocked_credit_card_cvc_, app_locale_, observed_submission,
+          raw_form),
       std::move(call_after_determine_field_types));
 
   return true;
@@ -2558,11 +2559,31 @@
     const std::vector<CreditCard>& credit_cards,
     const std::u16string& last_unlocked_credit_card_cvc,
     const std::string& app_locale,
-    FormStructure* submitted_form) {
-  // For each field in the |submitted_form|, extract the value.  Then for each
+    bool observed_submission,
+    FormStructure* form) {
+  // Temporary helper structure for measuring the impact of
+  // autofill::features::kAutofillVoteForSelectOptionValues.
+  // TODO(crbug.com/1395740) Remove this once the feature has settled.
+  struct AutofillVoteForSelectOptionValuesMetrics {
+    // Whether kAutofillVoteForSelectOptionValues classified more fields
+    // than the original version of this function w/o
+    // kAutofillVoteForSelectOptionValuesMetrics.
+    bool classified_more_field_types = false;
+    // Whether any field types were detected and assigned to fields for the
+    // current form.
+    bool classified_any_field_types = false;
+    // Whether any field was classified as a country field.
+    bool classified_field_as_country_field = false;
+    // Whether any <select> element was reclassified from a country field
+    // to a phone country code field due to
+    // kAutofillVoteForSelectOptionValuesMetrics.
+    bool switched_from_country_to_phone_country_code = false;
+  } metrics;
+
+  // For each field in the |form|, extract the value.  Then for each
   // profile or credit card, identify any stored types that match the value.
-  for (size_t i = 0; i < submitted_form->field_count(); ++i) {
-    AutofillField* field = submitted_form->field(i);
+  for (size_t i = 0; i < form->field_count(); ++i) {
+    AutofillField* field = form->field(i);
     if (!field->possible_types().empty() && field->IsEmpty()) {
       // This is a password field in a sign-in form. Skip checking its type
       // since |field->value| is not set.
@@ -2597,25 +2618,36 @@
 
     for (const AutofillProfile& profile : profiles) {
       profile.GetMatchingTypes(value, app_locale, &matching_types);
-      if (select_content)
+      if (select_content) {
+        ServerFieldTypeSet matching_types_backup = matching_types;
         profile.GetMatchingTypes(*select_content, app_locale, &matching_types);
+        if (matching_types_backup != matching_types)
+          metrics.classified_more_field_types = true;
+      }
     }
 
     // TODO(crbug/880531) set possible_types_validities for credit card too.
     for (const CreditCard& card : credit_cards) {
       card.GetMatchingTypes(value, app_locale, &matching_types);
-      if (select_content)
+      if (select_content) {
+        ServerFieldTypeSet matching_types_backup = matching_types;
         card.GetMatchingTypes(*select_content, app_locale, &matching_types);
+        if (matching_types_backup != matching_types)
+          metrics.classified_more_field_types = true;
+      }
     }
 
     // In case a select element has options like this
     //  <option value="US">+1</option>,
     // meaning that it contains a phone country code, we treat that as
     // sufficient evidence to only vote for phone country code.
+    if (matching_types.contains(ADDRESS_HOME_COUNTRY))
+      metrics.classified_field_as_country_field = true;
     if (select_content && matching_types.contains(ADDRESS_HOME_COUNTRY) &&
         MatchesRegex<kAugmentedPhoneCountryCodeRe>(*select_content)) {
       matching_types.erase(ADDRESS_HOME_COUNTRY);
       matching_types.insert(PHONE_HOME_COUNTRY_CODE);
+      metrics.switched_from_country_to_phone_country_code = true;
     }
 
     if (IsUPIVirtualPaymentAddress(value))
@@ -2624,6 +2656,9 @@
     if (field->state_is_a_matching_type())
       matching_types.insert(ADDRESS_HOME_STATE);
 
+    if (!matching_types.empty())
+      metrics.classified_any_field_types = true;
+
     if (matching_types.empty()) {
       matching_types.insert(UNKNOWN_TYPE);
       ServerFieldTypeValidityStateMap matching_types_validities;
@@ -2635,8 +2670,8 @@
   }
 
   // As CVCs are not stored, run special heuristics to detect CVC-like values.
-  AutofillField* cvc_field = GetBestPossibleCVCFieldForUpload(
-      *submitted_form, last_unlocked_credit_card_cvc);
+  AutofillField* cvc_field =
+      GetBestPossibleCVCFieldForUpload(*form, last_unlocked_credit_card_cvc);
   if (cvc_field) {
     ServerFieldTypeSet possible_types = cvc_field->possible_types();
     possible_types.erase(UNKNOWN_TYPE);
@@ -2644,7 +2679,32 @@
     cvc_field->set_possible_types(possible_types);
   }
 
-  DisambiguateUploadTypes(submitted_form);
+  if (observed_submission && metrics.classified_any_field_types) {
+    enum class Bucket {
+      kClassifiedAnyField = 0,
+      kClassifiedMoreFields = 1,
+      kClassifiedFieldAsCountryField = 2,
+      kSwitchedFromCountryToPhoneCountryCode = 3,
+      kMaxValue = 3
+    };
+    base::UmaHistogramEnumeration("Autofill.VoteForSelecteOptionValues",
+                                  Bucket::kClassifiedAnyField);
+    if (metrics.classified_more_field_types) {
+      base::UmaHistogramEnumeration("Autofill.VoteForSelecteOptionValues",
+                                    Bucket::kClassifiedMoreFields);
+    }
+    if (metrics.classified_field_as_country_field) {
+      base::UmaHistogramEnumeration("Autofill.VoteForSelecteOptionValues",
+                                    Bucket::kClassifiedFieldAsCountryField);
+    }
+    if (metrics.switched_from_country_to_phone_country_code) {
+      base::UmaHistogramEnumeration(
+          "Autofill.VoteForSelecteOptionValues",
+          Bucket::kSwitchedFromCountryToPhoneCountryCode);
+    }
+  }
+
+  DisambiguateUploadTypes(form);
 }
 
 // static
diff --git a/components/autofill/core/browser/browser_autofill_manager.h b/components/autofill/core/browser/browser_autofill_manager.h
index e2852ea..ef29330 100644
--- a/components/autofill/core/browser/browser_autofill_manager.h
+++ b/components/autofill/core/browser/browser_autofill_manager.h
@@ -335,10 +335,11 @@
       const std::vector<CreditCard>& credit_cards,
       const std::u16string& last_unlocked_credit_card_cvc,
       const std::string& app_locale,
-      FormStructure* submitted_form) {
-    DeterminePossibleFieldTypesForUpload(profiles, credit_cards,
-                                         last_unlocked_credit_card_cvc,
-                                         app_locale, submitted_form);
+      FormStructure* form) {
+    // For tests, the observed_submission is hardcoded to true.
+    DeterminePossibleFieldTypesForUpload(
+        profiles, credit_cards, last_unlocked_credit_card_cvc, app_locale,
+        /*observed_submission=*/true, form);
   }
 
   bool ShouldTriggerRefillForTest(const FormStructure& form_structure) {
@@ -598,7 +599,7 @@
   bool IsFormNonSecure(const FormData& form) const;
 
   // Uses the existing personal data in |profiles| and |credit_cards| to
-  // determine possible field types for the |submitted_form|.  This is
+  // determine possible field types for the |form|.  This is
   // potentially expensive -- on the order of 50ms even for a small set of
   // |stored_data|. Hence, it should not run on the UI thread -- to avoid
   // locking up the UI -- nor on the IO thread -- to avoid blocking IPC calls.
@@ -607,7 +608,8 @@
       const std::vector<CreditCard>& credit_cards,
       const std::u16string& last_unlocked_credit_card_cvc,
       const std::string& app_locale,
-      FormStructure* submitted_form);
+      bool observed_submission,
+      FormStructure* form);
 
   // Uses context about previous and next fields to select the appropriate type
   // for fields with ambiguous upload types.
diff --git a/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc b/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc
index d6d76d70..af0a357 100644
--- a/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc
+++ b/components/autofill/core/browser/metrics/autofill_metrics_unittest.cc
@@ -8506,9 +8506,6 @@
   {
     base::HistogramTester histograms;
     SubmitForm(form);
-    histograms.ExpectBucketCount(
-        "Autofill.FormEvents.CreditCard.OnNonsecurePage",
-        FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1);
     histograms.ExpectBucketCount("Autofill.FormEvents.CreditCard",
                                  FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1);
     histograms.ExpectBucketCount(
@@ -8553,11 +8550,6 @@
                                  FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1);
     histograms.ExpectBucketCount("Autofill.FormEvents.CreditCard",
                                  FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1);
-    // Check that the nonsecure histogram was not recorded. ExpectBucketCount()
-    // can't be used here because it expects the histogram to exist.
-    EXPECT_EQ(
-        0, histograms.GetTotalCountsForPrefix("Autofill.FormEvents.CreditCard")
-               ["Autofill.FormEvents.CreditCard.OnNonsecurePage"]);
   }
 }
 
diff --git a/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.cc b/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.cc
index 74b8e01..529ea0b8 100644
--- a/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.cc
+++ b/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.cc
@@ -293,13 +293,6 @@
 void CreditCardFormEventLogger::OnLog(const std::string& name,
                                       FormEvent event,
                                       const FormStructure& form) const {
-  // Log in a different histogram for credit card forms on nonsecure pages so
-  // that form interactions on nonsecure pages can be analyzed on their own.
-  if (!is_context_secure_) {
-    base::UmaHistogramEnumeration(name + ".OnNonsecurePage", event,
-                                  NUM_FORM_EVENTS);
-  }
-
   // Log a different histogram for credit card forms with credit card offers
   // available so that selection rate with offers and rewards can be compared on
   // their own.
diff --git a/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.h b/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.h
index 2c340815..4ef5de1e 100644
--- a/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.h
+++ b/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.h
@@ -45,10 +45,6 @@
 
   ~CreditCardFormEventLogger() override;
 
-  void set_is_context_secure(bool is_context_secure) {
-    is_context_secure_ = is_context_secure;
-  }
-
   // Invoked when `suggestions` are successfully fetched. `with_offer` indicates
   // whether an offer is attached to any of the suggestion in the list.
   // `metadata_logging_context` contains information about whether any card has
@@ -133,7 +129,6 @@
   // Returns whether the shown suggestions included a virtual credit card.
   bool DoSuggestionsIncludeVirtualCard();
 
-  bool is_context_secure_ = false;
   UnmaskAuthFlowType current_authentication_flow_;
   bool has_logged_masked_server_card_suggestion_selected_ = false;
   bool has_logged_virtual_card_suggestion_selected_ = false;
diff --git a/components/autofill/core/browser/payments/credit_card_access_manager.cc b/components/autofill/core/browser/payments/credit_card_access_manager.cc
index 572b839..93a66575 100644
--- a/components/autofill/core/browser/payments/credit_card_access_manager.cc
+++ b/components/autofill/core/browser/payments/credit_card_access_manager.cc
@@ -81,7 +81,6 @@
   }
   form_event_logger_->set_server_record_type_count(server_record_type_count);
   form_event_logger_->set_local_record_type_count(local_record_type_count);
-  form_event_logger_->set_is_context_secure(client_->IsContextSecure());
 }
 
 bool CreditCardAccessManager::UnmaskedCardCacheIsEmpty() {
diff --git a/components/autofill/core/browser/webdata/autofill_table.cc b/components/autofill/core/browser/webdata/autofill_table.cc
index 8fcb780..ad33b57 100644
--- a/components/autofill/core/browser/webdata/autofill_table.cc
+++ b/components/autofill/core/browser/webdata/autofill_table.cc
@@ -187,6 +187,7 @@
 constexpr base::StringPiece kBankName = "bank_name";
 // kNickname = "nickname"
 constexpr base::StringPiece kCardIssuer = "card_issuer";
+constexpr base::StringPiece kCardIssuerId = "card_issuer_id";
 constexpr base::StringPiece kInstrumentId = "instrument_id";
 constexpr base::StringPiece kVirtualCardEnrollmentState =
     "virtual_card_enrollment_state";
@@ -1220,6 +1221,9 @@
     case 107:
       *update_compatible_version = false;
       return MigrateToVersion107AddContactInfoTables();
+    case 108:
+      *update_compatible_version = false;
+      return MigrateToVersion108AddCardIssuerIdColumn();
   }
   return true;
 }
@@ -2048,8 +2052,8 @@
        base::StrCat({"metadata.", kUseCount}),
        base::StrCat({"metadata.", kUseDate}), kNetwork, kNameOnCard, kExpMonth,
        kExpYear, base::StrCat({"metadata.", kBillingAddressId}), kBankName,
-       kNickname, kCardIssuer, kInstrumentId, kVirtualCardEnrollmentState,
-       kCardArtUrl, kProductDescription},
+       kNickname, kCardIssuer, kCardIssuerId, kInstrumentId,
+       kVirtualCardEnrollmentState, kCardArtUrl, kProductDescription},
       "LEFT OUTER JOIN unmasked_credit_cards USING (id) "
       "LEFT OUTER JOIN server_card_metadata AS metadata USING (id)");
   while (s.Step()) {
@@ -2093,6 +2097,7 @@
     card->SetNickname(s.ColumnString16(index++));
     card->set_card_issuer(
         static_cast<CreditCard::Issuer>(s.ColumnInt(index++)));
+    card->set_issuer_id(s.ColumnString(index++));
     card->set_instrument_id(s.ColumnInt64(index++));
     card->set_virtual_card_enrollment_state(
         static_cast<CreditCard::VirtualCardEnrollmentState>(
@@ -2326,8 +2331,8 @@
   InsertBuilder(
       db_, masked_insert, kMaskedCreditCardsTable,
       {kId, kNetwork, kNameOnCard, kLastFour, kExpMonth, kExpYear, kBankName,
-       kNickname, kCardIssuer, kInstrumentId, kVirtualCardEnrollmentState,
-       kCardArtUrl, kProductDescription});
+       kNickname, kCardIssuer, kCardIssuerId, kInstrumentId,
+       kVirtualCardEnrollmentState, kCardArtUrl, kProductDescription});
 
   int index;
   for (const CreditCard& card : credit_cards) {
@@ -2343,6 +2348,7 @@
     masked_insert.BindString(index++, card.bank_name());
     masked_insert.BindString16(index++, card.nickname());
     masked_insert.BindInt(index++, static_cast<int>(card.card_issuer()));
+    masked_insert.BindString(index++, card.issuer_id());
     masked_insert.BindInt64(index++, card.instrument_id());
     masked_insert.BindInt(
         index++, static_cast<int>(card.virtual_card_enrollment_state()));
@@ -3259,6 +3265,24 @@
          transaction.Commit();
 }
 
+bool AutofillTable::MigrateToVersion108AddCardIssuerIdColumn() {
+  sql::Transaction transaction(db_);
+
+  if (!transaction.Begin())
+    return false;
+
+  if (!db_->DoesTableExist(kMaskedCreditCardsTable))
+    return false;
+
+  // Add card_issuer_id to masked_credit_cards.
+  if (!AddColumnIfNotExists(db_, kMaskedCreditCardsTable, kCardIssuerId,
+                            "VARCHAR")) {
+    return false;
+  }
+
+  return transaction.Commit();
+}
+
 bool AutofillTable::AddFormFieldValuesTime(
     const std::vector<FormFieldData>& elements,
     std::vector<AutofillChange>* changes,
@@ -3408,8 +3432,8 @@
   InsertBuilder(
       db_, masked_insert, kMaskedCreditCardsTable,
       {kId, kNetwork, kNameOnCard, kLastFour, kExpMonth, kExpYear, kBankName,
-       kNickname, kCardIssuer, kInstrumentId, kVirtualCardEnrollmentState,
-       kCardArtUrl, kProductDescription});
+       kNickname, kCardIssuer, kCardIssuerId, kInstrumentId,
+       kVirtualCardEnrollmentState, kCardArtUrl, kProductDescription});
 
   int index;
   for (const CreditCard& card : credit_cards) {
@@ -3425,6 +3449,7 @@
     masked_insert.BindString(index++, card.bank_name());
     masked_insert.BindString16(index++, card.nickname());
     masked_insert.BindInt(index++, static_cast<int>(card.card_issuer()));
+    masked_insert.BindString(index++, card.issuer_id());
     masked_insert.BindInt64(index++, card.instrument_id());
     masked_insert.BindInt(index++, card.virtual_card_enrollment_state());
     masked_insert.BindString(index++, card.card_art_url().spec());
@@ -3618,7 +3643,8 @@
        {kInstrumentId, "INTEGER DEFAULT 0"},
        {kVirtualCardEnrollmentState, "INTEGER DEFAULT 0"},
        {kCardArtUrl, "VARCHAR"},
-       {kProductDescription, "VARCHAR"}});
+       {kProductDescription, "VARCHAR"},
+       {kCardIssuerId, "VARCHAR"}});
 }
 
 bool AutofillTable::InitUnmaskedCreditCardsTable() {
diff --git a/components/autofill/core/browser/webdata/autofill_table.h b/components/autofill/core/browser/webdata/autofill_table.h
index e694c388..61dda7b 100644
--- a/components/autofill/core/browser/webdata/autofill_table.h
+++ b/components/autofill/core/browser/webdata/autofill_table.h
@@ -281,6 +281,7 @@
 //   product_description
 //                      The product description for the card. Used to be shown
 //                      in the UI when card is presented. Added in version 102.
+//   card_issuer_id     The id of the card's issuer.
 //
 // unmasked_credit_cards
 //                      When a masked credit credit card is unmasked and the
@@ -786,6 +787,7 @@
   bool MigrateToVersion105AddAutofillIBANTable();
   bool MigrateToVersion106RecreateAutofillIBANTable();
   bool MigrateToVersion107AddContactInfoTables();
+  bool MigrateToVersion108AddCardIssuerIdColumn();
 
   // Max data length saved in the table, AKA the maximum length allowed for
   // form data.
diff --git a/components/autofill/core/browser/webdata/autofill_table_unittest.cc b/components/autofill/core/browser/webdata/autofill_table_unittest.cc
index 1b71c02..65f6dc1 100644
--- a/components/autofill/core/browser/webdata/autofill_table_unittest.cc
+++ b/components/autofill/core/browser/webdata/autofill_table_unittest.cc
@@ -1901,6 +1901,7 @@
   inputs[0].SetRawInfo(CREDIT_CARD_EXP_MONTH, u"1");
   inputs[0].SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, u"2020");
   inputs[0].SetRawInfo(CREDIT_CARD_NUMBER, u"4111111111111111");
+  inputs[0].set_card_issuer(CreditCard::Issuer::GOOGLE);
   inputs[0].set_instrument_id(321);
   inputs[0].set_virtual_card_enrollment_state(
       CreditCard::VirtualCardEnrollmentState::UNENROLLED);
@@ -1914,7 +1915,8 @@
   inputs[1].SetNetworkForMaskedCard(kVisaCard);
   std::u16string nickname = u"Grocery card";
   inputs[1].SetNickname(nickname);
-  inputs[1].set_card_issuer(CreditCard::Issuer::GOOGLE);
+  inputs[1].set_card_issuer(CreditCard::Issuer::EXTERNAL_ISSUER);
+  inputs[1].set_issuer_id("amex");
   inputs[1].set_instrument_id(123);
   inputs[1].set_virtual_card_enrollment_state(
       CreditCard::VirtualCardEnrollmentState::ENROLLED);
@@ -1944,8 +1946,10 @@
   EXPECT_TRUE(outputs[0]->nickname().empty());
   EXPECT_EQ(nickname, outputs[1]->nickname());
 
-  EXPECT_EQ(CreditCard::Issuer::ISSUER_UNKNOWN, outputs[0]->card_issuer());
-  EXPECT_EQ(CreditCard::Issuer::GOOGLE, outputs[1]->card_issuer());
+  EXPECT_EQ(CreditCard::Issuer::GOOGLE, outputs[0]->card_issuer());
+  EXPECT_EQ(CreditCard::Issuer::EXTERNAL_ISSUER, outputs[1]->card_issuer());
+  EXPECT_EQ("", outputs[0]->issuer_id());
+  EXPECT_EQ("amex", outputs[1]->issuer_id());
 
   EXPECT_EQ(321, outputs[0]->instrument_id());
   EXPECT_EQ(123, outputs[1]->instrument_id());
@@ -2167,6 +2171,8 @@
   inputs[0].SetRawInfo(CREDIT_CARD_NUMBER, u"1111");
   inputs[0].SetNetworkForMaskedCard(kVisaCard);
   inputs[0].SetNickname(u"Grocery card");
+  inputs[0].set_card_issuer(CreditCard::Issuer::EXTERNAL_ISSUER);
+  inputs[0].set_issuer_id("amex");
   inputs[0].set_instrument_id(1);
   inputs[0].set_virtual_card_enrollment_state(
       CreditCard::VirtualCardEnrollmentState::ENROLLED);
@@ -2191,6 +2197,9 @@
   EXPECT_EQ(CreditCard::VirtualCardEnrollmentState::ENROLLED,
             outputs[0]->virtual_card_enrollment_state());
 
+  EXPECT_EQ(CreditCard::Issuer::EXTERNAL_ISSUER, outputs[0]->card_issuer());
+  EXPECT_EQ("amex", outputs[0]->issuer_id());
+
   EXPECT_EQ(GURL("https://www.example.com"), outputs[0]->card_art_url());
   EXPECT_EQ(u"Fake description", outputs[0]->product_description());
 
@@ -2207,6 +2216,8 @@
   ASSERT_TRUE(table_->GetServerCreditCards(&outputs));
   ASSERT_EQ(1U, outputs.size());
   EXPECT_EQ("card2", outputs[0]->server_id());
+  EXPECT_EQ(CreditCard::Issuer::ISSUER_UNKNOWN, outputs[0]->card_issuer());
+  EXPECT_EQ("", outputs[0]->issuer_id());
 
   // Make sure no metadata was added.
   ASSERT_TRUE(table_->GetServerCardsMetadata(&metadata_map));
diff --git a/components/bookmarks/browser/bookmark_pasteboard_helper_mac.mm b/components/bookmarks/browser/bookmark_pasteboard_helper_mac.mm
index b7acca6..69d17d8 100644
--- a/components/bookmarks/browser/bookmark_pasteboard_helper_mac.mm
+++ b/components/bookmarks/browser/bookmark_pasteboard_helper_mac.mm
@@ -127,12 +127,12 @@
   }
 }
 
-bool ReadBookmarkDictionaryListType(
-    NSPasteboard* pb,
-    std::vector<BookmarkNodeData::Element>* elements) {
+bool ReadChromiumBookmarks(NSPasteboard* pb,
+                           std::vector<BookmarkNodeData::Element>* elements) {
   id bookmarks = [pb propertyListForType:kUTTypeChromiumBookmarkDictionaryList];
   if (!bookmarks)
     return false;
+
   NSArray* bookmarks_array = base::mac::ObjCCast<NSArray>(bookmarks);
   if (!bookmarks_array)
     return false;
@@ -141,9 +141,8 @@
   return true;
 }
 
-bool ReadWebURLsWithTitlesPboardType(
-    NSPasteboard* pb,
-    std::vector<BookmarkNodeData::Element>* elements) {
+bool ReadStandardBookmarks(NSPasteboard* pb,
+                           std::vector<BookmarkNodeData::Element>* elements) {
   NSArray* urls = nil;
   NSArray* titles = nil;
   if (!ui::ClipboardUtil::URLsAndTitlesFromPasteboard(pb, &urls, &titles))
@@ -198,72 +197,43 @@
   return array;
 }
 
-void WriteBookmarkDictionaryListType(
-    NSPasteboardItem* item,
-    const std::vector<BookmarkNodeData::Element>& elements) {
-  NSArray* array = GetNSArrayForBookmarkList(elements);
-  [item setPropertyList:array forType:kUTTypeChromiumBookmarkDictionaryList];
-}
-
-void FillFlattenedArraysForBookmarks(
+void CollectUrlsAndTitlesOfBookmarks(
     const std::vector<BookmarkNodeData::Element>& elements,
     NSMutableArray* url_titles,
-    NSMutableArray* urls,
-    NSMutableArray* toplevel_string_data) {
+    NSMutableArray* urls) {
   for (const auto& element : elements) {
     NSString* title = base::SysUTF16ToNSString(element.title);
     if (element.is_url) {
       NSString* url = base::SysUTF8ToNSString(element.url.spec());
       [url_titles addObject:title];
       [urls addObject:url];
-      if (toplevel_string_data)
-        [toplevel_string_data addObject:url];
     } else {
-      if (toplevel_string_data)
-        [toplevel_string_data addObject:title];
-      FillFlattenedArraysForBookmarks(element.children, url_titles, urls, nil);
+      CollectUrlsAndTitlesOfBookmarks(element.children, url_titles, urls);
     }
   }
 }
 
-base::scoped_nsobject<NSPasteboardItem> WriteSimplifiedBookmarkTypes(
-    const std::vector<BookmarkNodeData::Element>& elements) {
-  NSMutableArray* url_titles = [NSMutableArray array];
-  NSMutableArray* urls = [NSMutableArray array];
-  NSMutableArray* toplevel_string_data = [NSMutableArray array];
-  FillFlattenedArraysForBookmarks(
-      elements, url_titles, urls, toplevel_string_data);
-
-  base::scoped_nsobject<NSPasteboardItem> item;
-  if ([urls count] > 0) {
-    if ([urls count] == 1) {
-      item = ui::ClipboardUtil::PasteboardItemFromUrl([urls firstObject],
-                                                      [url_titles firstObject]);
-    } else {
-      item = ui::ClipboardUtil::PasteboardItemFromUrls(urls, url_titles);
-    }
-  }
-
-  if (!item) {
-    item.reset([[NSPasteboardItem alloc] init]);
-  }
-
-  [item setString:[toplevel_string_data componentsJoinedByString:@"\n"]
-          forType:base::mac::CFToNSCast(kUTTypeUTF8PlainText)];
-  return item;
-}
-
-NSPasteboardItem* PasteboardItemFromBookmarks(
+// Generates a list of pasteboard items representing bookmarks. Note that the
+// special items are included only on the first of the items.
+NSArray<NSPasteboardItem*>* PasteboardItemsFromBookmarks(
     const std::vector<BookmarkNodeData::Element>& elements,
     const base::FilePath& profile_path) {
-  base::scoped_nsobject<NSPasteboardItem> item =
-      WriteSimplifiedBookmarkTypes(elements);
+  NSMutableArray* url_titles = [NSMutableArray array];
+  NSMutableArray* urls = [NSMutableArray array];
+  CollectUrlsAndTitlesOfBookmarks(elements, url_titles, urls);
 
-  WriteBookmarkDictionaryListType(item, elements);
+  NSArray<NSPasteboardItem*>* items =
+      ui::ClipboardUtil::PasteboardItemsFromUrls(urls, url_titles);
 
-  [item setString:base::SysUTF8ToNSString(profile_path.value())
-          forType:kUTTypeChromiumProfilePath];
-  return item.autorelease();
+  if (items.count) {
+    [items[0] setPropertyList:GetNSArrayForBookmarkList(elements)
+                      forType:kUTTypeChromiumBookmarkDictionaryList];
+
+    [items[0] setString:base::SysUTF8ToNSString(profile_path.value())
+                forType:kUTTypeChromiumProfilePath];
+  }
+
+  return items;
 }
 
 }  // namespace
@@ -272,12 +242,14 @@
     NSPasteboard* pb,
     const std::vector<BookmarkNodeData::Element>& elements,
     const base::FilePath& profile_path) {
-  if (elements.empty())
+  if (elements.empty()) {
     return;
+  }
 
-  NSPasteboardItem* item = PasteboardItemFromBookmarks(elements, profile_path);
+  NSArray<NSPasteboardItem*>* items =
+      PasteboardItemsFromBookmarks(elements, profile_path);
   [pb clearContents];
-  [pb writeObjects:@[ item ]];
+  [pb writeObjects:items];
 }
 
 bool ReadBookmarksFromPasteboard(
@@ -287,13 +259,15 @@
   elements->clear();
   NSString* profile = [pb stringForType:kUTTypeChromiumProfilePath];
   *profile_path = base::FilePath(base::SysNSStringToUTF8(profile));
-  return ReadBookmarkDictionaryListType(pb, elements) ||
-         ReadWebURLsWithTitlesPboardType(pb, elements);
+  return ReadChromiumBookmarks(pb, elements) ||
+         ReadStandardBookmarks(pb, elements);
 }
 
 bool PasteboardContainsBookmarks(NSPasteboard* pb) {
   NSArray* availableTypes = @[
-    ui::kUTTypeWebKitWebURLsWithTitles, kUTTypeChromiumBookmarkDictionaryList
+    ui::kUTTypeWebKitWebURLsWithTitles,
+    kUTTypeChromiumBookmarkDictionaryList,
+    NSPasteboardTypeURL,
   ];
   return [pb availableTypeFromArray:availableTypes] != nil;
 }
diff --git a/components/desks_storage/core/desk_sync_bridge_unittest.cc b/components/desks_storage/core/desk_sync_bridge_unittest.cc
index 0ffd07d..78c1caf3 100644
--- a/components/desks_storage/core/desk_sync_bridge_unittest.cc
+++ b/components/desks_storage/core/desk_sync_bridge_unittest.cc
@@ -22,6 +22,7 @@
 #include "base/test/bind.h"
 #include "base/test/simple_test_clock.h"
 #include "base/test/task_environment.h"
+#include "base/types/strong_alias.h"
 #include "components/account_id/account_id.h"
 #include "components/app_constants/constants.h"
 #include "components/app_restore/app_launch_info.h"
diff --git a/components/device_event_log/device_event_log.h b/components/device_event_log/device_event_log.h
index b3bd017e..a4a5723 100644
--- a/components/device_event_log/device_event_log.h
+++ b/components/device_event_log/device_event_log.h
@@ -73,6 +73,9 @@
 #define CAMERA_LOG(level)                         \
   DEVICE_LOG(::device_event_log::LOG_TYPE_CAMERA, \
              ::device_event_log::LOG_LEVEL_##level)
+#define GEOLOCATION_LOG(level)                         \
+  DEVICE_LOG(::device_event_log::LOG_TYPE_GEOLOCATION, \
+             ::device_event_log::LOG_LEVEL_##level)
 
 #if BUILDFLAG(IS_ANDROID) && defined(OFFICIAL_BUILD)
 // FIDO_LOG is discarded for release Android builds in order to reduce binary
@@ -133,8 +136,10 @@
   LOG_TYPE_SERIAL = 9,
   // Camera related events.
   LOG_TYPE_CAMERA = 10,
+  // Geolocation related events (i.e. services/device/geolocation).
+  LOG_TYPE_GEOLOCATION = 11,
   // Used internally, must be the last type (may be changed).
-  LOG_TYPE_UNKNOWN = 11
+  LOG_TYPE_UNKNOWN = 12
 };
 
 // Used to specify the detail level for logging. In GetAsString, used to
diff --git a/components/device_event_log/device_event_log_impl.cc b/components/device_event_log/device_event_log_impl.cc
index 12fd5b7..c1a5bddc 100644
--- a/components/device_event_log/device_event_log_impl.cc
+++ b/components/device_event_log/device_event_log_impl.cc
@@ -40,6 +40,7 @@
 const char kLogTypeFidoDesc[] = "FIDO";
 const char kLogTypeSerialDesc[] = "Serial";
 const char kLogTypeCameraDesc[] = "Camera";
+const char kLogTypeGeolocationDesc[] = "Geolocation";
 
 enum class ShowTime {
   kNone,
@@ -71,6 +72,8 @@
       return kLogTypeSerialDesc;
     case LOG_TYPE_CAMERA:
       return kLogTypeCameraDesc;
+    case LOG_TYPE_GEOLOCATION:
+      return kLogTypeGeolocationDesc;
     case LOG_TYPE_UNKNOWN:
       break;
   }
diff --git a/components/error_page/common/net_error_info.h b/components/error_page/common/net_error_info.h
index 3170946ab..db8c75e 100644
--- a/components/error_page/common/net_error_info.h
+++ b/components/error_page/common/net_error_info.h
@@ -75,6 +75,9 @@
   // page).
   NETWORK_ERROR_PAGE_OFFLINE_ERROR_SHOWN = 29,
 
+  // "Sign in to network" button clicked.
+  NETWORK_ERROR_PORTAL_SIGNIN_BUTTON_CLICKED = 30,
+
   NETWORK_ERROR_PAGE_EVENT_MAX,
 };
 
diff --git a/components/exo/wayland/zaura_shell.cc b/components/exo/wayland/zaura_shell.cc
index 478920d8..2dab565 100644
--- a/components/exo/wayland/zaura_shell.cc
+++ b/components/exo/wayland/zaura_shell.cc
@@ -51,11 +51,10 @@
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/manager/display_manager_util.h"
 #include "ui/display/screen.h"
-#include "ui/views/corewm/tooltip.h"
-#include "ui/views/corewm/tooltip_controller.h"
 #include "ui/views/widget/widget.h"
 #include "ui/wm/core/coordinate_conversion.h"
 #include "ui/wm/public/activation_client.h"
+#include "ui/wm/public/tooltip_client.h"
 
 namespace exo {
 namespace wayland {
@@ -122,18 +121,6 @@
   return ZAURA_SURFACE_OCCLUSION_STATE_UNKNOWN;
 }
 
-views::corewm::TooltipTrigger TooltipTrigger(uint32_t tooltip_trigger) {
-  switch (tooltip_trigger) {
-    case ZAURA_SURFACE_TOOLTIP_TRIGGER_CURSOR:
-      return views::corewm::TooltipTrigger::kCursor;
-    case ZAURA_SURFACE_TOOLTIP_TRIGGER_KEYBOARD:
-      return views::corewm::TooltipTrigger::kKeyboard;
-    default:
-      VLOG(2) << "Unknown aura-shell tooltip trigger: " << tooltip_trigger;
-      return views::corewm::TooltipTrigger::kCursor;
-  }
-}
-
 void aura_surface_set_frame(wl_client* client,
                             wl_resource* resource,
                             uint32_t type) {
@@ -690,14 +677,10 @@
   tooltip_text_ = base::UTF8ToUTF16(text);
   wm::SetTooltipText(surface_->window(), &tooltip_text_);
   wm::SetTooltipId(surface_->window(), surface_);
-  ash::Shell::Get()->tooltip_controller()->UpdateAndShow(
-      surface_->window(), tooltip_text_, position, TooltipTrigger(trigger),
-      show_delay, hide_delay);
 }
 
 void AuraSurface::HideTooltip() {
   tooltip_text_ = std::u16string();
-  ash::Shell::Get()->tooltip_controller()->HideAndReset();
 }
 
 chromeos::OrientationType OrientationLock(uint32_t orientation_lock) {
diff --git a/components/global_media_controls/public/views/media_item_ui_list_view.cc b/components/global_media_controls/public/views/media_item_ui_list_view.cc
index 8babf7d3..d76a5e3 100644
--- a/components/global_media_controls/public/views/media_item_ui_list_view.cc
+++ b/components/global_media_controls/public/views/media_item_ui_list_view.cc
@@ -74,6 +74,7 @@
     }
   }
 
+  item->SetScrollView(this);
   items_[id] = contents()->AddChildView(std::move(item));
 
   contents()->InvalidateLayout();
diff --git a/components/global_media_controls/public/views/media_item_ui_view.cc b/components/global_media_controls/public/views/media_item_ui_view.cc
index 1e6bab5..9b2980d8 100644
--- a/components/global_media_controls/public/views/media_item_ui_view.cc
+++ b/components/global_media_controls/public/views/media_item_ui_view.cc
@@ -31,6 +31,7 @@
 #include "ui/views/controls/button/image_button_factory.h"
 #include "ui/views/controls/highlight_path_generator.h"
 #include "ui/views/controls/image_view.h"
+#include "ui/views/controls/scroll_view.h"
 #include "ui/views/layout/box_layout.h"
 #include "ui/views/layout/fill_layout.h"
 
@@ -185,6 +186,11 @@
   UpdateDismissButtonVisibility();
 }
 
+void MediaItemUIView::OnGestureEvent(ui::GestureEvent* event) {
+  if (scroll_view_ && event->IsScrollGestureEvent())
+    scroll_view_->OnGestureEvent(event);
+}
+
 void MediaItemUIView::OnDidChangeFocus(views::View* focused_before,
                                        views::View* focused_now) {
   UpdateDismissButtonVisibility();
@@ -278,6 +284,22 @@
   return swipeable_container_->layer();
 }
 
+void MediaItemUIView::OnSlideChanged(bool in_progress) {
+  // Make sure we are only scrolling in one dimension.
+  if (scroll_view_ && in_progress && !is_sliding_ &&
+      slide_out_controller_->GetGestureAmount()) {
+    is_sliding_ = true;
+    scroll_view_->SetVerticalScrollBarMode(
+        views::ScrollView::ScrollBarMode::kDisabled);
+  }
+
+  if (!in_progress && scroll_view_ && is_sliding_) {
+    is_sliding_ = false;
+    scroll_view_->SetVerticalScrollBarMode(
+        views::ScrollView::ScrollBarMode::kEnabled);
+  }
+}
+
 void MediaItemUIView::OnSlideOut() {
   DismissNotification();
 }
@@ -296,6 +318,10 @@
   return title_;
 }
 
+void MediaItemUIView::SetScrollView(views::ScrollView* scroll_view) {
+  scroll_view_ = scroll_view;
+}
+
 views::ImageButton* MediaItemUIView::GetDismissButtonForTesting() {
   return dismiss_button_;
 }
diff --git a/components/global_media_controls/public/views/media_item_ui_view.h b/components/global_media_controls/public/views/media_item_ui_view.h
index 840375e..ea54614 100644
--- a/components/global_media_controls/public/views/media_item_ui_view.h
+++ b/components/global_media_controls/public/views/media_item_ui_view.h
@@ -64,6 +64,9 @@
   void OnMouseEntered(const ui::MouseEvent& event) override;
   void OnMouseExited(const ui::MouseEvent& event) override;
 
+  // views::View:
+  void OnGestureEvent(ui::GestureEvent* event) override;
+
   // views::FocusChangeListener:
   void OnWillChangeFocus(views::View* focused_before,
                          views::View* focused_now) override {}
@@ -88,7 +91,7 @@
   // views::SlideOutControllerDelegate:
   ui::Layer* GetSlideOutLayer() override;
   void OnSlideStarted() override {}
-  void OnSlideChanged(bool in_progress) override {}
+  void OnSlideChanged(bool in_progress) override;
   void OnSlideOut() override;
 
   // global_media_controls::MediaItemUI:
@@ -101,6 +104,9 @@
 
   const std::u16string& GetTitle() const;
 
+  // Set the scroll view that is currently holding this item.
+  void SetScrollView(views::ScrollView* scroll_view);
+
   views::ImageButton* GetDismissButtonForTesting();
 
   media_message_center::MediaNotificationViewImpl* view_for_testing() {
@@ -111,6 +117,9 @@
     return device_selector_view_;
   }
   MediaItemUIFooter* footer_view_for_testing() { return footer_view_; }
+  views::SlideOutController* slide_out_controller_for_testing() {
+    return slide_out_controller_.get();
+  }
 
   bool is_playing_for_testing() { return is_playing_; }
   bool is_expanded_for_testing() { return is_expanded_; }
@@ -133,6 +142,9 @@
 
   std::u16string title_;
 
+  // The scroll view that is currently holding this item.
+  raw_ptr<views::ScrollView> scroll_view_ = nullptr;
+
   // Always "visible" so that it reserves space in the header so that the
   // dismiss button can appear without forcing things to shift.
   raw_ptr<views::View> dismiss_button_placeholder_ = nullptr;
@@ -160,6 +172,8 @@
 
   bool is_expanded_ = false;
 
+  bool is_sliding_ = false;
+
   base::ObserverList<global_media_controls::MediaItemUIObserver> observers_;
 
   // Handles gesture events for swiping to dismiss notifications.
diff --git a/components/global_media_controls/public/views/media_item_ui_view_unittest.cc b/components/global_media_controls/public/views/media_item_ui_view_unittest.cc
index bfc5515..97c57fc4 100644
--- a/components/global_media_controls/public/views/media_item_ui_view_unittest.cc
+++ b/components/global_media_controls/public/views/media_item_ui_view_unittest.cc
@@ -20,7 +20,10 @@
 #include "ui/display/test/scoped_screen_override.h"
 #include "ui/display/test/test_screen.h"
 #include "ui/events/base_event_utils.h"
+#include "ui/events/gesture_event_details.h"
 #include "ui/events/test/event_generator.h"
+#include "ui/views/animation/slide_out_controller.h"
+#include "ui/views/controls/scroll_view.h"
 #include "ui/views/test/button_test_api.h"
 #include "ui/views/test/view_metadata_test_utils.h"
 #include "ui/views/test/views_test_base.h"
@@ -352,6 +355,37 @@
   SimulateHeaderClicked();
 }
 
+TEST_F(MediaItemUIViewTest, GestureScrollDisabledWhenSlidingOut) {
+  auto* scroll_view = new views::ScrollView();
+  item_ui()->SetScrollView(scroll_view);
+
+  // Vertical scroll bar should be enabled initially.
+  EXPECT_EQ(scroll_view->GetVerticalScrollBarMode(),
+            views::ScrollView::ScrollBarMode::kEnabled);
+
+  // Send a gesture scroll update event with some horizontal value.
+  gfx::Point point;
+  ui::GestureEvent gesture_scroll_update(
+      point.x(), point.y(), 0, ui::EventTimeForNow(),
+      ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_UPDATE, /*delta_x=*/1.0,
+                              /*delta_y=*/0.0));
+  item_ui()->slide_out_controller_for_testing()->OnGestureEvent(
+      &gesture_scroll_update);
+
+  // Vertical scroll bar should be disabled because of the sliding.
+  EXPECT_EQ(scroll_view->GetVerticalScrollBarMode(),
+            views::ScrollView::ScrollBarMode::kDisabled);
+
+  // Slide ending should re-enabled the vertical scroll bar.
+  ui::GestureEvent gesture_scroll_end(
+      point.x(), point.y(), 0, ui::EventTimeForNow(),
+      ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_END));
+  item_ui()->slide_out_controller_for_testing()->OnGestureEvent(
+      &gesture_scroll_end);
+  EXPECT_EQ(scroll_view->GetVerticalScrollBarMode(),
+            views::ScrollView::ScrollBarMode::kEnabled);
+}
+
 TEST_F(MediaItemUIViewTest, MetadataTest) {
   auto container_view = std::make_unique<MediaItemUIView>(
       kOtherTestNotificationId, notification_item(), nullptr, nullptr);
diff --git a/components/history/DEPS b/components/history/DEPS
index 2f786696..a5ebf47d1 100644
--- a/components/history/DEPS
+++ b/components/history/DEPS
@@ -4,6 +4,7 @@
   "+components/query_parser",
   "+components/prefs",
   "+components/sync",
+  "+components/version_info/channel.h",
   "+google_apis/gaia",
   "+net",
   "+services/network/public/cpp",
diff --git a/components/history/content/browser/BUILD.gn b/components/history/content/browser/BUILD.gn
index b7380db..38c6c9d 100644
--- a/components/history/content/browser/BUILD.gn
+++ b/components/history/content/browser/BUILD.gn
@@ -20,6 +20,7 @@
     "//base",
     "//components/download/public/common:public",
     "//components/history/core/browser",
+    "//components/version_info",
     "//components/visitedlink/browser",
     "//content/public/browser",
     "//url:url",
diff --git a/components/history/content/browser/history_database_helper.cc b/components/history/content/browser/history_database_helper.cc
index 18160bb2..3fdf603 100644
--- a/components/history/content/browser/history_database_helper.cc
+++ b/components/history/content/browser/history_database_helper.cc
@@ -8,16 +8,19 @@
 #include "components/download/public/common/download_interrupt_reasons.h"
 #include "components/history/content/browser/download_conversions.h"
 #include "components/history/core/browser/history_database_params.h"
+#include "components/version_info/channel.h"
 
 namespace history {
 
 HistoryDatabaseParams HistoryDatabaseParamsForPath(
-    const base::FilePath& history_dir) {
+    const base::FilePath& history_dir,
+    version_info::Channel channel) {
   return HistoryDatabaseParams(history_dir,
                                history::ToHistoryDownloadInterruptReason(
                                    download::DOWNLOAD_INTERRUPT_REASON_NONE),
                                history::ToHistoryDownloadInterruptReason(
-                                   download::DOWNLOAD_INTERRUPT_REASON_CRASH));
+                                   download::DOWNLOAD_INTERRUPT_REASON_CRASH),
+                               channel);
 }
 
 }  // namespace
diff --git a/components/history/content/browser/history_database_helper.h b/components/history/content/browser/history_database_helper.h
index d346b2c..3d69b77 100644
--- a/components/history/content/browser/history_database_helper.h
+++ b/components/history/content/browser/history_database_helper.h
@@ -5,6 +5,8 @@
 #ifndef COMPONENTS_HISTORY_CONTENT_BROWSER_HISTORY_DATABASE_HELPER_H_
 #define COMPONENTS_HISTORY_CONTENT_BROWSER_HISTORY_DATABASE_HELPER_H_
 
+#include "components/version_info/channel.h"
+
 namespace base {
 class FilePath;
 }
@@ -15,7 +17,8 @@
 
 // Returns a HistoryDatabaseParams for `history_dir`.
 HistoryDatabaseParams HistoryDatabaseParamsForPath(
-    const base::FilePath& history_dir);
+    const base::FilePath& history_dir,
+    version_info::Channel channel);
 
 }  // namespace history
 
diff --git a/components/history/core/browser/history_backend.cc b/components/history/core/browser/history_backend.cc
index a3074301..0e4147c 100644
--- a/components/history/core/browser/history_backend.cc
+++ b/components/history/core/browser/history_backend.cc
@@ -239,6 +239,27 @@
   void DoneRunOnMainThread() override {}
 };
 
+// Does base::debug::DumpWithoutCrashing(), but on Canary/Dev only, and at a
+// throttled rate. This is because our dump volume is high, and that can mask
+// OTHER crashes. This is similar to ReportUnrecoverableError() in Sync code.
+// https://crbug.com/1377512
+void SelectiveDumpWithoutCrashing(version_info::Channel channel) {
+  if (channel != version_info::Channel::CANARY &&
+      channel != version_info::Channel::DEV) {
+    return;
+  }
+
+  // We only want to upload |kErrorUploadRatio| ratio of errors.
+  const double kErrorUploadRatio = 0.1;
+  if (kErrorUploadRatio <= 0.0)
+    return;  // We are not allowed to upload errors.
+  double random_number = base::RandDouble();
+  if (random_number > kErrorUploadRatio)
+    return;
+
+  base::debug::DumpWithoutCrashing();
+}
+
 }  // namespace
 
 std::u16string FormatUrlForRedirectComparison(const GURL& url) {
@@ -1057,6 +1078,7 @@
 
   // Compute the file names.
   history_dir_ = history_database_params.history_dir;
+  channel_ = history_database_params.channel;
 
 #if DCHECK_IS_ON()
   DCHECK(!HistoryPathsTracker::GetInstance()->HasPath(history_dir_))
@@ -2898,7 +2920,7 @@
 
     // TODO(crbug.com/1321483): Remove DumpWithoutCrashing after fixing
     // transaction related bugs in History.
-    base::debug::DumpWithoutCrashing();
+    SelectiveDumpWithoutCrashing(channel_);
   }
 }
 
@@ -2936,7 +2958,7 @@
     error_message_key.Set(diagnostics_.error_message);
     // TODO(crbug.com/1321483): Remove DumpWithoutCrashing after fixing
     // transaction related bugs in History.
-    base::debug::DumpWithoutCrashing();
+    SelectiveDumpWithoutCrashing(channel_);
   }
   singleton_transaction_.reset();
 }
diff --git a/components/history/core/browser/history_backend.h b/components/history/core/browser/history_backend.h
index 6d3891fa..726def5 100644
--- a/components/history/core/browser/history_backend.h
+++ b/components/history/core/browser/history_backend.h
@@ -37,6 +37,7 @@
 #include "components/history/core/browser/sync/history_backend_for_sync.h"
 #include "components/history/core/browser/visit_tracker.h"
 #include "components/sync/driver/sync_service.h"
+#include "components/version_info/channel.h"
 #include "sql/init_status.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/origin.h"
@@ -950,6 +951,9 @@
   // Directory where database files will be stored, empty until Init is called.
   base::FilePath history_dir_;
 
+  // Used to control error reporting.
+  version_info::Channel channel_ = version_info::Channel::UNKNOWN;
+
   // The history/favicon databases. Either may be null if the database could
   // not be opened, all users must first check for null and return immediately
   // if it is. The favicon DB may be null when the history one isn't, but not
diff --git a/components/history/core/browser/history_database_params.cc b/components/history/core/browser/history_database_params.cc
index baf9b01c2..eac84bb 100644
--- a/components/history/core/browser/history_database_params.cc
+++ b/components/history/core/browser/history_database_params.cc
@@ -3,20 +3,24 @@
 // found in the LICENSE file.
 
 #include "components/history/core/browser/history_database_params.h"
+#include "components/version_info/channel.h"
 
 namespace history {
 
 HistoryDatabaseParams::HistoryDatabaseParams()
-    : download_interrupt_reason_none(0), download_interrupt_reason_crash(0) {}
+    : download_interrupt_reason_none(0),
+      download_interrupt_reason_crash(0),
+      channel(version_info::Channel::UNKNOWN) {}
 
 HistoryDatabaseParams::HistoryDatabaseParams(
     const base::FilePath& history_dir,
     DownloadInterruptReason download_interrupt_reason_none,
-    DownloadInterruptReason download_interrupt_reason_crash)
+    DownloadInterruptReason download_interrupt_reason_crash,
+    version_info::Channel channel)
     : history_dir(history_dir),
       download_interrupt_reason_none(download_interrupt_reason_none),
-      download_interrupt_reason_crash(download_interrupt_reason_crash) {
-}
+      download_interrupt_reason_crash(download_interrupt_reason_crash),
+      channel(channel) {}
 
 HistoryDatabaseParams::~HistoryDatabaseParams() {
 }
diff --git a/components/history/core/browser/history_database_params.h b/components/history/core/browser/history_database_params.h
index bb59731..7b2ee484 100644
--- a/components/history/core/browser/history_database_params.h
+++ b/components/history/core/browser/history_database_params.h
@@ -7,6 +7,7 @@
 
 #include "base/files/file_path.h"
 #include "components/history/core/browser/download_types.h"
+#include "components/version_info/channel.h"
 
 namespace history {
 
@@ -15,15 +16,16 @@
 // and HistoryBackend.
 struct HistoryDatabaseParams {
   HistoryDatabaseParams();
-  HistoryDatabaseParams(
-      const base::FilePath& history_dir,
-      DownloadInterruptReason download_interrupt_reason_none,
-      DownloadInterruptReason download_interrupt_reason_crash);
+  HistoryDatabaseParams(const base::FilePath& history_dir,
+                        DownloadInterruptReason download_interrupt_reason_none,
+                        DownloadInterruptReason download_interrupt_reason_crash,
+                        version_info::Channel channel);
   ~HistoryDatabaseParams();
 
-  base::FilePath history_dir;
-  DownloadInterruptReason download_interrupt_reason_none;
-  DownloadInterruptReason download_interrupt_reason_crash;
+  const base::FilePath history_dir;
+  const DownloadInterruptReason download_interrupt_reason_none;
+  const DownloadInterruptReason download_interrupt_reason_crash;
+  const version_info::Channel channel;
 };
 
 }  // namespace history
diff --git a/components/history/core/test/BUILD.gn b/components/history/core/test/BUILD.gn
index e6ce7e2..2c6132bc9 100644
--- a/components/history/core/test/BUILD.gn
+++ b/components/history/core/test/BUILD.gn
@@ -32,6 +32,7 @@
     "//base/test:test_support",
     "//components/history/core/browser",
     "//components/sync/protocol:protocol",
+    "//components/version_info",
     "//net",
     "//services/network/public/cpp",
     "//sql",
diff --git a/components/history/core/test/test_history_database.cc b/components/history/core/test/test_history_database.cc
index 2af7a484..c991e4d 100644
--- a/components/history/core/test/test_history_database.cc
+++ b/components/history/core/test/test_history_database.cc
@@ -5,6 +5,7 @@
 #include "components/history/core/test/test_history_database.h"
 
 #include "components/history/core/browser/history_database_params.h"
+#include "components/version_info/channel.h"
 
 namespace history {
 const DownloadInterruptReason kTestDownloadInterruptReasonNone = 0;
@@ -20,10 +21,9 @@
 
 HistoryDatabaseParams TestHistoryDatabaseParamsForPath(
     const base::FilePath& history_dir) {
-  return HistoryDatabaseParams(
-      history_dir,
-      kTestDownloadInterruptReasonNone,
-      kTestDownloadInterruptReasonCrash);
+  return HistoryDatabaseParams(history_dir, kTestDownloadInterruptReasonNone,
+                               kTestDownloadInterruptReasonCrash,
+                               version_info::Channel::UNKNOWN);
 }
 
 }  // namespace history
diff --git a/components/history/ios/browser/BUILD.gn b/components/history/ios/browser/BUILD.gn
index 956aafd9..1e5818d5 100644
--- a/components/history/ios/browser/BUILD.gn
+++ b/components/history/ios/browser/BUILD.gn
@@ -14,6 +14,7 @@
   deps = [
     "//base",
     "//components/history/core/browser",
+    "//components/version_info",
     "//ios/web",
     "//url",
   ]
diff --git a/components/history/ios/browser/history_database_helper.cc b/components/history/ios/browser/history_database_helper.cc
index c51f0e0..6c76d5c 100644
--- a/components/history/ios/browser/history_database_helper.cc
+++ b/components/history/ios/browser/history_database_helper.cc
@@ -25,11 +25,10 @@
 }  // namespace
 
 HistoryDatabaseParams HistoryDatabaseParamsForPath(
-    const base::FilePath& history_dir) {
-  return HistoryDatabaseParams(
-      history_dir,
-      kDownloadInterruptReasonNone,
-      kDownloadInterruptReasonCrash);
+    const base::FilePath& history_dir,
+    version_info::Channel channel) {
+  return HistoryDatabaseParams(history_dir, kDownloadInterruptReasonNone,
+                               kDownloadInterruptReasonCrash, channel);
 }
 
 }  // namespace
diff --git a/components/history/ios/browser/history_database_helper.h b/components/history/ios/browser/history_database_helper.h
index 16115bc..ba6172f 100644
--- a/components/history/ios/browser/history_database_helper.h
+++ b/components/history/ios/browser/history_database_helper.h
@@ -5,6 +5,8 @@
 #ifndef COMPONENTS_HISTORY_IOS_BROWSER_HISTORY_DATABASE_HELPER_H_
 #define COMPONENTS_HISTORY_IOS_BROWSER_HISTORY_DATABASE_HELPER_H_
 
+#include "components/version_info/channel.h"
+
 namespace base {
 class FilePath;
 }
@@ -15,7 +17,8 @@
 
 // Returns a HistoryDatabaseParams for `history_dir`.
 HistoryDatabaseParams HistoryDatabaseParamsForPath(
-    const base::FilePath& history_dir);
+    const base::FilePath& history_dir,
+    version_info::Channel channel);
 
 }  // namespace history
 
diff --git a/components/image_service/BUILD.gn b/components/image_service/BUILD.gn
new file mode 100644
index 0000000..68ed8e51
--- /dev/null
+++ b/components/image_service/BUILD.gn
@@ -0,0 +1,22 @@
+# 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.
+
+component("image_service") {
+  defines = [ "IS_IMAGE_SERVICE_IMPL" ]
+  sources = [
+    "image_service.cc",
+    "image_service.h",
+  ]
+  deps = [
+    "//base",
+    "//components/history/core/browser",
+    "//components/keyed_service/core",
+    "//components/omnibox/browser",
+    "//components/search_engines",
+    "//components/sync/driver",
+    "//components/unified_consent",
+    "//services/network/public/cpp",
+    "//services/network/public/mojom",
+  ]
+}
diff --git a/components/image_service/COMMON_METADATA b/components/image_service/COMMON_METADATA
new file mode 100644
index 0000000..3a4dd61c
--- /dev/null
+++ b/components/image_service/COMMON_METADATA
@@ -0,0 +1,3 @@
+monorail {
+  component: "UI>Browser>Journeys"
+}
diff --git a/components/image_service/DEPS b/components/image_service/DEPS
new file mode 100644
index 0000000..8f5c213d
--- /dev/null
+++ b/components/image_service/DEPS
@@ -0,0 +1,10 @@
+include_rules = [
+  "+components/history/core",
+  "+components/keyed_service/core",
+  "+components/omnibox/browser",
+  "+components/search_engines",
+  "+components/sync/driver",
+  "+components/unified_consent",
+  "+services/network/public/cpp",
+  "+services/network/public/mojom",
+]
diff --git a/components/image_service/DIR_METADATA b/components/image_service/DIR_METADATA
new file mode 100644
index 0000000..2ab835b9
--- /dev/null
+++ b/components/image_service/DIR_METADATA
@@ -0,0 +1 @@
+mixins: "//components/image_service/COMMON_METADATA"
diff --git a/components/image_service/OWNERS b/components/image_service/OWNERS
new file mode 100644
index 0000000..d912c7e
--- /dev/null
+++ b/components/image_service/OWNERS
@@ -0,0 +1,2 @@
+sophiechang@chromium.org
+tommycli@chromium.org
diff --git a/components/image_service/README.md b/components/image_service/README.md
new file mode 100644
index 0000000..7eab25e
--- /dev/null
+++ b/components/image_service/README.md
@@ -0,0 +1,4 @@
+# //components/image_service
+
+Service implementation for Chrome Images feature, to provide relevant images
+for Chrome UI usage.
diff --git a/chrome/browser/history_clusters/entity_image_service.cc b/components/image_service/image_service.cc
similarity index 89%
rename from chrome/browser/history_clusters/entity_image_service.cc
rename to components/image_service/image_service.cc
index 015c5a0..46070886 100644
--- a/chrome/browser/history_clusters/entity_image_service.cc
+++ b/components/image_service/image_service.cc
@@ -2,15 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/history_clusters/entity_image_service.h"
+#include "components/image_service/image_service.h"
 
 #include "base/barrier_closure.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
 #include "base/i18n/case_conversion.h"
 #include "base/memory/raw_ptr.h"
-#include "chrome/browser/profiles/profile.h"
-#include "components/history_clusters/core/config.h"
 #include "components/omnibox/browser/remote_suggestions_service.h"
 #include "components/omnibox/browser/search_suggestion_parser.h"
 #include "components/search_engines/template_url.h"
@@ -18,7 +16,7 @@
 #include "services/network/public/cpp/simple_url_loader.h"
 #include "services/network/public/mojom/url_response_head.mojom.h"
 
-namespace history_clusters {
+namespace image_service {
 
 namespace {
 
@@ -41,7 +39,7 @@
   explicit FetchJobManager(std::vector<history::Cluster>&& clusters)
       : clusters_(clusters) {}
 
-  void Start(EntityImageService* service, ResultCallback callback) {
+  void Start(ImageService* service, ResultCallback callback) {
     std::vector<Request> requests;
     for (auto& cluster : clusters_) {
       for (auto& visit : cluster.visits) {
@@ -106,7 +104,7 @@
 // A one-time use object that uses Suggest to get an image URL corresponding
 // to `search_query` and `entity_id`. This is a hacky temporary implementation,
 // ideally this should be replaced by persisted Suggest-provided entities.
-class EntityImageService::SuggestEntityImageURLFetcher {
+class ImageService::SuggestEntityImageURLFetcher {
  public:
   SuggestEntityImageURLFetcher(
       AutocompleteProviderClient* autocomplete_provider_client,
@@ -204,7 +202,7 @@
   base::WeakPtrFactory<SuggestEntityImageURLFetcher> weak_factory_{this};
 };
 
-EntityImageService::EntityImageService(
+ImageService::ImageService(
     std::unique_ptr<AutocompleteProviderClient> autocomplete_provider_client,
     syncer::SyncService* sync_service)
     : autocomplete_provider_client_(std::move(autocomplete_provider_client)),
@@ -212,13 +210,12 @@
           unified_consent::UrlKeyedDataCollectionConsentHelper::
               NewPersonalizedDataCollectionConsentHelper(sync_service)) {}
 
-EntityImageService::~EntityImageService() = default;
+ImageService::~ImageService() = default;
 
-void EntityImageService::PopulateEntityImagesFor(
+void ImageService::PopulateEntityImagesFor(
     std::vector<history::Cluster> clusters,
     base::OnceCallback<void(std::vector<history::Cluster>)> callback) {
-  if (!GetConfig().images || !url_consent_helper_ ||
-      !url_consent_helper_->IsEnabled()) {
+  if (!url_consent_helper_ || !url_consent_helper_->IsEnabled()) {
     return std::move(callback).Run(std::move(clusters));
   }
 
@@ -231,10 +228,9 @@
                            std::move(callback)));
 }
 
-bool EntityImageService::FetchImageFor(const std::u16string& search_query,
-                                       const std::string& entity_id,
-                                       ResultCallback callback) {
-  DCHECK(GetConfig().images);
+bool ImageService::FetchImageFor(const std::u16string& search_query,
+                                 const std::string& entity_id,
+                                 ResultCallback callback) {
   DCHECK(url_consent_helper_ && url_consent_helper_->IsEnabled());
 
   auto fetcher = std::make_unique<SuggestEntityImageURLFetcher>(
@@ -243,13 +239,13 @@
   // Use a raw pointer temporary so we can give ownership of the unique_ptr to
   // the callback and have a well defined SuggestEntityImageURLFetcher lifetime.
   auto* fetcher_raw_ptr = fetcher.get();
-  fetcher_raw_ptr->Start(base::BindOnce(
-      &EntityImageService::OnImageFetched, weak_factory_.GetWeakPtr(),
-      std::move(fetcher), std::move(callback)));
+  fetcher_raw_ptr->Start(
+      base::BindOnce(&ImageService::OnImageFetched, weak_factory_.GetWeakPtr(),
+                     std::move(fetcher), std::move(callback)));
   return true;
 }
 
-void EntityImageService::OnImageFetched(
+void ImageService::OnImageFetched(
     std::unique_ptr<SuggestEntityImageURLFetcher> fetcher,
     ResultCallback callback,
     const GURL& image_url) {
@@ -258,4 +254,4 @@
   // `fetcher` is owned by this method and will be deleted now.
 }
 
-}  // namespace history_clusters
+}  // namespace image_service
diff --git a/chrome/browser/history_clusters/entity_image_service.h b/components/image_service/image_service.h
similarity index 76%
rename from chrome/browser/history_clusters/entity_image_service.h
rename to components/image_service/image_service.h
index e68929f..dc00a37 100644
--- a/chrome/browser/history_clusters/entity_image_service.h
+++ b/components/image_service/image_service.h
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_HISTORY_CLUSTERS_ENTITY_IMAGE_SERVICE_H_
-#define CHROME_BROWSER_HISTORY_CLUSTERS_ENTITY_IMAGE_SERVICE_H_
+#ifndef COMPONENTS_IMAGE_SERVICE_IMAGE_SERVICE_H_
+#define COMPONENTS_IMAGE_SERVICE_IMAGE_SERVICE_H_
 
 #include <memory>
 #include <string>
 
+#include "base/component_export.h"
 #include "base/functional/callback_forward.h"
-#include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "components/history/core/browser/history_types.h"
 #include "components/keyed_service/core/keyed_service.h"
@@ -17,22 +17,21 @@
 #include "components/sync/driver/sync_service.h"
 #include "components/unified_consent/url_keyed_data_collection_consent_helper.h"
 
-namespace history_clusters {
+namespace image_service {
 
 // Used to get the image URL associated with a cluster. It doesn't actually
 // fetch the image, that's up to the UI to do.
-// TODO(tommycli): Move to /components and rename to `ImageService`.
-class EntityImageService : public KeyedService {
+class COMPONENT_EXPORT(IMAGE_SERVICE) ImageService : public KeyedService {
  public:
   using ResultCallback = base::OnceCallback<void(const GURL& image_url)>;
 
-  EntityImageService(
+  ImageService(
       std::unique_ptr<AutocompleteProviderClient> autocomplete_provider_client,
       syncer::SyncService* sync_service);
-  EntityImageService(const EntityImageService&) = delete;
-  EntityImageService& operator=(const EntityImageService&) = delete;
+  ImageService(const ImageService&) = delete;
+  ImageService& operator=(const ImageService&) = delete;
 
-  ~EntityImageService() override;
+  ~ImageService() override;
 
   // Populates entity images into the `image_url` of any eligible visits within
   // every cluster in `clusters`. `clusters` should be moved into the parameter.
@@ -61,9 +60,9 @@
   std::unique_ptr<unified_consent::UrlKeyedDataCollectionConsentHelper>
       url_consent_helper_;
 
-  base::WeakPtrFactory<EntityImageService> weak_factory_{this};
+  base::WeakPtrFactory<ImageService> weak_factory_{this};
 };
 
-}  // namespace history_clusters
+}  // namespace image_service
 
-#endif  // CHROME_BROWSER_HISTORY_CLUSTERS_ENTITY_IMAGE_SERVICE_H_
+#endif  // COMPONENTS_IMAGE_SERVICE_IMAGE_SERVICE_H_
diff --git a/components/live_caption/BUILD.gn b/components/live_caption/BUILD.gn
index 07fe457..b29058b3 100644
--- a/components/live_caption/BUILD.gn
+++ b/components/live_caption/BUILD.gn
@@ -9,6 +9,7 @@
     sources = [
       "caption_bubble_context.h",
       "caption_bubble_controller.h",
+      "caption_bubble_session_observer.h",
       "live_caption_controller.cc",
       "live_caption_controller.h",
       "live_translate_controller.cc",
diff --git a/components/live_caption/caption_bubble_context.h b/components/live_caption/caption_bubble_context.h
index 82eefb24..1e62958 100644
--- a/components/live_caption/caption_bubble_context.h
+++ b/components/live_caption/caption_bubble_context.h
@@ -5,6 +5,10 @@
 #ifndef COMPONENTS_LIVE_CAPTION_CAPTION_BUBBLE_CONTEXT_H_
 #define COMPONENTS_LIVE_CAPTION_CAPTION_BUBBLE_CONTEXT_H_
 
+#include <memory>
+#include <string>
+
+#include "components/live_caption/caption_bubble_session_observer.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/geometry/rect.h"
 
@@ -31,6 +35,11 @@
   // of the ash window.
   virtual absl::optional<gfx::Rect> GetBounds() const = 0;
 
+  // Returns the unique identifier for a caption bubble session. A caption
+  // bubble session is per-tab and resets when a user navigates away or reloads
+  // the page.
+  virtual const std::string GetSessionId() const = 0;
+
   // Activates the context. In Live Caption on browser, this activates the
   // browser window and tab of the web contents. Called when the Back To Tab
   // button is clicked in the CaptionBubble.
@@ -39,6 +48,13 @@
   // Whether or not the context is activatable. When Activate() is implemented
   // in child classes, the child classes must set this to be true.
   virtual bool IsActivatable() const = 0;
+
+  // Gets the session observer for the caption bubble context. On Chrome
+  // browser, a caption bubble session is per-tab and resets when a user
+  // navigates away or reloads the page.
+  // TODO(launch/4200463): Implement this for Ash if necessary.
+  virtual std::unique_ptr<CaptionBubbleSessionObserver>
+  GetCaptionBubbleSessionObserver() = 0;
 };
 
 }  // namespace captions
diff --git a/components/live_caption/caption_bubble_session_observer.h b/components/live_caption/caption_bubble_session_observer.h
new file mode 100644
index 0000000..d272ff7
--- /dev/null
+++ b/components/live_caption/caption_bubble_session_observer.h
@@ -0,0 +1,27 @@
+// 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 COMPONENTS_LIVE_CAPTION_CAPTION_BUBBLE_SESSION_OBSERVER_H_
+#define COMPONENTS_LIVE_CAPTION_CAPTION_BUBBLE_SESSION_OBSERVER_H_
+
+#include "base/functional/callback.h"
+
+namespace captions {
+
+using EndSessionCallback = base::RepeatingCallback<void(const std::string&)>;
+
+class CaptionBubbleSessionObserver {
+ public:
+  CaptionBubbleSessionObserver() = default;
+  virtual ~CaptionBubbleSessionObserver() = default;
+  CaptionBubbleSessionObserver(const CaptionBubbleSessionObserver&) = delete;
+  CaptionBubbleSessionObserver& operator=(const CaptionBubbleSessionObserver&) =
+      delete;
+
+  virtual void SetEndSessionCallback(EndSessionCallback callback) = 0;
+};
+
+}  // namespace captions
+
+#endif  // COMPONENTS_LIVE_CAPTION_CAPTION_BUBBLE_SESSION_OBSERVER_H_
diff --git a/components/live_caption/views/caption_bubble.cc b/components/live_caption/views/caption_bubble.cc
index 4f8d527..3bfab09 100644
--- a/components/live_caption/views/caption_bubble.cc
+++ b/components/live_caption/views/caption_bubble.cc
@@ -698,7 +698,7 @@
 void CaptionBubble::CloseButtonPressed() {
   LogSessionEvent(SessionEvent::kCloseButtonClicked);
   if (model_)
-    model_->Close();
+    model_->CloseButtonPressed();
 }
 
 void CaptionBubble::ExpandOrCollapseButtonPressed() {
diff --git a/components/live_caption/views/caption_bubble_controller_views.cc b/components/live_caption/views/caption_bubble_controller_views.cc
index 878a80c..5dacd0f6 100644
--- a/components/live_caption/views/caption_bubble_controller_views.cc
+++ b/components/live_caption/views/caption_bubble_controller_views.cc
@@ -5,7 +5,9 @@
 #include "components/live_caption/views/caption_bubble_controller_views.h"
 
 #include <memory>
+#include <set>
 #include <string>
+#include <unordered_map>
 
 #include "base/bind.h"
 #include "components/live_caption/caption_bubble_context.h"
@@ -103,9 +105,35 @@
 void CaptionBubbleControllerViews::SetActiveModel(
     CaptionBubbleContext* caption_bubble_context) {
   if (!caption_bubble_models_.count(caption_bubble_context)) {
-    caption_bubble_models_.emplace(
+    auto caption_bubble_model = std::make_unique<CaptionBubbleModel>(
         caption_bubble_context,
-        std::make_unique<CaptionBubbleModel>(caption_bubble_context));
+        base::BindRepeating(
+            &CaptionBubbleControllerViews::OnSessionEnded,
+            // Unretained is safe because |CaptionBubbleControllerViews|
+            // owns |caption_bubble_model|.
+            base::Unretained(this)));
+
+    if (base::Contains(closed_sessions_,
+                       caption_bubble_context->GetSessionId())) {
+      caption_bubble_model->Close();
+    }
+
+    caption_bubble_models_.emplace(caption_bubble_context,
+                                   std::move(caption_bubble_model));
+  }
+
+  if (!caption_bubble_session_observers_.count(
+          caption_bubble_context->GetSessionId())) {
+    std::unique_ptr<CaptionBubbleSessionObserver> observer =
+        caption_bubble_context->GetCaptionBubbleSessionObserver();
+
+    if (observer) {
+      observer->SetEndSessionCallback(
+          base::BindRepeating(&CaptionBubbleControllerViews::OnSessionReset,
+                              base::Unretained(this)));
+      caption_bubble_session_observers_.emplace(
+          caption_bubble_context->GetSessionId(), std::move(observer));
+    }
   }
 
   CaptionBubbleModel* caption_bubble_model =
@@ -116,6 +144,27 @@
   }
 }
 
+void CaptionBubbleControllerViews::OnSessionEnded(
+    const std::string& session_id) {
+  // Close all other CaptionBubbleModels that share this WebContents identifier.
+  for (const auto& caption_bubble_model : caption_bubble_models_) {
+    if (caption_bubble_model.first->GetSessionId() == session_id) {
+      caption_bubble_model.second->Close();
+    }
+  }
+
+  closed_sessions_.insert(session_id);
+}
+
+void CaptionBubbleControllerViews::OnSessionReset(
+    const std::string& session_id) {
+  if (base::Contains(closed_sessions_, session_id)) {
+    closed_sessions_.erase(session_id);
+  }
+
+  caption_bubble_session_observers_.erase(session_id);
+}
+
 bool CaptionBubbleControllerViews::IsWidgetVisibleForTesting() {
   return caption_widget_ && caption_widget_->IsVisible();
 }
diff --git a/components/live_caption/views/caption_bubble_controller_views.h b/components/live_caption/views/caption_bubble_controller_views.h
index 04217f86..5dbc467 100644
--- a/components/live_caption/views/caption_bubble_controller_views.h
+++ b/components/live_caption/views/caption_bubble_controller_views.h
@@ -6,10 +6,12 @@
 #define COMPONENTS_LIVE_CAPTION_VIEWS_CAPTION_BUBBLE_CONTROLLER_VIEWS_H_
 
 #include <memory>
+#include <set>
 #include <string>
 #include <unordered_map>
 
 #include "base/memory/raw_ptr.h"
+#include "base/memory/weak_ptr.h"
 #include "components/live_caption/caption_bubble_controller.h"
 #include "components/live_caption/views/caption_bubble.h"
 #include "components/prefs/pref_service.h"
@@ -23,6 +25,7 @@
 
 class CaptionBubble;
 class CaptionBubbleModel;
+class CaptionBubbleSessionObserver;
 
 ///////////////////////////////////////////////////////////////////////////////
 // Caption Bubble Controller for Views
@@ -70,6 +73,12 @@
   // already exist.
   void SetActiveModel(CaptionBubbleContext* caption_bubble_context);
 
+  // Called when the user closes the caption bubble.
+  void OnSessionEnded(const std::string& session_id);
+
+  // Called on a cross-origin navigation or reload.
+  void OnSessionReset(const std::string& session_id);
+
   bool IsWidgetVisibleForTesting() override;
   std::string GetBubbleLabelTextForTesting() override;
 
@@ -84,6 +93,18 @@
   // received.
   std::unordered_map<CaptionBubbleContext*, std::unique_ptr<CaptionBubbleModel>>
       caption_bubble_models_;
+
+  // A collection of closed session identifiers that should not display
+  // captions. Identifiers are removed from this collection when a user
+  // refreshes the page or navigates away.
+  std::set<std::string> closed_sessions_;
+
+  // Mapping of unique session identifiers to the observer that observes the
+  // sessions.
+  std::unordered_map<std::string, std::unique_ptr<CaptionBubbleSessionObserver>>
+      caption_bubble_session_observers_;
+
+  base::WeakPtrFactory<CaptionBubbleControllerViews> weak_factory_{this};
 };
 }  // namespace captions
 
diff --git a/components/live_caption/views/caption_bubble_model.cc b/components/live_caption/views/caption_bubble_model.cc
index 2cce2fe..686d649c 100644
--- a/components/live_caption/views/caption_bubble_model.cc
+++ b/components/live_caption/views/caption_bubble_model.cc
@@ -17,8 +17,9 @@
 
 namespace captions {
 
-CaptionBubbleModel::CaptionBubbleModel(CaptionBubbleContext* context)
-    : context_(context) {
+CaptionBubbleModel::CaptionBubbleModel(CaptionBubbleContext* context,
+                                       OnCaptionBubbleClosedCallback callback)
+    : caption_bubble_closed_callback_(callback), context_(context) {
   DCHECK(context_);
 }
 
@@ -62,16 +63,16 @@
   }
 }
 
+void CaptionBubbleModel::CloseButtonPressed() {
+  caption_bubble_closed_callback_.Run(context_->GetSessionId());
+  Close();
+}
+
 void CaptionBubbleModel::Close() {
   is_closed_ = true;
   ClearText();
 }
 
-void CaptionBubbleModel::Open() {
-  is_closed_ = false;
-  OnTextChanged();
-}
-
 void CaptionBubbleModel::OnError(
     CaptionBubbleErrorType error_type,
     OnErrorClickedCallback error_clicked_callback,
diff --git a/components/live_caption/views/caption_bubble_model.h b/components/live_caption/views/caption_bubble_model.h
index 1d48e3a..266a4da3 100644
--- a/components/live_caption/views/caption_bubble_model.h
+++ b/components/live_caption/views/caption_bubble_model.h
@@ -26,6 +26,8 @@
 using OnErrorClickedCallback = base::RepeatingCallback<void()>;
 using OnDoNotShowAgainClickedCallback =
     base::RepeatingCallback<void(CaptionBubbleErrorType, bool)>;
+using OnCaptionBubbleClosedCallback =
+    base::RepeatingCallback<void(const std::string&)>;
 
 ///////////////////////////////////////////////////////////////////////////////
 // Caption Bubble Model
@@ -51,7 +53,8 @@
 //
 class CaptionBubbleModel {
  public:
-  explicit CaptionBubbleModel(CaptionBubbleContext* context);
+  CaptionBubbleModel(CaptionBubbleContext* context,
+                     OnCaptionBubbleClosedCallback callback);
   ~CaptionBubbleModel();
   CaptionBubbleModel(const CaptionBubbleModel&) = delete;
   CaptionBubbleModel& operator=(const CaptionBubbleModel&) = delete;
@@ -70,13 +73,13 @@
                OnErrorClickedCallback error_clicked_callback,
                OnDoNotShowAgainClickedCallback error_silenced_callback);
 
-  // Mark the bubble as closed, clear the partial and final text, and alert the
+  // Mark the bubble as closed.
+  void CloseButtonPressed();
+
+  // Clear the partial and final text, and alert the
   // observer.
   void Close();
 
-  // Marks the bubble as open.
-  void Open();
-
   // Clears the partial and final text and alerts the observer.
   void ClearText();
 
@@ -105,6 +108,8 @@
   // The CaptionBubble observing changes to this model.
   raw_ptr<CaptionBubble, DanglingUntriaged> observer_ = nullptr;
 
+  OnCaptionBubbleClosedCallback caption_bubble_closed_callback_;
+
   const raw_ptr<CaptionBubbleContext, DanglingUntriaged> context_;
 };
 
diff --git a/components/mirroring/mojom/mirroring_service_host.mojom b/components/mirroring/mojom/mirroring_service_host.mojom
index ff4115e..79697a6 100644
--- a/components/mirroring/mojom/mirroring_service_host.mojom
+++ b/components/mirroring/mojom/mirroring_service_host.mojom
@@ -10,6 +10,7 @@
 
 // This interface is used to start a mirroring session through the Mirroring
 // Service.
+// TODO(crbug.com/1396108) : Remove the entire interface as a cleanup.
 interface MirroringServiceHost {
   // Starts a mirroring session through the Mirroring Service. |observer| gets
   // notifications about lifecycle events. |outbound_channel| is provided to
@@ -20,4 +21,11 @@
         pending_remote<SessionObserver> observer,
         pending_remote<CastMessageChannel> outbound_channel,
         pending_receiver<CastMessageChannel> inbound_channel);
+
+  // Replies back with the current tab source id of the active mirroring
+  // session if exist.
+  // When there is no id, it replies with -1. That is used instead of optional
+  // parameter as currently numeric types cannot be nullable in mojo
+  // (crbug.com/657632).
+  GetTabSourceId() => (int32 frame_tree_node_id);
 };
diff --git a/components/mirroring/mojom/session_observer.mojom b/components/mirroring/mojom/session_observer.mojom
index 6423f9c..61200935 100644
--- a/components/mirroring/mojom/session_observer.mojom
+++ b/components/mirroring/mojom/session_observer.mojom
@@ -43,4 +43,7 @@
 
   // Called when a message needs to be logged at ERROR level by the MR logger.
   LogErrorMessage(string message);
+
+  // Called when the source is changed.
+  OnSourceChanged();
 };
diff --git a/components/mirroring/mojom/session_parameters.mojom b/components/mirroring/mojom/session_parameters.mojom
index f3ad97be..6979123 100644
--- a/components/mirroring/mojom/session_parameters.mojom
+++ b/components/mirroring/mojom/session_parameters.mojom
@@ -57,4 +57,12 @@
   // parameter uses the default value defined in mirror_settings.cc.  A value of
   // zero disables refresh frame requests.
   mojo_base.mojom.TimeDelta? refresh_interval;
+
+  // If true, all video frames sent will be letterboxed/pillarboxed to fit the
+  // aspect ratio of the negotiated resolution.  This is to allow letterboxing
+  // to be selectively applied to receivers that have outstanding bugs with
+  // rendering variable aspect ratio frames.
+  //
+  // TODO(crbug.com/1363512): Remove support for sender side letterboxing.
+  bool force_letterboxing;
 };
diff --git a/components/mirroring/service/mirroring_features.cc b/components/mirroring/service/mirroring_features.cc
index 834ef91e..1e718447 100644
--- a/components/mirroring/service/mirroring_features.cc
+++ b/components/mirroring/service/mirroring_features.cc
@@ -13,7 +13,7 @@
 // TODO(crbug.com/1363512):  Remove support for sender side letterboxing.
 BASE_FEATURE(kCastDisableLetterboxing,
              "CastDisableLetterboxing",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+             base::FEATURE_ENABLED_BY_DEFAULT);
 
 // The mirroring service previously used a model name filter before even
 // attempting to query the receiver for media remoting support. This
diff --git a/components/mirroring/service/openscreen_session_host.cc b/components/mirroring/service/openscreen_session_host.cc
index 260b062..fbabebc 100644
--- a/components/mirroring/service/openscreen_session_host.cc
+++ b/components/mirroring/service/openscreen_session_host.cc
@@ -40,7 +40,9 @@
 #include "gpu/ipc/client/gpu_channel_host.h"
 #include "media/audio/audio_input_device.h"
 #include "media/base/audio_capturer_source.h"
+#include "media/base/audio_parameters.h"
 #include "media/base/bind_to_current_loop.h"
+#include "media/capture/video_capture_types.h"
 #include "media/cast/common/openscreen_conversion_helpers.h"
 #include "media/cast/encoding/encoding_support.h"
 #include "media/cast/sender/audio_sender.h"
@@ -160,6 +162,14 @@
   }
 }
 
+const std::string ToString(const media::VideoCaptureParams& params) {
+  return base::StringPrintf(
+      "requested_format = %s, buffer_type = %d, resolution_policy = %d",
+      media::VideoCaptureFormat::ToString(params.requested_format).c_str(),
+      static_cast<int>(params.buffer_type),
+      static_cast<int>(params.resolution_change_policy));
+}
+
 }  // namespace
 
 // Receives data from the audio capturer source, and calls `audio_data_callback`
@@ -412,6 +422,10 @@
             &OpenscreenSessionHost::CreateAudioStream, base::Unretained(this))),
         media::AudioInputDevice::Purpose::kLoopback,
         media::AudioInputDevice::DeadStreamDetection::kEnabled);
+    const media::AudioParameters& capture_params =
+        mirror_settings_.GetAudioCaptureParams();
+    LogInfoMessage(base::StrCat({"Creating AudioInputDevice with params ",
+                                 capture_params.AsHumanReadableString()}));
     audio_input_device_->Initialize(mirror_settings_.GetAudioCaptureParams(),
                                     audio_capturing_callback_.get());
     audio_input_device_->Start();
@@ -447,8 +461,12 @@
       mojo::PendingRemote<media::mojom::VideoCaptureHost> video_host;
       resource_provider_->GetVideoCaptureHost(
           video_host.InitWithNewPipeAndPassReceiver());
+      const media::VideoCaptureParams& capture_params =
+          mirror_settings_.GetVideoCaptureParams();
       video_capture_client_ = std::make_unique<VideoCaptureClient>(
-          mirror_settings_.GetVideoCaptureParams(), std::move(video_host));
+          capture_params, std::move(video_host));
+      LogInfoMessage(base::StrCat({"Starting VideoCaptureHost with params ",
+                                   ToString(capture_params)}));
       video_capture_client_->Start(
           base::BindRepeating(&VideoRtpStream::InsertVideoFrame,
                               video_stream_->AsWeakPtr()),
@@ -609,12 +627,23 @@
 void OpenscreenSessionHost::RestartMirroringStreaming() {
   if (state_ != State::kRemoting)
     return;
+
+  // Stop session instead of switching to mirroring when in Remote Playback
+  // mode.
+  if (session_params_.is_remote_playback) {
+    StopSession();
+    return;
+  }
+
   StopStreaming();
   state_ = State::kMirroring;
   Negotiate();
 }
 
 void OpenscreenSessionHost::SwitchSourceTab() {
+  if (observer_)
+    observer_->OnSourceChanged();
+
   if (state_ == State::kRemoting) {
     switching_tab_source_ = true;
     video_capture_client_.reset();
@@ -773,7 +802,10 @@
                  static_cast<double>(video.maximum.frame_rate));
 
     // TODO(crbug.com/1363512): Remove support for sender side letterboxing.
-    if (base::FeatureList::IsEnabled(features::kCastDisableLetterboxing)) {
+    if (session_params_.force_letterboxing) {
+      mirror_settings_.SetSenderSideLetterboxingEnabled(true);
+    } else if (base::FeatureList::IsEnabled(
+                   features::kCastDisableLetterboxing)) {
       mirror_settings_.SetSenderSideLetterboxingEnabled(false);
     } else {
       // Enable sender-side letterboxing if the receiver specifically does not
diff --git a/components/mirroring/service/openscreen_session_host_unittest.cc b/components/mirroring/service/openscreen_session_host_unittest.cc
index c227667..9519019 100644
--- a/components/mirroring/service/openscreen_session_host_unittest.cc
+++ b/components/mirroring/service/openscreen_session_host_unittest.cc
@@ -159,21 +159,22 @@
 
  protected:
   // mojom::SessionObserver implementation.
-  MOCK_METHOD1(OnError, void(SessionError));
-  MOCK_METHOD0(DidStart, void());
-  MOCK_METHOD0(DidStop, void());
-  MOCK_METHOD1(LogInfoMessage, void(const std::string&));
-  MOCK_METHOD1(LogErrorMessage, void(const std::string&));
+  MOCK_METHOD(void, OnError, (SessionError));
+  MOCK_METHOD(void, DidStart, ());
+  MOCK_METHOD(void, DidStop, ());
+  MOCK_METHOD(void, LogInfoMessage, (const std::string&));
+  MOCK_METHOD(void, LogErrorMessage, (const std::string&));
+  MOCK_METHOD(void, OnSourceChanged, ());
 
-  MOCK_METHOD0(OnGetVideoCaptureHost, void());
-  MOCK_METHOD0(OnGetNetworkContext, void());
-  MOCK_METHOD0(OnCreateAudioStream, void());
-  MOCK_METHOD0(OnConnectToRemotingSource, void());
+  MOCK_METHOD(void, OnGetVideoCaptureHost, ());
+  MOCK_METHOD(void, OnGetNetworkContext, ());
+  MOCK_METHOD(void, OnCreateAudioStream, ());
+  MOCK_METHOD(void, OnConnectToRemotingSource, ());
 
   // Called when an outbound message is sent.
-  MOCK_METHOD1(OnOutboundMessage, void(SenderMessage::Type type));
+  MOCK_METHOD(void, OnOutboundMessage, (SenderMessage::Type type));
 
-  MOCK_METHOD0(OnInitialized, void());
+  MOCK_METHOD(void, OnInitialized, ());
 
   // mojom::CastMessageChannel implementation (outbound messages).
   void OnMessage(mojom::CastMessagePtr message) override {
@@ -278,8 +279,10 @@
   }
 
   // Create a mirroring session. Expect to send OFFER message.
-  void CreateSession(SessionType session_type) {
+  void CreateSession(SessionType session_type,
+                     bool is_remote_playback = false) {
     session_type_ = session_type;
+    is_remote_playback_ = is_remote_playback;
     mojom::SessionParametersPtr session_params =
         mojom::SessionParameters::New();
     session_params->type = session_type_;
@@ -291,6 +294,10 @@
       session_params->target_playout_delay =
           base::Milliseconds(target_playout_delay_ms_);
     }
+    if (force_letterboxing_) {
+      session_params->force_letterboxing = true;
+    }
+    session_params->is_remote_playback = is_remote_playback_;
     cast_mode_ = "mirroring";
     mojo::PendingRemote<mojom::ResourceProvider> resource_provider_remote;
     mojo::PendingRemote<mojom::SessionObserver> session_observer_remote;
@@ -326,8 +333,10 @@
     EXPECT_CALL(*this, OnGetVideoCaptureHost()).Times(num_to_get_video_host);
     EXPECT_CALL(*this, OnCreateAudioStream()).Times(num_to_create_audio_stream);
     EXPECT_CALL(*this, OnError(_)).Times(0);
-    EXPECT_CALL(*this,
-                OnOutboundMessage(SenderMessage::Type::kGetCapabilities));
+    if (!is_remote_playback_) {
+      EXPECT_CALL(*this,
+                  OnOutboundMessage(SenderMessage::Type::kGetCapabilities));
+    }
     EXPECT_CALL(*this, DidStart());
     GenerateAndReplyWithAnswer();
     task_environment_.RunUntilIdle();
@@ -439,7 +448,7 @@
     Mock::VerifyAndClear(&remoting_source_);
   }
 
-  void StopRemoting() {
+  void StopRemotingAndRestartMirroring() {
     ASSERT_EQ(cast_mode_, "remoting");
     const RemotingStopReason reason = RemotingStopReason::LOCAL_PLAYBACK;
     // Expect to send OFFER message to fallback on mirroring.
@@ -452,6 +461,19 @@
     Mock::VerifyAndClear(&remoting_source_);
   }
 
+  void StopRemotingAndStopSession() {
+    ASSERT_EQ(cast_mode_, "remoting");
+    const RemotingStopReason reason = RemotingStopReason::LOCAL_PLAYBACK;
+    EXPECT_CALL(remoting_source_, OnStopped(reason));
+    if (video_host_)
+      EXPECT_CALL(*video_host_, OnStopped());
+    EXPECT_CALL(*this, DidStop());
+    remoter_->Stop(reason);
+    task_environment_.RunUntilIdle();
+    Mock::VerifyAndClear(this);
+    Mock::VerifyAndClear(&remoting_source_);
+  }
+
   void SwitchSourceTab() {
     const int get_video_host_call_count =
         session_type_ == SessionType::AUDIO_ONLY ? 0 : 1;
@@ -462,7 +484,8 @@
         .Times(get_video_host_call_count);
     EXPECT_CALL(*this, OnCreateAudioStream())
         .Times(create_audio_stream_call_count);
-    EXPECT_CALL(*this, OnConnectToRemotingSource);
+    EXPECT_CALL(*this, OnConnectToRemotingSource());
+    EXPECT_CALL(*this, OnSourceChanged());
 
     if (cast_mode_ == "remoting") {
       EXPECT_CALL(*this, OnOutboundMessage(SenderMessage::Type::kOffer));
@@ -495,6 +518,8 @@
     target_playout_delay_ms_ = target_playout_delay_ms;
   }
 
+  void ForceLetterboxing() { force_letterboxing_ = true; }
+
   void SetAnswer(std::unique_ptr<openscreen::cast::Answer> answer) {
     answer_ = std::move(answer);
   }
@@ -521,16 +546,18 @@
   mojo::Receiver<mojom::CastMessageChannel> outbound_channel_receiver_{this};
   mojo::Remote<mojom::CastMessageChannel> inbound_channel_;
   SessionType session_type_ = SessionType::AUDIO_AND_VIDEO;
+  bool is_remote_playback_ = false;
   mojo::Remote<media::mojom::Remoter> remoter_;
   NiceMock<MockRemotingSource> remoting_source_;
   std::string cast_mode_;
-  int32_t target_playout_delay_ms_ = kDefaultPlayoutDelay;
+  int32_t target_playout_delay_ms_{kDefaultPlayoutDelay};
+  bool force_letterboxing_{false};
 
   std::unique_ptr<OpenscreenSessionHost> session_host_;
   std::unique_ptr<MockNetworkContext> network_context_;
   std::unique_ptr<openscreen::cast::Answer> answer_;
 
-  int next_receiver_ssrc_ = 35336;
+  int next_receiver_ssrc_{35336};
   absl::optional<openscreen::cast::SenderMessage> last_sent_offer_;
 };
 
@@ -555,9 +582,7 @@
   StopSession();
 }
 
-TEST_F(OpenscreenSessionHostTest, AnswerWithConstraintsLetterboxDisabled) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndEnableFeature(features::kCastDisableLetterboxing);
+TEST_F(OpenscreenSessionHostTest, AnswerWithConstraints) {
   SetAnswer(std::make_unique<openscreen::cast::Answer>(kAnswerWithConstraints));
   media::VideoCaptureParams::SuggestedConstraints expected_constraints = {
       .min_frame_size = gfx::Size(2, 2),
@@ -586,6 +611,21 @@
             expected_constraints);
 }
 
+// TODO(crbug.com/1363512): Remove support for sender side letterboxing.
+TEST_F(OpenscreenSessionHostTest, AnswerWithConstraintsLetterboxForced) {
+  ForceLetterboxing();
+  SetAnswer(std::make_unique<openscreen::cast::Answer>(kAnswerWithConstraints));
+  media::VideoCaptureParams::SuggestedConstraints expected_constraints = {
+      .min_frame_size = gfx::Size(320, 180),
+      .max_frame_size = gfx::Size(1920, 1080),
+      .fixed_aspect_ratio = true};
+  CreateSession(SessionType::AUDIO_AND_VIDEO);
+  StartSession();
+  StopSession();
+  EXPECT_EQ(video_host_->GetVideoCaptureParams().SuggestConstraints(),
+            expected_constraints);
+}
+
 TEST_F(OpenscreenSessionHostTest, AnswerTimeout) {
   CreateSession(SessionType::AUDIO_AND_VIDEO);
   SignalAnswerTimeout();
@@ -597,10 +637,18 @@
   SendRemotingCapabilities();
   StartRemoting();
   RemotingStarted();
-  StopRemoting();
+  StopRemotingAndRestartMirroring();
   StopSession();
 }
 
+TEST_F(OpenscreenSessionHostTest, SwitchFromRemotingForRemotePlayback) {
+  CreateSession(SessionType::AUDIO_AND_VIDEO, true);
+  StartSession();
+  StartRemoting();
+  RemotingStarted();
+  StopRemotingAndStopSession();
+}
+
 TEST_F(OpenscreenSessionHostTest, RemotingNotSupported) {
   CreateSession(SessionType::AUDIO_AND_VIDEO);
   StartSession();
diff --git a/components/mirroring/service/session.cc b/components/mirroring/service/session.cc
index 95a80b0d..6e84054 100644
--- a/components/mirroring/service/session.cc
+++ b/components/mirroring/service/session.cc
@@ -283,6 +283,14 @@
   return media::remoting::IsKnownToSupportRemoting(receiver_model_name);
 }
 
+const std::string ToString(const media::VideoCaptureParams& params) {
+  return base::StringPrintf(
+      "requested_format = %s, buffer_type = %d, resolution_policy = %d",
+      media::VideoCaptureFormat::ToString(params.requested_format).c_str(),
+      static_cast<int>(params.buffer_type),
+      static_cast<int>(params.resolution_change_policy));
+}
+
 }  // namespace
 
 class Session::AudioCapturingCallback final
@@ -578,7 +586,10 @@
                  static_cast<double>(video.maximum.frame_rate));
 
     // TODO(crbug.com/1363512): Remove support for sender side letterboxing.
-    if (base::FeatureList::IsEnabled(features::kCastDisableLetterboxing)) {
+    if (session_params_.force_letterboxing) {
+      mirror_settings_.SetSenderSideLetterboxingEnabled(true);
+    } else if (base::FeatureList::IsEnabled(
+                   features::kCastDisableLetterboxing)) {
       mirror_settings_.SetSenderSideLetterboxingEnabled(false);
     } else {
       // Enable sender-side letterboxing if the receiver specifically does not
@@ -725,7 +736,11 @@
               &Session::CreateAudioStream, base::Unretained(this))),
           media::AudioInputDevice::Purpose::kLoopback,
           media::AudioInputDevice::DeadStreamDetection::kEnabled);
-      audio_input_device_->Initialize(mirror_settings_.GetAudioCaptureParams(),
+      const media::AudioParameters& capture_params =
+          mirror_settings_.GetAudioCaptureParams();
+      LogInfoMessage(base::StrCat({"Creating AudioInputDevice with params ",
+                                   capture_params.AsHumanReadableString()}));
+      audio_input_device_->Initialize(capture_params,
                                       audio_capturing_callback_.get());
       audio_input_device_->Start();
     }
@@ -749,6 +764,10 @@
         mojo::PendingRemote<media::mojom::VideoCaptureHost> video_host;
         resource_provider_->GetVideoCaptureHost(
             video_host.InitWithNewPipeAndPassReceiver());
+        const media::VideoCaptureParams& capture_params =
+            mirror_settings_.GetVideoCaptureParams();
+        LogInfoMessage(base::StrCat({"Starting VideoCaptureHost with params ",
+                                     ToString(capture_params)}));
         video_capture_client_ = std::make_unique<VideoCaptureClient>(
             mirror_settings_.GetVideoCaptureParams(), std::move(video_host));
         video_capture_client_->Start(
@@ -957,12 +976,23 @@
 void Session::RestartMirroringStreaming() {
   if (state_ != REMOTING)
     return;
+
+  // Stop session instead of switching to mirroring when in Remote Playback
+  // mode.
+  if (session_params_.is_remote_playback) {
+    StopSession();
+    return;
+  }
+
   StopStreaming();
   state_ = MIRRORING;
   CreateAndSendOffer();
 }
 
 void Session::SwitchSourceTab() {
+  if (observer_)
+    observer_->OnSourceChanged();
+
   if (state_ == REMOTING) {
     switching_tab_source_ = true;
     video_capture_client_.reset();
diff --git a/components/mirroring/service/session_unittest.cc b/components/mirroring/service/session_unittest.cc
index 09ff093..a045c7e 100644
--- a/components/mirroring/service/session_unittest.cc
+++ b/components/mirroring/service/session_unittest.cc
@@ -123,22 +123,22 @@
   ~SessionTest() override { task_environment_.RunUntilIdle(); }
 
  protected:
-  // mojom::SessionObserver implemenation.
-  MOCK_METHOD1(OnError, void(SessionError));
-  MOCK_METHOD0(DidStart, void());
-  MOCK_METHOD0(DidStop, void());
-  MOCK_METHOD1(LogInfoMessage, void(const std::string&));
-  MOCK_METHOD1(LogErrorMessage, void(const std::string&));
+  // mojom::SessionObserver implementation.
+  MOCK_METHOD(void, OnError, (SessionError));
+  MOCK_METHOD(void, DidStart, ());
+  MOCK_METHOD(void, DidStop, ());
+  MOCK_METHOD(void, LogInfoMessage, (const std::string&));
+  MOCK_METHOD(void, LogErrorMessage, (const std::string&));
+  MOCK_METHOD(void, OnSourceChanged, ());
 
-  MOCK_METHOD0(OnGetVideoCaptureHost, void());
-  MOCK_METHOD0(OnGetNetworkContext, void());
-  MOCK_METHOD0(OnCreateAudioStream, void());
-  MOCK_METHOD0(OnConnectToRemotingSource, void());
+  MOCK_METHOD(void, OnGetVideoCaptureHost, ());
+  MOCK_METHOD(void, OnGetNetworkContext, ());
+  MOCK_METHOD(void, OnCreateAudioStream, ());
+  MOCK_METHOD(void, OnConnectToRemotingSource, ());
 
-  // Called when sends an outbound message.
-  MOCK_METHOD1(OnOutboundMessage, void(const std::string& message_type));
+  MOCK_METHOD(void, OnOutboundMessage, (const std::string& message_type));
 
-  MOCK_METHOD0(OnInitDone, void());
+  MOCK_METHOD(void, OnInitDone, ());
 
   // mojom::CastMessageChannel implementation (outbound messages).
   void OnMessage(mojom::CastMessagePtr message) override {
@@ -253,8 +253,10 @@
   }
 
   // Create a mirroring session. Expect to send OFFER message.
-  void CreateSession(SessionType session_type) {
+  void CreateSession(SessionType session_type,
+                     bool is_remote_playback = false) {
     session_type_ = session_type;
+    is_remote_playback_ = is_remote_playback;
     mojom::SessionParametersPtr session_params =
         mojom::SessionParameters::New();
     session_params->receiver_address = receiver_endpoint_.address();
@@ -264,6 +266,7 @@
       session_params->target_playout_delay =
           base::Milliseconds(target_playout_delay_ms_);
     }
+    session_params->is_remote_playback = is_remote_playback_;
     cast_mode_ = "mirroring";
     mojo::PendingRemote<mojom::ResourceProvider> resource_provider_remote;
     mojo::PendingRemote<mojom::SessionObserver> session_observer_remote;
@@ -301,7 +304,9 @@
     EXPECT_CALL(*this, OnGetVideoCaptureHost()).Times(num_to_get_video_host);
     EXPECT_CALL(*this, OnCreateAudioStream()).Times(num_to_create_audio_stream);
     EXPECT_CALL(*this, OnError(_)).Times(0);
-    EXPECT_CALL(*this, OnOutboundMessage("GET_CAPABILITIES")).Times(1);
+    if (!is_remote_playback_) {
+      EXPECT_CALL(*this, OnOutboundMessage("GET_CAPABILITIES")).Times(1);
+    }
     EXPECT_CALL(*this, DidStart()).Times(1);
     SendAnswer();
     task_environment_.RunUntilIdle();
@@ -392,7 +397,7 @@
     Mock::VerifyAndClear(&remoting_source_);
   }
 
-  void StopRemoting() {
+  void StopRemotingAndRestartMirroring() {
     ASSERT_EQ(cast_mode_, "remoting");
     const RemotingStopReason reason = RemotingStopReason::LOCAL_PLAYBACK;
     // Expect to send OFFER message to fallback on mirroring.
@@ -405,6 +410,19 @@
     Mock::VerifyAndClear(&remoting_source_);
   }
 
+  void StopRemotingAndStopSession() {
+    ASSERT_EQ(cast_mode_, "remoting");
+    const RemotingStopReason reason = RemotingStopReason::LOCAL_PLAYBACK;
+    EXPECT_CALL(remoting_source_, OnStopped(reason));
+    if (video_host_)
+      EXPECT_CALL(*video_host_, OnStopped());
+    EXPECT_CALL(*this, DidStop());
+    remoter_->Stop(reason);
+    task_environment_.RunUntilIdle();
+    Mock::VerifyAndClear(this);
+    Mock::VerifyAndClear(&remoting_source_);
+  }
+
   void SwitchSourceTab() {
     const int get_video_host_call_count =
         session_type_ == SessionType::AUDIO_ONLY ? 0 : 1;
@@ -415,7 +433,8 @@
         .Times(get_video_host_call_count);
     EXPECT_CALL(*this, OnCreateAudioStream())
         .Times(create_audio_stream_call_count);
-    EXPECT_CALL(*this, OnConnectToRemotingSource);
+    EXPECT_CALL(*this, OnConnectToRemotingSource());
+    EXPECT_CALL(*this, OnSourceChanged());
 
     if (cast_mode_ == "remoting") {
       EXPECT_CALL(*this, OnOutboundMessage("OFFER"));
@@ -462,6 +481,7 @@
   mojo::Receiver<mojom::CastMessageChannel> outbound_channel_receiver_{this};
   mojo::Remote<mojom::CastMessageChannel> inbound_channel_;
   SessionType session_type_ = SessionType::AUDIO_AND_VIDEO;
+  bool is_remote_playback_ = false;
   mojo::Remote<media::mojom::Remoter> remoter_;
   NiceMock<MockRemotingSource> remoting_source_;
   std::string cast_mode_;
@@ -495,9 +515,7 @@
   StopSession();
 }
 
-TEST_F(SessionTest, AnswerWithConstraintsLetterboxDisabled) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndEnableFeature(features::kCastDisableLetterboxing);
+TEST_F(SessionTest, AnswerWithConstraints) {
   SetAnswer(std::make_unique<openscreen::cast::Answer>(kAnswerWithConstraints));
   media::VideoCaptureParams::SuggestedConstraints expected_constraints = {
       .min_frame_size = gfx::Size(2, 2),
@@ -537,10 +555,18 @@
   SendRemotingCapabilities();
   StartRemoting();
   RemotingStarted();
-  StopRemoting();
+  StopRemotingAndRestartMirroring();
   StopSession();
 }
 
+TEST_F(SessionTest, SwitchFromRemotingForRemotePlayback) {
+  CreateSession(SessionType::AUDIO_AND_VIDEO, true);
+  StartSession();
+  StartRemoting();
+  RemotingStarted();
+  StopRemotingAndStopSession();
+}
+
 TEST_F(SessionTest, StopSessionWhileRemoting) {
   CreateSession(SessionType::AUDIO_AND_VIDEO);
   StartSession();
diff --git a/components/neterror/resources/neterror.js b/components/neterror/resources/neterror.js
index 7c1c2f1..60016e34 100644
--- a/components/neterror/resources/neterror.js
+++ b/components/neterror/resources/neterror.js
@@ -8,6 +8,7 @@
  *   reloadButtonClick: function(string),
  *   detailsButtonClick: function(),
  *   diagnoseErrorsButtonClick: function(),
+ *   portalSigninsButtonClick: function(),
  *   trackEasterEgg: function(),
  *   updateEasterEggHighScore: function(number),
  *   resetEasterEggHighScore: function(),
@@ -61,6 +62,12 @@
   }
 }
 
+function portalSignin() {
+  if (window.errorPageController) {
+    errorPageController.portalSigninButtonClick();
+  }
+}
+
 // Subframes use a different layout but the same html file.  This is to make it
 // easier to support platforms that load the error page via different
 // mechanisms (Currently just iOS). We also use the subframe style for portals
diff --git a/components/ntp_tiles/icon_cacher_impl_unittest.cc b/components/ntp_tiles/icon_cacher_impl_unittest.cc
index fc8dab0b7..0cffc01 100644
--- a/components/ntp_tiles/icon_cacher_impl_unittest.cc
+++ b/components/ntp_tiles/icon_cacher_impl_unittest.cc
@@ -86,8 +86,8 @@
   IconCacherTestBase()
       : favicon_service_(/*favicon_client=*/nullptr, &history_service_) {
     CHECK(history_dir_.CreateUniqueTempDir());
-    CHECK(history_service_.Init(
-        history::HistoryDatabaseParams(history_dir_.GetPath(), 0, 0)));
+    CHECK(history_service_.Init(history::HistoryDatabaseParams(
+        history_dir_.GetPath(), 0, 0, version_info::Channel::UNKNOWN)));
   }
 
   void PreloadIcon(const GURL& url,
diff --git a/components/pdf/renderer/pdf_accessibility_tree.cc b/components/pdf/renderer/pdf_accessibility_tree.cc
index 528578c9..26fd423 100644
--- a/components/pdf/renderer/pdf_accessibility_tree.cc
+++ b/components/pdf/renderer/pdf_accessibility_tree.cc
@@ -68,11 +68,11 @@
   // Sends the given image to the Screen AIService for processing.
   bool ScheduleImageProcessing(
       const chrome_pdf::AccessibilityImageInfo& image,
-      screen_ai::mojom::ScreenAIAnnotator::AnnotateCallback callback) {
+      screen_ai::mojom::ScreenAIAnnotator::PerformOcrCallback callback) {
     if (!screen_ai_annotator_.is_bound())
       return false;
-    screen_ai_annotator_->Annotate(image.image_data, parent_tree_id_,
-                                   std::move(callback));
+    screen_ai_annotator_->PerformOcr(image.image_data, parent_tree_id_,
+                                     std::move(callback));
     return true;
   }
 
diff --git a/components/remote_cocoa/app_shim/bridged_content_view.mm b/components/remote_cocoa/app_shim/bridged_content_view.mm
index 5dda9a9..69aad30 100644
--- a/components/remote_cocoa/app_shim/bridged_content_view.mm
+++ b/components/remote_cocoa/app_shim/bridged_content_view.mm
@@ -59,26 +59,6 @@
                     NSHeight(content_rect) - point_in_window.y);
 }
 
-// Convert a |point| in |source_window|'s AppKit coordinate system (origin at
-// the bottom left of the window) to |target_view|'s coordinate, with the
-// origin at the top left of the view.
-// If |source_window| is nil, |point| will be treated as screen coordinates.
-gfx::Point MovePointToView(const NSPoint& point,
-                           NSWindow* source_window,
-                           NSView* target_view) {
-  NSPoint point_in_screen =
-      source_window ? ui::ConvertPointFromWindowToScreen(source_window, point)
-                    : point;
-
-  NSWindow* target_window = [target_view window];
-  NSPoint point_in_window =
-      ui::ConvertPointFromScreenToWindow(target_window, point_in_screen);
-  NSPoint point_in_view = [target_view convertPoint:point_in_window
-                                           fromView:nil];
-  return gfx::Point(point_in_window.x,
-                    NSHeight([target_view frame]) - point_in_view.y);
-}
-
 // Some keys are silently consumed by -[NSView interpretKeyEvents:]
 // They should not be processed as accelerators.
 // See comments at |keyDown:| for details.
@@ -325,20 +305,8 @@
     return;
   }
 
-  gfx::Point event_location;
-  if (remote_cocoa::IsNSToolbarFullScreenWindow(target)) {
-    // We are in immersive fullscreen. This event is generated from the overlay
-    // window which sits atop the toolbar. Convert the event location to the
-    // content view coordiate, which should have the same bounds as the overlay
-    // window.
-    // This is to handle the case that `target` may contain the titlebar which
-    // the overlay window does not contain. Without this, buttons in the toolbar
-    // are not clickable when the titlebar is revealed.
-    event_location = MovePointToView([theEvent locationInWindow], source, self);
-  } else {
-    event_location =
-        MovePointToWindow([theEvent locationInWindow], source, target);
-  }
+  gfx::Point event_location =
+      MovePointToWindow([theEvent locationInWindow], source, target);
   [self updateTooltipIfRequiredAt:event_location];
 
   if (isScrollEvent) {
diff --git a/components/remote_cocoa/app_shim/immersive_mode_controller.h b/components/remote_cocoa/app_shim/immersive_mode_controller.h
index 528d8eb..f0f0dd4 100644
--- a/components/remote_cocoa/app_shim/immersive_mode_controller.h
+++ b/components/remote_cocoa/app_shim/immersive_mode_controller.h
@@ -54,9 +54,6 @@
   // Start observing child windows of overlay_widget_.
   void ObserveOverlayChildWindows();
 
-  // Reparent children of `source` to `target`.
-  void ReparentChildWindows(NSWindow* source, NSWindow* target);
-
   bool enabled_ = false;
 
   NSWindow* const browser_widget_;
diff --git a/components/remote_cocoa/app_shim/immersive_mode_controller.mm b/components/remote_cocoa/app_shim/immersive_mode_controller.mm
index b5a0366..494df274 100644
--- a/components/remote_cocoa/app_shim/immersive_mode_controller.mm
+++ b/components/remote_cocoa/app_shim/immersive_mode_controller.mm
@@ -10,7 +10,6 @@
 #import "components/remote_cocoa/app_shim/bridged_content_view.h"
 #import "components/remote_cocoa/app_shim/immersive_mode_delegate_mac.h"
 #import "components/remote_cocoa/app_shim/native_widget_mac_nswindow.h"
-#import "components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h"
 #include "ui/gfx/geometry/rect.h"
 
 namespace {
@@ -104,18 +103,15 @@
   base::OnceClosure _view_will_appear_callback;
   base::scoped_nsobject<ImmersiveModeTitlebarObserver>
       _immersive_mode_titlebar_observer;
-  NSWindow* _overlay_window;
 }
 @end
 
 @implementation ImmersiveModeTitlebarViewController
 
-- (instancetype)initWithOverlayWindow:(NSWindow*)overlay_window
-               viewWillAppearCallback:
-                   (base::OnceClosure)view_will_appear_callback {
+- (instancetype)initWithViewWillAppearCallback:
+    (base::OnceClosure)viewWillAppearCallback {
   if ((self = [super init])) {
-    _overlay_window = overlay_window;
-    _view_will_appear_callback = std::move(view_will_appear_callback);
+    _view_will_appear_callback = std::move(viewWillAppearCallback);
   }
   return self;
 }
@@ -143,15 +139,6 @@
     return;
   }
 
-  // Attach overlay_widget to NSToolbarFullScreen so that children are placed on
-  // top of the toolbar.
-  // When exitting fullscreeen, we don't re-parent the overlay window back to
-  // the browser window because it seems to trigger re-entrancy in AppKit and
-  // cause crash.  This is safe because sub-widgets will be re-parented to the
-  // browser window and therefore the overlay window won't have any observable
-  // effect.
-  [self.view.window addChildWindow:_overlay_window ordered:NSWindowAbove];
-
   NSView* view = GetNSTitlebarContainerViewFromWindow(self.view.window);
   DCHECK(view);
   [view addObserver:_immersive_mode_titlebar_observer
@@ -302,8 +289,7 @@
   // overlay_view_.
   immersive_mode_titlebar_view_controller_.reset(
       [[ImmersiveModeTitlebarViewController alloc]
-           initWithOverlayWindow:overlay_widget_
-          viewWillAppearCallback:std::move(callback)]);
+          initWithViewWillAppearCallback:std::move(callback)]);
 
   // Create a NSWindow delegate that will be used to map the AppKit created
   // NSWindow to the overlay view widget's NSWindow.
@@ -355,9 +341,6 @@
   thin_titlebar_view_controller_.get().fullScreenMinHeight =
       kThinControllerHeight;
 
-  // Move sub-widgets from the browser widget to the overlay widget so that
-  // they are rendered above the toolbar.
-  ReparentChildWindows(browser_widget_, overlay_widget_);
   ObserveOverlayChildWindows();
 }
 
@@ -378,9 +361,6 @@
   if (@available(macOS 11.0, *)) {
     browser_widget_.titlebarSeparatorStyle = NSTitlebarSeparatorStyleAutomatic;
   }
-
-  // Move sub-widgets back to the browser widget.
-  ReparentChildWindows(overlay_widget_, browser_widget_);
 }
 
 void ImmersiveModeController::Enable() {
@@ -477,13 +457,6 @@
 
 void ImmersiveModeController::ObserveOverlayChildWindows() {
   // Watch the overlay Widget for new child Widgets.
-  auto observe_window = [this](NSWindow* window) {
-    [window addObserver:immersive_mode_window_observer_
-             forKeyPath:@"visible"
-                options:NSKeyValueObservingOptionInitial |
-                        NSKeyValueObservingOptionNew
-                context:nullptr];
-  };
   NativeWidgetMacNSWindow* overlay_window =
       base::mac::ObjCCastStrict<NativeWidgetMacNSWindow>(overlay_widget_);
   overlay_window.childWindowAddedHandler = ^(NSWindow* child) {
@@ -491,35 +464,12 @@
     if (!child.visible) {
       return;
     }
-    observe_window(child);
+    [child addObserver:immersive_mode_window_observer_
+            forKeyPath:@"visible"
+               options:NSKeyValueObservingOptionInitial |
+                       NSKeyValueObservingOptionNew
+               context:nullptr];
   };
-
-  // TODO(kerenzhu): DCHECK(overlay_window.bridge).
-  // Only in unittests the associated bridges might not exist.
-  if (!overlay_window.bridge)
-    return;
-
-  // Observer child Widgets that exist before entering fullscreen.
-  for (NativeWidgetNSWindowBridge* child_bridge :
-       overlay_window.bridge->child_windows()) {
-    if (child_bridge->window_visible()) {
-      RevealLock();
-      observe_window(child_bridge->ns_window());
-    }
-  }
-}
-
-void ImmersiveModeController::ReparentChildWindows(NSWindow* source,
-                                                   NSWindow* target) {
-  NativeWidgetNSWindowBridge* source_bridge =
-      NativeWidgetNSWindowBridge::GetFromNativeWindow(source);
-  NativeWidgetNSWindowBridge* target_bridge =
-      NativeWidgetNSWindowBridge::GetFromNativeWindow(target);
-
-  // TODO(kerenzhu): DCHECK(source_bridge && target_bridge)
-  // Only in unittests the associated bridges might not exist.
-  if (source_bridge && target_bridge)
-    source_bridge->MoveChildrenTo(target_bridge);
 }
 
 void ImmersiveModeController::RevealLock() {
@@ -529,7 +479,6 @@
 
 void ImmersiveModeController::RevealUnlock() {
   if (--revealed_lock_count_ < 1) {
-    DCHECK_EQ(revealed_lock_count_, 0);
     SetTitlebarPinned(false);
   }
 }
diff --git a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h
index d0247af5..156d06e 100644
--- a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h
+++ b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h
@@ -303,9 +303,6 @@
   // update widget and compositor size.
   void UpdateWindowGeometry();
 
-  // Move `child_windows_` to `target`.
-  void MoveChildrenTo(NativeWidgetNSWindowBridge* target);
-
  private:
   friend class views::test::BridgedNativeWidgetTestApi;
 
diff --git a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
index 75923b09..7fcbaf1 100644
--- a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
+++ b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
@@ -1651,18 +1651,6 @@
     invalidate_shadow_on_frame_swap_ = true;
 }
 
-void NativeWidgetNSWindowBridge::MoveChildrenTo(
-    NativeWidgetNSWindowBridge* target) {
-  // Make a copy of `child_windows_` because it will be updated during the loop.
-  std::vector<NativeWidgetNSWindowBridge*> child_windows(child_windows_);
-  for (NativeWidgetNSWindowBridge* child : child_windows) {
-    if (child != target) {
-      child->SetParent(target->id_);
-      child->host()->OnWindowParentChanged(target->id_);
-    }
-  }
-}
-
 void NativeWidgetNSWindowBridge::UpdateWindowDisplay() {
   if (fullscreen_controller_.IsInFullscreenTransition())
     return;
diff --git a/components/remote_cocoa/common/native_widget_ns_window_host.mojom b/components/remote_cocoa/common/native_widget_ns_window_host.mojom
index e29d17d..354a3b71 100644
--- a/components/remote_cocoa/common/native_widget_ns_window_host.mojom
+++ b/components/remote_cocoa/common/native_widget_ns_window_host.mojom
@@ -164,9 +164,6 @@
   // state has changed.
   OnWindowStateRestorationDataChanged(array<uint8> data);
 
-  // Called when this widget is reparented to another window.
-  OnWindowParentChanged(uint64 new_parent_id);
-
   // Accept or cancel the current dialog window (depending on the value of
   // |button|), if a current dialog exists.
   DoDialogButtonAction(ui.mojom.DialogButton button);
diff --git a/components/reporting/proto/synced/metric_data.proto b/components/reporting/proto/synced/metric_data.proto
index b21d6a7..8642da7e 100644
--- a/components/reporting/proto/synced/metric_data.proto
+++ b/components/reporting/proto/synced/metric_data.proto
@@ -438,11 +438,6 @@
 
 // App telemetry data.
 message AppTelemetry {
-  // App id.
-  optional string app_id = 1;
-  // Type of app being observed.
-  optional apps.ApplicationType app_type = 2;
-
   oneof app_metric_data {
     // App installation data.
     AppInstallData app_install_data = 3;
@@ -450,9 +445,11 @@
     AppUninstallData app_uninstall_data = 4;
     // App launch data.
     AppLaunchData app_launch_data = 5;
-    // App usage data
+    // App usage data.
     AppUsageData app_usage_data = 6;
   }
+
+  reserved 1, 2;
 }
 
 // App installation data.
@@ -463,24 +460,49 @@
   optional apps.ApplicationInstallReason app_install_reason = 2;
   // App installation time depending on the app lifecycle.
   optional apps.ApplicationInstallTime app_install_time = 3;
+  // App id.
+  optional string app_id = 4;
+  // Type of app.
+  optional apps.ApplicationType app_type = 5;
 }
 
 // App launch data.
 message AppLaunchData {
   // App launch source.
   optional apps.ApplicationLaunchSource app_launch_source = 1;
+  // App id.
+  optional string app_id = 2;
+  // Type of app.
+  optional apps.ApplicationType app_type = 3;
 }
 
 // App usage data.
 message AppUsageData {
-  // App foreground running time (in milliseconds).
-  optional int64 running_time_ms = 1;
+  message AppUsage {
+    // App foreground running time (in milliseconds).
+    optional int64 running_time_ms = 1;
+    // App id.
+    optional string app_id = 2;
+    // Type of app.
+    optional apps.ApplicationType app_type = 3;
+    // Application instance id. This will be unique per window/instance.
+    optional string app_instance_id = 4;
+  }
+
+  // Usage data that also includes other app metadata.
+  repeated AppUsage app_usage = 2;
+
+  reserved 1;
 }
 
 // App uninstall data.
 message AppUninstallData {
   // App uninstall source.
   optional apps.ApplicationUninstallSource app_uninstall_source = 1;
+  // App id.
+  optional string app_id = 2;
+  // Type of app.
+  optional apps.ApplicationType app_type = 3;
 }
 
 message PeripheralsTelemetry {
diff --git a/components/services/app_service/public/cpp/icon_coalescer_unittest.cc b/components/services/app_service/public/cpp/icon_coalescer_unittest.cc
index bbf910c..9db25a4 100644
--- a/components/services/app_service/public/cpp/icon_coalescer_unittest.cc
+++ b/components/services/app_service/public/cpp/icon_coalescer_unittest.cc
@@ -10,6 +10,8 @@
 #include "components/services/app_service/public/cpp/icon_coalescer.h"
 #include "components/services/app_service/public/cpp/icon_types.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/image/image_skia_rep.h"
 
 class AppsIconCoalescerTest : public testing::Test {
  protected:
diff --git a/components/services/app_service/public/mojom/types.mojom b/components/services/app_service/public/mojom/types.mojom
index 9858d7a..51cefab 100644
--- a/components/services/app_service/public/mojom/types.mojom
+++ b/components/services/app_service/public/mojom/types.mojom
@@ -7,7 +7,6 @@
 import "mojo/public/mojom/base/file_path.mojom";
 import "mojo/public/mojom/base/safe_base_name.mojom";
 import "mojo/public/mojom/base/time.mojom";
-import "ui/gfx/image/mojom/image.mojom";
 
 // Information about an app. See components/services/app_service/README.md.
 // Mojom App struct is DEPRECATED. When adding new fields, please use the App
@@ -250,51 +249,6 @@
   TriState tristate_value;
 };
 
-struct MenuItem {
-  // The type of the menu item.
-  MenuItemType type;
-
-  // The menu item command id. Used to identify the command when the menu item
-  // is executed.
-  int32 command_id;
-
-  // The grit id of the menu item label. Used when the menu item's type is
-  // kCommand, kRadio, or kSubmenu.
-  int32 string_id;
-
-  // The optional nested submenu item list.
-  array<MenuItem> submenu;
-
-  // The radio group id. All MenuItems with type kRadio will be grouped by this
-  // ID value in the menu.
-  int32 radio_group_id;
-
-  // Publisher-specific shortcut id. May be empty if not required.
-  string shortcut_id;
-
-  // The string label for this menu item. Used when the menu item's type is
-  // kPublisherCommand.
-  string label;
-
-  // The icon for the menu item. May be null if the item doesn't have an icon.
-  gfx.mojom.ImageSkia? image;
-};
-
-// The types of menu items shown in the app list or shelf.
-enum MenuItemType {
-  kCommand,    // Performs an action when selected.
-  kRadio,      // Can be selected/checked among a group of choices.
-  kSeparator,  // Shows a horizontal line separator.
-  kSubmenu,    // Presents a submenu within another menu.
-  kPublisherCommand, // Performs an app publisher shortcut action when selected.
-};
-
-// Which component requests context menus, the app list or shelf.
-enum MenuType {
-  kAppList,
-  kShelf,
-};
-
 // The intent filter matching condition types.
 enum ConditionType {
   kScheme,         // Matches the URL scheme (e.g. https, tel).
diff --git a/components/services/screen_ai/public/mojom/screen_ai_service.mojom b/components/services/screen_ai/public/mojom/screen_ai_service.mojom
index cb2c447..81352e4 100644
--- a/components/services/screen_ai/public/mojom/screen_ai_service.mojom
+++ b/components/services/screen_ai/public/mojom/screen_ai_service.mojom
@@ -11,21 +11,28 @@
 import "ui/accessibility/mojom/ax_tree_id.mojom";
 import "ui/accessibility/mojom/ax_tree_update.mojom";
 
-// Main interface a client uses for Visual Annotation function of Screen AI
-// service. Each browser can have one AXScreenAIAnnotator which contains an
-// ScreenAIAnnotator.
-// All annotators of one browser profile use one ScreenAIService.
+// Main interface a client uses for visual annotation functions of the Screen AI
+// service.
 interface ScreenAIAnnotator {
+  // Receives an image, such as a screenshot or a canvas content, as well as the
+  // ID of the accessibility tree that contains the image (`parent_tree_id`).
+  // It then asks the Screen AI library to perform semantic layout extraction on
+  // the image and returns the ID of the accessibility tree which would be
+  // created by the service containing the output of the library.
+  ExtractSemanticLayout(skia.mojom.BitmapN32 image,
+    ax.mojom.AXTreeID parent_tree_id) =>
+    (ax.mojom.AXTreeID child_tree_id);
+
   // Receives an image, such as a screenshot or a page from a PDF file, as well
   // as the ID of the accessibility tree that contains the image
-  // (`parent_tree_id`). It then asks the Screen AI library to perform object
-  // recognition and OCR on the image. It returns the ID of the accessibility
-  // tree which would be created by the Service containing the output of the
-  // library.
-  Annotate(skia.mojom.BitmapN32 image,
+  // (`parent_tree_id`). It then asks the Screen AI library to perform OCR on
+  // the image. It returns the ID of the accessibility tree which would be
+  // created by the Service containing the output of the library.
+  PerformOcr(skia.mojom.BitmapN32 image,
     ax.mojom.AXTreeID parent_tree_id) =>
     (ax.mojom.AXTreeID child_tree_id);
 };
+
 // This interface sends accessibility messages from the Screen AI Service to
 // `AXScreenAIAnnotator` in the browser process in non-ChromeOS or the extension
 // in ChromeOS.
@@ -42,8 +49,6 @@
 interface Screen2xMainContentExtractor {
   // Receives the accessibility tree, schedules processing, and returns the main
   // content of the given tree.
-  // TODO(https://crbug.com/1278249): Add an interface for sending back the
-  // result.
   ExtractMainContent(ax.mojom.AXTreeUpdate snapshot) =>
     (array<int32> content_node_ids);
 };
diff --git a/components/services/screen_ai/screen_ai_service_impl.cc b/components/services/screen_ai/screen_ai_service_impl.cc
index 7cafd9c..a26f2f0 100644
--- a/components/services/screen_ai/screen_ai_service_impl.cc
+++ b/components/services/screen_ai/screen_ai_service_impl.cc
@@ -211,7 +211,8 @@
 
 LibraryFunctions::LibraryFunctions(const base::FilePath& library_path) {
   library_ = base::ScopedNativeLibrary(library_path);
-  VLOG(2) << "Library load result: " << library_.GetError()->ToString();
+  std::string library_error = library_.GetError()->ToString();
+  DCHECK(library_error.empty()) << library_error;
 
   // General functions.
   get_library_version_ = reinterpret_cast<GetLibraryVersionFn>(
@@ -294,11 +295,12 @@
                                          std::move(main_content_extractor));
 }
 
-// TODO(https://crbug.com/1278249): Update mojo interface to have different
-// entry points for OCR and Layout Extraction requests and remove |Annotate|.
-void ScreenAIService::Annotate(const SkBitmap& image,
-                               const ui::AXTreeID& parent_tree_id,
-                               AnnotationCallback callback) {
+void ScreenAIService::PerformVisualAnnotation(
+    const SkBitmap& image,
+    const ui::AXTreeID& parent_tree_id,
+    AnnotationCallback callback,
+    bool run_ocr,
+    bool run_layout_extraction) {
   std::unique_ptr<ui::AXTreeUpdate> annotation =
       std::make_unique<ui::AXTreeUpdate>();
   ui::AXTreeUpdate* annotation_ptr = annotation.get();
@@ -311,9 +313,9 @@
   // binding the task.
   task_runner_->PostTaskAndReply(
       FROM_HERE,
-      base::BindOnce(&ScreenAIService::OcrInternal,
+      base::BindOnce(&ScreenAIService::VisualAnnotationInternal,
                      weak_ptr_factory_.GetWeakPtr(), std::move(image),
-                     std::move(parent_tree_id),
+                     std::move(parent_tree_id), run_ocr, run_layout_extraction,
                      base::Unretained(annotation_ptr)),
       base::BindOnce(
           [](mojo::Remote<mojom::ScreenAIAnnotatorClient>* client,
@@ -331,17 +333,45 @@
           std::move(annotation)));
 }
 
-void ScreenAIService::OcrInternal(const SkBitmap& image,
-                                  const ui::AXTreeID& parent_tree_id,
-                                  ui::AXTreeUpdate* annotation) {
+void ScreenAIService::ExtractSemanticLayout(const SkBitmap& image,
+                                            const ui::AXTreeID& parent_tree_id,
+                                            AnnotationCallback callback) {
+  PerformVisualAnnotation(std::move(image), parent_tree_id, std::move(callback),
+                          /*run_ocr=*/false,
+                          /*run_layout_extraction=*/true);
+}
+
+void ScreenAIService::PerformOcr(const SkBitmap& image,
+                                 const ui::AXTreeID& parent_tree_id,
+                                 AnnotationCallback callback) {
+  PerformVisualAnnotation(std::move(image), parent_tree_id, std::move(callback),
+                          /*run_ocr=*/true,
+                          /*run_layout_extraction=*/false);
+}
+
+void ScreenAIService::VisualAnnotationInternal(
+    const SkBitmap& image,
+    const ui::AXTreeID& parent_tree_id,
+    bool run_ocr,
+    bool run_layout_extraction,
+    ui::AXTreeUpdate* annotation) {
+  // Currently we only support either of OCR or LayoutExtraction features.
+  DCHECK_NE(run_ocr, run_layout_extraction);
   DCHECK(screen_ai_annotator_client_.is_bound());
 
   char* annotation_proto = nullptr;
   uint32_t annotation_proto_length = 0;
   // TODO(https://crbug.com/1278249): Consider adding a signature that
   // verifies the data integrity and source.
-  if (!CallLibraryOcrFunction(image, annotation_proto,
-                              annotation_proto_length)) {
+  bool result = false;
+  if (run_ocr) {
+    result = CallLibraryOcrFunction(image, annotation_proto,
+                                    annotation_proto_length);
+  } else /* if (run_layout_extraction) */ {
+    result = CallLibraryLayoutExtractionFunction(image, annotation_proto,
+                                                 annotation_proto_length);
+  }
+  if (!result) {
     DCHECK_EQ(annotation->tree_data.tree_id, ui::AXTreeIDUnknown());
     VLOG(1) << "Screen AI library could not process snapshot.";
     return;
@@ -376,6 +406,17 @@
                                           annotation_proto_length);
 }
 
+NO_SANITIZE("cfi-icall")
+bool ScreenAIService::CallLibraryLayoutExtractionFunction(
+    const SkBitmap& image,
+    char*& annotation_proto,
+    uint32_t& annotation_proto_length) {
+  DCHECK(library_functions_);
+  DCHECK(library_functions_->extract_layout_);
+  return library_functions_->extract_layout_(image, annotation_proto,
+                                             annotation_proto_length);
+}
+
 void ScreenAIService::ExtractMainContent(const ui::AXTreeUpdate& snapshot,
                                          ContentExtractionCallback callback) {
   std::unique_ptr<std::vector<int32_t>> content_node_ids =
diff --git a/components/services/screen_ai/screen_ai_service_impl.h b/components/services/screen_ai/screen_ai_service_impl.h
index cee20ea..c07d8da 100644
--- a/components/services/screen_ai/screen_ai_service_impl.h
+++ b/components/services/screen_ai/screen_ai_service_impl.h
@@ -129,9 +129,14 @@
   std::unique_ptr<LibraryFunctions> library_functions_;
 
   // mojom::ScreenAIAnnotator:
-  void Annotate(const SkBitmap& image,
-                const ui::AXTreeID& parent_tree_id,
-                AnnotationCallback callback) override;
+  void ExtractSemanticLayout(const SkBitmap& image,
+                             const ui::AXTreeID& parent_tree_id,
+                             AnnotationCallback callback) override;
+
+  // mojom::ScreenAIAnnotator:
+  void PerformOcr(const SkBitmap& image,
+                  const ui::AXTreeID& parent_tree_id,
+                  AnnotationCallback callback) override;
 
   // mojom::Screen2xMainContentExtractor:
   void ExtractMainContent(const ui::AXTreeUpdate& snapshot,
@@ -155,14 +160,26 @@
       mojo::PendingReceiver<mojom::Screen2xMainContentExtractor>
           main_content_extractor) override;
 
+  // Common section of PerformOcr and ExtractSemanticLayout functions.
+  void PerformVisualAnnotation(const SkBitmap& image,
+                               const ui::AXTreeID& parent_tree_id,
+                               AnnotationCallback callback,
+                               bool run_ocr,
+                               bool run_layout_extraction);
+
   // Wrapper functions for task scheduler.
-  void OcrInternal(const SkBitmap& image,
-                   const ui::AXTreeID& parent_tree_id,
-                   ui::AXTreeUpdate* annotation);
+  void VisualAnnotationInternal(const SkBitmap& image,
+                                const ui::AXTreeID& parent_tree_id,
+                                bool run_ocr,
+                                bool run_layout_extraction,
+                                ui::AXTreeUpdate* annotation);
   void ExtractMainContentInternal(const ui::AXTreeUpdate& snapshot,
                                   std::vector<int32_t>* content_node_ids);
 
   // Library function calls are isolated to have specific compiler directives.
+  bool CallLibraryLayoutExtractionFunction(const SkBitmap& image,
+                                           char*& annotation_proto,
+                                           uint32_t& annotation_proto_length);
   bool CallLibraryOcrFunction(const SkBitmap& image,
                               char*& annotation_proto,
                               uint32_t& annotation_proto_length);
diff --git a/components/services/storage/shared_storage/async_shared_storage_database.h b/components/services/storage/shared_storage/async_shared_storage_database.h
index 738c445..674cec0 100644
--- a/components/services/storage/shared_storage/async_shared_storage_database.h
+++ b/components/services/storage/shared_storage/async_shared_storage_database.h
@@ -62,7 +62,7 @@
 
   // `TrimMemory()`, `Get()`, `Set()`, `Append()`, `Delete()`, `Clear()`,
   // `Length()`, `Keys()`, `Entries()`, `PurgeMatchingOrigins()`,
-  // `PurgeStaleOrigins()`, `FetchOrigins()`, `MakeBudgetWithdrawal()`,
+  // `PurgeStale()`, `FetchOrigins()`, `MakeBudgetWithdrawal()`,
   // `GetRemainingBudget()`, `GetCreationTime()`, `GetMetadata()`, and
   // `GetEntriesForDevTools()` are all async versions of the corresponding
   // methods in `storage::SharedStorageDatabase`, with the modification that
@@ -187,13 +187,13 @@
       base::OnceCallback<void(OperationResult)> callback,
       bool perform_storage_cleanup = false) = 0;
 
-  // Clear all entries for all origins whose `last_read_time` (i.e. creation
-  // time) falls before `SharedStorageDatabase::clock_->Now() -
-  // SharedStorageDatabase::origin_staleness_threshold_`. Also purges, for all
-  // origins, all privacy budget withdrawals that have `time_stamps` older than
-  // `SharedStorageDatabase::clock_->Now() -
-  // SharedStorageDatabase::budget_interval_`.
-  virtual void PurgeStaleOrigins(
+  // Clear all entries whose `last_used_time` (currently the last write access)
+  // falls before `SharedStorageDatabase::clock_->Now() - staleness_threshold_`.
+  // Also purges, for all origins, all privacy budget withdrawals that have
+  // `time_stamps` older than `SharedStorageDatabase::clock_->Now() -
+  // budget_interval_`. The parameter of `callback` reports whether the
+  // transaction was successful.
+  virtual void PurgeStale(
       base::OnceCallback<void(OperationResult)> callback) = 0;
 
   // Fetches a vector of `mojom::StorageUsageInfoPtr`, with one
diff --git a/components/services/storage/shared_storage/async_shared_storage_database_impl.cc b/components/services/storage/shared_storage/async_shared_storage_database_impl.cc
index 867eea08..d955ede 100644
--- a/components/services/storage/shared_storage/async_shared_storage_database_impl.cc
+++ b/components/services/storage/shared_storage/async_shared_storage_database_impl.cc
@@ -169,11 +169,11 @@
       .Then(std::move(callback));
 }
 
-void AsyncSharedStorageDatabaseImpl::PurgeStaleOrigins(
+void AsyncSharedStorageDatabaseImpl::PurgeStale(
     base::OnceCallback<void(OperationResult)> callback) {
   DCHECK(callback);
   DCHECK(database_);
-  database_.AsyncCall(&SharedStorageDatabase::PurgeStaleOrigins)
+  database_.AsyncCall(&SharedStorageDatabase::PurgeStale)
       .Then(std::move(callback));
 }
 
@@ -270,6 +270,18 @@
       .Then(std::move(callback));
 }
 
+void AsyncSharedStorageDatabaseImpl::OverrideLastUsedTimeForTesting(
+    url::Origin context_origin,
+    std::u16string key,
+    base::Time new_last_used_time,
+    base::OnceCallback<void(bool)> callback) {
+  DCHECK(callback);
+  DCHECK(database_);
+  database_.AsyncCall(&SharedStorageDatabase::OverrideLastUsedTimeForTesting)
+      .WithArgs(std::move(context_origin), key, new_last_used_time)
+      .Then(std::move(callback));
+}
+
 void AsyncSharedStorageDatabaseImpl::OverrideSpecialStoragePolicyForTesting(
     scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy) {
   DCHECK(database_);
@@ -281,6 +293,7 @@
 void AsyncSharedStorageDatabaseImpl::OverrideClockForTesting(
     base::Clock* clock,
     base::OnceClosure callback) {
+  DCHECK(callback);
   DCHECK(database_);
   database_.AsyncCall(&SharedStorageDatabase::OverrideClockForTesting)
       .WithArgs(clock)
diff --git a/components/services/storage/shared_storage/async_shared_storage_database_impl.h b/components/services/storage/shared_storage/async_shared_storage_database_impl.h
index 82acd12..56b96af 100644
--- a/components/services/storage/shared_storage/async_shared_storage_database_impl.h
+++ b/components/services/storage/shared_storage/async_shared_storage_database_impl.h
@@ -113,8 +113,7 @@
                             base::Time end,
                             base::OnceCallback<void(OperationResult)> callback,
                             bool perform_storage_cleanup = false) override;
-  void PurgeStaleOrigins(
-      base::OnceCallback<void(OperationResult)> callback) override;
+  void PurgeStale(base::OnceCallback<void(OperationResult)> callback) override;
   void FetchOrigins(base::OnceCallback<
                         void(std::vector<mojom::StorageUsageInfoPtr>)> callback,
                     bool exclude_empty_origins = true) override;
@@ -143,11 +142,18 @@
   // Asynchronously determines the database `InitStatus`. Useful for testing.
   void DBStatusForTesting(base::OnceCallback<void(InitStatus)> callback);
 
-  // Changes `last_used_time` to `new_creation_time` for `context_origin`.
+  // Changes `creation_time` to `new_creation_time` for `context_origin`.
   void OverrideCreationTimeForTesting(url::Origin context_origin,
                                       base::Time new_creation_time,
                                       base::OnceCallback<void(bool)> callback);
 
+  // Changes `last_used_time` to `new_last_used_time` for `context_origin` and
+  // `key`.
+  void OverrideLastUsedTimeForTesting(url::Origin context_origin,
+                                      std::u16string key,
+                                      base::Time new_last_used_time,
+                                      base::OnceCallback<void(bool)> callback);
+
   // Overrides the `SpecialStoragePolicy` for tests.
   void OverrideSpecialStoragePolicyForTesting(
       scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy);
diff --git a/components/services/storage/shared_storage/async_shared_storage_database_impl_unittest.cc b/components/services/storage/shared_storage/async_shared_storage_database_impl_unittest.cc
index 70635e7..2bc8a07 100644
--- a/components/services/storage/shared_storage/async_shared_storage_database_impl_unittest.cc
+++ b/components/services/storage/shared_storage/async_shared_storage_database_impl_unittest.cc
@@ -56,7 +56,7 @@
 using DBType = SharedStorageTestDBType;
 
 const int kBudgetIntervalHours = 24;
-const int kOriginStalenessThresholdDays = 1;
+const int kStalenessThresholdDays = 1;
 const int kBitBudget = 8;
 const int kMaxEntriesPerOrigin = 5;
 const int kMaxStringLength = 100;
@@ -247,13 +247,31 @@
 
     auto callback = receiver_->MakeBoolCallback(
         DBOperation(
-            Type::DB_OVERRIDE_TIME, context_origin,
+            Type::DB_OVERRIDE_TIME_ORIGIN, context_origin,
             {TestDatabaseOperationReceiver::SerializeTime(new_creation_time)}),
         out_success);
     GetImpl()->OverrideCreationTimeForTesting(
         std::move(context_origin), new_creation_time, std::move(callback));
   }
 
+  void OverrideLastUsedTime(url::Origin context_origin,
+                            std::u16string key,
+                            base::Time new_last_used_time,
+                            bool* out_success) {
+    DCHECK(out_success);
+    DCHECK(async_database_);
+    DCHECK(receiver_);
+
+    auto callback = receiver_->MakeBoolCallback(
+        DBOperation(Type::DB_OVERRIDE_TIME_ENTRY, context_origin,
+                    {key, TestDatabaseOperationReceiver::SerializeTime(
+                              new_last_used_time)}),
+        out_success);
+    GetImpl()->OverrideLastUsedTimeForTesting(std::move(context_origin), key,
+                                              new_last_used_time,
+                                              std::move(callback));
+  }
+
   void OverrideClockSync(base::Clock* clock) {
     DCHECK(async_database_);
 
@@ -576,21 +594,21 @@
         std::move(callback), perform_storage_cleanup);
   }
 
-  void PurgeStaleOrigins(OperationResult* out_result) {
+  void PurgeStale(OperationResult* out_result) {
     DCHECK(out_result);
     DCHECK(async_database_);
     DCHECK(receiver_);
 
     auto callback = receiver_->MakeOperationResultCallback(
         DBOperation(Type::DB_PURGE_STALE), out_result);
-    async_database_->PurgeStaleOrigins(std::move(callback));
+    async_database_->PurgeStale(std::move(callback));
   }
 
-  OperationResult PurgeStaleOriginsSync() {
+  OperationResult PurgeStaleSync() {
     DCHECK(async_database_);
 
     base::test::TestFuture<OperationResult> future;
-    async_database_->PurgeStaleOrigins(future.GetCallback());
+    async_database_->PurgeStale(future.GetCallback());
     return future.Get();
   }
 
@@ -833,8 +851,8 @@
          {"SharedStorageBitBudget", base::NumberToString(kBitBudget)},
          {"SharedStorageBudgetInterval",
           TimeDeltaToString(base::Hours(kBudgetIntervalHours))},
-         {"SharedStorageOriginStalenessThreshold",
-          TimeDeltaToString(base::Days(kOriginStalenessThresholdDays))}});
+         {"SharedStorageStalenessThreshold",
+          TimeDeltaToString(base::Days(kStalenessThresholdDays))}});
   }
 };
 
@@ -964,16 +982,16 @@
 
   // Now only the single debit made within the current lookback window is
   // counted, although the entries are still in the table because we haven't
-  // called `PurgeStaleOriginsSync()`.
+  // called `PurgeStaleSync()`.
   EXPECT_DOUBLE_EQ(kBitBudget - 1.0, GetRemainingBudgetSync(kOrigin1).bits);
   EXPECT_DOUBLE_EQ(kBitBudget, GetRemainingBudgetSync(kOrigin2).bits);
   EXPECT_EQ(3, GetNumBudgetEntriesSync(kOrigin1));
   EXPECT_EQ(1, GetNumBudgetEntriesSync(kOrigin2));
   EXPECT_EQ(4, GetTotalNumBudgetEntriesSync());
 
-  // After `PurgeStaleOriginsSync()` runs, there will only be the most
+  // After `PurgeStaleSync()` runs, there will only be the most
   // recent debit left in the budget table
-  EXPECT_EQ(OperationResult::kSuccess, PurgeStaleOriginsSync());
+  EXPECT_EQ(OperationResult::kSuccess, PurgeStaleSync());
   EXPECT_DOUBLE_EQ(kBitBudget - 1.0, GetRemainingBudgetSync(kOrigin1).bits);
   EXPECT_DOUBLE_EQ(kBitBudget, GetRemainingBudgetSync(kOrigin2).bits);
   EXPECT_EQ(1, GetNumBudgetEntriesSync(kOrigin1));
@@ -990,8 +1008,8 @@
   EXPECT_EQ(1, GetNumBudgetEntriesSync(kOrigin1));
   EXPECT_EQ(1, GetTotalNumBudgetEntriesSync());
 
-  // After `PurgeStaleOriginsSync()` runs, the budget table will be empty.
-  EXPECT_EQ(OperationResult::kSuccess, PurgeStaleOriginsSync());
+  // After `PurgeStaleSync()` runs, the budget table will be empty.
+  EXPECT_EQ(OperationResult::kSuccess, PurgeStaleSync());
   EXPECT_DOUBLE_EQ(kBitBudget, GetRemainingBudgetSync(kOrigin1).bits);
   EXPECT_DOUBLE_EQ(kBitBudget, GetRemainingBudgetSync(kOrigin2).bits);
   EXPECT_EQ(0, GetTotalNumBudgetEntriesSync());
@@ -1281,7 +1299,7 @@
 
   // Now only the single debit made within the current lookback window is
   // counted, although the entries are still in the table because we haven't
-  // called `PurgeStaleOrigins()`.
+  // called `PurgeStale()`.
   BudgetResult budget_result13 = MakeBudgetResultForSqlError();
   GetRemainingBudget(kOrigin1, &budget_result13);
   BudgetResult budget_result14 = MakeBudgetResultForSqlError();
@@ -1293,10 +1311,10 @@
   int total_entries6 = -1;
   GetTotalNumBudgetEntries(&total_entries6);
 
-  // After `PurgeStaleOrigins()` runs, there will only be the most
+  // After `PurgeStale()` runs, there will only be the most
   // recent debit left in the budget table.
   OperationResult operation_result5 = OperationResult::kSqlError;
-  PurgeStaleOrigins(&operation_result5);
+  PurgeStale(&operation_result5);
   BudgetResult budget_result15 = MakeBudgetResultForSqlError();
   GetRemainingBudget(kOrigin1, &budget_result15);
   BudgetResult budget_result16 = MakeBudgetResultForSqlError();
@@ -1322,9 +1340,9 @@
   int total_entries8 = -1;
   GetTotalNumBudgetEntries(&total_entries8);
 
-  // After `PurgeStaleOrigins()` runs, the budget table will be empty.
+  // After `PurgeStale()` runs, the budget table will be empty.
   OperationResult operation_result6 = OperationResult::kSqlError;
-  PurgeStaleOrigins(&operation_result6);
+  PurgeStale(&operation_result6);
   BudgetResult budget_result19 = MakeBudgetResultForSqlError();
   GetRemainingBudget(kOrigin1, &budget_result19);
   BudgetResult budget_result20 = MakeBudgetResultForSqlError();
@@ -1382,14 +1400,14 @@
 
   // Now only the single debit made within the current lookback window is
   // counted, although the entries are still in the table because we haven't
-  // called `PurgeStaleOrigins()`.
+  // called `PurgeStale()`.
   EXPECT_DOUBLE_EQ(kBitBudget - 1.0, budget_result13.bits);
   EXPECT_DOUBLE_EQ(kBitBudget, budget_result14.bits);
   EXPECT_EQ(3, num_entries7);
   EXPECT_EQ(1, num_entries8);
   EXPECT_EQ(4, total_entries6);
 
-  // After `PurgeStaleOrigins()` runs, there will only be the most
+  // After `PurgeStale()` runs, there will only be the most
   // recent debit left in the budget table.
   EXPECT_EQ(OperationResult::kSuccess, operation_result5);
   EXPECT_DOUBLE_EQ(kBitBudget - 1.0, budget_result15.bits);
@@ -1405,7 +1423,7 @@
   EXPECT_EQ(1, num_entries11);
   EXPECT_EQ(1, total_entries8);
 
-  // After `PurgeStaleOrigins()` runs, the budget table will be empty.
+  // After `PurgeStale()` runs, the budget table will be empty.
   EXPECT_EQ(OperationResult::kSuccess, operation_result6);
   EXPECT_DOUBLE_EQ(kBitBudget, budget_result19.bits);
   EXPECT_DOUBLE_EQ(kBitBudget, budget_result20.bits);
@@ -1672,7 +1690,7 @@
   EXPECT_EQ(OperationResult::kNotFound, result3.result);
 }
 
-TEST_P(AsyncSharedStorageDatabaseImplParamTest, PurgeStaleOrigins) {
+TEST_P(AsyncSharedStorageDatabaseImplParamTest, PurgeStale) {
   url::Origin kOrigin1 = url::Origin::Create(GURL("http://www.example1.test"));
   url::Origin kOrigin2 = url::Origin::Create(GURL("http://www.example2.test"));
   url::Origin kOrigin3 = url::Origin::Create(GURL("http://www.example3.test"));
@@ -1752,12 +1770,12 @@
       DBOperation(Type::DB_FETCH_ORIGINS,
                   {TestDatabaseOperationReceiver::SerializeBool(true)}));
 
-  base::Time override_time1 =
-      base::Time::Now() - base::Days(kOriginStalenessThresholdDays + 1);
+  base::Time override_time =
+      base::Time::Now() - base::Days(kStalenessThresholdDays + 1);
   operation_list.push(DBOperation(
-      Type::DB_OVERRIDE_TIME, kOrigin1,
-      {TestDatabaseOperationReceiver::SerializeTime(override_time1)}));
-  operation_list.push(DBOperation(Type::DB_GET_CREATION_TIME, kOrigin1));
+      Type::DB_OVERRIDE_TIME_ENTRY, kOrigin1,
+      {u"key1", TestDatabaseOperationReceiver::SerializeTime(override_time)}));
+
   operation_list.push(DBOperation(Type::DB_PURGE_STALE));
 
   operation_list.push(DBOperation(Type::DB_LENGTH, kOrigin1));
@@ -1771,12 +1789,22 @@
       DBOperation(Type::DB_FETCH_ORIGINS,
                   {TestDatabaseOperationReceiver::SerializeBool(false)}));
 
-  base::Time override_time2 =
-      base::Time::Now() - base::Days(kOriginStalenessThresholdDays + 1);
   operation_list.push(DBOperation(
-      Type::DB_OVERRIDE_TIME, kOrigin3,
-      {TestDatabaseOperationReceiver::SerializeTime(override_time2)}));
+      Type::DB_OVERRIDE_TIME_ORIGIN, kOrigin3,
+      {TestDatabaseOperationReceiver::SerializeTime(override_time)}));
   operation_list.push(DBOperation(Type::DB_GET_CREATION_TIME, kOrigin3));
+  operation_list.push(DBOperation(
+      Type::DB_OVERRIDE_TIME_ENTRY, kOrigin3,
+      {u"key1", TestDatabaseOperationReceiver::SerializeTime(override_time)}));
+  operation_list.push(DBOperation(
+      Type::DB_OVERRIDE_TIME_ENTRY, kOrigin3,
+      {u"key2", TestDatabaseOperationReceiver::SerializeTime(override_time)}));
+  operation_list.push(DBOperation(
+      Type::DB_OVERRIDE_TIME_ENTRY, kOrigin3,
+      {u"key3", TestDatabaseOperationReceiver::SerializeTime(override_time)}));
+  operation_list.push(DBOperation(
+      Type::DB_OVERRIDE_TIME_ENTRY, kOrigin1,
+      {u"key2", TestDatabaseOperationReceiver::SerializeTime(override_time)}));
   operation_list.push(DBOperation(Type::DB_PURGE_STALE));
 
   operation_list.push(DBOperation(Type::DB_LENGTH, kOrigin1));
@@ -1808,7 +1836,7 @@
   std::vector<mojom::StorageUsageInfoPtr> infos1;
   FetchOrigins(&infos1);
 
-  // Check that calling `PurgeStaleOrigins()` on the uninitialized database
+  // Check that calling `PurgeStale()` on the uninitialized database
   // doesn't give an error.
   bool open1 = false;
   IsOpen(&open1);
@@ -1816,7 +1844,7 @@
   DBStatus(&status1);
 
   OperationResult result1 = OperationResult::kSqlError;
-  PurgeStaleOrigins(&result1);
+  PurgeStale(&result1);
 
   OperationResult result2 = OperationResult::kSqlError;
   Set(kOrigin1, u"key1", u"value1", &result2);
@@ -1860,13 +1888,10 @@
   FetchOrigins(&infos2);
 
   bool success1 = false;
-  OverrideCreationTime(kOrigin1, override_time1, &success1);
-
-  TimeResult time_result1;
-  GetCreationTime(kOrigin1, &time_result1);
+  OverrideLastUsedTime(kOrigin1, u"key1", override_time, &success1);
 
   OperationResult result12 = OperationResult::kSqlError;
-  PurgeStaleOrigins(&result12);
+  PurgeStale(&result12);
 
   int length5 = -1;
   Length(kOrigin1, &length5);
@@ -1883,13 +1908,22 @@
   FetchOrigins(&infos4, /*exclude_empty_origins=*/false);
 
   bool success2 = false;
-  OverrideCreationTime(kOrigin3, override_time2, &success2);
+  OverrideCreationTime(kOrigin3, override_time, &success2);
 
-  TimeResult time_result2;
-  GetCreationTime(kOrigin3, &time_result2);
+  TimeResult time_result;
+  GetCreationTime(kOrigin3, &time_result);
+
+  bool success3 = false;
+  OverrideLastUsedTime(kOrigin3, u"key1", override_time, &success3);
+  bool success4 = false;
+  OverrideLastUsedTime(kOrigin3, u"key2", override_time, &success4);
+  bool success5 = false;
+  OverrideLastUsedTime(kOrigin3, u"key3", override_time, &success5);
+  bool success6 = false;
+  OverrideLastUsedTime(kOrigin1, u"key2", override_time, &success6);
 
   OperationResult result13 = OperationResult::kSqlError;
-  PurgeStaleOrigins(&result13);
+  PurgeStale(&result13);
 
   int length9 = -1;
   Length(kOrigin1, &length9);
@@ -1920,7 +1954,7 @@
   EXPECT_EQ(!GetParam().in_memory_only, open1);
   EXPECT_EQ(InitStatus::kUnattempted, status1);
 
-  // No error from calling `PurgeStaleOrigins()` on an uninitialized
+  // No error from calling `PurgeStale()` on an uninitialized
   // database.
   EXPECT_EQ(OperationResult::kSuccess, result1);
 
@@ -1952,11 +1986,10 @@
   EXPECT_THAT(origins, ElementsAre(kOrigin1, kOrigin2, kOrigin3, kOrigin4));
 
   EXPECT_TRUE(success1);
-  EXPECT_EQ(override_time1, time_result1.time);
   EXPECT_EQ(OperationResult::kSuccess, result12);
 
-  // `kOrigin1` is cleared. The other origins are not.
-  EXPECT_EQ(0, length5);
+  // `kOrigin1` has 1 key cleared. The other origins are not modified.
+  EXPECT_EQ(1, length5);
   EXPECT_EQ(1, length6);
   EXPECT_EQ(3, length7);
   EXPECT_EQ(4, length8);
@@ -1964,18 +1997,24 @@
   origins.clear();
   for (const auto& info : infos3)
     origins.push_back(info->storage_key.origin());
-  EXPECT_THAT(origins, ElementsAre(kOrigin2, kOrigin3, kOrigin4));
+  EXPECT_THAT(origins, ElementsAre(kOrigin1, kOrigin2, kOrigin3, kOrigin4));
 
   origins.clear();
   for (const auto& info : infos4)
     origins.push_back(info->storage_key.origin());
-  EXPECT_THAT(origins, ElementsAre(kOrigin2, kOrigin3, kOrigin4));
+  EXPECT_THAT(origins, ElementsAre(kOrigin1, kOrigin2, kOrigin3, kOrigin4));
 
   EXPECT_TRUE(success2);
-  EXPECT_EQ(override_time2, time_result2.time);
+  EXPECT_EQ(override_time, time_result.time);
+
+  EXPECT_TRUE(success3);
+  EXPECT_TRUE(success4);
+  EXPECT_TRUE(success5);
+  EXPECT_TRUE(success6);
+
   EXPECT_EQ(OperationResult::kSuccess, result13);
 
-  // `kOrigin3` is cleared. The other remaining ones are not.
+  // `kOrigin1` and `kOrigin3` are cleared. The remaining ones are not modified.
   EXPECT_EQ(0, length9);
   EXPECT_EQ(1, length10);
   EXPECT_EQ(0, length11);
@@ -1986,10 +2025,12 @@
     origins.push_back(info->storage_key.origin());
   EXPECT_THAT(origins, ElementsAre(kOrigin2, kOrigin4));
 
+  // `kOrigin1` is still in `per_origin_mapping` even though it has no entries,
+  // as we didn't override its creation time to be old enough to have expired.
   origins.clear();
   for (const auto& info : infos6)
     origins.push_back(info->storage_key.origin());
-  EXPECT_THAT(origins, ElementsAre(kOrigin2, kOrigin4));
+  EXPECT_THAT(origins, ElementsAre(kOrigin1, kOrigin2, kOrigin4));
 
   // Database is still intact after trimming memory.
   EXPECT_EQ(OperationResult::kSuccess, result14);
@@ -2137,7 +2178,7 @@
   base::Time threshold2 = base::Time::Now() + base::Seconds(100);
   base::Time override_time1 = threshold2 + base::Milliseconds(5);
   operation_list.push(DBOperation(
-      Type::DB_OVERRIDE_TIME, kOrigin1,
+      Type::DB_OVERRIDE_TIME_ORIGIN, kOrigin1,
       {TestDatabaseOperationReceiver::SerializeTime(override_time1)}));
 
   size_t matcher_id2 =
@@ -2165,12 +2206,12 @@
 
   base::Time threshold3 = base::Time::Now() + base::Seconds(200);
   operation_list.push(
-      DBOperation(Type::DB_OVERRIDE_TIME, kOrigin3,
+      DBOperation(Type::DB_OVERRIDE_TIME_ORIGIN, kOrigin3,
                   {TestDatabaseOperationReceiver::SerializeTime(threshold3)}));
 
   base::Time threshold4 = threshold3 + base::Seconds(100);
   operation_list.push(
-      DBOperation(Type::DB_OVERRIDE_TIME, kOrigin5,
+      DBOperation(Type::DB_OVERRIDE_TIME_ORIGIN, kOrigin5,
                   {TestDatabaseOperationReceiver::SerializeTime(threshold4)}));
 
   size_t matcher_id3 = matcher_utility.RegisterMatcherFunction(
diff --git a/components/services/storage/shared_storage/shared_storage_database.cc b/components/services/storage/shared_storage/shared_storage_database.cc
index 77030c7c..cbee0b2 100644
--- a/components/services/storage/shared_storage/shared_storage_database.cc
+++ b/components/services/storage/shared_storage/shared_storage_database.cc
@@ -76,6 +76,9 @@
   if (!db.Execute(kValuesMappingSql))
     return false;
 
+  // Note that `length` tracks the total number of entries in `values_mapping`
+  // for `context_origin`, including any expired by not yet purged entries. The
+  // `Length()` method below returns the count of only the unexpired entries.
   static constexpr char kPerOriginMappingSql[] =
       "CREATE TABLE IF NOT EXISTS per_origin_mapping("
       "context_origin TEXT NOT NULL PRIMARY KEY,"
@@ -201,7 +204,7 @@
           static_cast<size_t>(options->max_iterator_batch_size)),
       bit_budget_(static_cast<double>(options->bit_budget)),
       budget_interval_(options->budget_interval),
-      origin_staleness_threshold_(options->origin_staleness_threshold),
+      staleness_threshold_(options->staleness_threshold),
       clock_(base::DefaultClock::GetInstance()) {
   DCHECK(!is_filebacked() || db_path_.IsAbsolute());
   db_file_status_ = is_filebacked() ? DBFileStatus::kNotChecked
@@ -257,8 +260,12 @@
   statement.BindString16(1, key);
 
   if (statement.Step()) {
-    return GetResult(statement.ColumnString16(0), statement.ColumnTime(1),
-                     OperationResult::kSuccess);
+    base::Time last_used_time = statement.ColumnTime(1);
+    OperationResult op_result =
+        (last_used_time >= clock_->Now() - staleness_threshold_)
+            ? OperationResult::kSuccess
+            : OperationResult::kExpired;
+    return GetResult(statement.ColumnString16(0), last_used_time, op_result);
   }
 
   if (!statement.Succeeded())
@@ -286,16 +293,19 @@
 
   GetResult get_result = Get(context_origin, key);
   if (get_result.result != OperationResult::kSuccess &&
-      get_result.result != OperationResult::kNotFound) {
+      get_result.result != OperationResult::kNotFound &&
+      get_result.result != OperationResult::kExpired) {
     return OperationResult::kSqlError;
   }
 
   std::string origin_str(SerializeOrigin(context_origin));
-  if (get_result.result == OperationResult::kSuccess) {
+  if (get_result.result == OperationResult::kSuccess ||
+      get_result.result == OperationResult::kExpired) {
     if (Delete(context_origin, key) != OperationResult::kSuccess)
       return OperationResult::kSqlError;
 
-    if (behavior == SharedStorageDatabase::SetBehavior::kIgnoreIfPresent) {
+    if (behavior == SharedStorageDatabase::SetBehavior::kIgnoreIfPresent &&
+        get_result.result != OperationResult::kExpired) {
       // We re-insert the old key-value pair with an updated `last_used_time`.
       if (!InsertIntoValuesMapping(origin_str, key, get_result.data))
         return OperationResult::kSqlError;
@@ -335,7 +345,8 @@
 
   GetResult get_result = Get(context_origin, key);
   if (get_result.result != OperationResult::kSuccess &&
-      get_result.result != OperationResult::kNotFound) {
+      get_result.result != OperationResult::kNotFound &&
+      get_result.result != OperationResult::kExpired) {
     return OperationResult::kSqlError;
   }
 
@@ -351,6 +362,11 @@
 
     if (Delete(context_origin, key) != OperationResult::kSuccess)
       return OperationResult::kSqlError;
+  } else if (get_result.result == OperationResult::kExpired) {
+    new_value = std::move(tail_value);
+
+    if (Delete(context_origin, key) != OperationResult::kSuccess)
+      return OperationResult::kSqlError;
   } else {
     new_value = std::move(tail_value);
 
@@ -439,12 +455,7 @@
       return -1;
   }
 
-  std::string origin_str(SerializeOrigin(context_origin));
-  int64_t length = NumEntries(origin_str);
-  if (!length)
-    return 0L;
-
-  return length;
+  return NumEntriesManualCount(SerializeOrigin(context_origin));
 }
 
 SharedStorageDatabase::OperationResult SharedStorageDatabase::Keys(
@@ -475,19 +486,10 @@
     }
   }
 
-  static constexpr char kCountSql[] =
-      "SELECT COUNT(*) FROM values_mapping WHERE context_origin=?";
-
-  sql::Statement count_statement(
-      db_.GetCachedStatement(SQL_FROM_HERE, kCountSql));
   std::string origin_str(SerializeOrigin(context_origin));
-  count_statement.BindString(0, origin_str);
+  int64_t key_count = NumEntriesManualCount(origin_str);
 
-  int64_t key_count = 0;
-  if (count_statement.Step())
-    key_count = count_statement.ColumnInt64(0);
-
-  if (!count_statement.Succeeded()) {
+  if (key_count == -1) {
     keys_listener->DidReadEntries(
         /*success=*/false, "SQL database could not retrieve key count.",
         /*entries=*/{}, /*has_more_entries=*/false, /*total_queued_to_send=*/0);
@@ -510,11 +512,14 @@
   }
 
   static constexpr char kSelectSql[] =
-      "SELECT key FROM values_mapping WHERE context_origin=? ORDER BY key";
+      "SELECT key FROM values_mapping "
+      "WHERE context_origin=? AND last_used_time>=? "
+      "ORDER BY key";
 
   sql::Statement select_statement(
       db_.GetCachedStatement(SQL_FROM_HERE, kSelectSql));
   select_statement.BindString(0, origin_str);
+  select_statement.BindTime(1, clock_->Now() - staleness_threshold_);
 
   bool has_more_entries = true;
   absl::optional<std::u16string> saved_first_key_for_next_batch;
@@ -592,19 +597,10 @@
     }
   }
 
-  static constexpr char kCountSql[] =
-      "SELECT COUNT(*) FROM values_mapping WHERE context_origin=?";
-
-  sql::Statement count_statement(
-      db_.GetCachedStatement(SQL_FROM_HERE, kCountSql));
   std::string origin_str(SerializeOrigin(context_origin));
-  count_statement.BindString(0, origin_str);
+  int64_t entry_count = NumEntriesManualCount(origin_str);
 
-  int64_t entry_count = 0;
-  if (count_statement.Step())
-    entry_count = count_statement.ColumnInt64(0);
-
-  if (!count_statement.Succeeded()) {
+  if (entry_count == -1) {
     entries_listener->DidReadEntries(
         /*success=*/false, "SQL database could not retrieve entry count.",
         /*entries=*/{}, /*has_more_entries=*/false, /*total_queued_to_send=*/0);
@@ -627,12 +623,14 @@
   }
 
   static constexpr char kSelectSql[] =
-      "SELECT key,value FROM values_mapping WHERE context_origin=? "
+      "SELECT key,value FROM values_mapping "
+      "WHERE context_origin=? AND last_used_time>=? "
       "ORDER BY key";
 
   sql::Statement select_statement(
       db_.GetCachedStatement(SQL_FROM_HERE, kSelectSql));
   select_statement.BindString(0, origin_str);
+  select_statement.BindTime(1, clock_->Now() - staleness_threshold_);
 
   bool has_more_entries = true;
   absl::optional<std::u16string> saved_first_key_for_next_batch;
@@ -751,10 +749,9 @@
   return OperationResult::kSuccess;
 }
 
-SharedStorageDatabase::OperationResult
-SharedStorageDatabase::PurgeStaleOrigins() {
+SharedStorageDatabase::OperationResult SharedStorageDatabase::PurgeStale() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK_GT(origin_staleness_threshold_, base::TimeDelta());
+  DCHECK_GT(staleness_threshold_, base::TimeDelta());
 
   if (LazyInit(DBCreationPolicy::kIgnoreIfAbsent) != InitStatus::kSuccess) {
     // We do not return an error if the database doesn't exist, but only if it
@@ -765,39 +762,71 @@
       return OperationResult::kInitFailure;
   }
 
-  static constexpr char kSelectSql[] =
-      "SELECT context_origin FROM per_origin_mapping "
-      "WHERE creation_time<? "
-      "ORDER BY creation_time";
-  sql::Statement select_statement(
-      db_.GetCachedStatement(SQL_FROM_HERE, kSelectSql));
-  select_statement.BindTime(0, clock_->Now() - origin_staleness_threshold_);
-
-  std::vector<std::string> stale_origins;
-
-  while (select_statement.Step())
-    stale_origins.push_back(select_statement.ColumnString(0));
-
-  if (!select_statement.Succeeded())
-    return OperationResult::kSqlError;
-
   sql::Transaction transaction(&db_);
   if (!transaction.Begin())
     return OperationResult::kSqlError;
 
-  for (const auto& origin : stale_origins) {
-    if (!Purge(origin, /*delete_origin_if_empty=*/true))
+  static constexpr char kDeleteEntriesSql[] =
+      "DELETE FROM values_mapping WHERE last_used_time<?";
+  sql::Statement entries_statement(
+      db_.GetCachedStatement(SQL_FROM_HERE, kDeleteEntriesSql));
+  entries_statement.BindTime(0, clock_->Now() - staleness_threshold_);
+
+  // Delete expired entries.
+  if (!entries_statement.Run())
+    return OperationResult::kSqlError;
+
+  static constexpr char kSelectSql[] =
+      "SELECT context_origin,creation_time,length FROM per_origin_mapping "
+      "ORDER BY creation_time";
+  sql::Statement select_statement(
+      db_.GetCachedStatement(SQL_FROM_HERE, kSelectSql));
+
+  // Update `per_origin_mapping` to agree with the correct post-purge `length`s.
+  // Also, for any origins that are now empty and whose `creation_time`s are
+  // prior to the lookback window, remove them from `per_origin_mapping`
+  // entirely.
+  while (select_statement.Step()) {
+    std::string origin = select_statement.ColumnString(0);
+    base::Time creation_time = select_statement.ColumnTime(1);
+    int64_t reported_length = select_statement.ColumnInt64(2);
+
+    // We want the count of all entries for this origin. There are unlikely to
+    // be any expired ones, since we just purged them, but one or more
+    // additional unpurged entries could have become expired in the meantime.
+    int64_t actual_length =
+        NumEntriesManualCount(origin, /*include_expired=*/true);
+
+    if (actual_length == -1)
+      return OperationResult::kSqlError;
+
+    if (actual_length == 0 &&
+        creation_time < clock_->Now() - staleness_threshold_) {
+      if (!DeleteFromPerOriginMapping(origin))
+        return OperationResult::kSqlError;
+      continue;
+    }
+
+    if (actual_length == reported_length) {
+      continue;
+    }
+
+    if (!UpdateLength(origin, actual_length - reported_length))
       return OperationResult::kSqlError;
   }
 
-  static constexpr char kDeleteSql[] =
+  if (!select_statement.Succeeded())
+    return OperationResult::kSqlError;
+
+  static constexpr char kDeleteWithdrawalsSql[] =
       "DELETE FROM budget_mapping WHERE time_stamp<?";
 
-  sql::Statement delete_statement(
-      db_.GetCachedStatement(SQL_FROM_HERE, kDeleteSql));
-  delete_statement.BindTime(0, clock_->Now() - budget_interval_);
+  sql::Statement withdrawals_statement(
+      db_.GetCachedStatement(SQL_FROM_HERE, kDeleteWithdrawalsSql));
+  withdrawals_statement.BindTime(0, clock_->Now() - budget_interval_);
 
-  if (!delete_statement.Run())
+  // Remove stale budget withdrawals.
+  if (!withdrawals_statement.Run())
     return OperationResult::kSqlError;
 
   if (!transaction.Commit())
@@ -1001,7 +1030,7 @@
     return false;
   }
 
-  // Don't delete or insert for non-existent origin.
+  // Don't override time for non-existent origin.
   if (result == OperationResult::kNotFound)
     return true;
 
@@ -1009,6 +1038,35 @@
       origin_str, new_creation_time, length, /*force_insertion=*/true);
 }
 
+bool SharedStorageDatabase::OverrideLastUsedTimeForTesting(
+    url::Origin context_origin,
+    std::u16string key,
+    base::Time new_last_used_time) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  if (LazyInit(DBCreationPolicy::kIgnoreIfAbsent) != InitStatus::kSuccess)
+    return false;
+
+  GetResult result = Get(context_origin, key);
+  if (result.result != OperationResult::kSuccess &&
+      result.result != OperationResult::kNotFound) {
+    return false;
+  }
+
+  // Don't override time for non-existent key.
+  if (result.result == OperationResult::kNotFound)
+    return true;
+
+  if (Delete(context_origin, key) != OperationResult::kSuccess)
+    return false;
+
+  if (!InsertIntoValuesMappingWithTime(SerializeOrigin(context_origin), key,
+                                       result.data, new_last_used_time)) {
+    return false;
+  }
+  return true;
+}
+
 void SharedStorageDatabase::OverrideClockForTesting(base::Clock* clock) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(clock);
@@ -1309,7 +1367,8 @@
   return transaction.Commit();
 }
 
-int64_t SharedStorageDatabase::NumEntries(const std::string& context_origin) {
+int64_t SharedStorageDatabase::NumEntriesTotal(
+    const std::string& context_origin) {
   // In theory, there ought to be at most one entry found. But we make no
   // assumption about the state of the disk. In the rare case that multiple
   // entries are found, we return only the `length` from the first entry found.
@@ -1321,10 +1380,35 @@
   sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, kSelectSql));
   statement.BindString(0, context_origin);
 
+  int64_t num_entries = 0;
+  if (statement.Step())
+    num_entries = statement.ColumnInt64(0);
+
+  return num_entries;
+}
+
+int64_t SharedStorageDatabase::NumEntriesManualCount(
+    const std::string& context_origin,
+    bool include_expired) {
+  const char* kCountSql =
+      (include_expired)
+          ? "SELECT COUNT(*) FROM values_mapping WHERE context_origin=?"
+          : "SELECT COUNT(*) FROM values_mapping "
+            "WHERE context_origin=? AND last_used_time>=?";
+
+  sql::Statement statement(db_.GetUniqueStatement(kCountSql));
+  statement.BindString(0, context_origin);
+
+  if (!include_expired)
+    statement.BindTime(1, clock_->Now() - staleness_threshold_);
+
   int64_t length = 0;
   if (statement.Step())
     length = statement.ColumnInt64(0);
 
+  if (!statement.Succeeded())
+    length = -1;
+
   return length;
 }
 
@@ -1401,10 +1485,11 @@
       context_origin, creation_time, new_length, !delete_origin_if_empty);
 }
 
-bool SharedStorageDatabase::InsertIntoValuesMapping(
+bool SharedStorageDatabase::InsertIntoValuesMappingWithTime(
     const std::string& context_origin,
     const std::u16string& key,
-    const std::u16string& value) {
+    const std::u16string& value,
+    base::Time last_used_time) {
   sql::Transaction transaction(&db_);
   if (!transaction.Begin())
     return false;
@@ -1417,7 +1502,7 @@
   statement.BindString(0, context_origin);
   statement.BindString16(1, key);
   statement.BindString16(2, value);
-  statement.BindTime(3, clock_->Now());
+  statement.BindTime(3, last_used_time);
 
   if (!statement.Run())
     return false;
@@ -1428,6 +1513,14 @@
   return transaction.Commit();
 }
 
+bool SharedStorageDatabase::InsertIntoValuesMapping(
+    const std::string& context_origin,
+    const std::u16string& key,
+    const std::u16string& value) {
+  return InsertIntoValuesMappingWithTime(context_origin, key, value,
+                                         clock_->Now());
+}
+
 bool SharedStorageDatabase::DeleteFromPerOriginMapping(
     const std::string& context_origin) {
   static constexpr char kDeleteSql[] =
@@ -1479,7 +1572,7 @@
 }
 
 bool SharedStorageDatabase::HasCapacity(const std::string& context_origin) {
-  return NumEntries(context_origin) < max_entries_per_origin_;
+  return NumEntriesTotal(context_origin) < max_entries_per_origin_;
 }
 
 void SharedStorageDatabase::LogInitHistograms() {
diff --git a/components/services/storage/shared_storage/shared_storage_database.h b/components/services/storage/shared_storage/shared_storage_database.h
index 71c8f1e..f168a0c 100644
--- a/components/services/storage/shared_storage/shared_storage_database.h
+++ b/components/services/storage/shared_storage/shared_storage_database.h
@@ -113,6 +113,7 @@
             // doesn't exist in the database.
     kTooManyFound = 8,  // Result if the number of keys/entries retrieved for
                         // `Keys()`/`Entries()` exceeds INT_MAX.
+    kExpired = 9,       // Result if the retrieved entry is expired.
   };
 
   // Bundles a retrieved string `data` and its last write time `last_used_time`
@@ -229,10 +230,13 @@
   // Releases all non-essential memory associated with this database connection.
   void TrimMemory();
 
-  // Retrieves the `entry` for `context_origin` and `key`. Returns a
-  // struct containing a `value` string if one is found, `absl::nullopt`
-  // otherwise, with a bool `success` indicating whether the transaction was
-  // free of errors.
+  // Retrieves the `value` for `context_origin` and `key`. Returns a
+  // struct containing a `data` string if a `value` is found, with an
+  // `OperationResult` indicating whether the value was found and the
+  // transaction was free of errors.
+  //
+  // If an expired value is found, then `OperationResult::kExpired` is returned;
+  // if no value is found, `OperationResult::kNotFound` is returned.
   //
   // Note that `key` is assumed to be of length at most
   // `max_string_length_`, with the burden on the caller to handle errors for
@@ -240,8 +244,9 @@
   [[nodiscard]] GetResult Get(url::Origin context_origin, std::u16string key);
 
   // Sets an entry for `context_origin` and `key` to have `value`.
-  // If `behavior` is `kIgnoreIfPresent` and an entry already exists for
-  // `context_origin` and `key`, then the table is not modified.
+  // If `behavior` is `kIgnoreIfPresent` and an unexpired entry already exists
+  // for `context_origin` and `key`, then the table is not modified. If an
+  // expired entry is found, the entry is replaced, regardless of `behavior`.
   // Returns an enum indicating whether or not a new entry is added, the request
   // is ignored, or if there is an error.
   //
@@ -257,10 +262,11 @@
       SetBehavior behavior = SetBehavior::kDefault);
 
   // Appends `tail_value` to the end of the current `value`
-  // for `context_origin` and `key`, if `key` exists. If
-  // `key` does not exist, creates an entry for `key` with value
-  // `tail_value`. Returns an enum indicating whether or not an entry is
-  // added/modified or if there is an error.
+  // for `context_origin` and `key`, if `key` exists and is not expired. If
+  // `key` does not exist, creates an entry for `key` with value `tail_value`.
+  // If `key` is expired, creates an entry for `key` with value `tail_value`
+  // after deleting the expired entry. Returns an enum indicating whether or not
+  // an entry is added/modified or if there is an error.
   //
   // Note that `key` and `value` are assumed to be each of length
   // at most `max_string_length_`, with the burden on the caller to handle
@@ -287,25 +293,25 @@
   // successful.
   [[nodiscard]] OperationResult Clear(url::Origin context_origin);
 
-  // Returns the number of entries for `context_origin` in the database, or -1
-  // on error. Note that this call will update the origin's `creation_time`.
+  // Returns the number of unexpired entries for `context_origin` in the
+  // database, or -1 on error.
   // TODO(crbug.com/1277662): Consider renaming to something more descriptive.
   [[nodiscard]] int64_t Length(url::Origin context_origin);
 
-  // From a list of all the keys for `context_origin` taken in lexicographic
-  // order, send batches of keys to the Shared Storage worklet's async iterator
-  // via a remote that consumes `pending_listener`. Returns whether the
-  // operation was successful.
+  // From a list of all the unexpired keys for `context_origin` taken in
+  // lexicographic order, send batches of keys to the Shared Storage worklet's
+  // async iterator via a remote that consumes `pending_listener`. Returns
+  // whether the operation was successful.
   [[nodiscard]] OperationResult Keys(
       const url::Origin& context_origin,
       mojo::PendingRemote<
           shared_storage_worklet::mojom::SharedStorageEntriesListener>
           pending_listener);
 
-  // From a list of all the key-value pairs for `context_origin` taken in
-  // lexicographic order, send batches of key-value pairs to the Shared Storage
-  // worklet's async iterator via a remote that consumes `pending_listener`.
-  // Returns whether the operation was successful.
+  // From a list of all the unexpired key-value pairs for `context_origin` taken
+  // in lexicographic order, send batches of key-value pairs to the Shared
+  // Storage worklet's async iterator via a remote that consumes
+  // `pending_listener`. Returns whether the operation was successful.
   [[nodiscard]] OperationResult Entries(
       const url::Origin& context_origin,
       mojo::PendingRemote<
@@ -322,11 +328,12 @@
       base::Time end,
       bool perform_storage_cleanup = false);
 
-  // Clear all entries for all origins whose `creation_time` falls before
-  // `clock_->Now() - origin_staleness_threshold_`. Also purges, for all
+  // Clear all entries whose `last_used_time` (currently the last write access)
+  // falls before `clock_->Now() - staleness_threshold_`. Also purges, for all
   // origins, all privacy budget withdrawals that have `time_stamps` older than
-  // `clock_->Now() - budget_interval_`.
-  [[nodiscard]] OperationResult PurgeStaleOrigins();
+  // `clock_->Now() - budget_interval_`. Returns whether the transaction was
+  // successful.
+  [[nodiscard]] OperationResult PurgeStale();
 
   // Fetches a vector of `mojom::StorageUsageInfoPtr`, with one
   // `mojom::StorageUsageInfoPtr` for each origin currently using shared
@@ -370,6 +377,13 @@
       url::Origin context_origin,
       base::Time new_creation_time);
 
+  // Changes `last_used_time` to `new_last_used_time` for `context_origin` and
+  // `key`.
+  [[nodiscard]] bool OverrideLastUsedTimeForTesting(
+      url::Origin context_origin,
+      std::u16string key,
+      base::Time new_last_used_time);
+
   // Overrides the clock used to check the time.
   void OverrideClockForTesting(base::Clock* clock);
 
@@ -447,10 +461,19 @@
                            bool delete_origin_if_empty = false)
       VALID_CONTEXT_REQUIRED(sequence_checker_);
 
-  // Returns the number of entries for `context_origin`, i.e. the `length`.
-  // Not named `Length()` to distinguish it from the public method called via
-  // `SequenceBound::AsyncCall()`.
-  [[nodiscard]] int64_t NumEntries(const std::string& context_origin)
+  // Returns the total number of entries for `context_origin`, including any
+  // expired entries for `context_origin` that have not yet been purged.
+  [[nodiscard]] int64_t NumEntriesTotal(const std::string& context_origin)
+      VALID_CONTEXT_REQUIRED(sequence_checker_);
+
+  // Returns the number of entries for `context_origin`, as determined by a
+  // manual "COUNT(*)" query, rather than relying on the `length` recorded in
+  // `per_origin_mapping`. If `include_expired`, then the count is scoped to all
+  // entries; otherwise it is only scoped to entries within the lookback window
+  // determined by `staleness_threshold_`. Returns -1 if there is a database
+  // error.
+  [[nodiscard]] int64_t NumEntriesManualCount(const std::string& context_origin,
+                                              bool include_expired = false)
       VALID_CONTEXT_REQUIRED(sequence_checker_);
 
   // Returns whether an entry exists for `context_origin` and `key`.
@@ -476,6 +499,14 @@
                                   bool delete_origin_if_empty = false)
       VALID_CONTEXT_REQUIRED(sequence_checker_);
 
+  // Inserts a tuple for `(context_origin,key,value,last_used_time)` into
+  // `values_mapping`. Also calls `UpdateLength()` with `delta=1`.
+  [[nodiscard]] bool InsertIntoValuesMappingWithTime(
+      const std::string& context_origin,
+      const std::u16string& key,
+      const std::u16string& value,
+      base::Time last_used_time) VALID_CONTEXT_REQUIRED(sequence_checker_);
+
   // Inserts a tuple for `(context_origin,key,value,clock_->Now())` into
   // `values_mapping` (i.e. uses the current time as `last_used_time`).
   // Also calls `UpdateLength()` with `delta=1`.
@@ -556,9 +587,9 @@
   // Interval over which `bit_budget_` is defined.
   const base::TimeDelta budget_interval_ GUARDED_BY_CONTEXT(sequence_checker_);
 
-  // Length of time between origin creation and origin expiration. When an
-  // origin's data is older than this threshold, it will be auto-purged.
-  const base::TimeDelta origin_staleness_threshold_
+  // Length of time between last key write access and key expiration. When an
+  // entry's data is older than this threshold, it will be auto-purged.
+  const base::TimeDelta staleness_threshold_
       GUARDED_BY_CONTEXT(sequence_checker_);
 
   // Clock used to determine current time. Can be overridden in tests.
diff --git a/components/services/storage/shared_storage/shared_storage_database_unittest.cc b/components/services/storage/shared_storage/shared_storage_database_unittest.cc
index 90bdc0e..28e6c81 100644
--- a/components/services/storage/shared_storage/shared_storage_database_unittest.cc
+++ b/components/services/storage/shared_storage/shared_storage_database_unittest.cc
@@ -39,6 +39,7 @@
 namespace {
 
 using ::testing::ElementsAre;
+using ::testing::Pair;
 using StorageKeyPolicyMatcherFunction =
     SharedStorageDatabase::StorageKeyPolicyMatcherFunction;
 using InitStatus = SharedStorageDatabase::InitStatus;
@@ -48,7 +49,7 @@
 using TimeResult = SharedStorageDatabase::TimeResult;
 
 const int kBudgetIntervalHours = 24;
-const int kOriginStalenessThresholdDays = 1;
+const int kStalenessThresholdDays = 1;
 const int kBitBudget = 8;
 const int kMaxEntriesPerOrigin = 5;
 const int kMaxEntriesPerOriginForIteratorTest = 1000;
@@ -415,7 +416,7 @@
             db_->PurgeMatchingOrigins(StorageKeyPolicyMatcherFunction(),
                                       base::Time::Min(), base::Time::Max(),
                                       /*perform_storage_cleanup=*/false));
-  EXPECT_EQ(OperationResult::kInitFailure, db_->PurgeStaleOrigins());
+  EXPECT_EQ(OperationResult::kInitFailure, db_->PurgeStale());
   EXPECT_EQ(OperationResult::kInitFailure,
             db_->GetEntriesForDevTools(kOrigin).result);
 
@@ -459,6 +460,7 @@
     db_ = std::make_unique<SharedStorageDatabase>(
         db_path, special_storage_policy_, std::move(options));
     db_->OverrideClockForTesting(&clock_);
+    clock_.SetNow(base::Time::Now());
 
     ASSERT_EQ(GetParam().in_memory_only, !db_->is_filebacked());
   }
@@ -478,8 +480,8 @@
          {"SharedStorageBitBudget", base::NumberToString(kBitBudget)},
          {"SharedStorageBudgetInterval",
           TimeDeltaToString(base::Hours(kBudgetIntervalHours))},
-         {"SharedStorageOriginStalenessThreshold",
-          TimeDeltaToString(base::Days(kOriginStalenessThresholdDays))}});
+         {"SharedStorageStalenessThreshold",
+          TimeDeltaToString(base::Days(kStalenessThresholdDays))}});
   }
 
   void CheckInitHistograms() {
@@ -500,8 +502,6 @@
                          testing::PrintToStringParamName());
 
 TEST_P(SharedStorageDatabaseParamTest, BasicOperations) {
-  clock_.SetNow(base::Time::Now());
-
   const url::Origin kOrigin1 =
       url::Origin::Create(GURL("http://www.example1.test"));
   EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key1", u"value1"));
@@ -542,8 +542,6 @@
 }
 
 TEST_P(SharedStorageDatabaseParamTest, IgnoreIfPresent) {
-  clock_.SetNow(base::Time::Now());
-
   const url::Origin kOrigin1 =
       url::Origin::Create(GURL("http://www.example1.test"));
   EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key1", u"value1"));
@@ -624,11 +622,23 @@
   last_used_time1 = db_->Get(kOrigin2, u"key2").last_used_time;
   ASSERT_LE(last_used_time1, now);
   ASSERT_GE(last_used_time1, now - TestTimeouts::action_max_timeout());
+
+  // Advance the clock so that the key expires.
+  clock_.Advance(base::Days(kStalenessThresholdDays) + base::Seconds(1));
+
+  // The expired entry will be replaced instead of ignored.
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin2, u"key2", u"replaced",
+                                            SetBehavior::kIgnoreIfPresent));
+  EXPECT_EQ(db_->Get(kOrigin2, u"key2").data, u"replaced");
+
+  // Verify that there are also no errors when setting a previously expired (but
+  // unexpunged) key with the default behavior.
+  EXPECT_EQ(OperationResult::kSet,
+            db_->Set(kOrigin1, u"key2", u"replaced", SetBehavior::kDefault));
+  EXPECT_EQ(db_->Get(kOrigin1, u"key2").data, u"replaced");
 }
 
 TEST_P(SharedStorageDatabaseParamTest, Append) {
-  clock_.SetNow(base::Time::Now());
-
   const url::Origin kOrigin1 =
       url::Origin::Create(GURL("http://www.example1.test"));
   EXPECT_EQ(OperationResult::kSet, db_->Append(kOrigin1, u"key1", u"value1"));
@@ -641,7 +651,7 @@
   ASSERT_GE(last_used_time1, now - TestTimeouts::action_max_timeout());
 
   // Advance the clock to put distance between the last used times.
-  clock_.Advance(base::Hours(12));
+  clock_.Advance(base::Days(kStalenessThresholdDays / 2.0));
 
   EXPECT_EQ(OperationResult::kSet, db_->Append(kOrigin1, u"key1", u"value1"));
   now = clock_.Now();
@@ -654,7 +664,7 @@
   ASSERT_GE(last_used_time2, now - TestTimeouts::action_max_timeout());
 
   // Advance the clock to put distance between the last used times.
-  clock_.Advance(base::Hours(12));
+  clock_.Advance(base::Days(kStalenessThresholdDays / 2.0));
 
   EXPECT_EQ(OperationResult::kSet, db_->Append(kOrigin1, u"key1", u"value1"));
   now = clock_.Now();
@@ -665,6 +675,92 @@
   ASSERT_GT(last_used_time3, last_used_time2);
   ASSERT_LE(last_used_time3, now);
   ASSERT_GE(last_used_time3, now - TestTimeouts::action_max_timeout());
+
+  // Advance the clock so that the key expires.
+  clock_.Advance(base::Days(kStalenessThresholdDays) + base::Seconds(1));
+
+  // The expired entry will be replaced instead of appended to.
+  EXPECT_EQ(OperationResult::kSet, db_->Append(kOrigin1, u"key1", u"replaced"));
+  EXPECT_EQ(db_->Get(kOrigin1, u"key1").data, u"replaced");
+}
+
+TEST_P(SharedStorageDatabaseParamTest, Get_NonUpdatedKeyExpires) {
+  const url::Origin kOrigin1 =
+      url::Origin::Create(GURL("http://www.example1.test"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key1", u"value1"));
+  base::Time set_time = clock_.Now();
+  GetResult result1 = db_->Get(kOrigin1, u"key1");
+  EXPECT_EQ(result1.data, u"value1");
+  EXPECT_EQ(result1.result, OperationResult::kSuccess);
+
+  // Verify that `result1.last_used_time` is set to `set_time` (within a
+  // tolerance).
+  ASSERT_LE(result1.last_used_time, set_time);
+  ASSERT_GE(result1.last_used_time,
+            set_time - TestTimeouts::action_max_timeout());
+
+  // Advance the clock halfway towards expiration of the key.
+  clock_.Advance(base::Days(kStalenessThresholdDays / 2.0));
+  EXPECT_GT(clock_.Now(), set_time);
+
+  // The information obtained is still the same.
+  GetResult result2 = db_->Get(kOrigin1, u"key1");
+  EXPECT_EQ(result2.data, u"value1");
+  EXPECT_EQ(result2.result, OperationResult::kSuccess);
+  ASSERT_LE(result2.last_used_time, set_time);
+  ASSERT_GE(result2.last_used_time,
+            set_time - TestTimeouts::action_max_timeout());
+
+  // Advance the clock to key expiration time.
+  clock_.Advance(base::Days(kStalenessThresholdDays / 2.0) + base::Seconds(1));
+
+  // The key has expired but not been cleared yet.
+  GetResult result3 = db_->Get(kOrigin1, u"key1");
+  EXPECT_EQ(result3.data, u"value1");
+  EXPECT_EQ(result3.result, OperationResult::kExpired);
+}
+
+TEST_P(SharedStorageDatabaseParamTest, Get_UpdatedKeyRemains) {
+  const url::Origin kOrigin1 =
+      url::Origin::Create(GURL("http://www.example1.test"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key1", u"value1"));
+  base::Time set_time1 = clock_.Now();
+  GetResult result1 = db_->Get(kOrigin1, u"key1");
+  EXPECT_EQ(result1.data, u"value1");
+  EXPECT_EQ(result1.result, OperationResult::kSuccess);
+
+  // Verify that `result1.last_used_time` is set to `set_time` (within a
+  // tolerance).
+  ASSERT_LE(result1.last_used_time, set_time1);
+  ASSERT_GE(result1.last_used_time,
+            set_time1 - TestTimeouts::action_max_timeout());
+
+  // Advance the clock halfway towards expiration of the key.
+  clock_.Advance(base::Days(kStalenessThresholdDays / 2.0));
+
+  // Modify the key.
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key1", u"value2"));
+  base::Time set_time2 = clock_.Now();
+  EXPECT_GT(set_time2, set_time1);
+
+  // The information obtained will be updated, including the `last_used_time`.
+  GetResult result2 = db_->Get(kOrigin1, u"key1");
+  EXPECT_EQ(result2.data, u"value2");
+  EXPECT_EQ(result2.result, OperationResult::kSuccess);
+  ASSERT_LE(result2.last_used_time, set_time2);
+  ASSERT_GE(result2.last_used_time,
+            set_time2 - TestTimeouts::action_max_timeout());
+
+  // Advance the clock to original key expiration time.
+  clock_.Advance(base::Days(kStalenessThresholdDays / 2.0) + base::Seconds(1));
+
+  // The key is not cleared because it has an updated expiration time.
+  GetResult result3 = db_->Get(kOrigin1, u"key1");
+  EXPECT_EQ(result3.data, u"value2");
+  EXPECT_EQ(result3.result, OperationResult::kSuccess);
+  ASSERT_LE(result3.last_used_time, set_time2);
+  ASSERT_GE(result3.last_used_time,
+            set_time2 - TestTimeouts::action_max_timeout());
 }
 
 TEST_P(SharedStorageDatabaseParamTest, Length) {
@@ -696,6 +792,20 @@
   EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key3", u"value3"));
   EXPECT_EQ(3L, db_->Length(kOrigin1));
   EXPECT_EQ(0L, db_->Length(kOrigin2));
+
+  // Advance the clock halfway towards expiration of the keys.
+  clock_.Advance(base::Days(kStalenessThresholdDays / 2.0));
+
+  // Update one entry.
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key1", u"value0"));
+  EXPECT_EQ(3L, db_->Length(kOrigin1));
+
+  // Advance the clock to original key expiration time.
+  clock_.Advance(base::Days(kStalenessThresholdDays / 2.0) + base::Seconds(1));
+
+  // 2 keys for `kOrigin1` have now expired, so `Length()` will not count them
+  // even though they have not been purged yet.
+  EXPECT_EQ(1L, db_->Length(kOrigin1));
 }
 
 TEST_P(SharedStorageDatabaseParamTest, Keys) {
@@ -756,6 +866,26 @@
   EXPECT_THAT(utility.TakeKeysForId(id5), ElementsAre(u"key1", u"key3"));
   EXPECT_EQ(1U, utility.BatchCountForId(id5));
   utility.VerifyNoErrorForId(id5);
+
+  // Advance the clock halfway towards expiration of the keys.
+  clock_.Advance(base::Days(kStalenessThresholdDays / 2.0));
+
+  // Update one entry.
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin2, u"key1", u"value0"));
+  EXPECT_EQ(2L, db_->Length(kOrigin1));
+
+  // Advance the clock to original key expiration time.
+  clock_.Advance(base::Days(kStalenessThresholdDays / 2.0) + base::Seconds(1));
+
+  size_t id6 = utility.RegisterListener();
+  EXPECT_EQ(OperationResult::kSuccess,
+            db_->Keys(kOrigin2, utility.BindNewPipeAndPassRemoteForId(id6)));
+  utility.FlushForId(id6);
+
+  // u"key3" is now expired.
+  EXPECT_THAT(utility.TakeKeysForId(id6), ElementsAre(u"key1"));
+  EXPECT_EQ(1U, utility.BatchCountForId(id6));
+  utility.VerifyNoErrorForId(id6);
 }
 
 TEST_P(SharedStorageDatabaseParamTest, Entries) {
@@ -780,8 +910,7 @@
             db_->Entries(kOrigin1, utility.BindNewPipeAndPassRemoteForId(id2)));
   utility.FlushForId(id2);
   EXPECT_THAT(utility.TakeEntriesForId(id2),
-              ElementsAre(std::make_pair(u"key1", u"value1"),
-                          std::make_pair(u"key2", u"value2")));
+              ElementsAre(Pair(u"key1", u"value1"), Pair(u"key2", u"value2")));
   EXPECT_EQ(1U, utility.BatchCountForId(id2));
   utility.VerifyNoErrorForId(id2);
 
@@ -803,9 +932,8 @@
             db_->Entries(kOrigin2, utility.BindNewPipeAndPassRemoteForId(id4)));
   utility.FlushForId(id4);
   EXPECT_THAT(utility.TakeEntriesForId(id4),
-              ElementsAre(std::make_pair(u"key1", u"value1"),
-                          std::make_pair(u"key2", u"value2"),
-                          std::make_pair(u"key3", u"value3")));
+              ElementsAre(Pair(u"key1", u"value1"), Pair(u"key2", u"value2"),
+                          Pair(u"key3", u"value3")));
   EXPECT_EQ(1U, utility.BatchCountForId(id4));
   utility.VerifyNoErrorForId(id4);
 
@@ -816,10 +944,30 @@
             db_->Entries(kOrigin2, utility.BindNewPipeAndPassRemoteForId(id5)));
   utility.FlushForId(id5);
   EXPECT_THAT(utility.TakeEntriesForId(id5),
-              ElementsAre(std::make_pair(u"key1", u"value1"),
-                          std::make_pair(u"key3", u"value3")));
+              ElementsAre(Pair(u"key1", u"value1"), Pair(u"key3", u"value3")));
   EXPECT_EQ(1U, utility.BatchCountForId(id5));
   utility.VerifyNoErrorForId(id5);
+
+  // Advance the clock halfway towards expiration of the keys.
+  clock_.Advance(base::Days(kStalenessThresholdDays / 2.0));
+
+  // Update one entry.
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin2, u"key1", u"value0"));
+  EXPECT_EQ(2L, db_->Length(kOrigin1));
+
+  // Advance the clock to original key expiration time.
+  clock_.Advance(base::Days(kStalenessThresholdDays / 2.0) + base::Seconds(1));
+
+  size_t id6 = utility.RegisterListener();
+  EXPECT_EQ(OperationResult::kSuccess,
+            db_->Entries(kOrigin2, utility.BindNewPipeAndPassRemoteForId(id6)));
+  utility.FlushForId(id6);
+
+  // u"key3" is now expired.
+  EXPECT_THAT(utility.TakeEntriesForId(id6),
+              ElementsAre(Pair(u"key1", u"value0")));
+  EXPECT_EQ(1U, utility.BatchCountForId(id6));
+  utility.VerifyNoErrorForId(id6);
 }
 
 TEST_P(SharedStorageDatabaseParamTest, Clear) {
@@ -894,8 +1042,6 @@
 }
 
 TEST_P(SharedStorageDatabaseParamTest, MakeBudgetWithdrawal) {
-  clock_.SetNow(base::Time::Now());
-
   // There should be no entries in the budget table.
   EXPECT_EQ(0L, db_->GetTotalNumBudgetEntriesForTesting());
 
@@ -962,16 +1108,16 @@
 
   // Now only the single debit made within the current lookback window is
   // counted, although the entries are still in the table because we haven't
-  // called `PurgeStaleWithdrawals()`.
+  // called `PurgeStale()`.
   EXPECT_DOUBLE_EQ(kBitBudget - 1.0, db_->GetRemainingBudget(kOrigin1).bits);
   EXPECT_DOUBLE_EQ(kBitBudget, db_->GetRemainingBudget(kOrigin2).bits);
   EXPECT_EQ(3L, db_->GetNumBudgetEntriesForTesting(kOrigin1));
   EXPECT_EQ(1L, db_->GetNumBudgetEntriesForTesting(kOrigin2));
   EXPECT_EQ(4L, db_->GetTotalNumBudgetEntriesForTesting());
 
-  // After `PurgeStaleOrigins()` runs, there will only be the most recent
+  // After `PurgeStale()` runs, there will only be the most recent
   // debit left in the budget table.
-  EXPECT_EQ(OperationResult::kSuccess, db_->PurgeStaleOrigins());
+  EXPECT_EQ(OperationResult::kSuccess, db_->PurgeStale());
   EXPECT_DOUBLE_EQ(kBitBudget - 1.0, db_->GetRemainingBudget(kOrigin1).bits);
   EXPECT_DOUBLE_EQ(kBitBudget, db_->GetRemainingBudget(kOrigin2).bits);
   EXPECT_EQ(1L, db_->GetNumBudgetEntriesForTesting(kOrigin1));
@@ -988,8 +1134,8 @@
   EXPECT_EQ(1L, db_->GetNumBudgetEntriesForTesting(kOrigin1));
   EXPECT_EQ(1L, db_->GetTotalNumBudgetEntriesForTesting());
 
-  // After `PurgeStaleOrigins()` runs, the budget table will be empty.
-  EXPECT_EQ(OperationResult::kSuccess, db_->PurgeStaleOrigins());
+  // After `PurgeStale()` runs, the budget table will be empty.
+  EXPECT_EQ(OperationResult::kSuccess, db_->PurgeStale());
   EXPECT_DOUBLE_EQ(kBitBudget, db_->GetRemainingBudget(kOrigin1).bits);
   EXPECT_DOUBLE_EQ(kBitBudget, db_->GetRemainingBudget(kOrigin2).bits);
   EXPECT_EQ(0L, db_->GetTotalNumBudgetEntriesForTesting());
@@ -1049,11 +1195,10 @@
   EXPECT_EQ(3L, db_->Length(kOrigin2));
   base::Time creation_time2 = db_->GetCreationTime(kOrigin2).time;
 
-  clock_.Advance(base::Days(kOriginStalenessThresholdDays) +
-                 base::Microseconds(1));
+  clock_.Advance(base::Days(kStalenessThresholdDays) + base::Microseconds(1));
 
   // Creation time will remain the same when all of `kOrigin1`'s entries are
-  // deleted via `Delete()` after expiration but `PurgeStaleOrigins()` has not
+  // deleted via `Delete()` after expiration but `PurgeStale()` has not
   // yet been called.
   EXPECT_EQ(OperationResult::kSuccess, db_->Delete(kOrigin1, u"key1"));
   EXPECT_EQ(OperationResult::kSuccess, db_->Delete(kOrigin1, u"key2"));
@@ -1061,13 +1206,13 @@
   EXPECT_EQ(creation_time1, db_->GetCreationTime(kOrigin1).time);
 
   // Creation time will remain the same when all of `kOrigin2`'s entries are
-  // deleted via `Clear()` after expiration but `PurgeStaleOrigins()` has not
+  // deleted via `Clear()` after expiration but `PurgeStale()` has not
   // yet been called.
   EXPECT_EQ(OperationResult::kSuccess, db_->Clear(kOrigin2));
   EXPECT_EQ(0L, db_->Length(kOrigin2));
   EXPECT_EQ(creation_time2, db_->GetCreationTime(kOrigin2).time);
 
-  EXPECT_EQ(OperationResult::kSuccess, db_->PurgeStaleOrigins());
+  EXPECT_EQ(OperationResult::kSuccess, db_->PurgeStale());
 
   // Creation times should not be found after a purge of stale origins.
   EXPECT_EQ(OperationResult::kNotFound, db_->GetCreationTime(kOrigin1).result);
@@ -1115,6 +1260,7 @@
     db_ = std::make_unique<SharedStorageDatabase>(
         db_path, special_storage_policy_, std::move(options));
     db_->OverrideClockForTesting(&clock_);
+    clock_.SetNow(base::Time::Now());
   }
 
   void InitSharedStorageFeature() override {
@@ -1208,7 +1354,6 @@
   EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key2", u"value2"));
   EXPECT_EQ(2L, db_->Length(kOrigin1));
 
-  clock_.SetNow(base::Time::Now());
   clock_.Advance(base::Milliseconds(50));
 
   // Time threshold that will be used as a starting point for deletion.
@@ -1229,7 +1374,6 @@
   const url::Origin kOrigin4 =
       url::Origin::Create(GURL("http://www.example4.test"));
 
-  clock_.SetNow(base::Time::Now());
   clock_.Advance(base::Milliseconds(50));
 
   // Time threshold that will be used as a starting point for deletion.
@@ -1296,7 +1440,7 @@
           threshold2, base::Time::Max(), GetParam().perform_storage_cleanup));
 }
 
-TEST_P(SharedStorageDatabaseParamTest, PurgeStaleOrigins) {
+TEST_P(SharedStorageDatabaseParamTest, PurgeStale) {
   EXPECT_TRUE(db_->FetchOrigins().empty());
 
   const url::Origin kOrigin1 =
@@ -1313,10 +1457,22 @@
   EXPECT_EQ(1L, db_->Length(kOrigin2));
   EXPECT_EQ(db_->Get(kOrigin2, u"key1").data, u"value1");
 
-  clock_.SetNow(base::Time::Now());
-  clock_.Advance(base::Days(kOriginStalenessThresholdDays));
+  clock_.Advance(base::Days(kStalenessThresholdDays));
   clock_.Advance(base::Microseconds(1));
 
+  // `Length()` does not count the expired keys.
+  EXPECT_EQ(0L, db_->Length(kOrigin1));
+  EXPECT_EQ(0L, db_->Length(kOrigin2));
+
+  // Update a key and set additional keys.
+  EXPECT_EQ(OperationResult::kSet, db_->Append(kOrigin1, u"key2", u"value2"));
+  EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin1, u"key3", u"value2"));
+  EXPECT_EQ(2L, db_->Length(kOrigin1));
+
+  EXPECT_EQ(OperationResult::kSet,
+            db_->Set(kOrigin2, u"key1", u"value0", SetBehavior::kDefault));
+  EXPECT_EQ(1L, db_->Length(kOrigin2));
+
   const url::Origin kOrigin3 =
       url::Origin::Create(GURL("http://www.example3.test"));
   EXPECT_EQ(OperationResult::kSet, db_->Set(kOrigin3, u"key1", u"value1"));
@@ -1342,36 +1498,52 @@
   EXPECT_LT(db_->GetCreationTime(kOrigin2).time,
             db_->GetCreationTime(kOrigin4).time);
 
-  EXPECT_EQ(OperationResult::kSuccess, db_->PurgeStaleOrigins());
+  EXPECT_EQ(OperationResult::kSuccess, db_->PurgeStale());
 
-  // `kOrigin1` expired.
-  EXPECT_EQ(0L, db_->Length(kOrigin1));
+  // `kOrigin1` had 1 key expire.
+  EXPECT_EQ(2L, db_->Length(kOrigin1));
 
-  // `kOrigin2` expired.
-  EXPECT_EQ(0L, db_->Length(kOrigin2));
+  // `kOrigin2` had no keys expire.
+  EXPECT_EQ(1L, db_->Length(kOrigin2));
 
-  // `kOrigin3` is active.
+  // `kOrigin3` had no keys expire.
   EXPECT_EQ(3L, db_->Length(kOrigin3));
 
-  // `kOrigin4` is active.
+  // `kOrigin4` had no keys expire.
   EXPECT_EQ(4L, db_->Length(kOrigin4));
 
   origins.clear();
   for (const auto& info : db_->FetchOrigins())
     origins.push_back(info->storage_key.origin());
-  EXPECT_THAT(origins, ElementsAre(kOrigin3, kOrigin4));
+  EXPECT_THAT(origins, ElementsAre(kOrigin1, kOrigin2, kOrigin3, kOrigin4));
 
-  clock_.Advance(base::Days(kOriginStalenessThresholdDays));
+  clock_.Advance(base::Days(kStalenessThresholdDays / 2.0));
+
+  // Will not set the new value but will update the write time.
+  EXPECT_EQ(OperationResult::kIgnored, db_->Set(kOrigin4, u"key1", u"value0",
+                                                SetBehavior::kIgnoreIfPresent));
+
+  clock_.Advance(base::Days(kStalenessThresholdDays / 2.0));
   clock_.Advance(base::Microseconds(1));
-  EXPECT_EQ(OperationResult::kSuccess, db_->PurgeStaleOrigins());
 
-  // `kOrigin3` expired.
+  EXPECT_EQ(OperationResult::kSuccess, db_->PurgeStale());
+
+  // `kOrigin1` had all keys expire.
+  EXPECT_EQ(0L, db_->Length(kOrigin1));
+
+  // `kOrigin2` had all keys expire
+  EXPECT_EQ(0L, db_->Length(kOrigin2));
+
+  // `kOrigin3` had all keys expire
   EXPECT_EQ(0L, db_->Length(kOrigin3));
 
-  // `kOrigin4` expired.
-  EXPECT_EQ(0L, db_->Length(kOrigin4));
+  // `kOrigin4` had all but one key expire.
+  EXPECT_EQ(1L, db_->Length(kOrigin4));
 
-  EXPECT_TRUE(db_->FetchOrigins().empty());
+  origins.clear();
+  for (const auto& info : db_->FetchOrigins())
+    origins.push_back(info->storage_key.origin());
+  EXPECT_THAT(origins, ElementsAre(kOrigin4));
 }
 
 TEST_P(SharedStorageDatabaseParamTest, TrimMemory) {
@@ -1507,6 +1679,12 @@
   ASSERT_TRUE(db_);
   ASSERT_TRUE(db_->is_filebacked());
 
+  // Override the clock and set to the last time in the file that is used to set
+  // a `last_used_time` for a value.
+  db_->OverrideClockForTesting(&clock_);
+  clock_.SetNow(base::Time::FromDeltaSinceWindowsEpoch(
+      base::Microseconds(13268941676192362)));
+
   url::Origin google_com = url::Origin::Create(GURL("http://google.com/"));
   TestSharedStorageEntriesListenerUtility utility(
       task_environment_.GetMainThreadTaskRunner());
@@ -1549,6 +1727,12 @@
   ASSERT_TRUE(db_);
   ASSERT_TRUE(db_->is_filebacked());
 
+  // Override the clock and set to the last time in the file that is used to set
+  // a `last_used_time` for a value.
+  db_->OverrideClockForTesting(&clock_);
+  clock_.SetNow(base::Time::FromDeltaSinceWindowsEpoch(
+      base::Microseconds(13268941676192362)));
+
   url::Origin google_com = url::Origin::Create(GURL("http://google.com/"));
   TestSharedStorageEntriesListenerUtility utility(
       task_environment_.GetMainThreadTaskRunner());
diff --git a/components/services/storage/shared_storage/shared_storage_manager.cc b/components/services/storage/shared_storage/shared_storage_manager.cc
index 40b4275..94015caf1d 100644
--- a/components/services/storage/shared_storage/shared_storage_manager.cc
+++ b/components/services/storage/shared_storage/shared_storage_manager.cc
@@ -47,8 +47,8 @@
           base::BindRepeating(&SharedStorageManager::OnMemoryPressure,
                               base::Unretained(this),
                               base::DoNothing()))) {
-  timer_.Start(FROM_HERE, options_->stale_origin_purge_initial_interval,
-               base::BindOnce(&SharedStorageManager::PurgeStaleOrigins,
+  timer_.Start(FROM_HERE, options_->stale_purge_initial_interval,
+               base::BindOnce(&SharedStorageManager::PurgeStale,
                               weak_ptr_factory_.GetWeakPtr()));
 }
 
@@ -340,6 +340,15 @@
           special_storage_policy);
 }
 
+void SharedStorageManager::OverrideClockForTesting(base::Clock* clock,
+                                                   base::OnceClosure callback) {
+  DCHECK(callback);
+  DCHECK(database_);
+  static_cast<AsyncSharedStorageDatabaseImpl*>(database_.get())
+      ->OverrideClockForTesting(  // IN-TEST
+          clock, std::move(callback));
+}
+
 void SharedStorageManager::OverrideDatabaseForTesting(
     std::unique_ptr<AsyncSharedStorageDatabase> override_async_database) {
   database_ = std::move(override_async_database);
@@ -442,25 +451,18 @@
       weak_ptr_factory_.GetWeakPtr(), std::move(callback));
 }
 
-void SharedStorageManager::PurgeStaleOrigins() {
-  // TODO(crbug.com/1317487): Move this DCHECK for
-  // `options_->origin_staleness_threshold` to `SharedStorageOptions` after
-  // removing the parameter from `SharedStorageDatabase::PurgeStaleOrigins()`
-  // and passing into the database constructor instead.
-  DCHECK(!options_->origin_staleness_threshold.is_zero());
+void SharedStorageManager::PurgeStale() {
   DCHECK(database_);
-
-  database_->PurgeStaleOrigins(
-      base::BindOnce(&SharedStorageManager::OnStaleOriginsPurged,
-                     weak_ptr_factory_.GetWeakPtr()));
+  database_->PurgeStale(base::BindOnce(&SharedStorageManager::OnStalePurged,
+                                       weak_ptr_factory_.GetWeakPtr()));
 }
 
-void SharedStorageManager::OnStaleOriginsPurged(OperationResult result) {
+void SharedStorageManager::OnStalePurged(OperationResult result) {
   DCHECK(database_);
   OnOperationResult(result);
 
-  timer_.Start(FROM_HERE, options_->stale_origin_purge_recurring_interval,
-               base::BindOnce(&SharedStorageManager::PurgeStaleOrigins,
+  timer_.Start(FROM_HERE, options_->stale_purge_recurring_interval,
+               base::BindOnce(&SharedStorageManager::PurgeStale,
                               weak_ptr_factory_.GetWeakPtr()));
 }
 
diff --git a/components/services/storage/shared_storage/shared_storage_manager.h b/components/services/storage/shared_storage/shared_storage_manager.h
index b229287..5392f5e 100644
--- a/components/services/storage/shared_storage/shared_storage_manager.h
+++ b/components/services/storage/shared_storage/shared_storage_manager.h
@@ -263,6 +263,8 @@
   void OverrideSpecialStoragePolicyForTesting(
       scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy);
 
+  void OverrideClockForTesting(base::Clock* clock, base::OnceClosure callback);
+
   void OverrideDatabaseForTesting(
       std::unique_ptr<AsyncSharedStorageDatabase> override_async_database);
 
@@ -286,18 +288,16 @@
   base::OnceCallback<void(OperationResult)> GetOperationResultCallback(
       base::OnceCallback<void(OperationResult)> callback);
 
-  // Purges the data for any origins that haven't been written to or read from
-  // for more than the `origin_staleness_threshold_`. Also purges, for all
-  // origins, all privacy budget withdrawals that have `time_stamps` older than
-  // the current time minus `SharedStorageDatabase::budget_interval_`.
-  void PurgeStaleOrigins();
+  // Clear all entries whose `last_used_time` (currently the last write access)
+  // falls before `SharedStorageDatabase::clock_->Now() -
+  // options_->staleness_threshold_`. Also purges, for all origins, all privacy
+  // budget withdrawals that have `time_stamps` older than
+  // `SharedStorageDatabase::clock_->Now() - options_->budget_interval_`. The
+  // parameter of `callback` reports whether the transaction was successful.
+  void PurgeStale();
 
-  // Processes the result of purging stale origins, then purges all privacy
-  // budget withdrawals that have `time_stamps` older than the current time
-  // minus `SharedStorageDatabase::budget_interval_`
-
-  // Starts the `timer_` for the next call to `PurgeStaleOrigins()`.
-  void OnStaleOriginsPurged(OperationResult result);
+  // Starts the `timer_` for the next call to `PurgeStale()`.
+  void OnStalePurged(OperationResult result);
 
   // Records metrics, including how many SQL errors were seen, when destructor
   // is called.
diff --git a/components/services/storage/shared_storage/shared_storage_manager_unittest.cc b/components/services/storage/shared_storage/shared_storage_manager_unittest.cc
index 9020120c..e43d3d1 100644
--- a/components/services/storage/shared_storage/shared_storage_manager_unittest.cc
+++ b/components/services/storage/shared_storage/shared_storage_manager_unittest.cc
@@ -222,8 +222,7 @@
                             bool perform_storage_cleanup = false) override {
     Run(std::move(callback));
   }
-  void PurgeStaleOrigins(
-      base::OnceCallback<void(OperationResult)> callback) override {
+  void PurgeStale(base::OnceCallback<void(OperationResult)> callback) override {
     Run(std::move(callback));
   }
   void FetchOrigins(base::OnceCallback<
@@ -400,11 +399,11 @@
         {blink::features::kSharedStorageAPI},
         // Set these intervals to be long enough not to interfere with the
         // basic tests.
-        {{"SharedStorageStaleOriginPurgeInitialInterval",
+        {{"SharedStorageStalePurgeInitialInterval",
           TimeDeltaToString(base::Hours(kInitialPurgeIntervalHours))},
-         {"SharedStorageStaleOriginPurgeRecurringInterval",
+         {"SharedStorageStalePurgeRecurringInterval",
           TimeDeltaToString(base::Hours(kRecurringPurgeIntervalHours))},
-         {"SharedStorageOriginStalenessThreshold",
+         {"SharedStorageStalenessThreshold",
           TimeDeltaToString(base::Hours(kThresholdHours))},
          {"SharedStorageBitBudget", base::NumberToString(kBitBudget)},
          {"SharedStorageBudgetInterval",
@@ -770,7 +769,7 @@
 
     auto callback = receiver_->MakeBoolCallback(
         DBOperation(
-            Type::DB_OVERRIDE_TIME, context_origin,
+            Type::DB_OVERRIDE_TIME_ORIGIN, context_origin,
             {TestDatabaseOperationReceiver::SerializeTime(new_creation_time)}),
         out_success);
     GetManager()->OverrideCreationTimeForTesting(
@@ -1403,20 +1402,23 @@
   EXPECT_DOUBLE_EQ(kBitBudget, origin3_metadata.remaining_budget);
 }
 
-TEST_P(SharedStorageManagerParamTest, AdvanceTime_StaleOriginsPurged) {
+TEST_P(SharedStorageManagerParamTest, AdvanceTime_StalePurged) {
   url::Origin kOrigin1 = url::Origin::Create(GURL("http://www.example1.test"));
   EXPECT_EQ(OperationResult::kSet, SetSync(kOrigin1, u"key1", u"value1"));
   EXPECT_FALSE(FetchOriginsSync().empty());
 
-  // Initial interval for checking origin staleness is
-  // `kInitialPurgeIntervalHours` hours for this test.
+  // Initial interval for checking staleness is `kInitialPurgeIntervalHours`
+  // hours for this test.
   task_environment_.FastForwardBy(base::Hours(kInitialPurgeIntervalHours));
   EXPECT_FALSE(FetchOriginsSync().empty());
+  EXPECT_LE(GetSync(kOrigin1, u"key1").last_used_time,
+            base::Time::Now() - base::Hours(kInitialPurgeIntervalHours));
   EXPECT_LE(GetCreationTimeSync(kOrigin1).time,
             base::Time::Now() - base::Hours(kInitialPurgeIntervalHours));
 
   // Subsequent intervals are `kRecurringPurgeIntervalHours` hours each.
   task_environment_.FastForwardBy(base::Hours(kRecurringPurgeIntervalHours));
+  EXPECT_EQ(GetSync(kOrigin1, u"key1").data, u"value1");
   EXPECT_FALSE(FetchOriginsSync().empty());
 
   // We have set the staleness threshold to `kThresholdHours` hours for this
@@ -1466,7 +1468,7 @@
   EXPECT_EQ(3, GetTotalNumBudgetEntriesSync());
 
   // Advance partway through the lookback window, to the point where the first
-  // call to `PurgeStaleOrigins()` happens.
+  // call to `PurgeStale()` happens.
   task_environment_.FastForwardBy(base::Hours(kInitialPurgeIntervalHours));
 
   // Remaining budgets continue to take into account the withdrawals above, as
@@ -1486,16 +1488,16 @@
   EXPECT_EQ(4, GetTotalNumBudgetEntriesSync());
 
   // Advance further through the lookback window, to the point where the second
-  // call to `PurgeStaleOrigins()` happens.
+  // call to `PurgeStale()` happens.
   task_environment_.FastForwardBy(base::Hours(kRecurringPurgeIntervalHours));
   // Advance further through the lookback window, to the point where the third
-  // call to `PurgeStaleOrigins()` happens.
+  // call to `PurgeStale()` happens.
   task_environment_.FastForwardBy(base::Hours(kRecurringPurgeIntervalHours));
   // Advance further through the lookback window, to the point where the fourth
-  // call to `PurgeStaleOrigins()` happens.
+  // call to `PurgeStale()` happens.
   task_environment_.FastForwardBy(base::Hours(kRecurringPurgeIntervalHours));
 
-  // After `PurgeStaleOrigins()` runs via the timer, there will only be the most
+  // After `PurgeStale()` runs via the timer, there will only be the most
   // recent debit left in the budget table.
   EXPECT_DOUBLE_EQ(kBitBudget - 1.0, GetRemainingBudgetSync(kOrigin1).bits);
   EXPECT_DOUBLE_EQ(kBitBudget, GetRemainingBudgetSync(kOrigin2).bits);
@@ -1989,7 +1991,7 @@
   base::Time threshold2 = base::Time::Now() + base::Days(1);
   base::Time override_time1 = threshold2 + base::Milliseconds(5);
   operation_list.push(DBOperation(
-      Type::DB_OVERRIDE_TIME, kOrigin1,
+      Type::DB_OVERRIDE_TIME_ORIGIN, kOrigin1,
       {TestDatabaseOperationReceiver::SerializeTime(override_time1)}));
 
   size_t matcher_id2 =
@@ -2014,12 +2016,12 @@
 
   base::Time threshold3 = threshold2 + base::Days(1);
   operation_list.push(
-      DBOperation(Type::DB_OVERRIDE_TIME, kOrigin3,
+      DBOperation(Type::DB_OVERRIDE_TIME_ORIGIN, kOrigin3,
                   {TestDatabaseOperationReceiver::SerializeTime(threshold3)}));
 
   base::Time threshold4 = threshold3 + base::Seconds(100);
   operation_list.push(
-      DBOperation(Type::DB_OVERRIDE_TIME, kOrigin5,
+      DBOperation(Type::DB_OVERRIDE_TIME_ORIGIN, kOrigin5,
                   {TestDatabaseOperationReceiver::SerializeTime(threshold4)}));
 
   size_t matcher_id3 = matcher_utility.RegisterMatcherFunction(
diff --git a/components/services/storage/shared_storage/shared_storage_options.cc b/components/services/storage/shared_storage/shared_storage_options.cc
index 97fd1d9..dbf31671 100644
--- a/components/services/storage/shared_storage/shared_storage_options.cc
+++ b/components/services/storage/shared_storage/shared_storage_options.cc
@@ -30,9 +30,9 @@
       blink::features::kMaxSharedStorageIteratorBatchSize.Get(),
       blink::features::kSharedStorageBitBudget.Get(),
       blink::features::kSharedStorageBudgetInterval.Get(),
-      blink::features::kSharedStorageStaleOriginPurgeInitialInterval.Get(),
-      blink::features::kSharedStorageStaleOriginPurgeRecurringInterval.Get(),
-      blink::features::kSharedStorageOriginStalenessThreshold.Get());
+      blink::features::kSharedStorageStalePurgeInitialInterval.Get(),
+      blink::features::kSharedStorageStalePurgeRecurringInterval.Get(),
+      blink::features::kSharedStorageStalenessThreshold.Get());
 }
 
 SharedStorageOptions::SharedStorageOptions(
@@ -44,9 +44,9 @@
     int max_iterator_batch_size,
     int bit_budget,
     base::TimeDelta budget_interval,
-    base::TimeDelta stale_origin_purge_initial_interval,
-    base::TimeDelta stale_origin_purge_recurring_interval,
-    base::TimeDelta origin_staleness_threshold)
+    base::TimeDelta stale_purge_initial_interval,
+    base::TimeDelta stale_purge_recurring_interval,
+    base::TimeDelta staleness_threshold)
     : max_page_size(max_page_size),
       max_cache_size(max_cache_size),
       max_entries_per_origin(max_entries_per_origin),
@@ -55,10 +55,9 @@
       max_iterator_batch_size(max_iterator_batch_size),
       bit_budget(bit_budget),
       budget_interval(budget_interval),
-      stale_origin_purge_initial_interval(stale_origin_purge_initial_interval),
-      stale_origin_purge_recurring_interval(
-          stale_origin_purge_recurring_interval),
-      origin_staleness_threshold(origin_staleness_threshold) {
+      stale_purge_initial_interval(stale_purge_initial_interval),
+      stale_purge_recurring_interval(stale_purge_recurring_interval),
+      staleness_threshold(staleness_threshold) {
   DCHECK(IsValidPageSize(max_page_size));
   DCHECK_GT(max_entries_per_origin, 0);
   DCHECK_GT(max_string_length, 0);
@@ -66,9 +65,9 @@
   DCHECK_GT(max_iterator_batch_size, 0);
   DCHECK_GT(bit_budget, 0);
   DCHECK(budget_interval.is_positive());
-  DCHECK(stale_origin_purge_initial_interval.is_positive());
-  DCHECK(stale_origin_purge_recurring_interval.is_positive());
-  DCHECK(origin_staleness_threshold.is_positive());
+  DCHECK(stale_purge_initial_interval.is_positive());
+  DCHECK(stale_purge_recurring_interval.is_positive());
+  DCHECK(staleness_threshold.is_positive());
 }
 
 std::unique_ptr<SharedStorageDatabaseOptions>
@@ -76,7 +75,7 @@
   return std::make_unique<SharedStorageDatabaseOptions>(
       max_page_size, max_cache_size, max_entries_per_origin, max_string_length,
       max_init_tries, max_iterator_batch_size, bit_budget, budget_interval,
-      origin_staleness_threshold);
+      staleness_threshold);
 }
 
 SharedStorageDatabaseOptions::SharedStorageDatabaseOptions(
@@ -88,7 +87,7 @@
     int max_iterator_batch_size,
     int bit_budget,
     base::TimeDelta budget_interval,
-    base::TimeDelta origin_staleness_threshold)
+    base::TimeDelta staleness_threshold)
     : max_page_size(max_page_size),
       max_cache_size(max_cache_size),
       max_entries_per_origin(max_entries_per_origin),
@@ -97,7 +96,7 @@
       max_iterator_batch_size(max_iterator_batch_size),
       bit_budget(bit_budget),
       budget_interval(budget_interval),
-      origin_staleness_threshold(origin_staleness_threshold) {
+      staleness_threshold(staleness_threshold) {
   DCHECK(IsValidPageSize(max_page_size));
   DCHECK_GT(max_entries_per_origin, 0);
   DCHECK_GT(max_string_length, 0);
@@ -105,7 +104,7 @@
   DCHECK_GT(max_iterator_batch_size, 0);
   DCHECK_GT(bit_budget, 0);
   DCHECK(budget_interval.is_positive());
-  DCHECK(origin_staleness_threshold.is_positive());
+  DCHECK(staleness_threshold.is_positive());
 }
 
 }  // namespace storage
diff --git a/components/services/storage/shared_storage/shared_storage_options.h b/components/services/storage/shared_storage/shared_storage_options.h
index e4aa436..ffde4359 100644
--- a/components/services/storage/shared_storage/shared_storage_options.h
+++ b/components/services/storage/shared_storage/shared_storage_options.h
@@ -28,9 +28,9 @@
                        int max_iterator_batch_size,
                        int bit_budget,
                        base::TimeDelta budget_interval,
-                       base::TimeDelta stale_origin_purge_initial_interval,
-                       base::TimeDelta stale_origin_purge_recurring_interval,
-                       base::TimeDelta origin_staleness_threshold);
+                       base::TimeDelta stale_purge_initial_interval,
+                       base::TimeDelta stale_purge_recurring_interval,
+                       base::TimeDelta staleness_threshold);
 
   // Creates a pointer to a smaller bundle of just the constants that need to
   // be forwarded to `AsyncSharedStorageDatabase` and `SharedStorageDatabase`.
@@ -65,15 +65,15 @@
   const base::TimeDelta budget_interval;
 
   // Initial interval at which stale origins are purged.
-  const base::TimeDelta stale_origin_purge_initial_interval;
+  const base::TimeDelta stale_purge_initial_interval;
 
   // Recurring interval at which stale origins are purged. May differ from
   // the initial interval.
-  const base::TimeDelta stale_origin_purge_recurring_interval;
+  const base::TimeDelta stale_purge_recurring_interval;
 
   // Length of time between origin creation and origin expiration. When an
   // origin's data is older than this threshold, it will be auto-purged.
-  const base::TimeDelta origin_staleness_threshold;
+  const base::TimeDelta staleness_threshold;
 };
 
 // Bundles Finch-configurable constants for the `AsyncSharedStorageDatabase`
@@ -92,7 +92,7 @@
                                int max_iterator_batch_size,
                                int bit_budget,
                                base::TimeDelta budget_interval,
-                               base::TimeDelta origin_staleness_threshold);
+                               base::TimeDelta staleness_threshold);
 
   // Maximum size of a database page, in bytes. Must be a power of 2 between
   // 512 and 65536 inclusive.
@@ -124,7 +124,7 @@
 
   // Length of time between origin creation and origin expiration. When an
   // origin's data is older than this threshold, it will be auto-purged.
-  const base::TimeDelta origin_staleness_threshold;
+  const base::TimeDelta staleness_threshold;
 };
 
 }  // namespace storage
diff --git a/components/services/storage/shared_storage/shared_storage_test_utils.cc b/components/services/storage/shared_storage/shared_storage_test_utils.cc
index 0faee352..7c79077 100644
--- a/components/services/storage/shared_storage/shared_storage_test_utils.cc
+++ b/components/services/storage/shared_storage/shared_storage_test_utils.cc
@@ -50,7 +50,8 @@
          type == Type::DB_APPEND || type == Type::DB_DELETE ||
          type == Type::DB_KEYS || type == Type::DB_ENTRIES ||
          type == Type::DB_MAKE_BUDGET_WITHDRAWAL ||
-         type == Type::DB_OVERRIDE_TIME);
+         type == Type::DB_OVERRIDE_TIME_ORIGIN ||
+         type == Type::DB_OVERRIDE_TIME_ENTRY);
 }
 
 TestDatabaseOperationReceiver::DBOperation::DBOperation(
diff --git a/components/services/storage/shared_storage/shared_storage_test_utils.h b/components/services/storage/shared_storage/shared_storage_test_utils.h
index 4410a28..59050fe 100644
--- a/components/services/storage/shared_storage/shared_storage_test_utils.h
+++ b/components/services/storage/shared_storage/shared_storage_test_utils.h
@@ -71,10 +71,11 @@
       DB_GET_REMAINING_BUDGET = 15,
       DB_IS_OPEN = 16,
       DB_STATUS = 17,
-      DB_OVERRIDE_TIME = 18,
-      DB_GET_NUM_BUDGET = 19,
-      DB_GET_TOTAL_NUM_BUDGET = 20,
-      DB_GET_CREATION_TIME = 21,
+      DB_OVERRIDE_TIME_ORIGIN = 18,
+      DB_OVERRIDE_TIME_ENTRY = 19,
+      DB_GET_NUM_BUDGET = 20,
+      DB_GET_TOTAL_NUM_BUDGET = 21,
+      DB_GET_CREATION_TIME = 22,
     } type;
     url::Origin origin;
     std::vector<std::u16string> params;
diff --git a/components/test/data/web_database/version_107.sql b/components/test/data/web_database/version_107.sql
new file mode 100644
index 0000000..b1d80b76
--- /dev/null
+++ b/components/test/data/web_database/version_107.sql
@@ -0,0 +1,35 @@
+PRAGMA foreign_keys=OFF;
+BEGIN TRANSACTION;
+CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR);
+INSERT INTO meta VALUES('mmap_status','-1');
+INSERT INTO meta VALUES('version','107');
+INSERT INTO meta VALUES('last_compatible_version','106');
+INSERT INTO meta VALUES('Builtin Keyword Version','127');
+CREATE TABLE token_service (service VARCHAR PRIMARY KEY NOT NULL,encrypted_token BLOB);
+CREATE TABLE keywords (id INTEGER PRIMARY KEY,short_name VARCHAR NOT NULL,keyword VARCHAR NOT NULL,favicon_url VARCHAR NOT NULL,url VARCHAR NOT NULL,safe_for_autoreplace INTEGER,originating_url VARCHAR,date_created INTEGER DEFAULT 0,usage_count INTEGER DEFAULT 0,input_encodings VARCHAR,suggest_url VARCHAR,prepopulate_id INTEGER DEFAULT 0,created_by_policy INTEGER DEFAULT 0,last_modified INTEGER DEFAULT 0,sync_guid VARCHAR,alternate_urls VARCHAR,image_url VARCHAR,search_url_post_params VARCHAR,suggest_url_post_params VARCHAR,image_url_post_params VARCHAR,new_tab_url VARCHAR,last_visited INTEGER DEFAULT 0, created_from_play_api INTEGER DEFAULT 0, is_active INTEGER DEFAULT 0, starter_pack_id INTEGER DEFAULT 0);
+CREATE TABLE autofill (name VARCHAR, value VARCHAR, value_lower VARCHAR, date_created INTEGER DEFAULT 0, date_last_used INTEGER DEFAULT 0, count INTEGER DEFAULT 1, PRIMARY KEY (name, value));
+CREATE TABLE credit_cards ( guid VARCHAR PRIMARY KEY, name_on_card VARCHAR, expiration_month INTEGER, expiration_year INTEGER, card_number_encrypted BLOB, date_modified INTEGER NOT NULL DEFAULT 0, origin VARCHAR DEFAULT '', use_count INTEGER NOT NULL DEFAULT 0, use_date INTEGER NOT NULL DEFAULT 0, billing_address_id VARCHAR, nickname VARCHAR);
+CREATE TABLE ibans ( guid VARCHAR PRIMARY KEY, use_count INTEGER NOT NULL DEFAULT 0, use_date INTEGER NOT NULL DEFAULT 0, value VARCHAR, nickname VARCHAR);
+CREATE TABLE autofill_profiles ( guid VARCHAR PRIMARY KEY, company_name VARCHAR, street_address VARCHAR, dependent_locality VARCHAR, city VARCHAR, state VARCHAR, zipcode VARCHAR, sorting_code VARCHAR, country_code VARCHAR, date_modified INTEGER NOT NULL DEFAULT 0, origin VARCHAR DEFAULT '', language_code VARCHAR, use_count INTEGER NOT NULL DEFAULT 0, use_date INTEGER NOT NULL DEFAULT 0, label VARCHAR, disallow_settings_visible_updates INTEGER NOT NULL DEFAULT 0);
+CREATE TABLE autofill_profile_addresses ( guid VARCHAR, street_address VARCHAR, street_name VARCHAR, dependent_street_name VARCHAR, house_number VARCHAR, subpremise VARCHAR, premise_name VARCHAR, street_address_status INTEGER DEFAULT 0, street_name_status INTEGER DEFAULT 0, dependent_street_name_status INTEGER DEFAULT 0, house_number_status INTEGER DEFAULT 0, subpremise_status INTEGER DEFAULT 0, premise_name_status INTEGER DEFAULT 0, dependent_locality VARCHAR, city VARCHAR, state VARCHAR, zip_code VARCHAR, sorting_code VARCHAR, country_code VARCHAR, dependent_locality_status INTEGER DEFAULT 0, city_status INTEGER DEFAULT 0, state_status INTEGER DEFAULT 0, zip_code_status INTEGER DEFAULT 0, sorting_code_status INTEGER DEFAULT 0, country_code_status INTEGER DEFAULT 0, apartment_number VARCHAR, floor VARCHAR, apartment_number_status INTEGER DEFAULT 0, floor_status INTEGER DEFAULT 0);
+CREATE TABLE autofill_profile_names ( guid VARCHAR, first_name VARCHAR, middle_name VARCHAR, last_name VARCHAR, full_name VARCHAR, honorific_prefix VARCHAR, first_last_name VARCHAR, conjunction_last_name VARCHAR, second_last_name VARCHAR, honorific_prefix_status INTEGER DEFAULT 0, first_name_status INTEGER DEFAULT 0, middle_name_status INTEGER DEFAULT 0, last_name_status INTEGER DEFAULT 0, first_last_name_status INTEGER DEFAULT 0, conjunction_last_name_status INTEGER DEFAULT 0, second_last_name_status INTEGER DEFAULT 0, full_name_status INTEGER DEFAULT 0, full_name_with_honorific_prefix VARCHAR, full_name_with_honorific_prefix_status INTEGER DEFAULT 0);
+CREATE TABLE autofill_profile_emails ( guid VARCHAR, email VARCHAR);
+CREATE TABLE autofill_profile_phones ( guid VARCHAR, number VARCHAR);
+CREATE TABLE masked_credit_cards (id VARCHAR,name_on_card VARCHAR,network VARCHAR,last_four VARCHAR,exp_month INTEGER DEFAULT 0,exp_year INTEGER DEFAULT 0, bank_name VARCHAR, nickname VARCHAR, card_issuer INTEGER DEFAULT 0, instrument_id INTEGER DEFAULT 0, virtual_card_enrollment_state INTEGER DEFAULT 0, card_art_url VARCHAR, product_description VARCHAR);
+CREATE TABLE unmasked_credit_cards (id VARCHAR,card_number_encrypted VARCHAR,unmask_date INTEGER NOT NULL DEFAULT 0);
+CREATE TABLE server_card_metadata (id VARCHAR NOT NULL,use_count INTEGER NOT NULL DEFAULT 0, use_date INTEGER NOT NULL DEFAULT 0, billing_address_id VARCHAR);
+CREATE TABLE server_addresses (id VARCHAR,company_name VARCHAR,street_address VARCHAR,address_1 VARCHAR,address_2 VARCHAR,address_3 VARCHAR,address_4 VARCHAR,postal_code VARCHAR,sorting_code VARCHAR,country_code VARCHAR,language_code VARCHAR, recipient_name VARCHAR, phone_number VARCHAR);
+CREATE TABLE server_address_metadata (id VARCHAR NOT NULL,use_count INTEGER NOT NULL DEFAULT 0, use_date INTEGER NOT NULL DEFAULT 0, has_converted BOOL NOT NULL DEFAULT FALSE);
+CREATE TABLE autofill_sync_metadata (model_type INTEGER NOT NULL, storage_key VARCHAR NOT NULL, value BLOB, PRIMARY KEY (model_type, storage_key));
+CREATE TABLE autofill_model_type_state (model_type INTEGER NOT NULL PRIMARY KEY, value BLOB);
+CREATE TABLE payments_customer_data (customer_id VARCHAR);
+CREATE TABLE payments_upi_vpa (vpa VARCHAR);
+CREATE TABLE server_card_cloud_token_data ( id VARCHAR, suffix VARCHAR, exp_month INTEGER DEFAULT 0, exp_year INTEGER DEFAULT 0, card_art_url VARCHAR, instrument_token VARCHAR);
+CREATE TABLE offer_data ( offer_id UNSIGNED LONG, offer_reward_amount VARCHAR, expiry UNSIGNED LONG, offer_details_url VARCHAR, merchant_domain VARCHAR, promo_code VARCHAR, value_prop_text VARCHAR, see_details_text VARCHAR, usage_instructions_text VARCHAR);
+CREATE TABLE offer_eligible_instrument ( offer_id UNSIGNED LONG,instrument_id UNSIGNED LONG);
+CREATE TABLE offer_merchant_domain ( offer_id UNSIGNED LONG,merchant_domain VARCHAR);
+CREATE TABLE contact_info( guid VARCHAR PRIMARY KEY, use_count INTEGER NOT NULL DEFAULT 0, use_date INTEGER NOT NULL DEFAULT 0, date_modified INTEGER NOT NULL DEFAULT 0, language_code VARCHAR, label VARCHAR);
+CREATE TABLE contact_info_type_tokens( guid VARCHAR, type INTEGER, value VARCHAR, verification_status INTEGER DEFAULT 0, PRIMARY KEY (guid, type));
+CREATE INDEX autofill_name ON autofill (name);
+CREATE INDEX autofill_name_value_lower ON autofill (name, value_lower);
+COMMIT;
diff --git a/components/viz/common/BUILD.gn b/components/viz/common/BUILD.gn
index a9fb7dc..fa9b19ea 100644
--- a/components/viz/common/BUILD.gn
+++ b/components/viz/common/BUILD.gn
@@ -169,8 +169,6 @@
     "constants.cc",
     "constants.h",
     "delegated_ink_prediction_configuration.h",
-    "display/de_jelly.cc",
-    "display/de_jelly.h",
     "display/overlay_strategy.cc",
     "display/overlay_strategy.h",
     "display/renderer_settings.cc",
@@ -356,10 +354,7 @@
   }
 
   if (is_android) {
-    deps += [
-      ":common_jni_headers",
-      "//gpu/config",
-    ]
+    deps += [ "//gpu/config" ]
   }
 
   public_deps = [
@@ -452,23 +447,3 @@
     "//testing/perf",
   ]
 }
-
-if (is_android) {
-  android_library("common_java") {
-    deps = [
-      "//base:base_java",
-      "//base:jni_java",
-      "//build/android:build_java",
-    ]
-    sources = [
-      "java/src/org/chromium/components/viz/common/VizSwitches.java",
-      "java/src/org/chromium/components/viz/common/display/DeJellyUtils.java",
-    ]
-  }
-
-  generate_jni("common_jni_headers") {
-    sources = [
-      "java/src/org/chromium/components/viz/common/display/DeJellyUtils.java",
-    ]
-  }
-}
diff --git a/components/viz/common/display/de_jelly.cc b/components/viz/common/display/de_jelly.cc
deleted file mode 100644
index d7fb5046..0000000
--- a/components/viz/common/display/de_jelly.cc
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2019 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/viz/common/display/de_jelly.h"
-
-#include "base/command_line.h"
-#include "build/build_config.h"
-#include "components/viz/common/features.h"
-#include "components/viz/common/switches.h"
-
-#if BUILDFLAG(IS_ANDROID)
-#include "base/android/jni_android.h"
-#include "base/android/jni_string.h"
-#include "base/time/time.h"
-#include "components/viz/common/common_jni_headers/DeJellyUtils_jni.h"
-#endif
-
-namespace viz {
-
-bool DeJellyEnabled() {
-  static bool enabled =
-      !base::FeatureList::IsEnabled(features::kDisableDeJelly) &&
-      base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableDeJelly);
-  return enabled;
-}
-
-bool DeJellyActive() {
-  if (!DeJellyEnabled())
-    return false;
-
-#if BUILDFLAG(IS_ANDROID)
-  return Java_DeJellyUtils_useDeJelly(base::android::AttachCurrentThread());
-#else
-  return true;
-#endif
-}
-
-float DeJellyScreenWidth() {
-  std::string value =
-      base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
-          switches::kDeJellyScreenWidth);
-  if (!value.empty())
-    return std::atoi(value.c_str());
-
-#if BUILDFLAG(IS_ANDROID)
-  return Java_DeJellyUtils_screenWidth(base::android::AttachCurrentThread());
-#else
-  return 1440.0f;
-#endif
-}
-
-float MaxDeJellyHeight() {
-  // Not currently configurable.
-  return 30.0f;
-}
-
-}  // namespace viz
diff --git a/components/viz/common/display/de_jelly.h b/components/viz/common/display/de_jelly.h
deleted file mode 100644
index eb44519..0000000
--- a/components/viz/common/display/de_jelly.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2019 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_VIZ_COMMON_DISPLAY_DE_JELLY_H_
-#define COMPONENTS_VIZ_COMMON_DISPLAY_DE_JELLY_H_
-
-#include "components/viz/common/viz_common_export.h"
-
-namespace viz {
-
-// Utility functions for use with de-jelly logic. Used in both viz process and
-// render process.
-
-// Whether experimental de-jelly is enabled. This indicates whether
-// DeJellyActive below may ever return true, and is used by the renderer
-// process to determine whether it should prepare frames for potential
-// de-jelly.
-bool VIZ_COMMON_EXPORT DeJellyEnabled();
-
-// Whether experimental de-jelly is *currently* active. This is different from
-// whether it is generally enabled, and may change frame-over-frame. This is
-// queried from the Viz process, before drawing a frame.
-bool VIZ_COMMON_EXPORT DeJellyActive();
-
-// The screen width to use for de-jelly logic.
-float VIZ_COMMON_EXPORT DeJellyScreenWidth();
-
-// The maximum additional content which may be exposed in a layer by de-jelly
-// skewing.
-float VIZ_COMMON_EXPORT MaxDeJellyHeight();
-
-}  // namespace viz
-
-#endif  // COMPONENTS_VIZ_COMMON_DISPLAY_DE_JELLY_H_
diff --git a/components/viz/common/features.cc b/components/viz/common/features.cc
index 7b98fd9d..767c24d 100644
--- a/components/viz/common/features.cc
+++ b/components/viz/common/features.cc
@@ -64,12 +64,6 @@
              "SimpleFrameRateThrottling",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
-// Kill-switch to disable de-jelly, even if flags/properties indicate it should
-// be enabled.
-BASE_FEATURE(kDisableDeJelly,
-             "DisableDeJelly",
-             base::FEATURE_DISABLED_BY_DEFAULT);
-
 #if BUILDFLAG(IS_ANDROID)
 // When wide color gamut content from the web is encountered, promote our
 // display to wide color gamut if supported.
diff --git a/components/viz/common/features.h b/components/viz/common/features.h
index da1c2c9..07589267 100644
--- a/components/viz/common/features.h
+++ b/components/viz/common/features.h
@@ -22,7 +22,6 @@
 VIZ_COMMON_EXPORT BASE_DECLARE_FEATURE(kEnableOverlayPrioritization);
 VIZ_COMMON_EXPORT BASE_DECLARE_FEATURE(kDelegatedCompositing);
 VIZ_COMMON_EXPORT BASE_DECLARE_FEATURE(kRecordSkPicture);
-VIZ_COMMON_EXPORT BASE_DECLARE_FEATURE(kDisableDeJelly);
 VIZ_COMMON_EXPORT BASE_DECLARE_FEATURE(kUseMultipleOverlays);
 VIZ_COMMON_EXPORT extern const char kMaxOverlaysParam[];
 VIZ_COMMON_EXPORT BASE_DECLARE_FEATURE(kVideoDetectorIgnoreNonVideos);
diff --git a/components/viz/common/java/src/org/chromium/components/viz/common/VizSwitches.java b/components/viz/common/java/src/org/chromium/components/viz/common/VizSwitches.java
deleted file mode 100644
index 2e8eb7e..0000000
--- a/components/viz/common/java/src/org/chromium/components/viz/common/VizSwitches.java
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2019 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.components.viz.common;
-
-/**
- * Contains command line switches that are specific to the viz/* portion of Chromium on Android.
- */
-public abstract class VizSwitches {
-    // Enables experimental de-jelly effect.
-    public static final String ENABLE_DE_JELLY = "enable-de-jelly";
-
-    // Prevent instantiation.
-    private VizSwitches() {}
-}
diff --git a/components/viz/common/java/src/org/chromium/components/viz/common/display/DeJellyUtils.java b/components/viz/common/java/src/org/chromium/components/viz/common/display/DeJellyUtils.java
deleted file mode 100644
index 71c86d49..0000000
--- a/components/viz/common/java/src/org/chromium/components/viz/common/display/DeJellyUtils.java
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright 2019 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.components.viz.common.display;
-
-import android.content.ComponentCallbacks;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.hardware.display.DisplayManager;
-import android.os.Build;
-import android.provider.Settings.Global;
-import android.view.Display;
-import android.view.Surface;
-import android.view.WindowManager;
-
-import org.chromium.base.ContextUtils;
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.JNINamespace;
-import org.chromium.base.compat.ApiHelperForR;
-import org.chromium.build.annotations.MainDex;
-
-import java.lang.reflect.Field;
-
-/**
- * Provides static utility functions to query de-jelly settings.
- */
-@JNINamespace("viz")
-@MainDex
-public class DeJellyUtils implements DisplayManager.DisplayListener, ComponentCallbacks {
-    /** Singleton DeJellyUtils instance */
-    private static DeJellyUtils sInstance;
-
-    /**
-     * @return The DeJellyUtils singleton.
-     */
-    private static DeJellyUtils getInstance() {
-        if (sInstance == null) sInstance = new DeJellyUtils();
-        return sInstance;
-    }
-
-    /** Whether the last processed rotation should have de-jelly applied. */
-    private boolean mRotationOk;
-    /** Whether the last processed configuration should have de-jelly applied. */
-    private boolean mConfigurationOk;
-    /** The last processed screen width. */
-    private float mScreenWidth;
-    /** Cached DisplayManager. */
-    private DisplayManager mManager;
-    /** Field used to identify in-use screen on some devices. */
-    private Field mDisplayDeviceType;
-
-    /** Int representing the sub-display, used with mDisplayDeviceType. */
-    private static final int SEM_DISPLAY_DEVICE_TYPE_SUB = 5;
-
-    private DeJellyUtils() {
-        // TODO(ericrk): We should probably plumb display information from the
-        // browser process, rather than re-querying it here.
-        mManager = (DisplayManager) ContextUtils.getApplicationContext().getSystemService(
-                Context.DISPLAY_SERVICE);
-        // Register callbacks which will notify of future changes.
-        mManager.registerDisplayListener(this, null);
-        ContextUtils.getApplicationContext().registerComponentCallbacks(this);
-
-        // Get current state, as we may need these values and callbacks will not yet have fired.
-        onDisplayChanged(0);
-        onConfigurationChanged(
-                ContextUtils.getApplicationContext().getResources().getConfiguration());
-
-        // See if we have a display device type field to query.
-        try {
-            Class configurationClass = Configuration.class;
-            mDisplayDeviceType = configurationClass.getDeclaredField("semDisplayDeviceType");
-        } catch (Exception e) {
-            // We do not require mDisplayDeviceType to exist. Continue.
-        }
-    }
-
-    // DisplayManager.DisplayListener implementation.
-    @Override
-    public void onDisplayAdded(int displayId) {}
-    @Override
-    public void onDisplayChanged(int displayId) {
-        // Ignore non-default display.
-        if (displayId != Display.DEFAULT_DISPLAY) return;
-
-        Display display = mManager.getDisplay(displayId);
-
-        // For now only support ROTATION_0.
-        // TODO(ericrk): Allow this to be customized.
-        int rotation = display.getRotation();
-        mRotationOk = rotation == Surface.ROTATION_0;
-
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
-            Rect realSize = ApiHelperForR.getMaximumWindowMetricsBounds(
-                    ContextUtils.getApplicationContext().getSystemService(WindowManager.class));
-            mScreenWidth = realSize.width();
-        } else {
-            Point realSize = new Point();
-            display.getRealSize(realSize);
-            mScreenWidth = realSize.x;
-        }
-    }
-    @Override
-    public void onDisplayRemoved(int displayId) {}
-
-    // ComponentCallbacks implementation.
-    @Override
-    public void onConfigurationChanged(Configuration configuration) {
-        if (mDisplayDeviceType != null) {
-            try {
-                mConfigurationOk =
-                        mDisplayDeviceType.getInt(configuration) != SEM_DISPLAY_DEVICE_TYPE_SUB;
-                return;
-            } catch (Exception e) {
-                // We don't require that this field exists, continue.
-            }
-        }
-        // Configuration is always ok if we can't query mDisplayDeviceType.
-        mConfigurationOk = true;
-    }
-    @Override
-    public void onLowMemory() {}
-
-    /**
-     * @return Whether de-jelly is externally enabled. This indicates whether
-     *         de-jelly may be used on a device in certain orientations /
-     *         configurations, not whether it is actively being used.
-     */
-    public static boolean externallyEnableDeJelly() {
-        // Support will be removed.
-        return false;
-    }
-
-    /**
-     * @return Whether the current screen / configuration should use the de-jelly effect.
-     */
-    @CalledByNative
-    private static boolean useDeJelly() {
-        DeJellyUtils utils = getInstance();
-
-        // Device specific flag which force-disables jelly scroll on a per-frame basis.
-        if (Global.getInt(ContextUtils.getApplicationContext().getContentResolver(),
-                    "sem_support_scroll_filter", 1)
-                == 0) {
-            return false;
-        }
-
-        return utils.mRotationOk && utils.mConfigurationOk;
-    }
-
-    /**
-     * @return the current screen width.
-     */
-    @CalledByNative
-    private static float screenWidth() {
-        return getInstance().mScreenWidth;
-    }
-};
diff --git a/components/viz/common/quads/render_pass_io.cc b/components/viz/common/quads/render_pass_io.cc
index 76406a2..cac75cf 100644
--- a/components/viz/common/quads/render_pass_io.cc
+++ b/components/viz/common/quads/render_pass_io.cc
@@ -1736,7 +1736,6 @@
   dict.SetStringKey("blend_mode", BlendModeToString(sqs.blend_mode));
   dict.SetIntKey("sorting_context_id", sqs.sorting_context_id);
   dict.SetBoolKey("is_fast_rounded_corner", sqs.is_fast_rounded_corner);
-  dict.SetDoubleKey("de_jelly_delta_y", sqs.de_jelly_delta_y);
   return dict;
 }
 
@@ -1795,12 +1794,10 @@
   absl::optional<int> sorting_context_id = dict.FindInt("sorting_context_id");
   absl::optional<bool> is_fast_rounded_corner =
       dict.FindBool("is_fast_rounded_corner");
-  absl::optional<double> de_jelly_delta_y = dict.FindDouble("de_jelly_delta_y");
 
   if (!quad_to_target_transform || !quad_layer_rect ||
       !visible_quad_layer_rect || !are_contents_opaque || !opacity ||
-      !blend_mode || !sorting_context_id || !is_fast_rounded_corner ||
-      !de_jelly_delta_y) {
+      !blend_mode || !sorting_context_id || !is_fast_rounded_corner) {
     return false;
   }
   gfx::Transform t_quad_to_target_transform;
@@ -1840,7 +1837,6 @@
               are_contents_opaque.value(), static_cast<float>(opacity.value()),
               t_blend_mode, sorting_context_id.value());
   sqs->is_fast_rounded_corner = is_fast_rounded_corner.value();
-  sqs->de_jelly_delta_y = static_cast<float>(de_jelly_delta_y.value());
   return true;
 }
 
diff --git a/components/viz/common/quads/render_pass_io_unittest.cc b/components/viz/common/quads/render_pass_io_unittest.cc
index 6d3bcf5..24060a8b 100644
--- a/components/viz/common/quads/render_pass_io_unittest.cc
+++ b/components/viz/common/quads/render_pass_io_unittest.cc
@@ -134,7 +134,6 @@
                             gradient_mask),
         gfx::Rect(5, 20, 1000, 200), false, 0.5f, SkBlendMode::kDstOver, 101);
     sqs1->is_fast_rounded_corner = true;
-    sqs1->de_jelly_delta_y = 0.7f;
   }
   base::Value dict0 = CompositorRenderPassToDict(*render_pass0);
   auto render_pass1 = CompositorRenderPassFromDict(dict0);
@@ -156,7 +155,6 @@
     EXPECT_EQ(SkBlendMode::kSrcOver, sqs0->blend_mode);
     EXPECT_EQ(0, sqs0->sorting_context_id);
     EXPECT_FALSE(sqs0->is_fast_rounded_corner);
-    EXPECT_EQ(0.0f, sqs0->de_jelly_delta_y);
 
     const SharedQuadState* sqs1 =
         render_pass1->shared_quad_state_list.ElementAt(1);
@@ -182,7 +180,6 @@
     EXPECT_EQ(SkBlendMode::kDstOver, sqs1->blend_mode);
     EXPECT_EQ(101, sqs1->sorting_context_id);
     EXPECT_TRUE(sqs1->is_fast_rounded_corner);
-    EXPECT_EQ(0.7f, sqs1->de_jelly_delta_y);
   }
   base::Value dict1 = CompositorRenderPassToDict(*render_pass1);
   EXPECT_EQ(dict0, dict1);
diff --git a/components/viz/common/quads/shared_quad_state.cc b/components/viz/common/quads/shared_quad_state.cc
index 9b71bab0..2191ce0b 100644
--- a/components/viz/common/quads/shared_quad_state.cc
+++ b/components/viz/common/quads/shared_quad_state.cc
@@ -31,8 +31,7 @@
          clip_rect == other.clip_rect &&
          are_contents_opaque == other.are_contents_opaque &&
          opacity == other.opacity && blend_mode == other.blend_mode &&
-         sorting_context_id == other.sorting_context_id &&
-         de_jelly_delta_y == other.de_jelly_delta_y;
+         sorting_context_id == other.sorting_context_id;
 }
 
 void SharedQuadState::SetAll(const SharedQuadState& other) {
@@ -94,7 +93,6 @@
   value->SetString("blend_mode", SkBlendMode_Name(blend_mode));
   value->SetInteger("sorting_context_id", sorting_context_id);
   value->SetBoolean("is_fast_rounded_corner", is_fast_rounded_corner);
-  value->SetDouble("de_jelly_delta_y", de_jelly_delta_y);
   TracedValue::MakeDictIntoImplicitSnapshotWithCategory(
       TRACE_DISABLED_BY_DEFAULT("viz.quads"), value, "viz::SharedQuadState",
       this);
diff --git a/components/viz/common/quads/shared_quad_state.h b/components/viz/common/quads/shared_quad_state.h
index a9bb1ecd..07fc4ad 100644
--- a/components/viz/common/quads/shared_quad_state.h
+++ b/components/viz/common/quads/shared_quad_state.h
@@ -79,8 +79,6 @@
   // This index points to the damage rect in the surface damage rect list where
   // the overlay quad belongs to. SetAll() doesn't update this data.
   absl::optional<size_t> overlay_damage_index;
-  // The amount to skew quads in this layer. For experimental de-jelly effect.
-  float de_jelly_delta_y = 0.0f;
 };
 
 }  // namespace viz
diff --git a/components/viz/common/switches.cc b/components/viz/common/switches.cc
index 8774fd9..26d28a6 100644
--- a/components/viz/common/switches.cc
+++ b/components/viz/common/switches.cc
@@ -16,10 +16,6 @@
 
 namespace switches {
 
-// Screen width is useful for debugging. Shipping implementations should detect
-// this.
-const char kDeJellyScreenWidth[] = "de-jelly-screen-width";
-
 // The default number of the BeginFrames to wait to activate a surface with
 // dependencies.
 const char kDeadlineToSynchronizeSurfaces[] =
@@ -32,9 +28,6 @@
 // Sets the number of max pending frames in the GL buffer queue to 1.
 const char kDoubleBufferCompositing[] = "double-buffer-compositing";
 
-// Experimental de-jelly support.
-const char kEnableDeJelly[] = "enable-de-jelly";
-
 // Enable compositing individual elements via hardware overlays when
 // permitted by device.
 // Setting the flag to "single-fullscreen" will try to promote a single
diff --git a/components/viz/common/switches.h b/components/viz/common/switches.h
index c664034f..2a657a6d 100644
--- a/components/viz/common/switches.h
+++ b/components/viz/common/switches.h
@@ -15,11 +15,9 @@
 namespace switches {
 
 // Keep list in alphabetical order.
-VIZ_COMMON_EXPORT extern const char kDeJellyScreenWidth[];
 VIZ_COMMON_EXPORT extern const char kDeadlineToSynchronizeSurfaces[];
 VIZ_COMMON_EXPORT extern const char kDisableFrameRateLimit[];
 VIZ_COMMON_EXPORT extern const char kDoubleBufferCompositing[];
-VIZ_COMMON_EXPORT extern const char kEnableDeJelly[];
 VIZ_COMMON_EXPORT extern const char kEnableHardwareOverlays[];
 
 #if BUILDFLAG(IS_CHROMEOS)
diff --git a/components/viz/service/display/display.cc b/components/viz/service/display/display.cc
index 1c3c87b1..1e105eb 100644
--- a/components/viz/service/display/display.cc
+++ b/components/viz/service/display/display.cc
@@ -1115,10 +1115,9 @@
   for (auto& observer : observers_)
     observer.OnDisplayDidFinishFrame(ack);
 
-  // Prevent de-jelly skew or a delegated ink trail from staying on the screen
+  // Prevent a delegated ink trail from staying on the screen
   // for more than one frame by forcing a new frame to be produced.
-  if (aggregator_->last_frame_had_jelly() ||
-      !renderer_->GetDelegatedInkTrailDamageRect().IsEmpty()) {
+  if (!renderer_->GetDelegatedInkTrailDamageRect().IsEmpty()) {
     scheduler_->SetNeedsOneBeginFrame(true);
   }
 
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc
index dba52d6..85d45b5b 100644
--- a/components/viz/service/display/skia_renderer.cc
+++ b/components/viz/service/display/skia_renderer.cc
@@ -74,6 +74,7 @@
 #include "third_party/skia/include/gpu/GrDirectContext.h"
 #include "third_party/skia/modules/skcms/skcms.h"
 #include "ui/base/ui_base_features.h"
+#include "ui/gfx/buffer_format_util.h"
 #include "ui/gfx/color_transform.h"
 #include "ui/gfx/geometry/angle_conversions.h"
 #include "ui/gfx/geometry/axis_transform2d.h"
@@ -3598,6 +3599,9 @@
   }
   // Assume full damage every time the pass is rendered.
   overlay->damage_rect = gfx::RectF(filter_bounds);
+  // Fill in |format| and |color_space| information based on selected backing.
+  overlay->color_space = color_space;
+  overlay->format = BufferFormat(buffer_format);
 #endif  // BUILDFLAG(IS_APPLE)
 }
 #endif  // BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_OZONE)
diff --git a/components/viz/service/display/surface_aggregator.cc b/components/viz/service/display/surface_aggregator.cc
index 7bc56f3..5bffafd 100644
--- a/components/viz/service/display/surface_aggregator.cc
+++ b/components/viz/service/display/surface_aggregator.cc
@@ -21,7 +21,6 @@
 #include "base/timer/elapsed_timer.h"
 #include "base/trace_event/trace_event.h"
 #include "cc/base/math_util.h"
-#include "components/viz/common/display/de_jelly.h"
 #include "components/viz/common/features.h"
 #include "components/viz/common/quads/aggregated_render_pass.h"
 #include "components/viz/common/quads/aggregated_render_pass_draw_quad.h"
@@ -189,8 +188,7 @@
       source_sqs->are_contents_opaque, source_sqs->opacity,
       source_sqs->blend_mode, source_sqs->sorting_context_id);
   shared_quad_state->is_fast_rounded_corner =
-      mask_filter_info_ext.is_fast_rounded_corner,
-  shared_quad_state->de_jelly_delta_y = source_sqs->de_jelly_delta_y;
+      mask_filter_info_ext.is_fast_rounded_corner;
   return shared_quad_state;
 }
 
@@ -287,7 +285,6 @@
       provider_(provider),
       aggregate_only_damaged_(aggregate_only_damaged),
       needs_surface_damage_rect_list_(needs_surface_damage_rect_list),
-      de_jelly_enabled_(DeJellyEnabled()),
       extra_pass_for_readback_option_(extra_pass_option) {
   DCHECK(manager_);
   DCHECK(provider_);
@@ -471,8 +468,7 @@
     const SurfaceDrawQuad& surface_quad) {
   const SharedQuadState* sqs = surface_quad.shared_quad_state;
   return surface_quad.allow_merge &&
-         base::IsApproximatelyEqual(sqs->opacity, 1.f, kOpacityEpsilon) &&
-         sqs->de_jelly_delta_y == 0;
+         base::IsApproximatelyEqual(sqs->opacity, 1.f, kOpacityEpsilon);
 }
 
 void SurfaceAggregator::OnSurfaceDestroyed(const SurfaceId& surface_id) {
@@ -747,8 +743,6 @@
       surface_quad->is_reflection &&
       !scaled_quad_to_target_transform.IsIdentityOrTranslation();
 
-  // We cannot merge passes if de-jelly is being applied, as we must have a
-  // renderpass to skew.
   bool merge_pass =
       CanPotentiallyMergePass(*surface_quad) && !reflected_and_scaled &&
       copy_requests.empty() && combined_transform.Preserves2dAxisAlignment() &&
@@ -1289,14 +1283,6 @@
           dest_shared_quad_state->overlay_damage_index = overlay_damage_index;
         }
 
-        if (de_jelly_enabled_) {
-          // If a surface is being drawn for a second time, clear our
-          // |de_jelly_delta_y|, as de-jelly is only needed the first time
-          // a surface draws.
-          if (!new_surfaces_.count(surface->surface_id()))
-            dest_shared_quad_state->de_jelly_delta_y = 0.0f;
-        }
-
         last_copied_source_shared_quad_state = quad->shared_quad_state;
         if (ignore_undamaged) {
           damage_rect_in_quad_space_valid = CalculateQuadSpaceDamageRect(
@@ -1845,9 +1831,6 @@
   if (surface->IsVideoCaptureOnFromClient())
     result.video_capture_enabled = true;
 
-  if (de_jelly_enabled_ && surface->HasUndrawnActiveFrame())
-    new_surfaces_.insert(surface->surface_id());
-
   if (root_resolved_pass.aggregation().will_draw)
     surface->OnWillBeDrawn();
 
@@ -2066,11 +2049,6 @@
     last_pass->damage_rect.Intersect(prewalk_damage_rect);
   }
 
-  // Now that we've handled our main surface aggregation, apply de-jelly effect
-  // if enabled.
-  if (de_jelly_enabled_)
-    HandleDeJelly(surface);
-
   AddColorConversionPass();
   AddRootReadbackPass();
 
@@ -2137,7 +2115,6 @@
   display_trace_id_ = -1;
   has_pixel_moving_backdrop_filter_ = false;
   has_copy_requests_ = false;
-  new_surfaces_.clear();
   resolved_surface_ranges_.clear();
   contained_surfaces_.clear();
   contained_frame_sinks_.clear();
@@ -2252,279 +2229,6 @@
       "transformed metadata", delegated_ink_metadata_->ToString());
 }
 
-void SurfaceAggregator::HandleDeJelly(Surface* surface) {
-  TRACE_EVENT0("viz", "SurfaceAggregator::HandleDeJelly");
-
-  if (!DeJellyActive()) {
-    SetLastFrameHadJelly(false);
-    return;
-  }
-
-  // |jelly_clip| is the rect that contains all de-jelly'd quads. It is used as
-  // an approximation for the containing non-skewed clip rect.
-  gfx::Rect jelly_clip;
-  // |max_skew| represents the maximum skew applied to an element. To prevent
-  // tearing due to slight inaccuracies, we apply the max skew to all skewed
-  // elements.
-  float max_skew = 0.0f;
-
-  // Iterate over each SharedQuadState in the root render pass and compute
-  // |max_skew| and |jelly_clip|.
-  auto* root_render_pass = dest_pass_list_->back().get();
-  float screen_width = DeJellyScreenWidth();
-  for (SharedQuadState* state : root_render_pass->shared_quad_state_list) {
-    float delta_y = state->de_jelly_delta_y;
-    if (delta_y == 0.0f)
-      continue;
-
-    // We are going to de-jelly this SharedQuadState. Expand the max clip.
-    if (state->clip_rect) {
-      jelly_clip.Union(*state->clip_rect);
-    }
-
-    // Compute the skew angle and update |max_skew|.
-    float de_jelly_angle = gfx::RadToDeg(atan2(delta_y, screen_width));
-    float sign = de_jelly_angle / std::abs(de_jelly_angle);
-    max_skew = std::max(std::abs(de_jelly_angle), std::abs(max_skew)) * sign;
-  }
-
-  // Exit if nothing was skewed.
-  if (max_skew == 0.0f) {
-    SetLastFrameHadJelly(false);
-    return;
-  }
-
-  SetLastFrameHadJelly(true);
-
-  // Remove the existing root render pass and create a new one which we will
-  // re-copy skewed quads / render-passes to.
-  // TODO(ericrk): Handle backdrop filters?
-  // TODO(ericrk): This will end up skewing copy requests. Address if
-  // necessary.
-  auto old_root = std::move(dest_pass_list_->back());
-  dest_pass_list_->pop_back();
-  auto new_root = root_render_pass->Copy(root_render_pass->id);
-  new_root->copy_requests = std::move(old_root->copy_requests);
-
-  // Data tracking the current sub RenderPass (if any) which is being appended
-  // to. We can keep re-using a sub RenderPass if the skew has not changed and
-  // if we are in the typical kSrcOver blend mode.
-  std::unique_ptr<AggregatedRenderPass> sub_render_pass;
-  SkBlendMode sub_render_pass_blend_mode;
-  float sub_render_pass_opacity;
-
-  // Apply de-jelly to all quads, promoting quads into render passes as
-  // necessary.
-  for (auto it = root_render_pass->quad_list.begin();
-       it != root_render_pass->quad_list.end();) {
-    auto* state = it->shared_quad_state;
-    bool has_skew = state->de_jelly_delta_y != 0.0f;
-
-    // If we have a sub RenderPass which is not compatible with our current
-    // quad, we must flush and clear it.
-    if (sub_render_pass) {
-      if (!has_skew || sub_render_pass_blend_mode != state->blend_mode ||
-          state->blend_mode != SkBlendMode::kSrcOver) {
-        AppendDeJellyRenderPass(max_skew, jelly_clip, sub_render_pass_opacity,
-                                sub_render_pass_blend_mode, new_root.get(),
-                                std::move(sub_render_pass));
-        sub_render_pass.reset();
-      }
-    }
-
-    // Create a new render pass if we have a skewed quad which is clipped more
-    // than jelly_clip.
-    bool create_render_pass =
-        has_skew && state->clip_rect && state->clip_rect != jelly_clip;
-    if (!sub_render_pass && create_render_pass) {
-      sub_render_pass = std::make_unique<AggregatedRenderPass>(1, 1);
-      gfx::Transform skew_transform;
-      skew_transform.Skew(0.0f, max_skew);
-      // Ignore rectangles for now, these are updated in
-      // CreateDeJellyRenderPassQuads.
-      sub_render_pass->SetNew(render_pass_id_generator_.GenerateNextId(),
-                              gfx::Rect(), gfx::Rect(), skew_transform);
-      // If blend mode is not kSrcOver, we apply it in the render pass.
-      if (state->blend_mode != SkBlendMode::kSrcOver) {
-        sub_render_pass_opacity = state->opacity;
-        sub_render_pass_blend_mode = state->blend_mode;
-      } else {
-        sub_render_pass_opacity = 1.0f;
-        sub_render_pass_blend_mode = SkBlendMode::kSrcOver;
-      }
-    }
-
-    if (sub_render_pass) {
-      CreateDeJellyRenderPassQuads(&it, root_render_pass->quad_list.end(),
-                                   jelly_clip, max_skew, sub_render_pass.get());
-    } else {
-      float skew = has_skew ? max_skew : 0.0f;
-      CreateDeJellyNormalQuads(&it, root_render_pass->quad_list.end(),
-                               new_root.get(), skew);
-    }
-  }
-  if (sub_render_pass) {
-    AppendDeJellyRenderPass(max_skew, jelly_clip, sub_render_pass_opacity,
-                            sub_render_pass_blend_mode, new_root.get(),
-                            std::move(sub_render_pass));
-  }
-
-  dest_pass_list_->push_back(std::move(new_root));
-}
-
-void SurfaceAggregator::CreateDeJellyRenderPassQuads(
-    cc::ListContainer<DrawQuad>::Iterator* quad_iterator,
-    const cc::ListContainer<DrawQuad>::Iterator& end,
-    const gfx::Rect& jelly_clip,
-    float skew,
-    AggregatedRenderPass* render_pass) {
-  auto* quad = **quad_iterator;
-  const auto* state = quad->shared_quad_state;
-
-  // Heuristic - we may have over-clipped a quad. If a quad is clipped by the
-  // |jelly_clip|, but contains content beyond |jelly_clip|, un-clip the quad by
-  // MaxDeJellyHeight().
-  int un_clip_top = 0;
-  int un_clip_bottom = 0;
-  DCHECK(state->clip_rect);
-  if (state->clip_rect->y() <= jelly_clip.y()) {
-    un_clip_top = MaxDeJellyHeight();
-  }
-  if (state->clip_rect->bottom() >= jelly_clip.bottom()) {
-    un_clip_bottom = MaxDeJellyHeight();
-  }
-
-  // Compute the required renderpass rect in target space.
-  // First, find the un-transformed visible rect.
-  gfx::Rect render_pass_visible_rect = state->visible_quad_layer_rect;
-  // Next, if this is a RenderPass quad, find any filters and expand the
-  // visible rect.
-  if (quad->material == DrawQuad::Material::kCompositorRenderPass) {
-    auto target_id = AggregatedRenderPassId(uint64_t{
-        CompositorRenderPassDrawQuad::MaterialCast(quad)->render_pass_id});
-    for (auto& rp : *dest_pass_list_) {
-      if (rp->id == target_id) {
-        render_pass_visible_rect =
-            rp->filters.MapRect(state->visible_quad_layer_rect, SkMatrix());
-        break;
-      }
-    }
-  }
-  // Next, find the enclosing Rect for the transformed target space RectF.
-  render_pass_visible_rect =
-      state->quad_to_target_transform.MapRect(render_pass_visible_rect);
-  // Finally, expand by our un_clip amounts.
-  render_pass_visible_rect.Inset(
-      gfx::Insets::TLBR(-un_clip_top, 0, -un_clip_bottom, 0));
-
-  // Expand the |render_pass|'s rects.
-  render_pass->output_rect =
-      gfx::UnionRects(render_pass->output_rect, render_pass_visible_rect);
-  render_pass->damage_rect = render_pass->output_rect;
-
-  // Create a new SharedQuadState based on |state|.
-  {
-    auto* new_state = render_pass->CreateAndAppendSharedQuadState();
-    *new_state = *state;
-    // If blend mode is not kSrcOver, we apply it in the RenderPass.
-    if (state->blend_mode != SkBlendMode::kSrcOver) {
-      new_state->opacity = 1.0f;
-      new_state->blend_mode = SkBlendMode::kSrcOver;
-    }
-
-    // Expand our clip by un clip amounts.
-    new_state->clip_rect->Inset(
-        gfx::Insets::TLBR(-un_clip_top, 0, -un_clip_bottom, 0));
-  }
-
-  // Append all quads sharing |new_state|.
-  AppendDeJellyQuadsForSharedQuadState(quad_iterator, end, render_pass, state);
-}
-
-void SurfaceAggregator::CreateDeJellyNormalQuads(
-    cc::ListContainer<DrawQuad>::Iterator* quad_iterator,
-    const cc::ListContainer<DrawQuad>::Iterator& end,
-    AggregatedRenderPass* root_pass,
-    float skew) {
-  auto* quad = **quad_iterator;
-  const auto* state = quad->shared_quad_state;
-
-  // Crearte a new SharedQuadState on |root_pass| and apply skew if any.
-  SharedQuadState* new_state = root_pass->CreateAndAppendSharedQuadState();
-  *new_state = *state;
-  if (skew != 0.0f) {
-    gfx::Transform skew_transform;
-    skew_transform.Skew(0.0f, skew);
-    new_state->quad_to_target_transform =
-        skew_transform * new_state->quad_to_target_transform;
-  }
-
-  // Append all quads sharing |new_state|.
-  AppendDeJellyQuadsForSharedQuadState(quad_iterator, end, root_pass, state);
-}
-
-void SurfaceAggregator::AppendDeJellyRenderPass(
-    float skew,
-    const gfx::Rect& jelly_clip,
-    float opacity,
-    SkBlendMode blend_mode,
-    AggregatedRenderPass* root_pass,
-    std::unique_ptr<AggregatedRenderPass> render_pass) {
-  // Create a new quad for this renderpass and append it to the pass list.
-  auto* new_state = root_pass->CreateAndAppendSharedQuadState();
-  gfx::Transform transform;
-  new_state->SetAll(transform, render_pass->output_rect,
-                    render_pass->output_rect, gfx::MaskFilterInfo(), jelly_clip,
-                    false, opacity, blend_mode, 0);
-  auto* quad =
-      root_pass->CreateAndAppendDrawQuad<AggregatedRenderPassDrawQuad>();
-  quad->SetNew(new_state, render_pass->output_rect, render_pass->output_rect,
-               render_pass->id, kInvalidResourceId, gfx::RectF(), gfx::Size(),
-               gfx::Vector2dF(), gfx::PointF(),
-               gfx::RectF(gfx::SizeF(render_pass->output_rect.size())), false,
-               1.0f);
-  gfx::Transform skew_transform;
-  skew_transform.Skew(0.0f, skew);
-  new_state->quad_to_target_transform =
-      skew_transform * new_state->quad_to_target_transform;
-  dest_pass_list_->push_back(std::move(render_pass));
-}
-
-void SurfaceAggregator::AppendDeJellyQuadsForSharedQuadState(
-    cc::ListContainer<DrawQuad>::Iterator* quad_iterator,
-    const cc::ListContainer<DrawQuad>::Iterator& end,
-    AggregatedRenderPass* render_pass,
-    const SharedQuadState* state) {
-  auto* quad = **quad_iterator;
-  while (quad->shared_quad_state == state) {
-    // Since we're dealing with post-aggregated passes, we should not have any
-    // RenderPassDrawQuads.
-    DCHECK_NE(quad->material, DrawQuad::Material::kCompositorRenderPass);
-    if (quad->material == DrawQuad::Material::kAggregatedRenderPass) {
-      const auto* pass_quad = AggregatedRenderPassDrawQuad::MaterialCast(quad);
-      render_pass->CopyFromAndAppendRenderPassDrawQuad(pass_quad);
-    } else {
-      render_pass->CopyFromAndAppendDrawQuad(quad);
-    }
-
-    ++(*quad_iterator);
-    if (*quad_iterator == end)
-      break;
-    quad = **quad_iterator;
-  }
-}
-
-void SurfaceAggregator::SetLastFrameHadJelly(bool had_jelly) {
-  // If we've just rendererd a jelly-free frame after one with jelly, we must
-  // damage the entire surface, as we may have removed jelly from an otherwise
-  // unchanged quad.
-  if (last_frame_had_jelly_ && !had_jelly) {
-    auto* root_pass = dest_pass_list_->back().get();
-    root_pass->damage_rect = root_pass->output_rect;
-  }
-  last_frame_had_jelly_ = had_jelly;
-}
-
 void SurfaceAggregator::DebugLogSurface(const Surface* surface,
                                         bool will_draw) {
   DBG_LOG("aggregator.surface.log", "D%d - %s, %s draws=%s",
diff --git a/components/viz/service/display/surface_aggregator.h b/components/viz/service/display/surface_aggregator.h
index 3eb2f10c..6e01986c 100644
--- a/components/viz/service/display/surface_aggregator.h
+++ b/components/viz/service/display/surface_aggregator.h
@@ -105,9 +105,6 @@
   void set_output_is_secure(bool secure) { output_is_secure_ = secure; }
   void set_take_copy_requests(bool value) { take_copy_requests_ = value; }
 
-  // Only used with experimental de-jelly effect.
-  bool last_frame_had_jelly() const { return last_frame_had_jelly_; }
-
   // Set the color spaces for the created RenderPasses, which is propagated
   // to the output surface.
   void SetDisplayColorSpaces(const gfx::DisplayColorSpaces& color_spaces);
@@ -324,42 +321,6 @@
   // potentially merge its root render pass. If so, returns true.
   static bool CanPotentiallyMergePass(const SurfaceDrawQuad& surface_quad);
 
-  // De-Jelly Effect:
-  // HandleDeJelly applies a de-jelly transform to quads in the root render
-  // pass.
-  void HandleDeJelly(Surface* surface);
-  // CreateDeJellyRenderPassQuads promotes skewed quads from the root render
-  // pass into |render_pass|. Skew is applied when |render_pass| is drawn.
-  void CreateDeJellyRenderPassQuads(
-      cc::ListContainer<DrawQuad>::Iterator* quad_iterator,
-      const cc::ListContainer<DrawQuad>::Iterator& end,
-      const gfx::Rect& jelly_clip,
-      float skew,
-      AggregatedRenderPass* render_pass);
-  // Appends quads directly to |root_pass|, applying |skew|.
-  void CreateDeJellyNormalQuads(
-      cc::ListContainer<DrawQuad>::Iterator* quad_iterator,
-      const cc::ListContainer<DrawQuad>::Iterator& end,
-      AggregatedRenderPass* root_pass,
-      float skew);
-  // Appends |render_pass| to |root_pass|, applying |skew|, |jelly_clip|,
-  // |opacity|, and |blend_mode|.
-  void AppendDeJellyRenderPass(
-      float skew,
-      const gfx::Rect& jelly_clip,
-      float opacity,
-      SkBlendMode blend_mode,
-      AggregatedRenderPass* root_pass,
-      std::unique_ptr<AggregatedRenderPass> render_pass);
-  // Appends quads from |quad_iterator| to |render_pass| for |state|.
-  void AppendDeJellyQuadsForSharedQuadState(
-      cc::ListContainer<DrawQuad>::Iterator* quad_iterator,
-      const cc::ListContainer<DrawQuad>::Iterator& end,
-      AggregatedRenderPass* render_pass,
-      const SharedQuadState* state);
-  // Update |last_frame_had_jelly_|, should be called once per frame.
-  void SetLastFrameHadJelly(bool had_jelly);
-
   // Logs the surface information for debugging purposes.
   void DebugLogSurface(const Surface* surface, bool will_draw);
 
@@ -377,9 +338,6 @@
   // If true, per-surface damage rect list will be produced.
   const bool needs_surface_damage_rect_list_;
 
-  // Whether de-jelly may be active.
-  const bool de_jelly_enabled_;
-
   const ExtraPassForReadbackOption extra_pass_for_readback_option_;
 
   // Will be true for duration of Aggregate() function.
@@ -468,13 +426,6 @@
   // Used to annotate the aggregated frame for debugging.
   std::unique_ptr<FrameAnnotator> frame_annotator_;
 
-  // Variables used for de-jelly:
-  // The set of surfacees being drawn for the first time. Used to determine if
-  // de-jelly skew should be applied to a surface.
-  base::flat_set<SurfaceId> new_surfaces_;
-  // Whether the last drawn frame had de-jelly skew applied. Used in production
-  // on Android only.
-  bool last_frame_had_jelly_ = false;
   // Whether the last drawn frame had a color conversion pass applied. Used in
   // production on Windows only (does not interact with jelly).
   bool last_frame_had_color_conversion_pass_ = false;
diff --git a/components/viz/test/data/render_pass_data/multi_surface_test/youtube_tab_focused/1641.json b/components/viz/test/data/render_pass_data/multi_surface_test/youtube_tab_focused/1641.json
index d08cf53b..ef17aa1 100644
--- a/components/viz/test/data/render_pass_data/multi_surface_test/youtube_tab_focused/1641.json
+++ b/components/viz/test/data/render_pass_data/multi_surface_test/youtube_tab_focused/1641.json
@@ -712,7 +712,6 @@
             "shared_quad_state_list": [ {
                "are_contents_opaque": false,
                "blend_mode": "kSrcOver",
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -743,7 +742,6 @@
                   "x": 4,
                   "y": 81
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -768,7 +766,6 @@
             }, {
                "are_contents_opaque": false,
                "blend_mode": "kSrcOver",
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -793,7 +790,6 @@
             }, {
                "are_contents_opaque": true,
                "blend_mode": "kSrcOver",
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -1404,7 +1400,6 @@
             "shared_quad_state_list": [ {
                "are_contents_opaque": false,
                "blend_mode": "kSrcOver",
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -1435,7 +1430,6 @@
                   "x": 0,
                   "y": 0
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -1466,7 +1460,6 @@
                   "x": 0,
                   "y": 0
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -1497,7 +1490,6 @@
                   "x": 0,
                   "y": 0
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -1528,7 +1520,6 @@
                   "x": 72,
                   "y": 57
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -1559,7 +1550,6 @@
                   "x": 0,
                   "y": 0
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -1590,7 +1580,6 @@
                   "x": 822,
                   "y": 960
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -1621,7 +1610,6 @@
                   "x": 486,
                   "y": 980
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -1652,7 +1640,6 @@
                   "x": 150,
                   "y": 980
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -1683,7 +1670,6 @@
                   "x": 822,
                   "y": 666
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -1714,7 +1700,6 @@
                   "x": 486,
                   "y": 666
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -1745,7 +1730,6 @@
                   "x": 150,
                   "y": 666
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -1776,7 +1760,6 @@
                   "x": 0,
                   "y": 0
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -1801,7 +1784,6 @@
             }, {
                "are_contents_opaque": true,
                "blend_mode": "kSrcOver",
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -2194,7 +2176,6 @@
             "shared_quad_state_list": [ {
                "are_contents_opaque": true,
                "blend_mode": "kSrcOver",
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -2225,7 +2206,6 @@
                   "x": 0,
                   "y": 0
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -2256,7 +2236,6 @@
                   "x": 0,
                   "y": 0
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -2287,7 +2266,6 @@
                   "x": 0,
                   "y": 0
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -3534,7 +3512,6 @@
             "shared_quad_state_list": [ {
                "are_contents_opaque": false,
                "blend_mode": "kSrcOver",
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -3559,7 +3536,6 @@
             }, {
                "are_contents_opaque": true,
                "blend_mode": "kSrcOver",
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -3584,7 +3560,6 @@
             }, {
                "are_contents_opaque": true,
                "blend_mode": "kSrcOver",
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -3615,7 +3590,6 @@
                   "x": 0,
                   "y": 0
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -3646,7 +3620,6 @@
                   "x": 1057,
                   "y": 369
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -3677,7 +3650,6 @@
                   "x": 999,
                   "y": 369
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -3708,7 +3680,6 @@
                   "x": 941,
                   "y": 369
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -3739,7 +3710,6 @@
                   "x": 883,
                   "y": 369
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -3770,7 +3740,6 @@
                   "x": 825,
                   "y": 369
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -3801,7 +3770,6 @@
                   "x": 546,
                   "y": 852
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -3832,7 +3800,6 @@
                   "x": 546,
                   "y": 852
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -3863,7 +3830,6 @@
                   "x": 546,
                   "y": 852
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -3894,7 +3860,6 @@
                   "x": 546,
                   "y": 852
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -3925,7 +3890,6 @@
                   "x": 281,
                   "y": 852
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -3956,7 +3920,6 @@
                   "x": 281,
                   "y": 852
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -3987,7 +3950,6 @@
                   "x": 281,
                   "y": 852
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -4018,7 +3980,6 @@
                   "x": 17,
                   "y": 852
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -4049,7 +4010,6 @@
                   "x": 17,
                   "y": 852
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -4080,7 +4040,6 @@
                   "x": 17,
                   "y": 852
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -4111,7 +4070,6 @@
                   "x": 17,
                   "y": 426
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -4142,7 +4100,6 @@
                   "x": 17,
                   "y": 426
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -4173,7 +4130,6 @@
                   "x": 17,
                   "y": 426
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -4204,7 +4160,6 @@
                   "x": 17,
                   "y": 426
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -4235,7 +4190,6 @@
                   "x": 0,
                   "y": 0
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -4266,7 +4220,6 @@
                   "x": 78,
                   "y": 113
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -4297,7 +4250,6 @@
                   "x": 78,
                   "y": 113
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -4328,7 +4280,6 @@
                   "x": 0,
                   "y": 0
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -4359,7 +4310,6 @@
                   "x": 0,
                   "y": 0
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -4390,7 +4340,6 @@
                   "x": 0,
                   "y": 0
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -4421,7 +4370,6 @@
                   "x": 0,
                   "y": 0
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -4446,7 +4394,6 @@
             }, {
                "are_contents_opaque": true,
                "blend_mode": "kSrcOver",
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -4572,7 +4519,6 @@
                   "x": 0,
                   "y": 0
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -4696,7 +4642,6 @@
                   "x": 0,
                   "y": 0
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -5763,7 +5708,6 @@
             "shared_quad_state_list": [ {
                "are_contents_opaque": false,
                "blend_mode": "kSrcOver",
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
@@ -5966,7 +5910,6 @@
                   "x": 0,
                   "y": 0
                },
-               "de_jelly_delta_y": 0.0,
                "is_fast_rounded_corner": false,
                "mask_filter_info": {
                   "rounded_corner_bounds": {
diff --git a/components/viz/test/data/render_pass_data/top_real_world_desktop/accu_weather_2018/0298.json b/components/viz/test/data/render_pass_data/top_real_world_desktop/accu_weather_2018/0298.json
index 2112a349..6600b60 100644
--- a/components/viz/test/data/render_pass_data/top_real_world_desktop/accu_weather_2018/0298.json
+++ b/components/viz/test/data/render_pass_data/top_real_world_desktop/accu_weather_2018/0298.json
@@ -1416,7 +1416,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1445,7 +1444,6 @@
             "x": 0,
             "y": 100
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1474,7 +1472,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1503,7 +1500,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1532,7 +1528,6 @@
             "x": 982,
             "y": 990
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1561,7 +1556,6 @@
             "x": 175,
             "y": 427
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1590,7 +1584,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1619,7 +1612,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1642,7 +1634,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1665,7 +1656,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1688,7 +1678,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1711,7 +1700,6 @@
       }, {
          "are_contents_opaque": true,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
diff --git a/components/viz/test/data/render_pass_data/top_real_world_desktop/amazon_2018/0030.json b/components/viz/test/data/render_pass_data/top_real_world_desktop/amazon_2018/0030.json
index b5397ee..b64ddee 100644
--- a/components/viz/test/data/render_pass_data/top_real_world_desktop/amazon_2018/0030.json
+++ b/components/viz/test/data/render_pass_data/top_real_world_desktop/amazon_2018/0030.json
@@ -1397,7 +1397,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1426,7 +1425,6 @@
             "x": 0,
             "y": 100
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1455,7 +1453,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1484,7 +1481,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1513,7 +1509,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1542,7 +1537,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1565,7 +1559,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1588,7 +1581,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1611,7 +1603,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1634,7 +1625,6 @@
       }, {
          "are_contents_opaque": true,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
diff --git a/components/viz/test/data/render_pass_data/top_real_world_desktop/blogspot_2018/0056.json b/components/viz/test/data/render_pass_data/top_real_world_desktop/blogspot_2018/0056.json
index c6ede76..4e16d4d 100644
--- a/components/viz/test/data/render_pass_data/top_real_world_desktop/blogspot_2018/0056.json
+++ b/components/viz/test/data/render_pass_data/top_real_world_desktop/blogspot_2018/0056.json
@@ -1247,7 +1247,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1276,7 +1275,6 @@
             "x": 0,
             "y": 100
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1305,7 +1303,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1334,7 +1331,6 @@
             "x": 1125,
             "y": 1100
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1363,7 +1359,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1386,7 +1381,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1409,7 +1403,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1432,7 +1425,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1455,7 +1447,6 @@
       }, {
          "are_contents_opaque": true,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
diff --git a/components/viz/test/data/render_pass_data/top_real_world_desktop/booking.com_2018/0173.json b/components/viz/test/data/render_pass_data/top_real_world_desktop/booking.com_2018/0173.json
index 7b7c9600..b32c8b3b 100644
--- a/components/viz/test/data/render_pass_data/top_real_world_desktop/booking.com_2018/0173.json
+++ b/components/viz/test/data/render_pass_data/top_real_world_desktop/booking.com_2018/0173.json
@@ -2267,7 +2267,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2296,7 +2295,6 @@
             "x": 0,
             "y": 100
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2325,7 +2323,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2354,7 +2351,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2383,7 +2379,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.22896799445152283,
          "quad_layer_rect": {
@@ -2412,7 +2407,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.1456349939107895,
          "quad_layer_rect": {
@@ -2441,7 +2435,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.9789680242538452,
          "quad_layer_rect": {
@@ -2470,7 +2463,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.8956350088119507,
          "quad_layer_rect": {
@@ -2499,7 +2491,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.7289689779281616,
          "quad_layer_rect": {
@@ -2528,7 +2519,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.6456360220909119,
          "quad_layer_rect": {
@@ -2557,7 +2547,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.478969007730484,
          "quad_layer_rect": {
@@ -2586,7 +2575,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.3956359922885895,
          "quad_layer_rect": {
@@ -2615,7 +2603,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.21236200630664825,
          "quad_layer_rect": {
@@ -2644,7 +2631,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.12902900576591492,
          "quad_layer_rect": {
@@ -2673,7 +2659,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.04569600149989128,
          "quad_layer_rect": {
@@ -2702,7 +2687,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.9623619914054871,
          "quad_layer_rect": {
@@ -2731,7 +2715,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.8790289759635925,
          "quad_layer_rect": {
@@ -2760,7 +2743,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.7956960201263428,
          "quad_layer_rect": {
@@ -2789,7 +2771,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.7123630046844482,
          "quad_layer_rect": {
@@ -2818,7 +2799,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.6290299892425537,
          "quad_layer_rect": {
@@ -2847,7 +2827,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.5456960201263428,
          "quad_layer_rect": {
@@ -2876,7 +2855,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.46236300468444824,
          "quad_layer_rect": {
@@ -2905,7 +2883,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.3790299892425537,
          "quad_layer_rect": {
@@ -2934,7 +2911,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.2956959903240204,
          "quad_layer_rect": {
@@ -2963,7 +2939,6 @@
             "x": 88,
             "y": 277
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2992,7 +2967,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3021,7 +2995,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3044,7 +3017,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3067,7 +3039,6 @@
       }, {
          "are_contents_opaque": true,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
diff --git a/components/viz/test/data/render_pass_data/top_real_world_desktop/cnn_2018/0479.json b/components/viz/test/data/render_pass_data/top_real_world_desktop/cnn_2018/0479.json
index 9dc2771..8dd04e5 100644
--- a/components/viz/test/data/render_pass_data/top_real_world_desktop/cnn_2018/0479.json
+++ b/components/viz/test/data/render_pass_data/top_real_world_desktop/cnn_2018/0479.json
@@ -1373,7 +1373,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1402,7 +1401,6 @@
             "x": 0,
             "y": 100
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1431,7 +1429,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1460,7 +1457,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1489,7 +1485,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1518,7 +1513,6 @@
             "x": 94,
             "y": 1212
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.29667332768440247,
          "quad_layer_rect": {
@@ -1547,7 +1541,6 @@
             "x": 94,
             "y": 1212
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.29667332768440247,
          "quad_layer_rect": {
@@ -1576,7 +1569,6 @@
             "x": 94,
             "y": 1212
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.29667332768440247,
          "quad_layer_rect": {
@@ -1605,7 +1597,6 @@
             "x": 94,
             "y": 1212
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.29667332768440247,
          "quad_layer_rect": {
@@ -1634,7 +1625,6 @@
             "x": 94,
             "y": 307
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1663,7 +1653,6 @@
             "x": 427,
             "y": 650
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1692,7 +1681,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1721,7 +1709,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1744,7 +1731,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1767,7 +1753,6 @@
       }, {
          "are_contents_opaque": true,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
diff --git a/components/viz/test/data/render_pass_data/top_real_world_desktop/ebay_2018/0044.json b/components/viz/test/data/render_pass_data/top_real_world_desktop/ebay_2018/0044.json
index 925049e..4d6934c 100644
--- a/components/viz/test/data/render_pass_data/top_real_world_desktop/ebay_2018/0044.json
+++ b/components/viz/test/data/render_pass_data/top_real_world_desktop/ebay_2018/0044.json
@@ -112,7 +112,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kDstIn",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -141,7 +140,6 @@
             "x": 1,
             "y": 1
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.9809520244598389,
          "quad_layer_rect": {
@@ -242,7 +240,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kDstIn",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -271,7 +268,6 @@
             "x": 1,
             "y": 1
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.9809520244598389,
          "quad_layer_rect": {
@@ -372,7 +368,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kDstIn",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -401,7 +396,6 @@
             "x": 2,
             "y": 1
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -502,7 +496,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kDstIn",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -531,7 +524,6 @@
             "x": 1,
             "y": 1
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.9809520244598389,
          "quad_layer_rect": {
@@ -632,7 +624,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kDstIn",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -661,7 +652,6 @@
             "x": 1,
             "y": 1
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.9809520244598389,
          "quad_layer_rect": {
@@ -762,7 +752,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kDstIn",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -791,7 +780,6 @@
             "x": 1,
             "y": 1
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.9809520244598389,
          "quad_layer_rect": {
@@ -892,7 +880,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kDstIn",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -921,7 +908,6 @@
             "x": 1,
             "y": 1
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2861,7 +2847,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2890,7 +2875,6 @@
             "x": 0,
             "y": 100
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2919,7 +2903,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2948,7 +2931,6 @@
             "x": 0,
             "y": 332
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2977,7 +2959,6 @@
             "x": 1314,
             "y": 881
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3006,7 +2987,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3035,7 +3015,6 @@
             "x": 1107,
             "y": 881
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3064,7 +3043,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3093,7 +3071,6 @@
             "x": 899,
             "y": 881
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3122,7 +3099,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3151,7 +3127,6 @@
             "x": 692,
             "y": 881
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3180,7 +3155,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3209,7 +3183,6 @@
             "x": 485,
             "y": 881
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3238,7 +3211,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3267,7 +3239,6 @@
             "x": 278,
             "y": 881
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3296,7 +3267,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3325,7 +3295,6 @@
             "x": 71,
             "y": 881
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3354,7 +3323,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3383,7 +3351,6 @@
             "x": 440,
             "y": 332
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3412,7 +3379,6 @@
             "x": 0,
             "y": 332
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3441,7 +3407,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3470,7 +3435,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3493,7 +3457,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3516,7 +3479,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3539,7 +3501,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3562,7 +3523,6 @@
       }, {
          "are_contents_opaque": true,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
diff --git a/components/viz/test/data/render_pass_data/top_real_world_desktop/espn_2018/0463.json b/components/viz/test/data/render_pass_data/top_real_world_desktop/espn_2018/0463.json
index 2b5ff84..2710022c7b 100644
--- a/components/viz/test/data/render_pass_data/top_real_world_desktop/espn_2018/0463.json
+++ b/components/viz/test/data/render_pass_data/top_real_world_desktop/espn_2018/0463.json
@@ -113,7 +113,6 @@
             "x": 20,
             "y": 65
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "mask_filter_info": {
             "rounded_corner_bounds": {
@@ -158,7 +157,6 @@
             "x": 20,
             "y": 65
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "mask_filter_info": {
             "rounded_corner_bounds": {
@@ -276,7 +274,6 @@
             "x": 20,
             "y": 65
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "mask_filter_info": {
             "rounded_corner_bounds": {
@@ -470,7 +467,6 @@
             "x": 0,
             "y": 0
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "mask_filter_info": {
             "rounded_corner_bounds": {
@@ -501,7 +497,6 @@
             "x": 0,
             "y": 0
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "mask_filter_info": {
             "rounded_corner_bounds": {
@@ -532,7 +527,6 @@
             "x": 0,
             "y": 0
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "mask_filter_info": {
             "rounded_corner_bounds": {
@@ -563,7 +557,6 @@
             "x": 0,
             "y": 0
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "mask_filter_info": {
             "rounded_corner_bounds": {
@@ -683,7 +676,6 @@
             "x": 418,
             "y": 499
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "mask_filter_info": {
             "rounded_corner_bounds": {
@@ -728,7 +720,6 @@
             "x": 418,
             "y": 499
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "mask_filter_info": {
             "rounded_corner_bounds": {
@@ -862,7 +853,6 @@
             "x": 20,
             "y": 499
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "mask_filter_info": {
             "rounded_corner_bounds": {
@@ -907,7 +897,6 @@
             "x": 20,
             "y": 499
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "mask_filter_info": {
             "rounded_corner_bounds": {
@@ -1069,7 +1058,6 @@
             "x": 418,
             "y": 499
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "mask_filter_info": {
             "rounded_corner_bounds": {
@@ -1114,7 +1102,6 @@
             "x": 20,
             "y": 499
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "mask_filter_info": {
             "rounded_corner_bounds": {
@@ -2674,7 +2661,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "mask_filter_info": {
             "rounded_corner_bounds": {
@@ -2705,7 +2691,6 @@
             "x": 0,
             "y": 100
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "mask_filter_info": {
             "rounded_corner_bounds": {
@@ -2736,7 +2721,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "mask_filter_info": {
             "rounded_corner_bounds": {
@@ -2767,7 +2751,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "mask_filter_info": {
             "rounded_corner_bounds": {
@@ -2798,7 +2781,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "mask_filter_info": {
             "rounded_corner_bounds": {
@@ -2829,7 +2811,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "mask_filter_info": {
             "rounded_corner_bounds": {
@@ -2860,7 +2841,6 @@
             "x": 319,
             "y": 1101
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "mask_filter_info": {
             "rounded_corner_bounds": {
@@ -2905,7 +2885,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "mask_filter_info": {
             "rounded_corner_bounds": {
@@ -2936,7 +2915,6 @@
             "x": 319,
             "y": 320
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "mask_filter_info": {
             "rounded_corner_bounds": {
@@ -2981,7 +2959,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "mask_filter_info": {
             "rounded_corner_bounds": {
@@ -3012,7 +2989,6 @@
             "x": 319,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "mask_filter_info": {
             "rounded_corner_bounds": {
@@ -3057,7 +3033,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "mask_filter_info": {
             "rounded_corner_bounds": {
@@ -3088,7 +3063,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "mask_filter_info": {
             "rounded_corner_bounds": {
@@ -3119,7 +3093,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "mask_filter_info": {
             "rounded_corner_bounds": {
@@ -3144,7 +3117,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "mask_filter_info": {
             "rounded_corner_bounds": {
@@ -3169,7 +3141,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "mask_filter_info": {
             "rounded_corner_bounds": {
@@ -3194,7 +3165,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "mask_filter_info": {
             "rounded_corner_bounds": {
@@ -3219,7 +3189,6 @@
       }, {
          "are_contents_opaque": true,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "mask_filter_info": {
             "rounded_corner_bounds": {
diff --git a/components/viz/test/data/render_pass_data/top_real_world_desktop/facebook_2018/0327.json b/components/viz/test/data/render_pass_data/top_real_world_desktop/facebook_2018/0327.json
index b78d5c4..cf6b65f4 100644
--- a/components/viz/test/data/render_pass_data/top_real_world_desktop/facebook_2018/0327.json
+++ b/components/viz/test/data/render_pass_data/top_real_world_desktop/facebook_2018/0327.json
@@ -1397,7 +1397,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1426,7 +1425,6 @@
             "x": 0,
             "y": 100
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1455,7 +1453,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1484,7 +1481,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1513,7 +1509,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1542,7 +1537,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1571,7 +1565,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1600,7 +1593,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1629,7 +1621,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1652,7 +1643,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1675,7 +1665,6 @@
       }, {
          "are_contents_opaque": true,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
diff --git a/components/viz/test/data/render_pass_data/top_real_world_desktop/gmail_2018/0066.json b/components/viz/test/data/render_pass_data/top_real_world_desktop/gmail_2018/0066.json
index 9f144c8..95b4160 100644
--- a/components/viz/test/data/render_pass_data/top_real_world_desktop/gmail_2018/0066.json
+++ b/components/viz/test/data/render_pass_data/top_real_world_desktop/gmail_2018/0066.json
@@ -117,7 +117,6 @@
             "x": 0,
             "y": 0
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.2608794867992401,
          "quad_layer_rect": {
@@ -146,7 +145,6 @@
             "x": 0,
             "y": 0
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -175,7 +173,6 @@
             "x": 0,
             "y": 0
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -514,7 +511,6 @@
             "x": 0,
             "y": 0
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -557,7 +553,6 @@
             "x": 0,
             "y": 0
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -600,7 +595,6 @@
             "x": 0,
             "y": 0
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -643,7 +637,6 @@
             "x": 0,
             "y": 0
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -686,7 +679,6 @@
             "x": 0,
             "y": 0
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -729,7 +721,6 @@
             "x": 24,
             "y": 0
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -772,7 +763,6 @@
             "x": 24,
             "y": 0
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 0.023103032261133194,
          "quad_layer_rect": {
@@ -815,7 +805,6 @@
             "x": 0,
             "y": 0
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -858,7 +847,6 @@
             "x": 0,
             "y": 0
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -895,7 +883,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2180,7 +2167,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2209,7 +2195,6 @@
             "x": 0,
             "y": 100
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2238,7 +2223,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2267,7 +2251,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.9768969416618347,
          "quad_layer_rect": {
@@ -2296,7 +2279,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2325,7 +2307,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.5975319743156433,
          "quad_layer_rect": {
@@ -2354,7 +2335,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2377,7 +2357,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2400,7 +2379,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2423,7 +2401,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2446,7 +2423,6 @@
       }, {
          "are_contents_opaque": true,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
diff --git a/components/viz/test/data/render_pass_data/top_real_world_desktop/google_calendar_2018/0053.json b/components/viz/test/data/render_pass_data/top_real_world_desktop/google_calendar_2018/0053.json
index 48d931c..792b95a 100644
--- a/components/viz/test/data/render_pass_data/top_real_world_desktop/google_calendar_2018/0053.json
+++ b/components/viz/test/data/render_pass_data/top_real_world_desktop/google_calendar_2018/0053.json
@@ -1213,7 +1213,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1242,7 +1241,6 @@
             "x": 0,
             "y": 100
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1271,7 +1269,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1300,7 +1297,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1329,7 +1325,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1358,7 +1353,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1381,7 +1375,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1404,7 +1397,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1427,7 +1419,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1450,7 +1441,6 @@
       }, {
          "are_contents_opaque": true,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
diff --git a/components/viz/test/data/render_pass_data/top_real_world_desktop/google_docs_2018/0369.json b/components/viz/test/data/render_pass_data/top_real_world_desktop/google_docs_2018/0369.json
index f0f063c..ea52712 100644
--- a/components/viz/test/data/render_pass_data/top_real_world_desktop/google_docs_2018/0369.json
+++ b/components/viz/test/data/render_pass_data/top_real_world_desktop/google_docs_2018/0369.json
@@ -1145,7 +1145,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1174,7 +1173,6 @@
             "x": 0,
             "y": 100
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1203,7 +1201,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.38690000772476196,
          "quad_layer_rect": {
@@ -1232,7 +1229,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1255,7 +1251,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1278,7 +1273,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1301,7 +1295,6 @@
       }, {
          "are_contents_opaque": true,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
diff --git a/components/viz/test/data/render_pass_data/top_real_world_desktop/google_image_search_2018/0044.json b/components/viz/test/data/render_pass_data/top_real_world_desktop/google_image_search_2018/0044.json
index 5ae24a9..4e6e659 100644
--- a/components/viz/test/data/render_pass_data/top_real_world_desktop/google_image_search_2018/0044.json
+++ b/components/viz/test/data/render_pass_data/top_real_world_desktop/google_image_search_2018/0044.json
@@ -1307,7 +1307,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1336,7 +1335,6 @@
             "x": 0,
             "y": 100
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1365,7 +1363,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1394,7 +1391,6 @@
             "x": 8,
             "y": 363
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1423,7 +1419,6 @@
             "x": 8,
             "y": 363
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1452,7 +1447,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1475,7 +1469,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1498,7 +1491,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1521,7 +1513,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1544,7 +1535,6 @@
       }, {
          "are_contents_opaque": true,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
diff --git a/components/viz/test/data/render_pass_data/top_real_world_desktop/google_plus_2018/0045.json b/components/viz/test/data/render_pass_data/top_real_world_desktop/google_plus_2018/0045.json
index efa6de7..37ed577 100644
--- a/components/viz/test/data/render_pass_data/top_real_world_desktop/google_plus_2018/0045.json
+++ b/components/viz/test/data/render_pass_data/top_real_world_desktop/google_plus_2018/0045.json
@@ -279,7 +279,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -302,7 +301,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -325,7 +323,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1562,7 +1559,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1591,7 +1587,6 @@
             "x": 0,
             "y": 100
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1620,7 +1615,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1649,7 +1643,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1678,7 +1671,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1707,7 +1699,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.9847120046615601,
          "quad_layer_rect": {
@@ -1736,7 +1727,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1759,7 +1749,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1782,7 +1771,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1805,7 +1793,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1828,7 +1815,6 @@
       }, {
          "are_contents_opaque": true,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
diff --git a/components/viz/test/data/render_pass_data/top_real_world_desktop/google_web_search_2018/0089.json b/components/viz/test/data/render_pass_data/top_real_world_desktop/google_web_search_2018/0089.json
index 3fbb603..0e7c574 100644
--- a/components/viz/test/data/render_pass_data/top_real_world_desktop/google_web_search_2018/0089.json
+++ b/components/viz/test/data/render_pass_data/top_real_world_desktop/google_web_search_2018/0089.json
@@ -1307,7 +1307,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1336,7 +1335,6 @@
             "x": 0,
             "y": 100
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1365,7 +1363,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1394,7 +1391,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.3799999952316284,
          "quad_layer_rect": {
@@ -1423,7 +1419,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.3799999952316284,
          "quad_layer_rect": {
@@ -1452,7 +1447,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.3799999952316284,
          "quad_layer_rect": {
@@ -1481,7 +1475,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.3799999952316284,
          "quad_layer_rect": {
@@ -1510,7 +1503,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1539,7 +1531,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1562,7 +1553,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1585,7 +1575,6 @@
       }, {
          "are_contents_opaque": true,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
diff --git a/components/viz/test/data/render_pass_data/top_real_world_desktop/linkedin_2018/0284.json b/components/viz/test/data/render_pass_data/top_real_world_desktop/linkedin_2018/0284.json
index d5819098..dec7a5e 100644
--- a/components/viz/test/data/render_pass_data/top_real_world_desktop/linkedin_2018/0284.json
+++ b/components/viz/test/data/render_pass_data/top_real_world_desktop/linkedin_2018/0284.json
@@ -99,7 +99,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.17434731125831604,
          "quad_layer_rect": {
@@ -122,7 +121,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1640,7 +1638,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1669,7 +1666,6 @@
             "x": 0,
             "y": 100
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1698,7 +1694,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1727,7 +1722,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.9999999403953552,
          "quad_layer_rect": {
@@ -1756,7 +1750,6 @@
             "x": 1104,
             "y": 289
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1785,7 +1778,6 @@
             "x": 77,
             "y": 240
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1814,7 +1806,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1843,7 +1834,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1866,7 +1856,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1889,7 +1878,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1912,7 +1900,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1935,7 +1922,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1958,7 +1944,6 @@
       }, {
          "are_contents_opaque": true,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
diff --git a/components/viz/test/data/render_pass_data/top_real_world_desktop/pinterest_2018/0120.json b/components/viz/test/data/render_pass_data/top_real_world_desktop/pinterest_2018/0120.json
index eac10a7..4391415 100644
--- a/components/viz/test/data/render_pass_data/top_real_world_desktop/pinterest_2018/0120.json
+++ b/components/viz/test/data/render_pass_data/top_real_world_desktop/pinterest_2018/0120.json
@@ -1266,7 +1266,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1295,7 +1294,6 @@
             "x": 0,
             "y": 100
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1324,7 +1322,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1353,7 +1350,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1382,7 +1378,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1411,7 +1406,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1434,7 +1428,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1457,7 +1450,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1480,7 +1472,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1503,7 +1494,6 @@
       }, {
          "are_contents_opaque": true,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
diff --git a/components/viz/test/data/render_pass_data/top_real_world_desktop/techcrunch_2018/0190.json b/components/viz/test/data/render_pass_data/top_real_world_desktop/techcrunch_2018/0190.json
index 3f970082..3c54030 100644
--- a/components/viz/test/data/render_pass_data/top_real_world_desktop/techcrunch_2018/0190.json
+++ b/components/viz/test/data/render_pass_data/top_real_world_desktop/techcrunch_2018/0190.json
@@ -1386,7 +1386,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1415,7 +1414,6 @@
             "x": 0,
             "y": 100
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1444,7 +1442,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1473,7 +1470,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1502,7 +1498,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1531,7 +1526,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1560,7 +1554,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1589,7 +1582,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1618,7 +1610,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1647,7 +1638,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1670,7 +1660,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1693,7 +1682,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1716,7 +1704,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1739,7 +1726,6 @@
       }, {
          "are_contents_opaque": true,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
diff --git a/components/viz/test/data/render_pass_data/top_real_world_desktop/twitch_2018/0396.json b/components/viz/test/data/render_pass_data/top_real_world_desktop/twitch_2018/0396.json
index fb917122..45126cc8 100644
--- a/components/viz/test/data/render_pass_data/top_real_world_desktop/twitch_2018/0396.json
+++ b/components/viz/test/data/render_pass_data/top_real_world_desktop/twitch_2018/0396.json
@@ -2465,7 +2465,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2494,7 +2493,6 @@
             "x": 0,
             "y": 100
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2523,7 +2521,6 @@
             "x": 0,
             "y": 218
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2552,7 +2549,6 @@
             "x": 0,
             "y": 274
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2581,7 +2577,6 @@
             "x": 1005,
             "y": 1192
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2624,7 +2619,6 @@
             "x": 1005,
             "y": 1192
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2667,7 +2661,6 @@
             "x": 1005,
             "y": 1192
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2710,7 +2703,6 @@
             "x": 605,
             "y": 1192
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2753,7 +2745,6 @@
             "x": 605,
             "y": 1192
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2796,7 +2787,6 @@
             "x": 605,
             "y": 1192
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2839,7 +2829,6 @@
             "x": 205,
             "y": 1192
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2882,7 +2871,6 @@
             "x": 205,
             "y": 1192
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2925,7 +2913,6 @@
             "x": 205,
             "y": 1192
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2968,7 +2955,6 @@
             "x": 1005,
             "y": 875
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3011,7 +2997,6 @@
             "x": 1005,
             "y": 875
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3054,7 +3039,6 @@
             "x": 1005,
             "y": 875
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3097,7 +3081,6 @@
             "x": 605,
             "y": 875
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3140,7 +3123,6 @@
             "x": 605,
             "y": 875
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3183,7 +3165,6 @@
             "x": 605,
             "y": 875
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3226,7 +3207,6 @@
             "x": 605,
             "y": 875
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3269,7 +3249,6 @@
             "x": 205,
             "y": 875
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3312,7 +3291,6 @@
             "x": 205,
             "y": 875
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3355,7 +3333,6 @@
             "x": 205,
             "y": 875
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3398,7 +3375,6 @@
             "x": 205,
             "y": 875
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3441,7 +3417,6 @@
             "x": 1005,
             "y": 388
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3484,7 +3459,6 @@
             "x": 1005,
             "y": 388
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3527,7 +3501,6 @@
             "x": 1005,
             "y": 388
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3570,7 +3543,6 @@
             "x": 1005,
             "y": 388
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3613,7 +3585,6 @@
             "x": 605,
             "y": 388
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3656,7 +3627,6 @@
             "x": 605,
             "y": 388
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3699,7 +3669,6 @@
             "x": 605,
             "y": 388
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3742,7 +3711,6 @@
             "x": 605,
             "y": 388
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3785,7 +3753,6 @@
             "x": 205,
             "y": 388
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3828,7 +3795,6 @@
             "x": 205,
             "y": 388
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3871,7 +3837,6 @@
             "x": 205,
             "y": 388
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3914,7 +3879,6 @@
             "x": 205,
             "y": 388
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3957,7 +3921,6 @@
             "x": 1005,
             "y": 274
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -4000,7 +3963,6 @@
             "x": 1005,
             "y": 274
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -4043,7 +4005,6 @@
             "x": 1005,
             "y": 274
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -4086,7 +4047,6 @@
             "x": 605,
             "y": 274
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -4129,7 +4089,6 @@
             "x": 605,
             "y": 274
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -4172,7 +4131,6 @@
             "x": 605,
             "y": 274
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -4215,7 +4173,6 @@
             "x": 205,
             "y": 274
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -4258,7 +4215,6 @@
             "x": 205,
             "y": 274
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -4301,7 +4257,6 @@
             "x": 205,
             "y": 274
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -4344,7 +4299,6 @@
             "x": 0,
             "y": 218
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -4373,7 +4327,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -4396,7 +4349,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -4419,7 +4371,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -4442,7 +4393,6 @@
       }, {
          "are_contents_opaque": true,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
diff --git a/components/viz/test/data/render_pass_data/top_real_world_desktop/twitter_2018/0352.json b/components/viz/test/data/render_pass_data/top_real_world_desktop/twitter_2018/0352.json
index e80f4ad..2148b36 100644
--- a/components/viz/test/data/render_pass_data/top_real_world_desktop/twitter_2018/0352.json
+++ b/components/viz/test/data/render_pass_data/top_real_world_desktop/twitter_2018/0352.json
@@ -139,7 +139,6 @@
             "x": 503,
             "y": 5924
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -182,7 +181,6 @@
             "x": 503,
             "y": 5924
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -225,7 +223,6 @@
             "x": 503,
             "y": 5924
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -434,7 +431,6 @@
             "x": 503,
             "y": 4417
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -477,7 +473,6 @@
             "x": 503,
             "y": 4417
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -520,7 +515,6 @@
             "x": 503,
             "y": 4417
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": true,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1992,7 +1986,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2021,7 +2014,6 @@
             "x": 0,
             "y": 100
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2050,7 +2042,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2079,7 +2070,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2108,7 +2098,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2137,7 +2126,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2166,7 +2154,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2195,7 +2182,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2224,7 +2210,6 @@
             "x": 502,
             "y": 1138
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2267,7 +2252,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2296,7 +2280,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2325,7 +2308,6 @@
             "x": 502,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2368,7 +2350,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2391,7 +2372,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2414,7 +2394,6 @@
       }, {
          "are_contents_opaque": true,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
diff --git a/components/viz/test/data/render_pass_data/top_real_world_desktop/wikipedia_2018/0048.json b/components/viz/test/data/render_pass_data/top_real_world_desktop/wikipedia_2018/0048.json
index fc5d815c..2ac179fd 100644
--- a/components/viz/test/data/render_pass_data/top_real_world_desktop/wikipedia_2018/0048.json
+++ b/components/viz/test/data/render_pass_data/top_real_world_desktop/wikipedia_2018/0048.json
@@ -1217,7 +1217,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1246,7 +1245,6 @@
             "x": 0,
             "y": 100
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1275,7 +1273,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1304,7 +1301,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1327,7 +1323,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1350,7 +1345,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1373,7 +1367,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1396,7 +1389,6 @@
       }, {
          "are_contents_opaque": true,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
diff --git a/components/viz/test/data/render_pass_data/top_real_world_desktop/wordpress_2018/0075.json b/components/viz/test/data/render_pass_data/top_real_world_desktop/wordpress_2018/0075.json
index ba37e31..8fc7d10 100644
--- a/components/viz/test/data/render_pass_data/top_real_world_desktop/wordpress_2018/0075.json
+++ b/components/viz/test/data/render_pass_data/top_real_world_desktop/wordpress_2018/0075.json
@@ -1337,7 +1337,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1366,7 +1365,6 @@
             "x": 0,
             "y": 100
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1395,7 +1393,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1424,7 +1421,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.9800000190734863,
          "quad_layer_rect": {
@@ -1453,7 +1449,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1482,7 +1477,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1505,7 +1499,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1528,7 +1521,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1551,7 +1543,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1574,7 +1565,6 @@
       }, {
          "are_contents_opaque": true,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
diff --git a/components/viz/test/data/render_pass_data/top_real_world_desktop/yahoo_answers_2018/0074.json b/components/viz/test/data/render_pass_data/top_real_world_desktop/yahoo_answers_2018/0074.json
index 333ee25..0a8be22c 100644
--- a/components/viz/test/data/render_pass_data/top_real_world_desktop/yahoo_answers_2018/0074.json
+++ b/components/viz/test/data/render_pass_data/top_real_world_desktop/yahoo_answers_2018/0074.json
@@ -1386,7 +1386,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1415,7 +1414,6 @@
             "x": 0,
             "y": 100
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1444,7 +1442,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1473,7 +1470,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1502,7 +1498,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1531,7 +1526,6 @@
             "x": 1186,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1560,7 +1554,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1589,7 +1582,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1618,7 +1610,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1647,7 +1638,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1670,7 +1660,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -1693,7 +1682,6 @@
       }, {
          "are_contents_opaque": true,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
diff --git a/components/viz/test/data/render_pass_data/top_real_world_desktop/yahoo_sports_2018/0269.json b/components/viz/test/data/render_pass_data/top_real_world_desktop/yahoo_sports_2018/0269.json
index d9f16cb5..7efd50a 100644
--- a/components/viz/test/data/render_pass_data/top_real_world_desktop/yahoo_sports_2018/0269.json
+++ b/components/viz/test/data/render_pass_data/top_real_world_desktop/yahoo_sports_2018/0269.json
@@ -2477,7 +2477,6 @@
       "shared_quad_state_list": [ {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2506,7 +2505,6 @@
             "x": 0,
             "y": 100
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2535,7 +2533,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2564,7 +2561,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2593,7 +2589,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2622,7 +2617,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.023814285174012184,
          "quad_layer_rect": {
@@ -2651,7 +2645,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.023814285174012184,
          "quad_layer_rect": {
@@ -2680,7 +2673,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.12625713646411896,
          "quad_layer_rect": {
@@ -2709,7 +2701,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.12625713646411896,
          "quad_layer_rect": {
@@ -2738,7 +2729,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.12625713646411896,
          "quad_layer_rect": {
@@ -2767,7 +2757,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.12625713646411896,
          "quad_layer_rect": {
@@ -2796,7 +2785,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.46843332052230835,
          "quad_layer_rect": {
@@ -2825,7 +2813,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 0.46843332052230835,
          "quad_layer_rect": {
@@ -2854,7 +2841,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2883,7 +2869,6 @@
             "x": 25,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2912,7 +2897,6 @@
             "x": 797,
             "y": 1065
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2941,7 +2925,6 @@
             "x": 434,
             "y": 1065
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2970,7 +2953,6 @@
             "x": 300,
             "y": 913
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -2999,7 +2981,6 @@
             "x": 25,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3028,7 +3009,6 @@
             "x": 300,
             "y": 913
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3057,7 +3037,6 @@
             "x": 300,
             "y": 913
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3086,7 +3065,6 @@
             "x": 25,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3115,7 +3093,6 @@
             "x": 797,
             "y": 786
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3144,7 +3121,6 @@
             "x": 434,
             "y": 786
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3173,7 +3149,6 @@
             "x": 300,
             "y": 634
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3202,7 +3177,6 @@
             "x": 25,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3231,7 +3205,6 @@
             "x": 300,
             "y": 634
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3260,7 +3233,6 @@
             "x": 300,
             "y": 634
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3289,7 +3261,6 @@
             "x": 25,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3318,7 +3289,6 @@
             "x": 797,
             "y": 506
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3347,7 +3317,6 @@
             "x": 434,
             "y": 506
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3376,7 +3345,6 @@
             "x": 300,
             "y": 354
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3405,7 +3373,6 @@
             "x": 25,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3434,7 +3401,6 @@
             "x": 300,
             "y": 354
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3463,7 +3429,6 @@
             "x": 300,
             "y": 354
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3492,7 +3457,6 @@
             "x": 25,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3521,7 +3485,6 @@
             "x": 797,
             "y": 227
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3550,7 +3513,6 @@
             "x": 434,
             "y": 227
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3579,7 +3541,6 @@
             "x": 300,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3608,7 +3569,6 @@
             "x": 25,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3637,7 +3597,6 @@
             "x": 300,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3666,7 +3625,6 @@
             "x": 300,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3695,7 +3653,6 @@
             "x": 25,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3724,7 +3681,6 @@
             "x": 0,
             "y": 155
          },
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3747,7 +3703,6 @@
       }, {
          "are_contents_opaque": false,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
@@ -3770,7 +3725,6 @@
       }, {
          "are_contents_opaque": true,
          "blend_mode": "kSrcOver",
-         "de_jelly_delta_y": 0.0,
          "is_fast_rounded_corner": false,
          "opacity": 1.0,
          "quad_layer_rect": {
diff --git a/components/webapps/browser/installable/installable_metrics.h b/components/webapps/browser/installable/installable_metrics.h
index 3da2f36..c88cac8 100644
--- a/components/webapps/browser/installable/installable_metrics.h
+++ b/components/webapps/browser/installable/installable_metrics.h
@@ -188,8 +188,11 @@
   // profile.
   kExternalLockScreen = 18,
 
+  // Tests often need a way of fully installing apps to clean up OS integration.
+  kTestCleanup = 19,
+
   // Add any new values above this one.
-  kMaxValue = kExternalLockScreen,
+  kMaxValue = kTestCleanup,
 };
 
 // This is the result of the promotability check that is recorded in the
diff --git a/components/webdata/common/BUILD.gn b/components/webdata/common/BUILD.gn
index f5ffa9a..ed94439c 100644
--- a/components/webdata/common/BUILD.gn
+++ b/components/webdata/common/BUILD.gn
@@ -45,6 +45,7 @@
     "//components/test/data/web_database/version_104.sql",
     "//components/test/data/web_database/version_105.sql",
     "//components/test/data/web_database/version_106.sql",
+    "//components/test/data/web_database/version_107.sql",
     "//components/test/data/web_database/version_82.sql",
     "//components/test/data/web_database/version_83.sql",
     "//components/test/data/web_database/version_84.sql",
diff --git a/components/webdata/common/web_database.cc b/components/webdata/common/web_database.cc
index f368eb6..c4d6adc 100644
--- a/components/webdata/common/web_database.cc
+++ b/components/webdata/common/web_database.cc
@@ -13,7 +13,7 @@
 // corresponding changes must happen in the unit tests, and new migration test
 // added.  See |WebDatabaseMigrationTest::kCurrentTestedVersionNumber|.
 // static
-const int WebDatabase::kCurrentVersionNumber = 107;
+const int WebDatabase::kCurrentVersionNumber = 108;
 
 const int WebDatabase::kDeprecatedVersionNumber = 82;
 
@@ -213,4 +213,4 @@
 
 bool WebDatabase::MigrateToVersion105DropIbansTable() {
   return db_.Execute("DROP TABLE IF EXISTS ibans");
-}
\ No newline at end of file
+}
diff --git a/components/webdata/common/web_database_migration_unittest.cc b/components/webdata/common/web_database_migration_unittest.cc
index 47635837..cb5cfe4 100644
--- a/components/webdata/common/web_database_migration_unittest.cc
+++ b/components/webdata/common/web_database_migration_unittest.cc
@@ -141,7 +141,7 @@
   base::ScopedTempDir temp_dir_;
 };
 
-const int WebDatabaseMigrationTest::kCurrentTestedVersionNumber = 107;
+const int WebDatabaseMigrationTest::kCurrentTestedVersionNumber = 108;
 
 void WebDatabaseMigrationTest::LoadDatabase(
     const base::FilePath::StringType& file) {
@@ -982,3 +982,37 @@
     EXPECT_TRUE(connection.DoesTableExist("contact_info_type_tokens"));
   }
 }
+
+// Tests addition of card_isser_id in masked_credit_cards table.
+TEST_F(WebDatabaseMigrationTest, MigrateVersion107ToCurrent) {
+  ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_107.sql")));
+
+  // Verify pre-conditions.
+  {
+    sql::Database connection;
+    ASSERT_TRUE(connection.Open(GetDatabasePath()));
+    ASSERT_TRUE(sql::MetaTable::DoesTableExist(&connection));
+
+    sql::MetaTable meta_table;
+    ASSERT_TRUE(meta_table.Init(&connection, 107, 106));
+
+    EXPECT_FALSE(
+        connection.DoesColumnExist("masked_credit_cards", "card_issuer_id"));
+  }
+
+  DoMigration();
+
+  // Verify post-conditions.
+  {
+    sql::Database connection;
+    ASSERT_TRUE(connection.Open(GetDatabasePath()));
+    ASSERT_TRUE(sql::MetaTable::DoesTableExist(&connection));
+
+    // Check version.
+    EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection));
+
+    // The card_issuer_id column and should exist.
+    EXPECT_TRUE(
+        connection.DoesColumnExist("masked_credit_cards", "card_issuer_id"));
+  }
+}
diff --git a/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc b/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc
index 3f131183..fb8c9188 100644
--- a/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc
+++ b/content/browser/attribution_reporting/attribution_data_host_manager_impl.cc
@@ -4,6 +4,8 @@
 
 #include "content/browser/attribution_reporting/attribution_data_host_manager_impl.h"
 
+#include <stddef.h>
+
 #include <utility>
 #include <vector>
 
@@ -132,10 +134,7 @@
     registration_type_ = type;
   }
 
-  int num_data_registered() const {
-    DCHECK_GE(num_data_registered_, 0);
-    return num_data_registered_;
-  }
+  size_t num_data_registered() const { return num_data_registered_; }
 
   base::TimeTicks register_time() const { return register_time_; }
 
@@ -145,10 +144,7 @@
     return nav_type_;
   }
 
-  void IncrementNumDataRegistered() {
-    DCHECK_GE(num_data_registered_, 0);
-    ++num_data_registered_;
-  }
+  void IncrementNumDataRegistered() { ++num_data_registered_; }
 
  private:
   // Top-level origin the data host was created in.
@@ -157,7 +153,7 @@
 
   AttributionRegistrationType registration_type_;
 
-  int num_data_registered_ = 0;
+  size_t num_data_registered_ = 0;
 
   // Logically const.
   base::TimeTicks register_time_;
@@ -507,7 +503,7 @@
   switch (context.registration_type()) {
     case AttributionRegistrationType::kSourceOrTrigger:
       OnSourceEligibleDataHostFinished(context.register_time());
-      DCHECK_EQ(context.num_data_registered(), 0);
+      DCHECK_EQ(context.num_data_registered(), 0u);
       return;
     case AttributionRegistrationType::kTrigger:
       histogram_name = "Conversions.RegisteredTriggersPerDataHost";
@@ -518,7 +514,7 @@
       break;
   }
 
-  if (int num = context.num_data_registered(); num > 0)
+  if (size_t num = context.num_data_registered())
     base::UmaHistogramExactLinear(histogram_name, num, 101);
 }
 
@@ -576,7 +572,7 @@
   if (it == redirect_registrations_.end())
     return;
 
-  DCHECK_GE(it->second.pending_source_data, 0u);
+  DCHECK_GT(it->second.pending_source_data, 0u);
   NavigationRedirectSourceRegistrations& registrations = it->second;
   registrations.pending_source_data--;
 
diff --git a/content/browser/attribution_reporting/attribution_internals_browsertest.cc b/content/browser/attribution_reporting/attribution_internals_browsertest.cc
index 40487e2..743d2c6 100644
--- a/content/browser/attribution_reporting/attribution_internals_browsertest.cc
+++ b/content/browser/attribution_reporting/attribution_internals_browsertest.cc
@@ -145,7 +145,7 @@
         .shadowRoot.querySelector('tbody');
     let obs = new MutationObserver((_, obs) => {
       if (table.children.length === 1 &&
-          table.children[0].children[0].innerText === "No sent or pending reports.") {
+          table.children[0].children[0]?.innerText === "No sent or pending reports.") {
         obs.disconnect();
         document.title = $1;
       }
@@ -243,8 +243,7 @@
         .shadowRoot.querySelector('tbody');
     let obs = new MutationObserver((_, obs) => {
       if (table.children.length === 1 &&
-          table.children[0].children[0].innerText ===
-          "No sources.") {
+          table.children[0].children[0]?.innerText === "No sources.") {
         obs.disconnect();
         document.title = $1;
       }
@@ -315,32 +314,32 @@
         .shadowRoot.querySelector('tbody');
     let obs = new MutationObserver((_, obs) => {
       if (table.children.length === 7 &&
-          table.children[0].children[0].innerText === $1 &&
-          table.children[0].children[9].innerText === "Navigation" &&
-          table.children[1].children[9].innerText === "Event" &&
-          table.children[0].children[10].innerText === "0" &&
-          table.children[1].children[10].innerText === $2 &&
-          table.children[0].children[11].innerText === "{}" &&
-          table.children[1].children[11].innerText === '{\n "a": [\n  "b",\n  "c"\n ]\n}' &&
-          table.children[0].children[12].innerText === "{}" &&
-          table.children[1].children[12].innerText === '{\n "a": "0x1"\n}' &&
-          table.children[0].children[13].innerText === "0 / 65536" &&
-          table.children[1].children[13].innerText === "1300 / 65536" &&
-          table.children[0].children[14].innerText === "19" &&
-          table.children[1].children[14].innerText === "" &&
-          table.children[0].children[15].innerText === "" &&
-          table.children[1].children[15].innerText === "13, 17" &&
-          table.children[0].children[16].innerText === "" &&
-          table.children[1].children[16].innerText === "14, 18" &&
-          table.children[0].children[1].innerText === "Unattributable: noised" &&
-          table.children[1].children[1].innerText === "Attributable" &&
-          table.children[2].children[1].innerText === "Attributable: reached event-level attribution limit" &&
-          table.children[3].children[1].innerText === "Rejected: internal error" &&
-          table.children[4].children[1].innerText === "Rejected: insufficient source capacity" &&
-          table.children[5].children[1].innerText === "Rejected: insufficient unique destination capacity" &&
-          table.children[6].children[1].innerText === "Rejected: excessive reporting origins" &&
-          table.children[5].children[17].innerText === "disabled" &&
-          table.children[6].children[17].innerText === "enabled") {
+          table.children[0].children[0]?.innerText === $1 &&
+          table.children[0].children[9]?.innerText === "Navigation" &&
+          table.children[1].children[9]?.innerText === "Event" &&
+          table.children[0].children[10]?.innerText === "0" &&
+          table.children[1].children[10]?.innerText === $2 &&
+          table.children[0].children[11]?.innerText === "{}" &&
+          table.children[1].children[11]?.innerText === '{\n "a": [\n  "b",\n  "c"\n ]\n}' &&
+          table.children[0].children[12]?.innerText === "{}" &&
+          table.children[1].children[12]?.innerText === '{\n "a": "0x1"\n}' &&
+          table.children[0].children[13]?.innerText === "0 / 65536" &&
+          table.children[1].children[13]?.innerText === "1300 / 65536" &&
+          table.children[0].children[14]?.innerText === "19" &&
+          table.children[1].children[14]?.innerText === "" &&
+          table.children[0].children[15]?.innerText === "" &&
+          table.children[1].children[15]?.innerText === "13, 17" &&
+          table.children[0].children[16]?.innerText === "" &&
+          table.children[1].children[16]?.innerText === "14, 18" &&
+          table.children[0].children[1]?.innerText === "Unattributable: noised" &&
+          table.children[1].children[1]?.innerText === "Attributable" &&
+          table.children[2].children[1]?.innerText === "Attributable: reached event-level attribution limit" &&
+          table.children[3].children[1]?.innerText === "Rejected: internal error" &&
+          table.children[4].children[1]?.innerText === "Rejected: insufficient source capacity" &&
+          table.children[5].children[1]?.innerText === "Rejected: insufficient unique destination capacity" &&
+          table.children[6].children[1]?.innerText === "Rejected: excessive reporting origins" &&
+          table.children[5].children[17]?.innerText === "disabled" &&
+          table.children[6].children[17]?.innerText === "enabled") {
         obs.disconnect();
         document.title = $3;
       }
@@ -367,16 +366,15 @@
                         'sources" target="_blank">Failed Source Registration' +
                         '</a>';
     const metadata = '<dl><dt>Failure Reason</dt><dd>invalid JSON</dd>' +
-                     '<dt>Report To</dt><dd>https://a.test</dd>' +
+                     '<dt>Reporting Origin</dt><dd>https://a.test</dd>' +
                      '<dt>Attribution-Reporting-Register-Source Header</dt>'+
                      '<dd><pre><code>!</code></pre></dd></dl>';
 
     let obs = new MutationObserver((_, obs) => {
       if (table.children.length === 1 &&
-          table.children[0].children.length >= 3 &&
-          table.children[0].children[1].innerHTML === description &&
-          table.children[0].children[2].innerHTML === metadata
-      )  {
+          table.children[0].children[1]?.innerHTML === description &&
+          table.children[0].children[2]?.innerHTML === metadata
+      ) {
         obs.disconnect();
         document.title = $1;
       }
@@ -406,14 +404,13 @@
                     'reports" target="_blank">Cleared Debug Key</a>';
     const metadata = '<dl><dt>Cleared Debug Key</dt><dd>1234</dd>' +
                      '<dt>From</dt><dd>Source</dd>'+
-                     '<dt>Report To</dt><dd>https://report.test</dd></dl>';
+                     '<dt>Reporting Origin</dt><dd>https://report.test</dd></dl>';
 
     let obs = new MutationObserver((_, obs) => {
       if (table.children.length === 1 &&
-          table.children[0].children.length >= 3 &&
-          table.children[0].children[1].innerHTML === description &&
-          table.children[0].children[2].innerHTML === metadata
-      )  {
+          table.children[0].children[1]?.innerHTML === description &&
+          table.children[0].children[2]?.innerHTML === metadata
+      ) {
         obs.disconnect();
         document.title = $1;
       }
@@ -444,14 +441,13 @@
                     'reports" target="_blank">Cleared Debug Key</a>';
     const metadata = '<dl><dt>Cleared Debug Key</dt><dd>1234</dd>' +
                      '<dt>From</dt><dd>Trigger</dd>'+
-                     '<dt>Report To</dt><dd>https://report.test</dd></dl>';
+                     '<dt>Reporting Origin</dt><dd>https://report.test</dd></dl>';
 
     let obs = new MutationObserver((_, obs) => {
       if (table.children.length === 1 &&
-          table.children[0].children.length >= 3 &&
-          table.children[0].children[1].innerHTML === description &&
-          table.children[0].children[2].innerHTML === metadata
-      )  {
+          table.children[0].children[1]?.innerHTML === description &&
+          table.children[0].children[2]?.innerHTML === metadata
+      ) {
         obs.disconnect();
         document.title = $1;
       }
@@ -609,24 +605,24 @@
           .shadowRoot.querySelector('tbody');
       let obs = new MutationObserver((_, obs) => {
         if (table.children.length === 6 &&
-            table.children[0].children[3].innerText ===
+            table.children[0].children[3]?.innerText ===
               "https://report.test/.well-known/attribution-reporting/report-event-attribution" &&
-            table.children[0].children[6].innerText === "13" &&
-            table.children[0].children[7].innerText === "yes" &&
-            table.children[0].children[2].innerText === "Pending" &&
-            table.children[1].children[6].innerText === "11" &&
-            table.children[1].children[2].innerText ===
+            table.children[0].children[6]?.innerText === "13" &&
+            table.children[0].children[7]?.innerText === "yes" &&
+            table.children[0].children[2]?.innerText === "Pending" &&
+            table.children[1].children[6]?.innerText === "11" &&
+            table.children[1].children[2]?.innerText ===
               "Replaced by higher-priority report: 21abd97f-73e8-4b88-9389-a9fee6abda5e" &&
-            table.children[2].children[6].innerText === "0" &&
-            table.children[2].children[7].innerText === "no" &&
-            table.children[2].children[2].innerText === "Sent: HTTP 200" &&
+            table.children[2].children[6]?.innerText === "0" &&
+            table.children[2].children[7]?.innerText === "no" &&
+            table.children[2].children[2]?.innerText === "Sent: HTTP 200" &&
             !table.children[2].classList.contains('send-error') &&
-            table.children[3].children[2].innerText === "Prohibited by browser policy" &&
+            table.children[3].children[2]?.innerText === "Prohibited by browser policy" &&
             !table.children[3].classList.contains('send-error') &&
-            table.children[4].children[2].innerText === "Network error: ERR_METHOD_NOT_SUPPORTED" &&
+            table.children[4].children[2]?.innerText === "Network error: ERR_METHOD_NOT_SUPPORTED" &&
             table.children[4].classList.contains('send-error') &&
-            table.children[5].children[2].innerText === "Network error: ERR_TIMED_OUT" &&
-            table.children[5].children[3].innerText ===
+            table.children[5].children[2]?.innerText === "Network error: ERR_TIMED_OUT" &&
+            table.children[5].children[3]?.innerText ===
               "https://report.test/.well-known/attribution-reporting/debug/report-event-attribution") {
           obs.disconnect();
           document.title = $1;
@@ -651,21 +647,21 @@
           .shadowRoot.querySelector('tbody');
       let obs = new MutationObserver((_, obs) => {
         if (table.children.length === 6 &&
-            table.children[5].children[3].innerText ===
+            table.children[5].children[3]?.innerText ===
               "https://report.test/.well-known/attribution-reporting/report-event-attribution" &&
-            table.children[5].children[6].innerText === "13" &&
-            table.children[5].children[7].innerText === "yes" &&
-            table.children[5].children[2].innerText === "Pending" &&
-            table.children[4].children[6].innerText === "11" &&
-            table.children[4].children[2].innerText ===
+            table.children[5].children[6]?.innerText === "13" &&
+            table.children[5].children[7]?.innerText === "yes" &&
+            table.children[5].children[2]?.innerText === "Pending" &&
+            table.children[4].children[6]?.innerText === "11" &&
+            table.children[4].children[2]?.innerText ===
               "Replaced by higher-priority report: 21abd97f-73e8-4b88-9389-a9fee6abda5e" &&
-            table.children[3].children[6].innerText === "0" &&
-            table.children[3].children[7].innerText === "no" &&
-            table.children[3].children[2].innerText === "Sent: HTTP 200" &&
-            table.children[2].children[2].innerText === "Prohibited by browser policy" &&
-            table.children[1].children[2].innerText === "Network error: ERR_METHOD_NOT_SUPPORTED" &&
-            table.children[0].children[2].innerText === "Network error: ERR_TIMED_OUT" &&
-            table.children[0].children[3].innerText ===
+            table.children[3].children[6]?.innerText === "0" &&
+            table.children[3].children[7]?.innerText === "no" &&
+            table.children[3].children[2]?.innerText === "Sent: HTTP 200" &&
+            table.children[2].children[2]?.innerText === "Prohibited by browser policy" &&
+            table.children[1].children[2]?.innerText === "Network error: ERR_METHOD_NOT_SUPPORTED" &&
+            table.children[0].children[2]?.innerText === "Network error: ERR_TIMED_OUT" &&
+            table.children[0].children[3]?.innerText ===
               "https://report.test/.well-known/attribution-reporting/debug/report-event-attribution") {
           obs.disconnect();
           document.title = $1;
@@ -688,21 +684,21 @@
           .shadowRoot.querySelector('tbody');
       let obs = new MutationObserver((_, obs) => {
         if (table.children.length === 6 &&
-            table.children[0].children[3].innerText ===
+            table.children[0].children[3]?.innerText ===
               "https://report.test/.well-known/attribution-reporting/report-event-attribution" &&
-            table.children[0].children[6].innerText === "13" &&
-            table.children[0].children[7].innerText === "yes" &&
-            table.children[0].children[2].innerText === "Pending" &&
-            table.children[1].children[6].innerText === "11" &&
-            table.children[1].children[2].innerText ===
+            table.children[0].children[6]?.innerText === "13" &&
+            table.children[0].children[7]?.innerText === "yes" &&
+            table.children[0].children[2]?.innerText === "Pending" &&
+            table.children[1].children[6]?.innerText === "11" &&
+            table.children[1].children[2]?.innerText ===
               "Replaced by higher-priority report: 21abd97f-73e8-4b88-9389-a9fee6abda5e" &&
-            table.children[2].children[6].innerText === "0" &&
-            table.children[2].children[7].innerText === "no" &&
-            table.children[2].children[2].innerText === "Sent: HTTP 200" &&
-            table.children[3].children[2].innerText === "Prohibited by browser policy" &&
-            table.children[4].children[2].innerText === "Network error: ERR_METHOD_NOT_SUPPORTED" &&
-            table.children[5].children[2].innerText === "Network error: ERR_TIMED_OUT" &&
-            table.children[5].children[3].innerText ===
+            table.children[2].children[6]?.innerText === "0" &&
+            table.children[2].children[7]?.innerText === "no" &&
+            table.children[2].children[2]?.innerText === "Sent: HTTP 200" &&
+            table.children[3].children[2]?.innerText === "Prohibited by browser policy" &&
+            table.children[4].children[2]?.innerText === "Network error: ERR_METHOD_NOT_SUPPORTED" &&
+            table.children[5].children[2]?.innerText === "Network error: ERR_TIMED_OUT" &&
+            table.children[5].children[3]?.innerText ===
               "https://report.test/.well-known/attribution-reporting/debug/report-event-attribution") {
           obs.disconnect();
           document.title = $1;
@@ -765,8 +761,8 @@
 
     const setTitleIfDone = (_, obs) => {
       if (table.children.length === 2 &&
-          table.children[0].children[6].innerText === "7" &&
-          table.children[1].children[2].innerText === "Sent: HTTP 200") {
+          table.children[0].children[6]?.innerText === "7" &&
+          table.children[1].children[2]?.innerText === "Sent: HTTP 200") {
         if (obs) {
           obs.disconnect();
         }
@@ -825,8 +821,8 @@
         .shadowRoot.querySelector('tbody');
     let obs = new MutationObserver((_, obs) => {
       if (table.children.length === 2 &&
-          table.children[0].children[0].innerText === "5" &&
-          table.children[1].children[0].innerText === "6") {
+          table.children[0].children[0]?.innerText === "5" &&
+          table.children[1].children[0]?.innerText === "6") {
         obs.disconnect();
         document.title = $1;
       }
@@ -847,7 +843,7 @@
         .shadowRoot.querySelector('tbody');
     let obs = new MutationObserver((_, obs) => {
       if (table.children.length === 1 &&
-          table.children[0].children[0].innerText === "No sources.") {
+          table.children[0].children[0]?.innerText === "No sources.") {
         obs.disconnect();
         document.title = $1;
       }
@@ -889,8 +885,7 @@
         .shadowRoot.querySelector('tbody');
     const setTitleIfDone = (_, obs) => {
       if (table.children.length === 1 &&
-          table.children[0].children.length >= 7 &&
-          table.children[0].children[6].innerText === "7") {
+          table.children[0].children[6]?.innerText === "7") {
           if (obs) {
             obs.disconnect();
           }
@@ -1018,16 +1013,16 @@
           .shadowRoot.querySelector('tbody');
       let obs = new MutationObserver((_, obs) => {
         if (table.children.length === 6 &&
-            table.children[0].children[3].innerText ===
+            table.children[0].children[3]?.innerText ===
               "https://report.test/.well-known/attribution-reporting/report-aggregate-attribution" &&
-            table.children[0].children[2].innerText === "Pending" &&
-            table.children[0].children[6].innerText === '[ {  "key": "0x1",  "value": 2 }]' &&
-            table.children[1].children[2].innerText === "Sent: HTTP 200" &&
-            table.children[2].children[2].innerText === "Prohibited by browser policy" &&
-            table.children[3].children[2].innerText === "Dropped due to assembly failure" &&
-            table.children[4].children[2].innerText === "Network error: ERR_INVALID_REDIRECT" &&
-            table.children[5].children[2].innerText === "Network error: ERR_INTERNET_DISCONNECTED" &&
-            table.children[5].children[3].innerText ===
+            table.children[0].children[2]?.innerText === "Pending" &&
+            table.children[0].children[6]?.innerText === '[ {  "key": "0x1",  "value": 2 }]' &&
+            table.children[1].children[2]?.innerText === "Sent: HTTP 200" &&
+            table.children[2].children[2]?.innerText === "Prohibited by browser policy" &&
+            table.children[3].children[2]?.innerText === "Dropped due to assembly failure" &&
+            table.children[4].children[2]?.innerText === "Network error: ERR_INVALID_REDIRECT" &&
+            table.children[5].children[2]?.innerText === "Network error: ERR_INTERNET_DISCONNECTED" &&
+            table.children[5].children[3]?.innerText ===
               "https://report.test/.well-known/attribution-reporting/debug/report-aggregate-attribution") {
           obs.disconnect();
           document.title = $1;
@@ -1099,11 +1094,11 @@
           .shadowRoot.querySelector('tbody');
       let obs = new MutationObserver((_, obs) => {
         if (table.children.length === 1 &&
-            table.children[0].children[1].innerText === "Success: Report stored" &&
-            table.children[0].children[2].innerText === "Success: Report stored" &&
-            table.children[0].children[3].innerText === "https://d.test" &&
-            table.children[0].children[4].innerText === "https://r.test" &&
-            table.children[0].children[5].innerText.includes('{')) {
+            table.children[0].children[1]?.innerText === "Success: Report stored" &&
+            table.children[0].children[2]?.innerText === "Success: Report stored" &&
+            table.children[0].children[3]?.innerText === "https://d.test" &&
+            table.children[0].children[4]?.innerText === "https://r.test" &&
+            table.children[0].children[5]?.innerText.includes('{')) {
           obs.disconnect();
           document.title = $1;
         }
@@ -1188,7 +1183,7 @@
         .shadowRoot.querySelector('tbody');
     let obs = new MutationObserver((_, obs) => {
       if (table.children.length === 1 &&
-          table.children[0].children[0].innerText === "No sent or pending reports.") {
+          table.children[0].children[0]?.innerText === "No sent or pending reports.") {
         obs.disconnect();
         document.title = $1;
       }
@@ -1243,8 +1238,8 @@
       let label = document.querySelector('#show-debug-event-reports span');
       let obs = new MutationObserver((_, obs) => {
         if (table.children.length === 2 &&
-            table.children[0].children[6].innerText === "1" &&
-            table.children[1].children[6].innerText === "2" &&
+            table.children[0].children[6]?.innerText === "1" &&
+            table.children[1].children[6]?.innerText === "2" &&
             label.innerText === '') {
           obs.disconnect();
           document.title = $1;
@@ -1282,7 +1277,7 @@
       let label = document.querySelector('#show-debug-event-reports span');
       let obs = new MutationObserver((_, obs) => {
         if (table.children.length === 1 &&
-            table.children[0].children[6].innerText === "2" &&
+            table.children[0].children[6]?.innerText === "2" &&
             label.innerText === ' (2 hidden)') {
           obs.disconnect();
           document.title = $1;
@@ -1310,9 +1305,9 @@
       let label = document.querySelector('#show-debug-event-reports span');
       let obs = new MutationObserver((_, obs) => {
         if (table.children.length === 3 &&
-            table.children[0].children[6].innerText === "1" &&
-            table.children[1].children[6].innerText === "2" &&
-            table.children[2].children[6].innerText === "3" &&
+            table.children[0].children[6]?.innerText === "1" &&
+            table.children[1].children[6]?.innerText === "2" &&
+            table.children[2].children[6]?.innerText === "3" &&
             label.innerText === '') {
           obs.disconnect();
           document.title = $1;
@@ -1348,10 +1343,9 @@
 
     let obs = new MutationObserver((_, obs) => {
       if (table.children.length === 1 &&
-          table.children[0].children.length >= 4 &&
-          table.children[0].children[1].innerText === url &&
-          table.children[0].children[2].innerText === 'HTTP 200' &&
-          table.children[0].children[3].innerText.includes('source-unknown-error')
+          table.children[0].children[1]?.innerText === url &&
+          table.children[0].children[2]?.innerText === 'HTTP 200' &&
+          table.children[0].children[3]?.innerText.includes('source-unknown-error')
       ) {
         obs.disconnect();
         document.title = $1;
diff --git a/content/browser/back_forward_cache_browsertest.cc b/content/browser/back_forward_cache_browsertest.cc
index 979c418..fcde216 100644
--- a/content/browser/back_forward_cache_browsertest.cc
+++ b/content/browser/back_forward_cache_browsertest.cc
@@ -2253,7 +2253,7 @@
     params_capturer.Wait();
     EXPECT_TRUE(params_capturer.has_user_gesture());
     EXPECT_TRUE(root->current_frame_host()
-                    ->last_navigation_started_with_transient_activation());
+                    ->last_committed_common_params_has_user_gesture());
   }
   RenderFrameHostImpl* rfh_a = current_frame_host();
 
@@ -2261,7 +2261,7 @@
   EXPECT_TRUE(NavigateToURL(shell(), url_b));
   EXPECT_TRUE(rfh_a->IsInBackForwardCache());
   EXPECT_FALSE(root->current_frame_host()
-                   ->last_navigation_started_with_transient_activation());
+                   ->last_committed_common_params_has_user_gesture());
 
   // 3) GoBack to A. RenderFrameHost of A should be restored from the
   // back-forward cache, and "has_user_gesture" is set to false correctly.
@@ -2280,7 +2280,7 @@
     // The navigation doesn't have user gesture.
     EXPECT_FALSE(params_capturer.has_user_gesture());
     EXPECT_FALSE(root->current_frame_host()
-                     ->last_navigation_started_with_transient_activation());
+                     ->last_committed_common_params_has_user_gesture());
   }
 
   // 4) Same-document navigation to A#foo without user gesture. At this point
@@ -2295,7 +2295,7 @@
     // The navigation doesn't have user gesture.
     EXPECT_FALSE(params_capturer.has_user_gesture());
     EXPECT_FALSE(root->current_frame_host()
-                     ->last_navigation_started_with_transient_activation());
+                     ->last_committed_common_params_has_user_gesture());
   }
 }
 
diff --git a/content/browser/back_forward_cache_not_restored_reasons_browsertest.cc b/content/browser/back_forward_cache_not_restored_reasons_browsertest.cc
index 157b1087..89580c9 100644
--- a/content/browser/back_forward_cache_not_restored_reasons_browsertest.cc
+++ b/content/browser/back_forward_cache_not_restored_reasons_browsertest.cc
@@ -312,4 +312,77 @@
               rfh_a_result);
 }
 
+// Test when a server redirect happens on history navigation, causing a
+// SiteInstance change and a new navigation entry. Ensure that the reasons from
+// the old entry are copied to the new one and reported internally, but not to
+// the API.
+IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTestWithNotRestoredReasons,
+                       ServerRedirect) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+
+  GURL url_a(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html"));
+  GURL url_c(embedded_test_server()->GetURL("c.com", "/title1.html"));
+
+  // Navigate to a.com. This time the redirect does not happen.
+  ASSERT_TRUE(NavigateToURL(web_contents(), url_a));
+  RenderFrameHostImplWrapper rfh_a(current_frame_host());
+  EXPECT_EQ(url_a, rfh_a->GetLastCommittedURL());
+  // Replace the history URL to a URL that would redirect to b.com when
+  // navigated to.
+  std::string replace_state =
+      "window.history.replaceState(null, '', '/server-redirect?" +
+      url_b.spec() + "');";
+  EXPECT_TRUE(ExecJs(rfh_a.get(), replace_state));
+
+  // Navigate to c.com, and evict |rfh_a| by executing JavaScript.
+  EXPECT_TRUE(NavigateToURL(shell(), url_c));
+  EvictByJavaScript(rfh_a.get());
+
+  // Navigate back.
+  GURL url_a_redirect(embedded_test_server()->GetURL(
+      "a.com", "/server-redirect?" + url_b.spec()));
+  TestNavigationManager navigation_manager(web_contents(), url_a_redirect);
+  web_contents()->GetController().GoBack();
+
+  // Wait for the navigation to start.
+  EXPECT_TRUE(navigation_manager.WaitForRequestStart());
+  auto* navigation_request =
+      NavigationRequest::From(navigation_manager.GetNavigationHandle());
+  auto reasons =
+      navigation_request->commit_params().not_restored_reasons.Clone();
+  // The reasons have not been reset yet.
+  auto rfh_a_result = MatchesNotRestoredReasons(
+      blink::mojom::BFCacheBlocked::kYes,
+      MatchesSameOriginDetails(
+          /*id=*/"", /*name=*/"", /*src=*/"", /*url=*/url_a_redirect.spec(),
+          /*reasons=*/{"JavaScript execution"},
+          /*children=*/{}));
+  EXPECT_THAT(reasons, rfh_a_result);
+
+  // Redirect happens, and now the reasons are reset.
+  EXPECT_TRUE(navigation_manager.WaitForResponse());
+  auto* reasons_after_redirect =
+      navigation_request->commit_params().not_restored_reasons.get();
+  EXPECT_THAT(reasons_after_redirect, nullptr);
+  navigation_manager.WaitForNavigationFinished();
+
+  // Eviction reasons should be recorded internally.
+  ExpectNotRestored({NotRestoredReason::kJavaScriptExecution}, {}, {}, {}, {},
+                    FROM_HERE);
+  // Redirect happened once.
+  EXPECT_TRUE(ExecJs(current_frame_host(),
+                     "performance.getEntriesByType('navigation')[0]."
+                     "redirectCount == 1"));
+  // Navigation type should be navigate, instead of back-forward because of the
+  // redirect.
+  EXPECT_TRUE(ExecJs(current_frame_host(),
+                     "performance.getEntriesByType('navigation')[0]."
+                     "type == 'navigate'"));
+  // NotRestoredReasons are not sent to the renderer because of redirect.
+  EXPECT_TRUE(ExecJs(current_frame_host(),
+                     "performance.getEntriesByType('navigation')[0]."
+                     "notRestoredReasons == null"));
+}
+
 }  // namespace content
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index 3ce52a78..63f23b3 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -253,8 +253,6 @@
     switches::kEnableBackgroundThreadPool,
     switches::kEnableGpuRasterization,
     switches::kEnableLogging,
-    switches::kEnableDeJelly,
-    switches::kDeJellyScreenWidth,
     switches::kDoubleBufferCompositing,
     switches::kHeadless,
     switches::kLoggingLevel,
diff --git a/content/browser/picture_in_picture/video_picture_in_picture_content_browsertest.cc b/content/browser/picture_in_picture/video_picture_in_picture_content_browsertest.cc
index 7dd0a00..74048aa8 100644
--- a/content/browser/picture_in_picture/video_picture_in_picture_content_browsertest.cc
+++ b/content/browser/picture_in_picture/video_picture_in_picture_content_browsertest.cc
@@ -632,40 +632,6 @@
   WaitForPlaybackState(VideoOverlayWindow::PlaybackState::kPlaying);
 }
 
-class AutoPictureInPictureContentBrowserTest
-    : public VideoPictureInPictureContentBrowserTest {
- public:
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    ContentBrowserTest::SetUpCommandLine(command_line);
-
-    base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
-        switches::kEnableBlinkFeatures,
-        "PictureInPictureAPI,AutoPictureInPicture");
-  }
-};
-
-// Show/hide fullscreen page and check that Auto Picture-in-Picture is
-// triggered.
-IN_PROC_BROWSER_TEST_F(AutoPictureInPictureContentBrowserTest,
-                       AutoPictureInPictureTriggeredWhenFullscreen) {
-  ASSERT_TRUE(NavigateToURL(
-      shell(), GetTestUrl("media/picture_in_picture", "one-video.html")));
-
-  ASSERT_EQ(true, EvalJs(shell(), "enterFullscreen();"));
-
-  ASSERT_TRUE(ExecJs(shell(), "video.autoPictureInPicture = true;"));
-  ASSERT_TRUE(ExecJs(shell(), "addPictureInPictureEventListeners();"));
-  ASSERT_EQ(true, EvalJs(shell(), "play();"));
-
-  // Hide page and check that video entered Picture-in-Picture automatically.
-  shell()->web_contents()->WasHidden();
-  WaitForTitle(u"enterpictureinpicture");
-
-  // Show page and check that video left Picture-in-Picture automatically.
-  shell()->web_contents()->WasShown();
-  WaitForTitle(u"leavepictureinpicture");
-}
-
 IN_PROC_BROWSER_TEST_F(VideoPictureInPictureContentBrowserTest,
                        EnterPictureInPictureHasNoChildWebContents) {
   ASSERT_TRUE(NavigateToURL(
diff --git a/content/browser/preloading/prerender/prerender_host_registry.cc b/content/browser/preloading/prerender/prerender_host_registry.cc
index 7cfd601c..0bdff70 100644
--- a/content/browser/preloading/prerender/prerender_host_registry.cc
+++ b/content/browser/preloading/prerender/prerender_host_registry.cc
@@ -398,15 +398,17 @@
   return frame_tree_node_id;
 }
 
-void PrerenderHostRegistry::CancelHosts(
+std::set<int> PrerenderHostRegistry::CancelHosts(
     const std::vector<int>& frame_tree_node_ids,
-    PrerenderFinalStatus final_status) {
+    const PrerenderCancellationReason& reason) {
   TRACE_EVENT1("navigation", "PrerenderHostRegistry::CancelHosts",
                "frame_tree_node_ids", frame_tree_node_ids);
 
   // Cancel must not be requested during activation.
   CHECK(!reserved_prerender_host_);
 
+  std::set<int> cancelled_ids;
+
   for (int host_id : frame_tree_node_ids) {
     // Look up the id in the non-reserved host map.
     if (auto iter = prerender_host_by_frame_tree_node_id_.find(host_id);
@@ -419,9 +421,12 @@
       std::unique_ptr<PrerenderHost> prerender_host = std::move(iter->second);
       prerender_host_by_frame_tree_node_id_.erase(iter);
 
+      reason.ReportMetrics(prerender_host->trigger_type(),
+                           prerender_host->embedder_histogram_suffix());
+
       // Asynchronously delete the prerender host.
-      ScheduleToDeleteAbandonedHost(std::move(prerender_host),
-                                    PrerenderCancellationReason(final_status));
+      ScheduleToDeleteAbandonedHost(std::move(prerender_host), reason);
+      cancelled_ids.insert(host_id);
     }
 
     if (base::FeatureList::IsEnabled(blink::features::kPrerender2InNewTab)) {
@@ -435,7 +440,8 @@
 
         std::unique_ptr<PrerenderNewTabHandle> handle = std::move(iter->second);
         prerender_new_tab_handle_by_frame_tree_node_id_.erase(iter);
-        handle->CancelPrerendering(final_status);
+        handle->CancelPrerendering(reason);
+        cancelled_ids.insert(host_id);
       }
     } else {
       DCHECK(prerender_new_tab_handle_by_frame_tree_node_id_.empty());
@@ -448,6 +454,8 @@
       running_prerender_host_id_ == RenderFrameHost::kNoFrameTreeNodeId) {
     StartPrerendering(RenderFrameHost::kNoFrameTreeNodeId);
   }
+
+  return cancelled_ids;
 }
 
 bool PrerenderHostRegistry::CancelHost(int frame_tree_node_id,
@@ -461,53 +469,13 @@
     const PrerenderCancellationReason& reason) {
   TRACE_EVENT1("navigation", "PrerenderHostRegistry::CancelHost",
                "frame_tree_node_id", frame_tree_node_id);
-
-  // Cancel must not be requested during activation.
-  CHECK(!reserved_prerender_host_);
-
-  // Look up the id in the non-reserved host map, remove it from the map, and
-  // record the cancellation reason.
-  if (auto iter =
-          prerender_host_by_frame_tree_node_id_.find(frame_tree_node_id);
-      iter != prerender_host_by_frame_tree_node_id_.end()) {
-    std::unique_ptr<PrerenderHost> prerender_host = std::move(iter->second);
-    prerender_host_by_frame_tree_node_id_.erase(iter);
-
-    reason.ReportMetrics(prerender_host->trigger_type(),
-                         prerender_host->embedder_histogram_suffix());
-
-    // Asynchronously delete the prerender host.
-    ScheduleToDeleteAbandonedHost(std::move(prerender_host), reason);
-
-    // Start another prerender if the running prerender is cancelled.
-    if (running_prerender_host_id_ == frame_tree_node_id) {
-      running_prerender_host_id_ = RenderFrameHost::kNoFrameTreeNodeId;
-      StartPrerendering(RenderFrameHost::kNoFrameTreeNodeId);
-    }
-
-    return true;
-  }
-
-  if (base::FeatureList::IsEnabled(blink::features::kPrerender2InNewTab)) {
-    // Look up the id in the prerender new-tab handle map, remove it from the
-    // map, and record the cancellation reason.
-    if (auto iter = prerender_new_tab_handle_by_frame_tree_node_id_.find(
-            frame_tree_node_id);
-        iter != prerender_new_tab_handle_by_frame_tree_node_id_.end()) {
-      iter->second->CancelPrerendering(reason.final_status());
-      prerender_new_tab_handle_by_frame_tree_node_id_.erase(iter);
-      return true;
-    }
-  } else {
-    DCHECK(prerender_new_tab_handle_by_frame_tree_node_id_.empty());
-  }
-
-  return false;
+  std::set<int> cancelled_ids = CancelHosts({frame_tree_node_id}, reason);
+  return !cancelled_ids.empty();
 }
 
 void PrerenderHostRegistry::CancelHostsForTrigger(
     PrerenderTriggerType trigger_type,
-    PrerenderFinalStatus final_status) {
+    const PrerenderCancellationReason& reason) {
   TRACE_EVENT1("navigation", "PrerenderHostRegistry::CancelHostsForTrigger",
                "trigger_type", trigger_type);
 
@@ -535,24 +503,29 @@
     DCHECK(prerender_new_tab_handle_by_frame_tree_node_id_.empty());
   }
 
-  CancelHosts(ids_to_be_deleted, final_status);
+  CancelHosts(ids_to_be_deleted, reason);
 }
 
 void PrerenderHostRegistry::CancelAllHosts(PrerenderFinalStatus final_status) {
   // Cancel must not be requested during activation.
   CHECK(!reserved_prerender_host_);
 
+  PrerenderCancellationReason reason(final_status);
+
   auto prerender_host_map = std::move(prerender_host_by_frame_tree_node_id_);
   for (auto& iter : prerender_host_map) {
     std::unique_ptr<PrerenderHost> prerender_host = std::move(iter.second);
-    ScheduleToDeleteAbandonedHost(std::move(prerender_host),
-                                  PrerenderCancellationReason(final_status));
+    ScheduleToDeleteAbandonedHost(std::move(prerender_host), reason);
   }
 
-  auto prerender_new_tab_handle_map =
-      std::move(prerender_new_tab_handle_by_frame_tree_node_id_);
-  for (auto& iter : prerender_new_tab_handle_map)
-    iter.second->CancelPrerendering(final_status);
+  if (base::FeatureList::IsEnabled(blink::features::kPrerender2InNewTab)) {
+    auto prerender_new_tab_handle_map =
+        std::move(prerender_new_tab_handle_by_frame_tree_node_id_);
+    for (auto& iter : prerender_new_tab_handle_map)
+      iter.second->CancelPrerendering(reason);
+  } else {
+    DCHECK(prerender_new_tab_handle_by_frame_tree_node_id_.empty());
+  }
 
   pending_prerenders_.clear();
 }
@@ -777,13 +750,15 @@
             base::BindOnce(&PrerenderHostRegistry::CancelHostsForTrigger,
                            base::Unretained(this),
                            PrerenderTriggerType::kEmbedder,
-                           PrerenderFinalStatus::kTimeoutBackgrounded));
+                           PrerenderCancellationReason(
+                               PrerenderFinalStatus::kTimeoutBackgrounded)));
         timeout_timer_for_speculation_rules_.Start(
             FROM_HERE, kTimeToLiveInBackgroundForSpeculationRules,
             base::BindOnce(&PrerenderHostRegistry::CancelHostsForTrigger,
                            base::Unretained(this),
                            PrerenderTriggerType::kSpeculationRule,
-                           PrerenderFinalStatus::kTimeoutBackgrounded));
+                           PrerenderCancellationReason(
+                               PrerenderFinalStatus::kTimeoutBackgrounded)));
         break;
       case Visibility::OCCLUDED:
       case Visibility::VISIBLE:
@@ -833,6 +808,13 @@
   }
 }
 
+void PrerenderHostRegistry::PrimaryMainFrameRenderProcessGone(
+    base::TerminationStatus status) {
+  CancelAllHosts(status == base::TERMINATION_STATUS_PROCESS_CRASHED
+                     ? PrerenderFinalStatus::kRendererProcessCrashed
+                     : PrerenderFinalStatus::kRendererProcessKilled);
+}
+
 int PrerenderHostRegistry::FindHostToActivateInternal(
     NavigationRequest& navigation_request) {
   RenderFrameHostImpl* render_frame_host =
@@ -911,11 +893,17 @@
       cancelled_prerenders.push_back(host_id);
     }
   }
-  for (const auto& [host_id, _] :
-       prerender_new_tab_handle_by_frame_tree_node_id_) {
-    cancelled_prerenders.push_back(host_id);
+  if (base::FeatureList::IsEnabled(blink::features::kPrerender2InNewTab)) {
+    for (const auto& [host_id, _] :
+         prerender_new_tab_handle_by_frame_tree_node_id_) {
+      cancelled_prerenders.push_back(host_id);
+    }
+  } else {
+    DCHECK(prerender_new_tab_handle_by_frame_tree_node_id_.empty());
   }
-  CancelHosts(cancelled_prerenders, PrerenderFinalStatus::kTriggerDestroyed);
+  CancelHosts(
+      cancelled_prerenders,
+      PrerenderCancellationReason(PrerenderFinalStatus::kTriggerDestroyed));
   pending_prerenders_.clear();
 
   return host->frame_tree_node_id();
diff --git a/content/browser/preloading/prerender/prerender_host_registry.h b/content/browser/preloading/prerender/prerender_host_registry.h
index f6ab5b4..a3698d2 100644
--- a/content/browser/preloading/prerender/prerender_host_registry.h
+++ b/content/browser/preloading/prerender/prerender_host_registry.h
@@ -117,14 +117,14 @@
   bool CancelHost(int frame_tree_node_id,
                   const PrerenderCancellationReason& reason);
 
-  // Cancels the existing hosts specified in the vector with the same final
-  // status.
-  void CancelHosts(const std::vector<int>& frame_tree_node_ids,
-                   PrerenderFinalStatus final_status);
+  // Cancels the existing hosts specified in the vector with the same reason.
+  // Returns a subset of `frame_tree_node_ids` that were actually cancelled.
+  std::set<int> CancelHosts(const std::vector<int>& frame_tree_node_ids,
+                            const PrerenderCancellationReason& reason);
 
   // Cancels the existing hosts that were triggered by `trigger_type`.
   void CancelHostsForTrigger(PrerenderTriggerType trigger_type,
-                             PrerenderFinalStatus final_status);
+                             const PrerenderCancellationReason& reason);
 
   // Applies CancelHost for all existing PrerenderHost.
   void CancelAllHosts(PrerenderFinalStatus final_status);
@@ -219,6 +219,8 @@
       RenderFrameHost* render_frame_host,
       const GlobalRequestID& request_id,
       const blink::mojom::ResourceLoadInfo& resource_load_info) override;
+  void PrimaryMainFrameRenderProcessGone(
+      base::TerminationStatus status) override;
 
   int FindHostToActivateInternal(NavigationRequest& navigation_request);
 
diff --git a/content/browser/preloading/prerender/prerender_new_tab_handle.cc b/content/browser/preloading/prerender/prerender_new_tab_handle.cc
index 6ea64c7..9b2fb4a 100644
--- a/content/browser/preloading/prerender/prerender_new_tab_handle.cc
+++ b/content/browser/preloading/prerender/prerender_new_tab_handle.cc
@@ -80,8 +80,8 @@
 }
 
 void PrerenderNewTabHandle::CancelPrerendering(
-    PrerenderFinalStatus final_status) {
-  GetPrerenderHostRegistry().CancelHost(prerender_host_id_, final_status);
+    const PrerenderCancellationReason& reason) {
+  GetPrerenderHostRegistry().CancelHost(prerender_host_id_, reason);
 }
 
 std::unique_ptr<WebContentsImpl>
diff --git a/content/browser/preloading/prerender/prerender_new_tab_handle.h b/content/browser/preloading/prerender/prerender_new_tab_handle.h
index 85d77d2..cf7b117 100644
--- a/content/browser/preloading/prerender/prerender_new_tab_handle.h
+++ b/content/browser/preloading/prerender/prerender_new_tab_handle.h
@@ -6,7 +6,7 @@
 #define CONTENT_BROWSER_PRELOADING_PRERENDER_PRERENDER_NEW_TAB_HANDLE_H_
 
 #include "content/browser/preloading/prerender/prerender_attributes.h"
-#include "content/browser/preloading/prerender/prerender_final_status.h"
+#include "content/browser/preloading/prerender/prerender_metrics.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/common/frame.mojom.h"
 #include "content/public/browser/browser_context.h"
@@ -43,7 +43,7 @@
   int StartPrerendering();
 
   // Cancels prerendering started in `web_contents_`.
-  void CancelPrerendering(PrerenderFinalStatus final_status);
+  void CancelPrerendering(const PrerenderCancellationReason& reason);
 
   // Passes the ownership of `web_contents_` to the caller if it's available for
   // new tab navigation with given params.
diff --git a/content/browser/preloading/prerenderer.cc b/content/browser/preloading/prerenderer.cc
index d1e9473..4672dc50 100644
--- a/content/browser/preloading/prerenderer.cc
+++ b/content/browser/preloading/prerenderer.cc
@@ -8,6 +8,7 @@
 #include "content/browser/preloading/prerender/prerender_attributes.h"
 #include "content/browser/preloading/prerender/prerender_final_status.h"
 #include "content/browser/preloading/prerender/prerender_host_registry.h"
+#include "content/browser/preloading/prerender/prerender_metrics.h"
 #include "content/browser/preloading/prerender/prerender_navigation_utils.h"
 #include "content/browser/preloading/prerender/prerender_new_tab_handle.h"
 #include "content/browser/renderer_host/render_frame_host_delegate.h"
@@ -163,8 +164,9 @@
     started_it = equal_prerender_end;
   }
 
-  registry_->CancelHosts(removed_prerender_rules,
-                         PrerenderFinalStatus::kTriggerDestroyed);
+  registry_->CancelHosts(
+      removed_prerender_rules,
+      PrerenderCancellationReason(PrerenderFinalStatus::kTriggerDestroyed));
 
   // Actually start the candidates once the diffing is done.
   auto& rfhi = static_cast<RenderFrameHostImpl&>(render_frame_host());
@@ -308,8 +310,9 @@
     for (auto& prerender_info : started_prerenders_) {
       started_prerender_ids.push_back(prerender_info.prerender_host_id);
     }
-    registry_->CancelHosts(started_prerender_ids,
-                           PrerenderFinalStatus::kTriggerDestroyed);
+    registry_->CancelHosts(
+        started_prerender_ids,
+        PrerenderCancellationReason(PrerenderFinalStatus::kTriggerDestroyed));
   }
 
   started_prerenders_.clear();
diff --git a/content/browser/renderer_host/back_forward_cache_impl.cc b/content/browser/renderer_host/back_forward_cache_impl.cc
index 24e3806..1d0859f2 100644
--- a/content/browser/renderer_host/back_forward_cache_impl.cc
+++ b/content/browser/renderer_host/back_forward_cache_impl.cc
@@ -1536,7 +1536,6 @@
 std::unique_ptr<BackForwardCacheCanStoreTreeResult>
 BackForwardCacheCanStoreTreeResult::CreateEmptyTreeForNavigation(
     NavigationRequest* navigation) {
-  DCHECK(!navigation->GetRenderFrameHost()->IsNestedWithinFencedFrame());
   DCHECK(BackForwardCacheMetrics::IsCrossDocumentMainFrameHistoryNavigation(
       navigation));
   std::unique_ptr<BackForwardCacheCanStoreTreeResult> empty_tree(
diff --git a/content/browser/renderer_host/document_user_data_browsertest.cc b/content/browser/renderer_host/document_user_data_browsertest.cc
index aca9515..f42f599 100644
--- a/content/browser/renderer_host/document_user_data_browsertest.cc
+++ b/content/browser/renderer_host/document_user_data_browsertest.cc
@@ -300,7 +300,7 @@
   RenderFrameHostImpl* pending_rfh =
       root->render_manager()->speculative_frame_host();
   NavigationRequest* navigation_request = root->navigation_request();
-  EXPECT_EQ(navigation_request->associated_rfh_type(),
+  EXPECT_EQ(navigation_request->GetAssociatedRFHType(),
             NavigationRequest::AssociatedRenderFrameHostType::SPECULATIVE);
   EXPECT_TRUE(pending_rfh);
 
@@ -379,7 +379,7 @@
   RenderFrameHostImpl* current_rfh =
       root->render_manager()->current_frame_host();
   NavigationRequest* navigation_request = root->navigation_request();
-  EXPECT_EQ(navigation_request->associated_rfh_type(),
+  EXPECT_EQ(navigation_request->GetAssociatedRFHType(),
             NavigationRequest::AssociatedRenderFrameHostType::CURRENT);
   EXPECT_TRUE(current_rfh);
   EXPECT_TRUE(current_rfh->IsActive());
@@ -475,7 +475,7 @@
   RenderFrameHostImpl* pending_rfh =
       root->render_manager()->speculative_frame_host();
   NavigationRequest* navigation_request = root->navigation_request();
-  EXPECT_EQ(navigation_request->associated_rfh_type(),
+  EXPECT_EQ(navigation_request->GetAssociatedRFHType(),
             NavigationRequest::AssociatedRenderFrameHostType::SPECULATIVE);
   EXPECT_TRUE(pending_rfh);
 
diff --git a/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc b/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc
index 962c63f..f07bedd 100644
--- a/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc
+++ b/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc
@@ -28,6 +28,7 @@
 #include "ui/gfx/geometry/size_conversions.h"
 #include "ui/strings/grit/ui_strings.h"
 #include "ui/touch_selection/touch_handle_drawable_aura.h"
+#include "ui/touch_selection/touch_selection_magnifier_runner.h"
 #include "ui/touch_selection/touch_selection_menu_runner.h"
 
 namespace content {
@@ -297,6 +298,21 @@
   }
 }
 
+void TouchSelectionControllerClientAura::ShowMagnifier(
+    const gfx::PointF& position) {
+  if (auto* magnifier_runner =
+          ui::TouchSelectionMagnifierRunner::GetInstance()) {
+    magnifier_runner->ShowMagnifier(rwhva_->GetNativeView(), position);
+  }
+}
+
+void TouchSelectionControllerClientAura::CloseMagnifier() {
+  if (auto* magnifier_runner =
+          ui::TouchSelectionMagnifierRunner::GetInstance()) {
+    magnifier_runner->CloseMagnifier();
+  }
+}
+
 bool TouchSelectionControllerClientAura::SupportsAnimation() const {
   // We don't pass this to the active client, since it is assumed it will have
   // the same behaviour as the Aura client.
@@ -385,6 +401,7 @@
     case ui::INSERTION_HANDLE_DRAG_STOPPED:
       handle_drag_in_progress_ = false;
       UpdateQuickMenu();
+      CloseMagnifier();
       break;
     case ui::SELECTION_HANDLES_MOVED:
     case ui::INSERTION_HANDLE_MOVED:
@@ -404,7 +421,10 @@
 
 void TouchSelectionControllerClientAura::OnDragUpdate(
     const ui::TouchSelectionDraggable::Type type,
-    const gfx::PointF& position) {}
+    const gfx::PointF& position) {
+  DCHECK(handle_drag_in_progress_);
+  ShowMagnifier(position);
+}
 
 void TouchSelectionControllerClientAura::InternalClient::OnDragUpdate(
     const ui::TouchSelectionDraggable::Type type,
diff --git a/content/browser/renderer_host/input/touch_selection_controller_client_aura.h b/content/browser/renderer_host/input/touch_selection_controller_client_aura.h
index 2373c89..92d0a0b5 100644
--- a/content/browser/renderer_host/input/touch_selection_controller_client_aura.h
+++ b/content/browser/renderer_host/input/touch_selection_controller_client_aura.h
@@ -83,6 +83,9 @@
   void ShowQuickMenu();
   void UpdateQuickMenu();
 
+  void ShowMagnifier(const gfx::PointF& position);
+  void CloseMagnifier();
+
   // ui::TouchSelectionControllerClient:
   bool SupportsAnimation() const override;
   void SetNeedsAnimate() override;
diff --git a/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc b/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
index e1dd9a6..ce9efb7 100644
--- a/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
+++ b/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
@@ -37,6 +37,7 @@
 #include "ui/events/test/event_generator.h"
 #include "ui/events/test/motion_event_test_utils.h"
 #include "ui/touch_selection/touch_selection_controller_test_api.h"
+#include "ui/touch_selection/touch_selection_magnifier_runner.h"
 
 namespace content {
 namespace {
@@ -57,6 +58,33 @@
   return true;
 }
 
+// A mock touch selection magnifier runner to use whenever a default one is not
+// installed.
+class TestTouchSelectionMagnifierRunner
+    : public ui::TouchSelectionMagnifierRunner {
+ public:
+  TestTouchSelectionMagnifierRunner() = default;
+
+  TestTouchSelectionMagnifierRunner(const TestTouchSelectionMagnifierRunner&) =
+      delete;
+  TestTouchSelectionMagnifierRunner& operator=(
+      const TestTouchSelectionMagnifierRunner&) = delete;
+
+  ~TestTouchSelectionMagnifierRunner() override = default;
+
+ private:
+  void ShowMagnifier(aura::Window* context,
+                     const gfx::PointF& position) override {
+    magnifier_running_ = true;
+  }
+
+  void CloseMagnifier() override { magnifier_running_ = false; }
+
+  bool IsRunning() const override { return magnifier_running_; }
+
+  bool magnifier_running_ = false;
+};
+
 // A mock touch selection menu runner to use whenever a default one is not
 // installed.
 class TestTouchSelectionMenuRunner : public ui::TouchSelectionMenuRunner {
@@ -200,17 +228,21 @@
 
   void SetUpOnMainThread() override {
     ContentBrowserTest::SetUpOnMainThread();
+    if (!ui::TouchSelectionMagnifierRunner::GetInstance())
+      magnifier_runner_ = std::make_unique<TestTouchSelectionMagnifierRunner>();
     if (!ui::TouchSelectionMenuRunner::GetInstance())
       menu_runner_ = std::make_unique<TestTouchSelectionMenuRunner>();
   }
 
  private:
   void TearDownOnMainThread() override {
+    magnifier_runner_ = nullptr;
     menu_runner_ = nullptr;
     selection_controller_client_ = nullptr;
     ContentBrowserTest::TearDownOnMainThread();
   }
 
+  std::unique_ptr<TestTouchSelectionMagnifierRunner> magnifier_runner_;
   std::unique_ptr<TestTouchSelectionMenuRunner> menu_runner_;
 
   raw_ptr<TestTouchSelectionControllerClientAura> selection_controller_client_ =
@@ -934,6 +966,7 @@
 
   EXPECT_EQ(ui::TouchSelectionController::INACTIVE,
             rwhva->selection_controller()->active_status());
+  EXPECT_FALSE(ui::TouchSelectionMagnifierRunner::GetInstance()->IsRunning());
   EXPECT_FALSE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
   EXPECT_EQ(2.f, rwhva->GetDeviceScaleFactor());
   EXPECT_EQ(gfx::RectF(),
@@ -988,6 +1021,7 @@
       ui::PointerDetails(ui::EventPointerType::kTouch, 0));
   rwhva->OnTouchEvent(&touch_down);
   selection_controller_client()->Wait();
+  EXPECT_FALSE(ui::TouchSelectionMagnifierRunner::GetInstance()->IsRunning());
 
   // Move it.
   selection_controller_client()->InitWaitForSelectionEvent(
@@ -998,6 +1032,7 @@
       ui::PointerDetails(ui::EventPointerType::kTouch, 0));
   rwhva->OnTouchEvent(&touch_move);
   selection_controller_client()->Wait();
+  EXPECT_TRUE(ui::TouchSelectionMagnifierRunner::GetInstance()->IsRunning());
 
   // Then release.
   selection_controller_client()->InitWaitForSelectionEvent(
@@ -1007,6 +1042,7 @@
                           ui::PointerDetails(ui::EventPointerType::kTouch, 0));
   rwhva->OnTouchEvent(&touch_up);
   selection_controller_client()->Wait();
+  EXPECT_FALSE(ui::TouchSelectionMagnifierRunner::GetInstance()->IsRunning());
 
   // The handle should have moved to right.
   EXPECT_EQ(start_top.y(), controller->start().edge_start().y());
@@ -1071,6 +1107,7 @@
       ui::PointerDetails(ui::EventPointerType::kTouch, 0));
   rwhva->OnTouchEvent(&touch_down);
   selection_controller_client()->Wait();
+  EXPECT_FALSE(ui::TouchSelectionMagnifierRunner::GetInstance()->IsRunning());
 
   // Move it.
   selection_controller_client()->InitWaitForSelectionEvent(
@@ -1081,6 +1118,7 @@
       ui::PointerDetails(ui::EventPointerType::kTouch, 0));
   rwhva->OnTouchEvent(&touch_move);
   selection_controller_client()->Wait();
+  EXPECT_TRUE(ui::TouchSelectionMagnifierRunner::GetInstance()->IsRunning());
 
   // Then release.
   selection_controller_client()->InitWaitForSelectionEvent(
@@ -1090,6 +1128,7 @@
                           ui::PointerDetails(ui::EventPointerType::kTouch, 0));
   rwhva->OnTouchEvent(&touch_up);
   selection_controller_client()->Wait();
+  EXPECT_FALSE(ui::TouchSelectionMagnifierRunner::GetInstance()->IsRunning());
 
   gfx::RectF moved_handle_rect =
       rwhva->selection_controller()->GetStartHandleRect();
diff --git a/content/browser/renderer_host/navigation_controller_impl.cc b/content/browser/renderer_host/navigation_controller_impl.cc
index 46b7434..5288566 100644
--- a/content/browser/renderer_host/navigation_controller_impl.cc
+++ b/content/browser/renderer_host/navigation_controller_impl.cc
@@ -1371,6 +1371,7 @@
             GetLastCommittedEntry(), is_main_frame_navigation,
             params.document_sequence_number);
   }
+
   // Notify the last active entry that we have navigated away.
   if (is_main_frame_navigation && !is_same_document_navigation) {
     if (auto* metrics = GetLastCommittedEntry()->back_forward_cache_metrics()) {
@@ -3831,7 +3832,8 @@
           /*soft_navigation_heuristics_task_id=*/absl::nullopt,
           /*modified_runtime_features=*/
           base::flat_map<::blink::mojom::RuntimeFeatureState, bool>(),
-          /*fenced_frame_properties=*/absl::nullopt);
+          /*fenced_frame_properties=*/absl::nullopt,
+          /*not_restored_reasons=*/nullptr);
 #if BUILDFLAG(IS_ANDROID)
   if (ValidateDataURLAsString(params.data_url_as_string)) {
     commit_params->data_url_as_string = params.data_url_as_string->data();
diff --git a/content/browser/renderer_host/navigation_controller_impl_browsertest.cc b/content/browser/renderer_host/navigation_controller_impl_browsertest.cc
index 0a1f6c7..977fe17 100644
--- a/content/browser/renderer_host/navigation_controller_impl_browsertest.cc
+++ b/content/browser/renderer_host/navigation_controller_impl_browsertest.cc
@@ -16256,7 +16256,7 @@
     url2_capturer.Wait();
     EXPECT_TRUE(url2_capturer.has_user_gesture());
     EXPECT_TRUE(root->current_frame_host()
-                    ->last_navigation_started_with_transient_activation());
+                    ->last_committed_common_params_has_user_gesture());
   }
 
   {
@@ -16266,7 +16266,7 @@
     url3_capturer.Wait();
     EXPECT_FALSE(url3_capturer.has_user_gesture());
     EXPECT_FALSE(root->current_frame_host()
-                     ->last_navigation_started_with_transient_activation());
+                     ->last_committed_common_params_has_user_gesture());
   }
 }
 
@@ -16291,7 +16291,7 @@
     url2_capturer.Wait();
     EXPECT_TRUE(url2_capturer.has_user_gesture());
     EXPECT_TRUE(root->current_frame_host()
-                    ->last_navigation_started_with_transient_activation());
+                    ->last_committed_common_params_has_user_gesture());
   }
 
   {
@@ -16301,7 +16301,7 @@
     url3_capturer.Wait();
     EXPECT_FALSE(url3_capturer.has_user_gesture());
     EXPECT_FALSE(root->current_frame_host()
-                     ->last_navigation_started_with_transient_activation());
+                     ->last_committed_common_params_has_user_gesture());
   }
 }
 
@@ -16326,7 +16326,7 @@
     url2_capturer.Wait();
     EXPECT_TRUE(url2_capturer.has_user_gesture());
     EXPECT_TRUE(root->current_frame_host()
-                    ->last_navigation_started_with_transient_activation());
+                    ->last_committed_common_params_has_user_gesture());
   }
 
   {
@@ -16336,7 +16336,7 @@
     url3_capturer.Wait();
     EXPECT_FALSE(url3_capturer.has_user_gesture());
     EXPECT_FALSE(root->current_frame_host()
-                     ->last_navigation_started_with_transient_activation());
+                     ->last_committed_common_params_has_user_gesture());
   }
 }
 
@@ -16361,7 +16361,7 @@
     url2_capturer.Wait();
     EXPECT_TRUE(url2_capturer.has_user_gesture());
     EXPECT_TRUE(root->current_frame_host()
-                    ->last_navigation_started_with_transient_activation());
+                    ->last_committed_common_params_has_user_gesture());
   }
 
   {
@@ -16371,7 +16371,7 @@
     url3_capturer.Wait();
     EXPECT_FALSE(url3_capturer.has_user_gesture());
     EXPECT_FALSE(root->current_frame_host()
-                     ->last_navigation_started_with_transient_activation());
+                     ->last_committed_common_params_has_user_gesture());
   }
 }
 
@@ -16397,7 +16397,7 @@
     url1_capturer.Wait();
     EXPECT_FALSE(url1_capturer.has_user_gesture());
     EXPECT_FALSE(root->current_frame_host()
-                     ->last_navigation_started_with_transient_activation());
+                     ->last_committed_common_params_has_user_gesture());
   }
 
   {
@@ -16407,7 +16407,7 @@
     url2_capturer.Wait();
     EXPECT_FALSE(url2_capturer.has_user_gesture());
     EXPECT_FALSE(root->current_frame_host()
-                     ->last_navigation_started_with_transient_activation());
+                     ->last_committed_common_params_has_user_gesture());
   }
 
   {
@@ -16417,7 +16417,7 @@
     url3_capturer.Wait();
     EXPECT_TRUE(url3_capturer.has_user_gesture());
     EXPECT_TRUE(root->current_frame_host()
-                    ->last_navigation_started_with_transient_activation());
+                    ->last_committed_common_params_has_user_gesture());
   }
 
   {
@@ -16427,7 +16427,7 @@
     url4_capturer.Wait();
     EXPECT_FALSE(url4_capturer.has_user_gesture());
     EXPECT_FALSE(root->current_frame_host()
-                     ->last_navigation_started_with_transient_activation());
+                     ->last_committed_common_params_has_user_gesture());
   }
 
   {
@@ -16444,7 +16444,7 @@
     url5_capturer.Wait();
     EXPECT_TRUE(url5_capturer.has_user_gesture());
     EXPECT_TRUE(root->current_frame_host()
-                    ->last_navigation_started_with_transient_activation());
+                    ->last_committed_common_params_has_user_gesture());
   }
 }
 
@@ -16476,7 +16476,7 @@
     url1_capturer.Wait();
     EXPECT_TRUE(url1_capturer.has_user_gesture());
     EXPECT_TRUE(root->current_frame_host()
-                    ->last_navigation_started_with_transient_activation());
+                    ->last_committed_common_params_has_user_gesture());
   }
 
   {
@@ -16486,7 +16486,7 @@
     url2_capturer.Wait();
     EXPECT_FALSE(url2_capturer.has_user_gesture());
     EXPECT_FALSE(root->current_frame_host()
-                     ->last_navigation_started_with_transient_activation());
+                     ->last_committed_common_params_has_user_gesture());
   }
 
   {
@@ -16496,7 +16496,7 @@
     url3_capturer.Wait();
     EXPECT_FALSE(url3_capturer.has_user_gesture());
     EXPECT_FALSE(root->current_frame_host()
-                     ->last_navigation_started_with_transient_activation());
+                     ->last_committed_common_params_has_user_gesture());
   }
 
   {
@@ -16513,7 +16513,7 @@
     url4_capturer.Wait();
     EXPECT_TRUE(url4_capturer.has_user_gesture());
     EXPECT_TRUE(root->current_frame_host()
-                    ->last_navigation_started_with_transient_activation());
+                    ->last_committed_common_params_has_user_gesture());
   }
 }
 
@@ -22242,6 +22242,78 @@
             root->render_manager()->speculative_frame_host());
 }
 
+// Tests that when a RenderFrameHost gets into the "pending deletion" state due
+// to another RenderFrameHost committing in the same FrameTreeNode, it won't
+// cancel other navigations happening in the same FrameTreeNode.
+IN_PROC_BROWSER_TEST_P(NavigationControllerBrowserTest,
+                       UnloadingPreviousRFHOnCommitWontCancelNavigation) {
+  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  GURL url_b1(embedded_test_server()->GetURL("b.com", "/title1.html"));
+  GURL url_b2(embedded_test_server()->GetURL("b.com", "/title2.html"));
+  // Load `main_url`.
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
+  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+                            ->GetPrimaryFrameTree()
+                            .root();
+  RenderFrameHostImplWrapper rfh_a(current_main_frame_host());
+
+  // Start the cross-site navigation to `url_b1`, then start the cross-site
+  // navigation to `url_b2` just before the navigation to `url_b1` processes its
+  // DidCommitNavigation message, so that both navigation can exist at the same
+  // time (the previous NavigationRequest has already been moved to the pending
+  // commit speculative RFH, and they both use the same speculative RFH because
+  // they use the same SiteInstance).
+  TestNavigationManager b1_nav(shell()->web_contents(), url_b1);
+  TestNavigationManager b2_nav(shell()->web_contents(), url_b2);
+  NavigationStarterBeforeDidCommitNavigation urlb2_navigation_starter(
+      contents(), shell(), url_b1, url_b2);
+  shell()->LoadURL(url_b1);
+
+  // Check the navigation to `url_b1` started.
+  EXPECT_TRUE(b1_nav.WaitForResponse());
+  EXPECT_EQ(b1_nav.GetNavigationHandle(), root->navigation_request());
+  b1_nav.ResumeNavigation();
+
+  // Check the navigation to `url_b2` started.
+  EXPECT_TRUE(b2_nav.WaitForRequestStart());
+  EXPECT_EQ(b2_nav.GetNavigationHandle(), root->navigation_request());
+
+  // Wait for the `url_b1` navigation to finish.
+  b1_nav.WaitForNavigationFinished();
+  EXPECT_TRUE(b1_nav.was_successful());
+
+  // The RenderFrameHost had changed, which means we have started to unload the
+  // previous RenderFrameHost or saved it in BFCache.
+  RenderFrameHostImplWrapper rfh_b(current_main_frame_host());
+  EXPECT_NE(rfh_b.get(), rfh_a.get());
+  EXPECT_TRUE(!rfh_a.get() || !rfh_a->IsActive());
+
+  // Check that the `url_b2` navigation didn't get cancelled and its associate
+  // RFH type is set to NONE.
+  EXPECT_NE(nullptr, root->navigation_request());
+  EXPECT_EQ(b2_nav.GetNavigationHandle(), root->navigation_request());
+  EXPECT_EQ(root->navigation_request()->GetAssociatedRFHType(),
+            NavigationRequest::AssociatedRenderFrameHostType::NONE);
+
+  // Check that the `url_b2` navigation's associated RFH type gets updated when
+  // it gets its final RenderFrameHost.
+  b2_nav.ResumeNavigation();
+  EXPECT_TRUE(b2_nav.WaitForResponse());
+  if (IsBackForwardCacheEnabled() || ShouldCreateNewHostForAllFrames()) {
+    // When BFCache or RenderDocument is enabled, the `url_b2` navigation won't
+    // reuse the current RFH.
+    EXPECT_EQ(root->navigation_request()->GetAssociatedRFHType(),
+              NavigationRequest::AssociatedRenderFrameHostType::SPECULATIVE);
+  } else {
+    EXPECT_EQ(root->navigation_request()->GetAssociatedRFHType(),
+              NavigationRequest::AssociatedRenderFrameHostType::CURRENT);
+  }
+
+  // Assert that the `url_b2` navigation committed successfully.
+  b2_nav.WaitForNavigationFinished();
+  EXPECT_TRUE(b2_nav.was_successful());
+}
+
 INSTANTIATE_TEST_SUITE_P(
     All,
     NavigationControllerAlertDialogBrowserTest,
diff --git a/content/browser/renderer_host/navigation_entry_impl.cc b/content/browser/renderer_host/navigation_entry_impl.cc
index bc243477..e00759b6 100644
--- a/content/browser/renderer_host/navigation_entry_impl.cc
+++ b/content/browser/renderer_host/navigation_entry_impl.cc
@@ -23,6 +23,7 @@
 #include "content/browser/renderer_host/frame_tree_node.h"
 #include "content/browser/renderer_host/navigation_controller_impl.h"
 #include "content/browser/renderer_host/navigation_entry_restore_context_impl.h"
+#include "content/browser/renderer_host/navigation_request.h"
 #include "content/browser/web_package/subresource_web_bundle_navigation_info.h"
 #include "content/browser/web_package/web_bundle_navigation_info.h"
 #include "content/common/content_constants_internal.h"
@@ -926,7 +927,8 @@
           soft_navigation_heuristics_task_id,
           /*modified_runtime_features=*/
           base::flat_map<::blink::mojom::RuntimeFeatureState, bool>(),
-          /*fenced_frame_properties=*/absl::nullopt);
+          /*fenced_frame_properties=*/absl::nullopt,
+          /*not_restored_reasons=*/nullptr);
 #if BUILDFLAG(IS_ANDROID)
   // `data_url_as_string` is saved in NavigationEntry but should only be used by
   // main frames, because loadData* navigations can only happen on the main
@@ -1177,6 +1179,25 @@
   }
 }
 
+void NavigationEntryImpl::UpdateBackForwardCacheNotRestoredReasons(
+    NavigationRequest* navigation_request) {
+  DCHECK(BackForwardCacheMetrics::IsCrossDocumentMainFrameHistoryNavigation(
+      navigation_request));
+  if (!back_forward_cache_metrics()) {
+    // Create a metrics object if there is none.
+    FrameNavigationEntry* frame_navigation_entry =
+        GetFrameEntry(navigation_request->frame_tree_node());
+    scoped_refptr<BackForwardCacheMetrics> metrics =
+        base::WrapRefCounted(new BackForwardCacheMetrics(
+            frame_navigation_entry->document_sequence_number()));
+    set_back_forward_cache_metrics(std::move(metrics));
+  }
+  // Update NotRestoredReasons to include additional reasons only
+  // known when we navigate back to the NavigationEntry.
+  back_forward_cache_metrics()->UpdateNotRestoredReasonsForNavigation(
+      navigation_request);
+}
+
 GURL NavigationEntryImpl::GetHistoryURLForDataURL() {
   return GetBaseURLForDataURL().is_empty() ? GURL() : GetVirtualURL();
 }
diff --git a/content/browser/renderer_host/navigation_entry_impl.h b/content/browser/renderer_host/navigation_entry_impl.h
index 30292e9..6dafc92 100644
--- a/content/browser/renderer_host/navigation_entry_impl.h
+++ b/content/browser/renderer_host/navigation_entry_impl.h
@@ -310,6 +310,13 @@
   void RemoveEntryForFrame(FrameTreeNode* frame_tree_node,
                            bool only_if_different_position);
 
+  // Update NotRestoredReasons for |navigation_request| which should be a
+  // cross-document main frame navigation and is not served from back/forward
+  // cache. This will create a metrics object if there is none, which can happen
+  // when doing a session restore.
+  void UpdateBackForwardCacheNotRestoredReasons(
+      NavigationRequest* navigation_request);
+
   void set_unique_id(int unique_id) { unique_id_ = unique_id; }
 
   void set_started_from_context_menu(bool started_from_context_menu) {
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc
index 832f679..63bfed2 100644
--- a/content/browser/renderer_host/navigation_request.cc
+++ b/content/browser/renderer_host/navigation_request.cc
@@ -87,6 +87,7 @@
 #include "content/browser/web_package/web_bundle_source.h"
 #include "content/browser/web_package/web_bundle_utils.h"
 #include "content/common/content_constants_internal.h"
+#include "content/common/content_navigation_policy.h"
 #include "content/common/debug_utils.h"
 #include "content/common/features.h"
 #include "content/common/navigation_params_utils.h"
@@ -1300,7 +1301,8 @@
           /*soft_navigation_heuristic_task_id=*/absl::nullopt,
           /*modified_runtime_features=*/
           base::flat_map<::blink::mojom::RuntimeFeatureState, bool>(),
-          /*fenced_frame_properties=*/absl::nullopt);
+          /*fenced_frame_properties=*/absl::nullopt,
+          /*not_restored_reasons=*/nullptr);
 
   // CreateRendererInitiated() should only be triggered when the navigation is
   // initiated by a frame in the same process.
@@ -1441,7 +1443,8 @@
           /*soft_navigation_heuristic_task_id=*/absl::nullopt,
           /*modified_runtime_features=*/
           base::flat_map<::blink::mojom::RuntimeFeatureState, bool>(),
-          /*fenced_frame_properties=*/absl::nullopt);
+          /*fenced_frame_properties=*/absl::nullopt,
+          /*not_restored_reasons=*/nullptr);
   blink::mojom::BeginNavigationParamsPtr begin_params =
       blink::mojom::BeginNavigationParams::New();
   std::unique_ptr<NavigationRequest> navigation_request(new NavigationRequest(
@@ -1914,6 +1917,24 @@
       }
     }
   }
+
+  // Only update the BackForwardCacheMetrics if this is for a navigation that
+  // could've been served from the bfcache.
+  if (IsBackForwardCacheEnabled() && !IsServedFromBackForwardCache() && entry &&
+      BackForwardCacheMetrics::IsCrossDocumentMainFrameHistoryNavigation(
+          this)) {
+    // Update NotRestoredReasons and create a metrics object if there's none.
+    entry->UpdateBackForwardCacheNotRestoredReasons(this);
+    auto* metrics = entry->back_forward_cache_metrics();
+    DCHECK(metrics);
+    if (base::FeatureList::IsEnabled(
+            blink::features::kBackForwardCacheSendNotRestoredReasons)) {
+      // Only populate the web-exposed NotRestoredReasons when needed by
+      // the NotRestoredReasons API.
+      commit_params_->not_restored_reasons =
+          metrics->GetWebExposedNotRestoredReasons();
+    }
+  }
 }
 
 NavigationRequest::~NavigationRequest() {
@@ -2531,13 +2552,23 @@
     common_params_->should_replace_current_entry = true;
   }
 
-  DCHECK_NE(AssociatedRenderFrameHostType::NONE, associated_rfh_type_);
-  RenderFrameHostImpl* navigating_frame_host =
-      associated_rfh_type_ == AssociatedRenderFrameHostType::SPECULATIVE
-          ? frame_tree_node_->render_manager()->speculative_frame_host()
-          : frame_tree_node_->current_frame_host();
-  DCHECK(navigating_frame_host);
-  SetExpectedProcess(navigating_frame_host->GetProcess());
+  // Set the expected process for this navigation, if we can. The navigation
+  // might not have an associated RenderFrameHost yet, which is possible if it
+  // can't create a speculative RenderFrameHost when there's a pending commit
+  // navigation (when navigation queueing is enabled), or it had an associated
+  // RenderFrameHost when the NavigationRequest was created but another
+  // navigation had committed in between that time and StartNavigation, which
+  // invalidates the `associated_rfh_type_`. It's fine to skip setting the
+  // expected process in this case, as we'll set the expected process again from
+  // ReadyToCommitNavigation(), when we know the final RenderFrameHost for the
+  // navigation.
+  if (associated_rfh_type_ != AssociatedRenderFrameHostType::NONE) {
+    RenderFrameHostImpl* navigating_frame_host =
+        associated_rfh_type_ == AssociatedRenderFrameHostType::SPECULATIVE
+            ? frame_tree_node_->render_manager()->speculative_frame_host()
+            : frame_tree_node_->current_frame_host();
+    SetExpectedProcess(navigating_frame_host->GetProcess());
+  }
 
   DCHECK(!IsNavigationStarted());
   SetState(WILL_START_REQUEST);
@@ -2810,6 +2841,10 @@
   // navigation was redirected.
   commit_params_->page_state = std::string();
 
+  // Reset NotRestoredReasons as the reasons are for the original page and not
+  // for the redirected one.
+  commit_params_->not_restored_reasons = nullptr;
+
   // A request was made. Record it before we decide to block this response for
   // a reason or another.
   RecordAddressSpaceFeature();
@@ -3864,7 +3899,7 @@
 
     // Update the associated RenderFrameHost type, which could have changed
     // due to redirects during navigation.
-    set_associated_rfh_type(
+    SetAssociatedRFHType(
         render_frame_host_ ==
                 frame_tree_node_->render_manager()->current_frame_host()
             ? AssociatedRenderFrameHostType::CURRENT
@@ -4224,7 +4259,7 @@
   render_frame_host_ = render_frame_host;
 
   // Update the associated RenderFrameHost type.
-  set_associated_rfh_type(
+  SetAssociatedRFHType(
       render_frame_host_ ==
               frame_tree_node_->render_manager()->current_frame_host()
           ? AssociatedRenderFrameHostType::CURRENT
@@ -7227,6 +7262,25 @@
   return render_frame_host_;
 }
 
+NavigationRequest::AssociatedRenderFrameHostType
+NavigationRequest::GetAssociatedRFHType() const {
+  CHECK_LT(state_, READY_TO_COMMIT)
+      << "Use GetRenderFrameHost() instead when the final RenderFrameHost for "
+         "the navigation had been picked";
+  return associated_rfh_type_;
+}
+
+void NavigationRequest::SetAssociatedRFHType(
+    AssociatedRenderFrameHostType type) {
+  if (associated_rfh_type_ != AssociatedRenderFrameHostType::NONE &&
+      type == AssociatedRenderFrameHostType::NONE) {
+    // If we're transitioning to "NONE" when the previous state was not "NONE",
+    // we might have called SetExpectedProcess() before, so reset it now.
+    ResetExpectedProcess();
+  }
+  associated_rfh_type_ = type;
+}
+
 const net::HttpRequestHeaders& NavigationRequest::GetRequestHeaders() {
   if (!request_headers_) {
     request_headers_.emplace();
diff --git a/content/browser/renderer_host/navigation_request.h b/content/browser/renderer_host/navigation_request.h
index ce17d2f..1192bd76 100644
--- a/content/browser/renderer_host/navigation_request.h
+++ b/content/browser/renderer_host/navigation_request.h
@@ -480,12 +480,9 @@
 
   bool from_begin_navigation() const { return from_begin_navigation_; }
 
-  AssociatedRenderFrameHostType associated_rfh_type() const {
-    return associated_rfh_type_;
-  }
-  void set_associated_rfh_type(AssociatedRenderFrameHostType type) {
-    associated_rfh_type_ = type;
-  }
+  AssociatedRenderFrameHostType GetAssociatedRFHType() const;
+
+  void SetAssociatedRFHType(AssociatedRenderFrameHostType type);
 
   void set_was_discarded() { commit_params_->was_discarded = true; }
 
diff --git a/content/browser/renderer_host/navigator_unittest.cc b/content/browser/renderer_host/navigator_unittest.cc
index 24669589..b542279 100644
--- a/content/browser/renderer_host/navigator_unittest.cc
+++ b/content/browser/renderer_host/navigator_unittest.cc
@@ -396,15 +396,15 @@
   // RFHI that navigation2 depends on.
   navigation2->Redirect(kUrl2);
   EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
-  EXPECT_TRUE(node->navigation_request()->associated_rfh_type() ==
+  EXPECT_TRUE(node->navigation_request()->GetAssociatedRFHType() ==
               NavigationRequest::AssociatedRenderFrameHostType::CURRENT);
 
   navigation2->ReadyToCommit();
   EXPECT_EQ(1u, raw_runner->NumPendingTasks());
   EXPECT_TRUE(navigation2->IsDeferred());
   EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
-  EXPECT_EQ(node->navigation_request()->associated_rfh_type(),
-            NavigationRequest::AssociatedRenderFrameHostType::SPECULATIVE);
+  EXPECT_EQ(node->navigation_request()->GetRenderFrameHost(),
+            GetSpeculativeRenderFrameHost(node));
 
   // Abort the initial navigation.
   navigation1->AbortFromRenderer();
diff --git a/content/browser/renderer_host/page_impl_browsertest.cc b/content/browser/renderer_host/page_impl_browsertest.cc
index b1f3c626..c3ac5b3 100644
--- a/content/browser/renderer_host/page_impl_browsertest.cc
+++ b/content/browser/renderer_host/page_impl_browsertest.cc
@@ -316,7 +316,7 @@
   RenderFrameHostImpl* pending_rfh =
       root->render_manager()->speculative_frame_host();
   NavigationRequest* navigation_request = root->navigation_request();
-  EXPECT_EQ(navigation_request->associated_rfh_type(),
+  EXPECT_EQ(navigation_request->GetAssociatedRFHType(),
             NavigationRequest::AssociatedRenderFrameHostType::SPECULATIVE);
   EXPECT_TRUE(pending_rfh);
 
diff --git a/content/browser/renderer_host/policy_container_host_browsertest.cc b/content/browser/renderer_host/policy_container_host_browsertest.cc
index ce2ac24..17696eb1 100644
--- a/content/browser/renderer_host/policy_container_host_browsertest.cc
+++ b/content/browser/renderer_host/policy_container_host_browsertest.cc
@@ -842,13 +842,13 @@
   NavigationRequest* navigation_request =
       NavigationRequest::From(manager.GetNavigationHandle());
   if (ShouldSkipEarlyCommitPendingForCrashedFrame()) {
-    EXPECT_EQ(navigation_request->associated_rfh_type(),
+    EXPECT_EQ(navigation_request->GetAssociatedRFHType(),
               NavigationRequest::AssociatedRenderFrameHostType::SPECULATIVE);
   } else {
     // Policy container is properly initialized in the early committed
     // RenderFrameHost.
     EXPECT_TRUE(current_frame_host()->policy_container_host());
-    EXPECT_EQ(navigation_request->associated_rfh_type(),
+    EXPECT_EQ(navigation_request->GetAssociatedRFHType(),
               NavigationRequest::AssociatedRenderFrameHostType::CURRENT);
 
     // The policy is copied from the previous RFH following the crash.
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index b3ae0e0..ebe7626 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -1131,18 +1131,6 @@
   }
 }
 
-// Helper function to get navgation entry if |request| is a history navigation
-// that didn't get served from back/forward cache.
-NavigationEntryImpl* GetNavigationEntryIfNonBackForwardCacheHistoryNavigation(
-    NavigationRequest* request) {
-  if (!request->IsServedFromBackForwardCache() &&
-      BackForwardCacheMetrics::IsCrossDocumentMainFrameHistoryNavigation(
-          request)) {
-    return static_cast<NavigationEntryImpl*>(request->GetNavigationEntry());
-  }
-  return nullptr;
-}
-
 }  // namespace
 
 class RenderFrameHostImpl::SubresourceLoaderFactoriesConfig {
@@ -3785,7 +3773,7 @@
 
   // Sets whether the last navigation has user gesture/transient activation or
   // not.
-  last_navigation_started_with_transient_activation_ =
+  last_committed_common_params_has_user_gesture_ =
       navigation_request->common_params().has_user_gesture;
 
   // Navigations that activate an existing bfcached or prerendered document do
@@ -4073,6 +4061,9 @@
     const blink::FramePolicy& frame_policy,
     std::string frame_name,
     std::string frame_unique_name) {
+  DCHECK(lifecycle_state_ == LifecycleStateImpl::kActive ||
+         lifecycle_state_ == LifecycleStateImpl::kPrerendering);
+
   // Initialize the RenderFrameHost for the new node.  We always create child
   // frames in the same SiteInstance as the current frame, and they can swap to
   // a different one if they navigate away.
@@ -4085,7 +4076,8 @@
   // about the new frame.  Create a proxy for the child frame in all
   // SiteInstances that have a proxy for the frame's parent, since all frames
   // in a frame tree should have the same set of proxies.
-  frame_tree_node_->render_manager()->CreateProxiesForChildFrame(child.get());
+  CHECK(owner_);
+  owner_->GetRenderFrameHostManager().CreateProxiesForChildFrame(child.get());
 
   // When the child is added, it hasn't committed any navigation yet - its
   // initial empty document should inherit the origin of its parent (the origin
@@ -4386,27 +4378,6 @@
   return BackForwardCacheDisablingFeatureHandle(this, feature);
 }
 
-void RenderFrameHostImpl::UpdateBackForwardCacheNotRestoredReasons(
-    NavigationRequest* navigation_request) {
-  if (NavigationEntryImpl* entry =
-          GetNavigationEntryIfNonBackForwardCacheHistoryNavigation(
-              navigation_request)) {
-    if (!entry->back_forward_cache_metrics()) {
-      // Create a metrics if there is none.
-      FrameNavigationEntry* frame_navigation_entry =
-          entry->GetFrameEntry(navigation_request->frame_tree_node());
-      scoped_refptr<BackForwardCacheMetrics> metrics =
-          base::WrapRefCounted(new BackForwardCacheMetrics(
-              frame_navigation_entry->document_sequence_number()));
-      entry->set_back_forward_cache_metrics(std::move(metrics));
-    }
-    // Update NotRestoredReasons to include additional reasons only
-    // known at commit time, before reporting to the renderer.
-    entry->back_forward_cache_metrics()->UpdateNotRestoredReasonsForNavigation(
-        navigation_request);
-  }
-}
-
 bool RenderFrameHostImpl::IsFrozen() {
   // TODO(crbug.com/1081920): Account for non-bfcache freezing here as well.
   return lifecycle_state() == LifecycleStateImpl::kInBackForwardCache;
@@ -12162,33 +12133,12 @@
     }
   }
 
-  blink::mojom::BackForwardCacheNotRestoredReasonsPtr not_restored_reasons;
-  UpdateBackForwardCacheNotRestoredReasons(navigation_request);
-  // Only populate the web-exposed NotRestoredReasons when needed by the
-  // NotRestoredReasons API, i.e. for cross-document main frame history
-  // navigations that are not served by back/forward cache where back/forward
-  // cache flag and NotRestoredReasons flag are enabled.
-  if (IsBackForwardCacheEnabled() &&
-      base::FeatureList::IsEnabled(
-          blink::features::kBackForwardCacheSendNotRestoredReasons)) {
-    if (NavigationEntryImpl* entry =
-            GetNavigationEntryIfNonBackForwardCacheHistoryNavigation(
-                navigation_request)) {
-      auto* metrics = entry->back_forward_cache_metrics();
-      // There must be a metrics object since if there's none
-      // |UpdateBackForwardCacheNotRestoredReasons| should have created one.
-      DCHECK(metrics);
-      // Only populate the web-exposed NotRestoredReasons when needed by the
-      // NotRestoredReasons API, i.e. for cross-document main frame history
-      // navigations that are not served by back/forward cache.
-      // TODO(yuzus): Do not set this when navigation gets redirected.
-      not_restored_reasons = metrics->GetWebExposedNotRestoredReasons();
-    }
-  }
-
   // Save the last sent NotRestoredReasons value for testing, so that we can
   // verify them in tests.
-  not_restored_reasons_for_testing_ = not_restored_reasons.Clone();
+  // TODO(yuzus): Remove |not_restored_reasons_for_testing_| and modify
+  // |FrameNavigateParamsCapturer|.
+  not_restored_reasons_for_testing_ =
+      commit_params->not_restored_reasons.Clone();
 
   commit_params->commit_sent = base::TimeTicks::Now();
   navigation_client->CommitNavigation(
@@ -12201,7 +12151,6 @@
       devtools_navigation_token, permissions_policy,
       std::move(policy_container), std::move(code_cache_host),
       std::move(cookie_manager_info), std::move(storage_info),
-      std::move(not_restored_reasons),
       BuildCommitNavigationCallback(navigation_request));
   base::UmaHistogramTimes(
       base::StrCat({"Navigation.SendCommitNavigationTime.",
@@ -12228,7 +12177,6 @@
   DCHECK_NE(GURL(), common_params->url);
   DCHECK_NE(net::OK, error_code);
   IncreaseCommitNavigationCounter();
-  UpdateBackForwardCacheNotRestoredReasons(navigation_request);
   navigation_client->CommitFailedNavigation(
       std::move(common_params), std::move(commit_params),
       has_stale_copy_in_cache, error_code, extended_error_code,
diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/browser/renderer_host/render_frame_host_impl.h
index 406d4bd9..7161ded 100644
--- a/content/browser/renderer_host/render_frame_host_impl.h
+++ b/content/browser/renderer_host/render_frame_host_impl.h
@@ -588,14 +588,6 @@
   // BackForwardCacheBrowserTest::AddBlocklistedFeature should be used.
   void UseDummyStickyBackForwardCacheDisablingFeatureForTesting();
 
-  // Update NotRestoredReasons for |navigation_request| if this is a
-  // cross-document main frame navigation and is not served from back/forward
-  // cache. This will create a metrics object if there is none. This can happen
-  // when we create a new navigation entry such as session restore.
-  // TODO(yuzus): Move this to NavigationEntry.
-  void UpdateBackForwardCacheNotRestoredReasons(
-      NavigationRequest* navigation_request);
-
   const blink::mojom::BackForwardCacheNotRestoredReasonsPtr&
   NotRestoredReasonsForTesting() {
     return not_restored_reasons_for_testing_;
@@ -848,10 +840,10 @@
 
   // Returns true if last committed navigation's CommonNavigationParam's
   // `has_user_gesture` is true. Should only be used to get the state of the
-  // lat navigation, and not the current state of user activation of this
+  // last navigation, and not the current state of user activation of this
   // RenderFrameHost. See comment on the variable declaration for more details.
-  bool last_navigation_started_with_transient_activation() {
-    return last_navigation_started_with_transient_activation_;
+  bool last_committed_common_params_has_user_gesture() const {
+    return last_committed_common_params_has_user_gesture_;
   }
 
   // Returns true if `dest_url_info` should be considered the same site as the
@@ -3886,12 +3878,15 @@
   int64_t last_post_id_ = 0;
 
   // Whether the last committed navigation's CommonNavigationParams'
-  // `has_user_gesture` is true or not. Note that this is just the cached value
-  // of what happened during the last navigation, and does not reflect the
-  // user activation state of this RenderFrameHost. To get the current/live user
+  // `has_user_gesture` is true or not. Note that this doesn't always represent
+  // whether the navigation was started with user activation or not, because the
+  // user activation can be filtered out at a later point to avoid being exposed
+  // to the committed document. Also, this is just the cached value of what
+  // happened during the last navigation, and does not reflect the user
+  // activation state of this RenderFrameHost. To get the current/live user
   // activation state, get the value from RenderFrameHostImpl's
   // HasStickyUserActivation() or HasTransientUserActivation() instead.
-  bool last_navigation_started_with_transient_activation_ = false;
+  bool last_committed_common_params_has_user_gesture_ = false;
 
   // Whether the last committed navigation is to an error document.
   bool is_error_document_ = false;
diff --git a/content/browser/renderer_host/render_frame_host_impl_browsertest.cc b/content/browser/renderer_host/render_frame_host_impl_browsertest.cc
index 5c45a116..05a5814 100644
--- a/content/browser/renderer_host/render_frame_host_impl_browsertest.cc
+++ b/content/browser/renderer_host/render_frame_host_impl_browsertest.cc
@@ -4480,7 +4480,7 @@
   RenderFrameHostImpl* pending_rfh =
       root->render_manager()->speculative_frame_host();
   NavigationRequest* navigation_request = root->navigation_request();
-  EXPECT_EQ(navigation_request->associated_rfh_type(),
+  EXPECT_EQ(navigation_request->GetAssociatedRFHType(),
             NavigationRequest::AssociatedRenderFrameHostType::SPECULATIVE);
   EXPECT_TRUE(pending_rfh);
 
@@ -4594,7 +4594,7 @@
   RenderFrameHostImpl* speculative_rfh =
       root->render_manager()->speculative_frame_host();
   NavigationRequest* navigation_request = root->navigation_request();
-  EXPECT_EQ(navigation_request->associated_rfh_type(),
+  EXPECT_EQ(navigation_request->GetAssociatedRFHType(),
             NavigationRequest::AssociatedRenderFrameHostType::SPECULATIVE);
   EXPECT_TRUE(speculative_rfh);
 
@@ -4671,10 +4671,10 @@
       root->render_manager()->current_frame_host();
   NavigationRequest* navigation_request = root->navigation_request();
   if (ShouldSkipEarlyCommitPendingForCrashedFrame()) {
-    EXPECT_EQ(navigation_request->associated_rfh_type(),
+    EXPECT_EQ(navigation_request->GetAssociatedRFHType(),
               NavigationRequest::AssociatedRenderFrameHostType::SPECULATIVE);
   } else {
-    EXPECT_EQ(navigation_request->associated_rfh_type(),
+    EXPECT_EQ(navigation_request->GetAssociatedRFHType(),
               NavigationRequest::AssociatedRenderFrameHostType::CURRENT);
   }
 
diff --git a/content/browser/renderer_host/render_frame_host_manager.cc b/content/browser/renderer_host/render_frame_host_manager.cc
index 7d850de4e..2ba6f3a 100644
--- a/content/browser/renderer_host/render_frame_host_manager.cc
+++ b/content/browser/renderer_host/render_frame_host_manager.cc
@@ -632,24 +632,42 @@
 
   if (render_frame_host == speculative_render_frame_host_.get()) {
     // A cross-RenderFrameHost navigation completed, so show the new renderer.
-    // If there are same-RenderFrameHost navigations that are ongoing, they will
-    // be canceled by the call to ResetNavigationRequest() below (if not
-    // pending-commit) or when the speculative RenderFrameHost replaces the
-    // current one during the CommitPending() call.
-    // TODO(https://crbug.com/1220337): Ensure that pending-commit navigations
-    // won't get deleted, which will be guaranteed when we only allow one
-    // cross-document navigation per FrameTreeNode to be pending commit at any
-    // given moment. Also, don't cancel non-pending-commit navigation requests
-    // too, so that navigations that are queued to wait for pending commit
-    // navigations won't end up just getting canceled after the pending commit
-    // navigation got to this point. Currently we need to cancel these
-    // navigations still, because the navigations can't handle a change from
-    // being a "same-RFH" navigation to a "speculative-RFH" navigation yet
-    // (outside of redirects).
     CommitPending(std::move(speculative_render_frame_host_),
                   std::move(stored_page_to_restore_), clear_proxies_on_commit);
-    frame_tree_node_->ResetNavigationRequest(
-        NavigationDiscardReason::kCommittedNavigation);
+
+    if (base::FeatureList::IsEnabled(
+            kAvoidUnnecessaryNavigationCancellations)) {
+      // When kAvoidUnnecessaryNavigationCancellations is enabled, if there are
+      // other navigation requests that are ongoing, set their "associated
+      // RenderFrameHost type" NONE, as the old type may no longer be accurate:
+      // - If it was previously set to CURRENT, the current RenderFrameHost
+      // had already changed to the previously-speculative RenderFrameHost. It
+      // most likely will commit to a new speculative RenderFrameHost, but that
+      // doesn't exist yet and so we shouldn't change the type to SPECULATIVE.
+      // - If it was previously set to SPECULATIVE, the previously-speculative
+      // RenderFrameHost is no longer speculative. However we can't just set the
+      // type to CURRENT, as the navigation might actually want to create a new
+      // speculative RenderFrameHost too and not reuse the now-current RFH
+      // (e.g., with RenderDocument).
+      // A new "associated RenderFrameHost" type value will be recalculated when
+      // the navigation recalculates its RenderFrameHost either at
+      // StartNavigation (if it hasn't reached that stage yet) or ReadyToCommit
+      // time. Note that we don't update this value for pending commit
+      // navigations (and hence we only check the FrameTreeNode's
+      // NavigationRequest), as the value is only used until before the
+      // navigation gets to the "pending commit" stage.
+      if (frame_tree_node_->navigation_request()) {
+        frame_tree_node_->navigation_request()->SetAssociatedRFHType(
+            NavigationRequest::AssociatedRenderFrameHostType::NONE);
+      }
+    } else {
+      // When kAvoidUnnecessaryNavigationCancellations is disabled, if there are
+      // other navigations that are ongoing, cancel them if they're not pending
+      // commit. Note that the pending commit navigations that are in the old
+      // RFH will get deleted when the old RFH gets unloaded.
+      frame_tree_node_->ResetNavigationRequest(
+          NavigationDiscardReason::kCommittedNavigation);
+    }
     return;
   }
 
@@ -1093,12 +1111,12 @@
     // TODO(https://crbug.com/1220337): Don't delete the speculative
     // RenderFrameHost when it is pending commit.
     DiscardSpeculativeRFH(NavigationDiscardReason::kNewNavigation);
-    request->set_associated_rfh_type(
+    request->SetAssociatedRFHType(
         NavigationRequest::AssociatedRenderFrameHostType::CURRENT);
   } else {
     RenderFrameHostImpl* dest_rfh = GetFrameHostForNavigation(request);
     DCHECK(dest_rfh);
-    request->set_associated_rfh_type(
+    request->SetAssociatedRFHType(
         dest_rfh == render_frame_host_.get()
             ? NavigationRequest::AssociatedRenderFrameHostType::CURRENT
             : NavigationRequest::AssociatedRenderFrameHostType::SPECULATIVE);
@@ -1444,7 +1462,7 @@
   NavigationRequest* navigation_request =
       frame_tree_node_->navigation_request();
   if (navigation_request &&
-      navigation_request->associated_rfh_type() ==
+      navigation_request->GetAssociatedRFHType() ==
           NavigationRequest::AssociatedRenderFrameHostType::SPECULATIVE) {
     return;
   }
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index e4259aaf..05c8b94 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -3318,7 +3318,6 @@
     switches::kDisableLogging,
     switches::kDisableBackgroundMediaSuspend,
     switches::kDisableNotifications,
-    switches::kEnableDeJelly,
     switches::kDisableOriginTrialControlledBlinkFeatures,
     switches::kDisablePepper3DImageChromium,
     switches::kDisablePermissionsAPI,
diff --git a/content/browser/resources/attribution_reporting/attribution_internals.ts b/content/browser/resources/attribution_reporting/attribution_internals.ts
index eb28a2f..c934d01 100644
--- a/content/browser/resources/attribution_reporting/attribution_internals.ts
+++ b/content/browser/resources/attribution_reporting/attribution_internals.ts
@@ -296,7 +296,8 @@
       new ValueColumn<Source, string>('Source Origin', (e) => e.sourceOrigin),
       new ValueColumn<Source, string>(
           'Destination', (e) => e.attributionDestination),
-      new ValueColumn<Source, string>('Report To', (e) => e.reportingOrigin),
+      new ValueColumn<Source, string>(
+          'Reporting Origin', (e) => e.reportingOrigin),
       new DateColumn<Source>('Source Registration Time', (e) => e.sourceTime),
       new DateColumn<Source>('Expiry Time', (e) => e.expiryTime),
       new DateColumn<Source>(
@@ -385,7 +386,8 @@
           'Aggregatable Status', (e) => e.aggregatableStatus),
       new ValueColumn<Trigger, string>(
           'Destination', (e) => e.destinationOrigin),
-      new ValueColumn<Trigger, string>('Report To', (e) => e.reportingOrigin),
+      new ValueColumn<Trigger, string>(
+          'Reporting Origin', (e) => e.reportingOrigin),
       new CodeColumn<Trigger>('Registration JSON', (e) => e.registrationJson),
     ];
 
@@ -725,11 +727,11 @@
 
 abstract class Log {
   readonly timestamp: Date;
-  readonly reportTo: string;
+  readonly reportingOrigin: string;
 
   constructor(mojo: {time: number, reportingOrigin: Origin}) {
     this.timestamp = new Date(mojo.time);
-    this.reportTo = originToText(mojo.reportingOrigin);
+    this.reportingOrigin = originToText(mojo.reportingOrigin);
   }
 
   abstract renderDescription(td: HTMLElement): void;
@@ -741,7 +743,8 @@
   new ValueColumn<ClearedDebugKeyLog, string>(
       'Cleared Debug Key', e => e.clearedDebugKey),
   new ValueColumn<ClearedDebugKeyLog, string>('From', e => e.clearedFrom),
-  new ValueColumn<ClearedDebugKeyLog, string>('Report To', e => e.reportTo),
+  new ValueColumn<ClearedDebugKeyLog, string>(
+      'Reporting Origin', e => e.reportingOrigin),
 ];
 
 class ClearedDebugKeyLog extends Log {
@@ -784,7 +787,7 @@
       new ValueColumn<FailedSourceRegistrationLog, string>(
           'Failure Reason', e => e.failureReason),
       new ValueColumn<FailedSourceRegistrationLog, string>(
-          'Report To', e => e.reportTo),
+          'Reporting Origin', e => e.reportingOrigin),
       new CodeColumn<FailedSourceRegistrationLog>(
           'Attribution-Reporting-Register-Source Header', e => e.headerValue),
     ];
diff --git a/content/browser/service_worker/service_worker_test_utils.cc b/content/browser/service_worker/service_worker_test_utils.cc
index a8b439e8..0c341a6 100644
--- a/content/browser/service_worker/service_worker_test_utils.cc
+++ b/content/browser/service_worker/service_worker_test_utils.cc
@@ -99,7 +99,6 @@
       mojo::PendingRemote<blink::mojom::CodeCacheHost> code_cache_host,
       mojom::CookieManagerInfoPtr cookie_manager_info,
       mojom::StorageInfoPtr storage_info,
-      blink::mojom::BackForwardCacheNotRestoredReasonsPtr not_restored_reasons,
       CommitNavigationCallback callback) override {
     std::move(on_received_callback_).Run(std::move(container_info));
     std::move(callback).Run(MinimalDidCommitNavigationLoadParams(), nullptr);
@@ -263,7 +262,6 @@
       base::UnguessableToken::Create(),
       std::vector<blink::ParsedPermissionsPolicyDeclaration>(),
       CreateStubPolicyContainer(), mojo::NullRemote(), nullptr, nullptr,
-      /*not_restored_reasons=*/nullptr,
       base::BindOnce(
           [](mojom::DidCommitProvisionalLoadParamsPtr validated_params,
              mojom::DidCommitProvisionalLoadInterfaceParamsPtr
diff --git a/content/browser/shared_storage/shared_storage_browsertest.cc b/content/browser/shared_storage/shared_storage_browsertest.cc
index 7acf1aa..6a88848 100644
--- a/content/browser/shared_storage/shared_storage_browsertest.cc
+++ b/content/browser/shared_storage/shared_storage_browsertest.cc
@@ -16,6 +16,7 @@
 #include "base/test/bind.h"
 #include "base/test/mock_callback.h"
 #include "base/test/scoped_feature_list.h"
+#include "base/test/simple_test_clock.h"
 #include "base/test/test_future.h"
 #include "content/browser/private_aggregation/private_aggregation_manager_impl.h"
 #include "content/browser/private_aggregation/private_aggregation_test_utils.h"
@@ -91,6 +92,8 @@
 
 const double kBudgetAllowed = 5.0;
 
+const int kStalenessThresholdDays = 1;
+
 const char kSelectFrom8URLsScript[] = R"(
     let urls = [];
     for (let i = 0; i < 8; ++i) {
@@ -106,6 +109,10 @@
 
 const char kRemainingBudgetPrefix[] = "remaining budget: ";
 
+std::string TimeDeltaToString(base::TimeDelta delta) {
+  return base::StrCat({base::NumberToString(delta.InMilliseconds()), "ms"});
+}
+
 void WaitForHistogram(const std::string& histogram_name) {
   // Continue if histogram was already recorded.
   if (base::StatisticsRecorder::FindHistogram(histogram_name))
@@ -577,7 +584,10 @@
                                        {{blink::features::kSharedStorageAPI,
                                          {{"SharedStorageBitBudget",
                                            base::NumberToString(
-                                               kBudgetAllowed)}}},
+                                               kBudgetAllowed)},
+                                          {"SharedStorageStalenessThreshold",
+                                           TimeDeltaToString(base::Days(
+                                               kStalenessThresholdDays))}}},
                                         {features::
                                              kPrivacySandboxAdsAPIsOverride,
                                          {}}},
@@ -2324,6 +2334,96 @@
         SharedStorageEventParams::CreateDefault()}});
 }
 
+IN_PROC_BROWSER_TEST_F(SharedStorageBrowserTest, GetOperationInWorklet) {
+  base::SimpleTestClock clock;
+  base::RunLoop loop;
+  static_cast<StoragePartitionImpl*>(shell()
+                                         ->web_contents()
+                                         ->GetBrowserContext()
+                                         ->GetDefaultStoragePartition())
+      ->GetSharedStorageManager()
+      ->OverrideClockForTesting(&clock, loop.QuitClosure());
+  loop.Run();
+  clock.SetNow(base::Time::Now());
+
+  GURL url = https_server()->GetURL("a.test", kSimplePagePath);
+  EXPECT_TRUE(NavigateToURL(shell(), url));
+
+  EXPECT_TRUE(ExecJs(shell(), R"(
+      sharedStorage.set('key0', 'value0');
+    )"));
+
+  WebContentsConsoleObserver console_observer(shell()->web_contents());
+  GURL script_url =
+      https_server()->GetURL("a.test", "/shared_storage/getter_module.js");
+
+  EXPECT_TRUE(ExecJs(
+      shell(), JsReplace("sharedStorage.worklet.addModule($1)", script_url)));
+
+  EXPECT_TRUE(ExecJs(shell(), R"(
+        sharedStorage.run('get-operation', {data: {'key': 'key0'}});
+      )"));
+
+  // There are 2 "worklet operations": `addModule()` and `run()`.
+  test_worklet_host_manager()
+      .GetAttachedWorkletHost()
+      ->WaitForWorkletResponsesCount(2);
+
+  // Advance clock so that key will expire.
+  clock.Advance(base::Days(kStalenessThresholdDays) + base::Seconds(1));
+
+  EXPECT_TRUE(ExecJs(shell(), R"(
+        sharedStorage.run('get-operation', {data: {'key': 'key0'}});
+      )"));
+
+  // There is one "worklet operation": `run()`.
+  test_worklet_host_manager()
+      .GetAttachedWorkletHost()
+      ->WaitForWorkletResponsesCount(1);
+
+  EXPECT_EQ(4u, console_observer.messages().size());
+  EXPECT_EQ("sharedStorage.length(): 1",
+            base::UTF16ToUTF8(console_observer.messages()[0].message));
+  EXPECT_EQ("sharedStorage.get('key0'): value0",
+            base::UTF16ToUTF8(console_observer.messages()[1].message));
+  EXPECT_EQ("sharedStorage.length(): 0",
+            base::UTF16ToUTF8(console_observer.messages()[2].message));
+  EXPECT_EQ("sharedStorage.get('key0'): undefined",
+            base::UTF16ToUTF8(console_observer.messages()[3].message));
+  EXPECT_EQ(blink::mojom::ConsoleMessageLevel::kInfo,
+            console_observer.messages()[0].log_level);
+  EXPECT_EQ(blink::mojom::ConsoleMessageLevel::kInfo,
+            console_observer.messages()[1].log_level);
+  EXPECT_EQ(blink::mojom::ConsoleMessageLevel::kInfo,
+            console_observer.messages()[2].log_level);
+  EXPECT_EQ(blink::mojom::ConsoleMessageLevel::kInfo,
+            console_observer.messages()[3].log_level);
+
+  WaitForHistograms({kTimingRunExecutedInWorkletHistogram});
+  histogram_tester_.ExpectTotalCount(kTimingRunExecutedInWorkletHistogram, 2);
+
+  std::string origin_str = url::Origin::Create(url).Serialize();
+  ExpectAccessObserved(
+      {{AccessType::kDocumentSet, MainFrameId(), origin_str,
+        SharedStorageEventParams::CreateForSet("key0", "value0", false)},
+       {AccessType::kDocumentAddModule, MainFrameId(), origin_str,
+        SharedStorageEventParams::CreateForAddModule(script_url)},
+       {AccessType::kDocumentRun, MainFrameId(), origin_str,
+        SharedStorageEventParams::CreateForRun("get-operation",
+                                               std::vector<uint8_t>())},
+       {AccessType::kWorkletLength, MainFrameId(), origin_str,
+        SharedStorageEventParams::CreateDefault()},
+       {AccessType::kWorkletGet, MainFrameId(), origin_str,
+        SharedStorageEventParams::CreateForGetOrDelete("key0")},
+       {AccessType::kDocumentRun, MainFrameId(), origin_str,
+        SharedStorageEventParams::CreateForRun("get-operation",
+                                               std::vector<uint8_t>())},
+       {AccessType::kWorkletLength, MainFrameId(), origin_str,
+        SharedStorageEventParams::CreateDefault()},
+       {AccessType::kWorkletGet, MainFrameId(), origin_str,
+        SharedStorageEventParams::CreateForGetOrDelete("key0")}});
+}
+
 IN_PROC_BROWSER_TEST_F(SharedStorageBrowserTest,
                        AccessStorageInSameOriginDocument) {
   GURL url = https_server()->GetURL("a.test", kSimplePagePath);
diff --git a/content/browser/shared_storage/shared_storage_worklet_host.cc b/content/browser/shared_storage/shared_storage_worklet_host.cc
index 7f22348..2cfb74c 100644
--- a/content/browser/shared_storage/shared_storage_worklet_host.cc
+++ b/content/browser/shared_storage/shared_storage_worklet_host.cc
@@ -474,7 +474,8 @@
       [](SharedStorageGetCallback callback, GetResult result) {
         // If the key is not found but there is no other error, the worklet will
         // resolve the promise to undefined.
-        if (result.result == OperationResult::kNotFound) {
+        if (result.result == OperationResult::kNotFound ||
+            result.result == OperationResult::kExpired) {
           std::move(callback).Run(
               shared_storage_worklet::mojom::SharedStorageGetStatus::kNotFound,
               /*error_message=*/"sharedStorage.get() could not find key",
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
index f5de71e..19733d05 100644
--- a/content/browser/storage_partition_impl.cc
+++ b/content/browser/storage_partition_impl.cc
@@ -799,26 +799,6 @@
                              storage_key);
 }
 
-void ClearPluginPrivateDataOnFileTaskRunner(
-    scoped_refptr<storage::FileSystemContext> filesystem_context,
-    base::OnceClosure callback) {
-  DCHECK(filesystem_context->default_file_task_runner()
-             ->RunsTasksInCurrentSequence());
-  DVLOG(3) << "Clearing plugin data: " << filesystem_context;
-
-  // The Plugin Private File System has been deprecated. Delete all data at
-  // %profile/File System/Plugins.
-  auto plugin_path = filesystem_context->partition_path()
-                         .Append(storage::kFileSystemDirectory)
-                         .Append(FILE_PATH_LITERAL("Plugins"));
-
-  filesystem_context->default_file_task_runner()->PostTaskAndReply(
-      FROM_HERE,
-      base::BindOnce(base::IgnoreResult(&base::DeletePathRecursively),
-                     plugin_path),
-      std::move(callback));
-}
-
 }  // namespace
 
 class StoragePartitionImpl::URLLoaderFactoryForBrowserProcess
@@ -1039,8 +1019,8 @@
     kQuota = 3,
     kLocalStorage = 4,
     kSessionStorage = 5,
-    kShaderCache = 6,  // Deprecated in favor of using kGpuCache.
-    kPluginPrivate = 7,
+    kShaderCache = 6,    // Deprecated in favor of using kGpuCache.
+    kPluginPrivate = 7,  // Deprecated.
     kConversions = 8,
     kAggregationService = 9,
     kSharedStorage = 10,
@@ -2609,15 +2589,6 @@
             CreateTaskCompletionClosure(TracingDataType::kPrivateAggregation)));
   }
 
-  // TODO(crbug.com/1340250): The Plugin Private File System is removed, but
-  // some devices may still have old data on their machine. For now greedily try
-  // to delete this data, but we'll want to remove this code at some point.
-  filesystem_context->default_file_task_runner()->PostTask(
-      FROM_HERE, base::BindOnce(&ClearPluginPrivateDataOnFileTaskRunner,
-                                base::WrapRefCounted(filesystem_context),
-                                CreateTaskCompletionClosure(
-                                    TracingDataType::kPluginPrivate)));
-
   if (base::FeatureList::IsEnabled(blink::features::kSharedStorageAPI) &&
       shared_storage_manager &&
       (remove_mask_ & REMOVE_DATA_MASK_SHARED_STORAGE)) {
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 1d6df01..9278914d 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -6069,7 +6069,13 @@
 
   // If this is a user-initiated navigation, start allowing JavaScript dialogs
   // again.
-  if (render_frame_host->last_navigation_started_with_transient_activation() &&
+  //
+  // TODO(https://crbug.com/1399296): Consider using the actual value of
+  // "whether a navigation started with user activation or not" instead of
+  // has_user_gesture, which might get filtered out when navigating from
+  // proxies. If so, we can remove tracking of
+  // `last_committed_common_params_has_user_gesture` entirely.
+  if (render_frame_host->last_committed_common_params_has_user_gesture() &&
       dialog_manager_) {
     DCHECK(is_active);
     dialog_manager_->CancelDialogs(this, /*reset_state=*/true);
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index bc5f1bf..8b7c5118 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -208,6 +208,8 @@
     {wf::EnableBrowserVerifiedUserActivationMouse,
      features::kBrowserVerifiedUserActivationMouse},
     {wf::EnableCompositeBGColorAnimation, features::kCompositeBGColorAnimation},
+    {wf::EnableCompositeClipPathAnimation,
+     features::kCompositeClipPathAnimation},
     {wf::EnableConsolidatedMovementXY, features::kConsolidatedMovementXY},
     {wf::EnableCooperativeScheduling, features::kCooperativeScheduling},
     {wf::EnableDevicePosture, features::kDevicePosture},
diff --git a/content/common/navigation_client.mojom b/content/common/navigation_client.mojom
index 39dc7c8..69a3b98 100644
--- a/content/common/navigation_client.mojom
+++ b/content/common/navigation_client.mojom
@@ -13,7 +13,6 @@
 import "services/network/public/mojom/url_loader.mojom";
 import "services/network/public/mojom/url_loader_factory.mojom";
 import "services/network/public/mojom/url_response_head.mojom";
-import "third_party/blink/public/mojom/back_forward_cache_not_restored_reasons.mojom";
 import "third_party/blink/public/mojom/commit_result/commit_result.mojom";
 import "third_party/blink/public/mojom/dom_storage/storage_area.mojom";
 import "third_party/blink/public/mojom/frame/policy_container.mojom";
@@ -245,9 +244,6 @@
   // browser. These may be null if the NavigationThreadingOptimizations feature
   // is disabled. |cookie_manager_info| may also be null for non HTTP/HTTPS
   // navigations, or if the origin is opaque.
-  // |not_restored_reasons| contain the reasons why this navigation is not
-  // served from back/forward cache if applicable. This is only sent for
-  // cross-document main frame history navigations.
   CommitNavigation(
       blink.mojom.CommonNavigationParams common_params,
       blink.mojom.CommitNavigationParams request_params,
@@ -265,8 +261,7 @@
       blink.mojom.PolicyContainer policy_container,
       pending_remote<blink.mojom.CodeCacheHost>? code_cache_host,
       CookieManagerInfo? cookie_manager_info,
-      StorageInfo? storage_info,
-      blink.mojom.BackForwardCacheNotRestoredReasons? not_restored_reasons)
+      StorageInfo? storage_info)
       => (DidCommitProvisionalLoadParams params,
           DidCommitProvisionalLoadInterfaceParams? interface_params);
 
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index f75499c..22603cb 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -225,6 +225,10 @@
              "CompositeBGColorAnimation",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+BASE_FEATURE(kCompositeClipPathAnimation,
+             "CompositeClipPathAnimation",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 // When enabled, code cache does not use a browsing_data filter for deletions.
 BASE_FEATURE(kCodeCacheDeletionWithoutFilter,
              "CodeCacheDeletionWithoutFilter",
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index ff4ee95..5e8b22b 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -48,6 +48,7 @@
 CONTENT_EXPORT BASE_DECLARE_FEATURE(
     kClearCrossSiteCrossBrowsingContextGroupWindowName);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kCompositeBGColorAnimation);
+CONTENT_EXPORT BASE_DECLARE_FEATURE(kCompositeClipPathAnimation);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kCodeCacheDeletionWithoutFilter);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kConsolidatedMovementXY);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kCooperativeScheduling);
diff --git a/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc b/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc
index e4da107e..d2bfea3 100644
--- a/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc
+++ b/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc
@@ -485,8 +485,15 @@
       !capabilities.image_ycbcr_420v_disabled_for_video_frames) {
     return media::GpuVideoAcceleratorFactories::OutputFormat::NV12_SINGLE_GMB;
   }
-  if (capabilities.texture_rg)
+  if (capabilities.texture_rg) {
+#if BUILDFLAG(IS_WIN)
+    // Windows supports binding single shmem GMB as separate shared images. We
+    // prefer single GMB because it makes dcomp overlay code simpler.
+    return media::GpuVideoAcceleratorFactories::OutputFormat::NV12_SINGLE_GMB;
+#else
     return media::GpuVideoAcceleratorFactories::OutputFormat::NV12_DUAL_GMB;
+#endif
+  }
   return media::GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED;
 }
 
diff --git a/content/renderer/navigation_client.cc b/content/renderer/navigation_client.cc
index fe1d9dd..c1d52f6 100644
--- a/content/renderer/navigation_client.cc
+++ b/content/renderer/navigation_client.cc
@@ -44,7 +44,6 @@
     mojo::PendingRemote<blink::mojom::CodeCacheHost> code_cache_host,
     mojom::CookieManagerInfoPtr cookie_manager_info,
     mojom::StorageInfoPtr storage_info,
-    blink::mojom::BackForwardCacheNotRestoredReasonsPtr not_restored_reasons,
     CommitNavigationCallback callback) {
   DCHECK(blink::IsRequestDestinationFrame(common_params->request_destination));
 
@@ -63,7 +62,7 @@
       devtools_navigation_token, permissions_policy,
       std::move(policy_container), std::move(code_cache_host),
       std::move(cookie_manager_info), std::move(storage_info),
-      std::move(not_restored_reasons), std::move(callback));
+      std::move(callback));
 }
 
 void NavigationClient::CommitFailedNavigation(
diff --git a/content/renderer/navigation_client.h b/content/renderer/navigation_client.h
index aff0be3..39364fdc 100644
--- a/content/renderer/navigation_client.h
+++ b/content/renderer/navigation_client.h
@@ -11,7 +11,6 @@
 #include "mojo/public/cpp/bindings/associated_receiver.h"
 #include "mojo/public/cpp/bindings/pending_associated_receiver.h"
 #include "third_party/blink/public/common/permissions_policy/permissions_policy.h"
-#include "third_party/blink/public/mojom/back_forward_cache_not_restored_reasons.mojom.h"
 
 namespace content {
 
@@ -44,7 +43,6 @@
       mojo::PendingRemote<blink::mojom::CodeCacheHost> code_cache_host,
       mojom::CookieManagerInfoPtr cookie_manager_info,
       mojom::StorageInfoPtr storage_info,
-      blink::mojom::BackForwardCacheNotRestoredReasonsPtr not_restored_reasons,
       CommitNavigationCallback callback) override;
   void CommitFailedNavigation(
       blink::mojom::CommonNavigationParamsPtr common_params,
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 0176c0d..ff5b733 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -2587,7 +2587,6 @@
     mojo::PendingRemote<blink::mojom::CodeCacheHost> code_cache_host,
     mojom::CookieManagerInfoPtr cookie_manager_info,
     mojom::StorageInfoPtr storage_info,
-    blink::mojom::BackForwardCacheNotRestoredReasonsPtr not_restored_reasons,
     mojom::NavigationClient::CommitNavigationCallback commit_callback) {
   DCHECK(navigation_client_impl_);
   DCHECK(!blink::IsRendererDebugURL(common_params->url));
@@ -2643,7 +2642,7 @@
       std::move(controller_service_worker_info), std::move(container_info),
       std::move(prefetch_loader_factory), std::move(code_cache_host),
       std::move(cookie_manager_info), std::move(storage_info),
-      std::move(document_state), std::move(not_restored_reasons));
+      std::move(document_state));
 
   // Handle a navigation that has a non-empty `data_url_as_string`, or perform
   // a "loadDataWithBaseURL" navigation, which is different from a normal data:
@@ -2764,7 +2763,6 @@
     mojom::CookieManagerInfoPtr cookie_manager_info,
     mojom::StorageInfoPtr storage_info,
     std::unique_ptr<DocumentState> document_state,
-    blink::mojom::BackForwardCacheNotRestoredReasonsPtr not_restored_reasons,
     std::unique_ptr<WebNavigationParams> navigation_params) {
   if (common_params->url.IsAboutSrcdoc()) {
     WebNavigationParams::FillStaticResponse(navigation_params.get(),
@@ -2785,10 +2783,11 @@
   if (commit_params->is_view_source)
     frame_->EnableViewSourceMode(true);
 
-  if (not_restored_reasons) {
+  if (commit_params->not_restored_reasons) {
     // Save the Back/Forward Cache NotRestoredReasons struct to WebLocalFrame to
     // report for PerformanceNavigationTiming API.
-    frame_->SetNotRestoredReasons(std::move(not_restored_reasons));
+    frame_->SetNotRestoredReasons(
+        std::move(commit_params->not_restored_reasons));
   }
 
   // Note: this intentionally does not call |Detach()| before |reset()|. If
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index f5bddeb..52a705c 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -76,7 +76,6 @@
 #include "third_party/blink/public/common/tokens/tokens.h"
 #include "third_party/blink/public/common/unique_name/unique_name_helper.h"
 #include "third_party/blink/public/mojom/autoplay/autoplay.mojom.h"
-#include "third_party/blink/public/mojom/back_forward_cache_not_restored_reasons.mojom.h"
 #include "third_party/blink/public/mojom/browser_interface_broker.mojom.h"
 #include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
 #include "third_party/blink/public/mojom/commit_result/commit_result.mojom.h"
@@ -458,7 +457,6 @@
       mojo::PendingRemote<blink::mojom::CodeCacheHost> code_cache_host,
       mojom::CookieManagerInfoPtr cookie_manager_info,
       mojom::StorageInfoPtr storage_info,
-      blink::mojom::BackForwardCacheNotRestoredReasonsPtr not_restored_reasons,
       mojom::NavigationClient::CommitNavigationCallback commit_callback);
   void CommitFailedNavigation(
       blink::mojom::CommonNavigationParamsPtr common_params,
@@ -972,7 +970,6 @@
       mojom::CookieManagerInfoPtr cookie_manager_info,
       mojom::StorageInfoPtr storage_info,
       std::unique_ptr<DocumentState> document_state,
-      blink::mojom::BackForwardCacheNotRestoredReasonsPtr not_restored_reasons,
       std::unique_ptr<blink::WebNavigationParams> navigation_params);
 
   // Decodes a data url for navigation commit.
diff --git a/content/test/data/shared_storage/getter_module.js b/content/test/data/shared_storage/getter_module.js
new file mode 100644
index 0000000..24cfa8f6
--- /dev/null
+++ b/content/test/data/shared_storage/getter_module.js
@@ -0,0 +1,19 @@
+// 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.
+
+
+class GetOperation {
+  async run(data) {
+    console.log(`sharedStorage.length(): ` + await sharedStorage.length());
+    if (data && data.hasOwnProperty('key')) {
+      console.log(
+          `sharedStorage.get('${data['key']}'): ` +
+          await sharedStorage.get(data['key']));
+    } else {
+      console.log('No `data`, or `data` does not have `key`.');
+    }
+  }
+}
+
+register('get-operation', GetOperation);
diff --git a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
index d5e77f00..b60b641b 100644
--- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
@@ -355,6 +355,16 @@
 
 crbug.com/1345777 [ android ] Pixel_VideoStreamFromWebGLCanvas [ Skip ]
 
+# WebGPU interop fails on windows and mac with unaccelerated webcodec videoFrame -- pixel color diff
+crbug.com/1395227 [ mac ] Pixel_WebGPUImportVideoFrameUnaccelerated [ Failure ]
+crbug.com/1395227 [ mac ] Pixel_WebGPUImportVideoFrameUnacceleratedOffscreenCanvas [ Failure ]
+crbug.com/1395227 [ mac ] Pixel_WebGPUImportVideoFrame [ Failure ]
+crbug.com/1395227 [ mac ] Pixel_WebGPUImportVideoFrameOffscreenCanvas [ Failure ]
+crbug.com/1395227 [ win ] Pixel_WebGPUImportVideoFrameUnaccelerated [ Failure ]
+crbug.com/1395227 [ win ] Pixel_WebGPUImportVideoFrameUnacceleratedOffscreenCanvas [ Failure ]
+crbug.com/1395227 [ win ] Pixel_WebGPUImportVideoFrame [ Failure ]
+crbug.com/1395227 [ win ] Pixel_WebGPUImportVideoFrameOffscreenCanvas [ Failure ]
+
 # Pixel_VideoStreamFromWebGL* tests sporadically fail on Linux FYI Release (NVIDIA) bot
 crbug.com/1348002 [ linux nvidia ] Pixel_VideoStreamFromWebGLAlphaCanvas [ Failure ]
 
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
index b3016b8..c388387 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
@@ -694,6 +694,8 @@
 crbug.com/1215700 [ linux intel display-server-wayland no-passthrough ] deqp/functional/gles3/negativetextureapi.html [ Failure ]
 crbug.com/1218607 [ linux intel display-server-wayland no-passthrough ] conformance2/reading/read-pixels-from-fbo-test.html [ Failure ]
 crbug.com/1231736 [ linux intel display-server-wayland no-passthrough ] deqp/functional/gles3/clipping.html [ Failure ]
+crbug.com/1399117 [ linux intel display-server-wayland no-passthrough ] WebglExtension_WEBGL_provoking_vertex [ Skip ]
+
 
 # Failures on validating command decoder only; won't fix.
 crbug.com/angleproject/5038 [ linux intel display-server-wayland no-passthrough ] conformance/extensions/ext-color-buffer-half-float.html [ Failure ]
diff --git a/content/test/navigation_simulator_impl.cc b/content/test/navigation_simulator_impl.cc
index b34ee36b..7b895bc 100644
--- a/content/test/navigation_simulator_impl.cc
+++ b/content/test/navigation_simulator_impl.cc
@@ -709,10 +709,6 @@
     browser_interface_broker_receiver_.reset();
   }
 
-  // Update back/forward cache NotRestoredReasons.
-  if (previous_rfh)
-    previous_rfh->UpdateBackForwardCacheNotRestoredReasons(request_);
-
   // The initial `navigation_url_` may have been mapped to a new URL at this
   // point. Overwrite it here with the desired value to correctly mock the
   // DidCommitProvisionalLoadParams.
@@ -870,10 +866,6 @@
   if (!previous_rfh->IsRenderFrameLive())
     drop_unload_ack_ = true;
 
-  // Update back/forward cache NotRestoredReasons.
-  if (previous_rfh)
-    previous_rfh->UpdateBackForwardCacheNotRestoredReasons(request_);
-
   auto params = BuildDidCommitProvisionalLoadParams(
       false /* same_document */, true /* failed_navigation */,
       render_frame_host_->last_http_status_code());
diff --git a/content/test/test_render_frame.cc b/content/test/test_render_frame.cc
index b382dd2d..225605f 100644
--- a/content/test/test_render_frame.cc
+++ b/content/test/test_render_frame.cc
@@ -275,7 +275,6 @@
           blink::mojom::PolicyContainerPolicies::New(),
           mock_policy_container_host.BindNewEndpointAndPassDedicatedRemote()),
       mojo::NullRemote() /* code_cache_host */, nullptr, nullptr,
-      /* not_restored_reasons */ nullptr,
       base::BindOnce(&MockFrameHost::DidCommitProvisionalLoad,
                      base::Unretained(mock_frame_host_.get())));
 }
diff --git a/device/bluetooth/bluetooth_socket_thread.cc b/device/bluetooth/bluetooth_socket_thread.cc
index 86ab4e4..202a884 100644
--- a/device/bluetooth/bluetooth_socket_thread.cc
+++ b/device/bluetooth/bluetooth_socket_thread.cc
@@ -30,8 +30,7 @@
   g_instance.Get().reset();
 }
 
-BluetoothSocketThread::BluetoothSocketThread()
-    : active_socket_count_(0) {}
+BluetoothSocketThread::BluetoothSocketThread() = default;
 
 BluetoothSocketThread::~BluetoothSocketThread() {
   if (thread_) {
@@ -43,13 +42,13 @@
 
 void BluetoothSocketThread::OnSocketActivate() {
   DCHECK(thread_checker_.CalledOnValidThread());
-  active_socket_count_++;
+  base::subtle::Barrier_AtomicIncrement(&active_socket_count_, 1);
   EnsureStarted();
 }
 
 void BluetoothSocketThread::OnSocketDeactivate() {
   DCHECK(thread_checker_.CalledOnValidThread());
-  active_socket_count_--;
+  base::subtle::Barrier_AtomicIncrement(&active_socket_count_, -1);
 }
 
 void BluetoothSocketThread::EnsureStarted() {
@@ -66,7 +65,7 @@
 
 scoped_refptr<base::SequencedTaskRunner> BluetoothSocketThread::task_runner()
     const {
-  DCHECK(active_socket_count_ > 0);
+  DCHECK(base::subtle::NoBarrier_Load(&active_socket_count_) > 0);
   DCHECK(thread_);
   DCHECK(task_runner_.get());
 
diff --git a/device/bluetooth/bluetooth_socket_thread.h b/device/bluetooth/bluetooth_socket_thread.h
index 94eac394..baa9c5d5 100644
--- a/device/bluetooth/bluetooth_socket_thread.h
+++ b/device/bluetooth/bluetooth_socket_thread.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 
+#include "base/atomicops.h"
 #include "base/memory/ref_counted.h"
 #include "base/threading/thread_checker.h"
 #include "device/bluetooth/bluetooth_export.h"
@@ -44,7 +45,7 @@
   void EnsureStarted();
 
   base::ThreadChecker thread_checker_;
-  int active_socket_count_;
+  base::subtle::Atomic32 active_socket_count_ = 0;
   std::unique_ptr<base::Thread> thread_;
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
 };
diff --git a/device/bluetooth/floss/bluetooth_socket_floss_unittest.cc b/device/bluetooth/floss/bluetooth_socket_floss_unittest.cc
index 24570fb..52dd1239 100644
--- a/device/bluetooth/floss/bluetooth_socket_floss_unittest.cc
+++ b/device/bluetooth/floss/bluetooth_socket_floss_unittest.cc
@@ -248,7 +248,7 @@
 }
 
 // TODO (b/243420879) - Fix flakiness to re-enable
-TEST_F(BluetoothSocketFlossTest, DISABLED_Listen) {
+TEST_F(BluetoothSocketFlossTest, Listen) {
   // Get socket id for next returned socket.
   FlossSocketManager::SocketId id = fake_floss_socket_manager_->GetNextId();
 
diff --git a/extensions/browser/BUILD.gn b/extensions/browser/BUILD.gn
index c61098ad..f321502 100644
--- a/extensions/browser/BUILD.gn
+++ b/extensions/browser/BUILD.gn
@@ -110,6 +110,8 @@
     "api/declarative_net_request/constants.h",
     "api/declarative_net_request/declarative_net_request_api.cc",
     "api/declarative_net_request/declarative_net_request_api.h",
+    "api/declarative_net_request/declarative_net_request_prefs_helper.cc",
+    "api/declarative_net_request/declarative_net_request_prefs_helper.h",
     "api/declarative_net_request/extension_url_pattern_index_matcher.cc",
     "api/declarative_net_request/extension_url_pattern_index_matcher.h",
     "api/declarative_net_request/file_backed_ruleset_source.cc",
@@ -851,6 +853,7 @@
     "api/declarative/deduping_factory_unittest.cc",
     "api/declarative/rules_registry_unittest.cc",
     "api/declarative_net_request/composite_matcher_unittest.cc",
+    "api/declarative_net_request/declarative_net_request_prefs_helper_unittest.cc",
     "api/declarative_net_request/file_sequence_helper_unittest.cc",
     "api/declarative_net_request/flat_ruleset_indexer_unittest.cc",
     "api/declarative_net_request/indexed_rule_unittest.cc",
diff --git a/extensions/browser/api/declarative_net_request/constants.cc b/extensions/browser/api/declarative_net_request/constants.cc
index a74bd46..1aba661 100644
--- a/extensions/browser/api/declarative_net_request/constants.cc
+++ b/extensions/browser/api/declarative_net_request/constants.cc
@@ -122,6 +122,10 @@
     "The number of enabled static rulesets exceeds the enabled ruleset count "
     "limit.";
 
+const char kDisabledStaticRuleCountExceeded[] =
+    "The number of disabled static rules exceeds the disabled rule count "
+    "limit.";
+
 const char kTabNotFoundError[] = "No tab with id: *.";
 const char kIncrementActionCountWithoutUseAsBadgeTextError[] =
     "Cannot increment action count unless displaying action count as badge "
diff --git a/extensions/browser/api/declarative_net_request/constants.h b/extensions/browser/api/declarative_net_request/constants.h
index 9a251b84..85bf1fa 100644
--- a/extensions/browser/api/declarative_net_request/constants.h
+++ b/extensions/browser/api/declarative_net_request/constants.h
@@ -210,6 +210,9 @@
 extern const char kInternalErrorUpdatingEnabledRulesets[];
 extern const char kEnabledRulesetCountExceeded[];
 
+// Static rule toggling API errors.
+extern const char kDisabledStaticRuleCountExceeded[];
+
 // setExtensionActionOptions API errors.
 extern const char kTabNotFoundError[];
 extern const char kIncrementActionCountWithoutUseAsBadgeTextError[];
@@ -239,6 +242,9 @@
 // profile.
 constexpr int kMaxStaticRulesPerProfile = 300000;
 
+// The per-extension maximum amount of disabled static rules.
+constexpr int kMaxDisabledStaticRules = 5000;
+
 // Identifier for a Flatbuffer containing `flat::EmbedderConditions` as the
 // root.
 extern const char kEmbedderConditionsBufferIdentifier[];
diff --git a/extensions/browser/api/declarative_net_request/declarative_net_request_prefs_helper.cc b/extensions/browser/api/declarative_net_request/declarative_net_request_prefs_helper.cc
new file mode 100644
index 0000000..1db042d
--- /dev/null
+++ b/extensions/browser/api/declarative_net_request/declarative_net_request_prefs_helper.cc
@@ -0,0 +1,206 @@
+// 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 "extensions/browser/api/declarative_net_request/declarative_net_request_prefs_helper.h"
+
+#include <string>
+
+#include "base/containers/contains.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/string_util.h"
+#include "extensions/browser/api/declarative_net_request/utils.h"
+#include "extensions/browser/extension_prefs.h"
+#include "extensions/common/constants.h"
+#include "services/preferences/public/cpp/scoped_pref_update.h"
+
+namespace extensions::declarative_net_request {
+
+namespace {
+
+// Additional preferences keys, which are not needed by external clients.
+
+// Key corresponding to which we store a ruleset's disabled rule ids for the
+// Declarative Net Request API.
+constexpr const char kDNRDisabledStaticRuleIds[] =
+    "dnr_disabled_static_rule_ids";
+
+base::flat_set<int> GetDisabledStaticRuleIdsFromDict(
+    const base::Value::Dict* disabled_rule_ids_dict,
+    RulesetID ruleset_id) {
+  if (!disabled_rule_ids_dict)
+    return {};
+
+  const base::Value::List* disabled_rule_id_list =
+      disabled_rule_ids_dict->FindList(
+          base::NumberToString(ruleset_id.value()));
+  if (!disabled_rule_id_list) {
+    // Just ignore the prefs value if it is corrupted.
+    // TODO(blee@igalia.com) The corrupted prefs value should be recovered by
+    // wiping the value so that the extension returns to the sane state.
+    return {};
+  }
+
+  base::flat_set<int> disabled_rule_ids;
+  for (const base::Value& disabled_rule_id : *disabled_rule_id_list) {
+    if (!disabled_rule_id.is_int()) {
+      // Just ignore the prefs value if it is corrupted.
+      // TODO(blee@igalia.com) The corrupted prefs value should be recovered by
+      // wiping the value so that the extension returns to the sane state.
+      return {};
+    }
+
+    disabled_rule_ids.insert(disabled_rule_id.GetInt());
+  }
+
+  return disabled_rule_ids;
+}
+
+size_t CountDisabledRules(const base::Value::Dict* disabled_rule_ids_dict) {
+  if (!disabled_rule_ids_dict)
+    return 0;
+
+  size_t count = 0;
+  for (const auto [key, value] : *disabled_rule_ids_dict) {
+    if (!value.is_list())
+      continue;
+    count += value.GetList().size();
+  }
+  return count;
+}
+
+}  // namespace
+
+DeclarativeNetRequestPrefsHelper::DeclarativeNetRequestPrefsHelper(
+    ExtensionPrefs& prefs)
+    : prefs_(prefs) {}
+DeclarativeNetRequestPrefsHelper::~DeclarativeNetRequestPrefsHelper() = default;
+
+DeclarativeNetRequestPrefsHelper::RuleIdsToUpdate::RuleIdsToUpdate(
+    const absl::optional<std::vector<int>>& ids_to_disable,
+    const absl::optional<std::vector<int>>& ids_to_enable) {
+  if (ids_to_disable)
+    this->ids_to_disable.insert(ids_to_disable->begin(), ids_to_disable->end());
+
+  if (ids_to_enable) {
+    for (int id : *ids_to_enable) {
+      // |ids_to_disable| takes priority over |ids_to_enable|.
+      if (base::Contains(this->ids_to_disable, id))
+        continue;
+      this->ids_to_enable.insert(id);
+    }
+  }
+}
+
+DeclarativeNetRequestPrefsHelper::RuleIdsToUpdate::RuleIdsToUpdate(
+    RuleIdsToUpdate&& other) = default;
+DeclarativeNetRequestPrefsHelper::RuleIdsToUpdate::~RuleIdsToUpdate() = default;
+
+DeclarativeNetRequestPrefsHelper::UpdateDisabledStaticRulesResult::
+    UpdateDisabledStaticRulesResult() = default;
+DeclarativeNetRequestPrefsHelper::UpdateDisabledStaticRulesResult::
+    UpdateDisabledStaticRulesResult(UpdateDisabledStaticRulesResult&& other) =
+        default;
+DeclarativeNetRequestPrefsHelper::UpdateDisabledStaticRulesResult::
+    ~UpdateDisabledStaticRulesResult() = default;
+
+const base::Value::Dict*
+DeclarativeNetRequestPrefsHelper::GetDisabledRuleIdsDict(
+    const ExtensionId& extension_id) const {
+  return prefs_.ReadPrefAsDict(
+      extension_id,
+      ExtensionPrefs::JoinPrefs(
+          {ExtensionPrefs::kDNRStaticRulesetPref, kDNRDisabledStaticRuleIds}));
+}
+
+base::flat_set<int> DeclarativeNetRequestPrefsHelper::GetDisabledStaticRuleIds(
+    const ExtensionId& extension_id,
+    RulesetID ruleset_id) const {
+  return GetDisabledStaticRuleIdsFromDict(GetDisabledRuleIdsDict(extension_id),
+                                          ruleset_id);
+}
+
+size_t DeclarativeNetRequestPrefsHelper::GetDisabledStaticRuleCount(
+    const ExtensionId& extension_id) const {
+  return CountDisabledRules(GetDisabledRuleIdsDict(extension_id));
+}
+
+void DeclarativeNetRequestPrefsHelper::SetDisabledStaticRuleIds(
+    const ExtensionId& extension_id,
+    RulesetID ruleset_id,
+    const base::flat_set<int>& disabled_rule_ids) {
+  std::string key = ExtensionPrefs::JoinPrefs(
+      {ExtensionPrefs::kDNRStaticRulesetPref, kDNRDisabledStaticRuleIds});
+
+  ExtensionPrefs::ScopedDictionaryUpdate update(&prefs_, extension_id, key);
+
+  if (disabled_rule_ids.empty()) {
+    std::unique_ptr<prefs::DictionaryValueUpdate> disabled_rule_ids_dict =
+        update.Get();
+    if (disabled_rule_ids_dict)
+      disabled_rule_ids_dict->Remove(base::NumberToString(ruleset_id.value()));
+    return;
+  }
+
+  std::unique_ptr<prefs::DictionaryValueUpdate> disabled_rule_ids_dict =
+      update.Create();
+
+  base::Value::List ids_list;
+  ids_list.reserve(disabled_rule_ids.size());
+  for (int id : disabled_rule_ids)
+    ids_list.Append(id);
+
+  disabled_rule_ids_dict->Set(base::NumberToString(ruleset_id.value()),
+                              base::Value(std::move(ids_list)));
+}
+
+DeclarativeNetRequestPrefsHelper::UpdateDisabledStaticRulesResult
+DeclarativeNetRequestPrefsHelper::UpdateDisabledStaticRules(
+    const ExtensionId& extension_id,
+    RulesetID ruleset_id,
+    const RuleIdsToUpdate& rule_ids_to_update) {
+  UpdateDisabledStaticRulesResult result;
+
+  const base::Value::Dict* disabled_rule_ids_dict =
+      GetDisabledRuleIdsDict(extension_id);
+
+  base::flat_set<int> old_disabled_rule_ids(
+      GetDisabledStaticRuleIdsFromDict(disabled_rule_ids_dict, ruleset_id));
+
+  for (int id : old_disabled_rule_ids) {
+    if (base::Contains(rule_ids_to_update.ids_to_enable, id)) {
+      result.changed = true;
+      continue;
+    }
+    result.disabled_rule_ids_after_update.insert(id);
+  }
+  for (int id : rule_ids_to_update.ids_to_disable) {
+    auto pair = result.disabled_rule_ids_after_update.insert(id);
+    if (pair.second)
+      result.changed = true;
+  }
+
+  if (!result.changed) {
+    result.disabled_rule_ids_after_update.clear();
+    return result;
+  }
+
+  int count_before = old_disabled_rule_ids.size();
+  int count_after = result.disabled_rule_ids_after_update.size();
+  int new_count =
+      CountDisabledRules(disabled_rule_ids_dict) + count_after - count_before;
+  DCHECK_GE(new_count, 0);
+
+  if (new_count > GetDisabledStaticRuleLimit()) {
+    result.error = kDisabledStaticRuleCountExceeded;
+    result.changed = false;
+    result.disabled_rule_ids_after_update.clear();
+    return result;
+  }
+
+  SetDisabledStaticRuleIds(extension_id, ruleset_id,
+                           result.disabled_rule_ids_after_update);
+  return result;
+}
+
+}  // namespace extensions::declarative_net_request
\ No newline at end of file
diff --git a/extensions/browser/api/declarative_net_request/declarative_net_request_prefs_helper.h b/extensions/browser/api/declarative_net_request/declarative_net_request_prefs_helper.h
new file mode 100644
index 0000000..06a74f6
--- /dev/null
+++ b/extensions/browser/api/declarative_net_request/declarative_net_request_prefs_helper.h
@@ -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.
+
+#ifndef EXTENSIONS_BROWSER_API_DECLARATIVE_NET_REQUEST_DECLARATIVE_NET_REQUEST_PREFS_HELPER_H_
+#define EXTENSIONS_BROWSER_API_DECLARATIVE_NET_REQUEST_DECLARATIVE_NET_REQUEST_PREFS_HELPER_H_
+
+#include <vector>
+
+#include "base/containers/flat_set.h"
+#include "base/values.h"
+#include "extensions/common/api/declarative_net_request/constants.h"
+#include "extensions/common/extension_id.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace extensions {
+class ExtensionPrefs;
+
+namespace declarative_net_request {
+
+// ExtensionPrefs helper class for DeclarativeNetRequest.
+// This class is stateless, as it is intended to provides one-off operations
+// that hits ExtensionPrefs whenever DeclarativeNetRequest preference value
+// is fetched or set.
+// If any performance issues are noticed, we could look into optimizing this
+// class to keep a bit more state. (e.g. keeping disabled static rule count
+// and updating it whenever UpdateDisabledStaticRules() is called, so that
+// GetDisabledStaticRuleCount() doesn't hit ExtensionPrefs to calculate the
+// size each time)
+class DeclarativeNetRequestPrefsHelper {
+ public:
+  explicit DeclarativeNetRequestPrefsHelper(ExtensionPrefs&);
+  ~DeclarativeNetRequestPrefsHelper();
+
+  // Prevent copy constructor and dynamic allocation so that the instance
+  // lifecycle can be scoped by stack.
+  DeclarativeNetRequestPrefsHelper(const DeclarativeNetRequestPrefsHelper&) =
+      delete;
+  void* operator new(size_t) = delete;
+
+  // Struct that contains the rule ids to disable or enable.
+  struct RuleIdsToUpdate {
+    RuleIdsToUpdate(const absl::optional<std::vector<int>>& ids_to_disable,
+                    const absl::optional<std::vector<int>>& ids_to_enable);
+    RuleIdsToUpdate(RuleIdsToUpdate&&);
+    ~RuleIdsToUpdate();
+
+    bool Empty() { return ids_to_disable.empty() && ids_to_enable.empty(); }
+
+    base::flat_set<int> ids_to_disable;
+    base::flat_set<int> ids_to_enable;
+  };
+
+  // Struct that contains UpdateDisabledStaticRules() result.
+  struct UpdateDisabledStaticRulesResult {
+    UpdateDisabledStaticRulesResult();
+    UpdateDisabledStaticRulesResult(UpdateDisabledStaticRulesResult&&);
+    ~UpdateDisabledStaticRulesResult();
+
+    // True if the UpdateDisabledStaticRules() call changed the disabled rule
+    // ids.
+    bool changed = false;
+
+    // Disabled rule ids after update. (empty if it was not changed)
+    base::flat_set<int> disabled_rule_ids_after_update;
+
+    // Error while updating the disabled rule ids.
+    absl::optional<std::string> error;
+  };
+
+  // Returns the set of disabled rule ids of a static ruleset.
+  base::flat_set<int> GetDisabledStaticRuleIds(const ExtensionId& extension_id,
+                                               RulesetID ruleset_id) const;
+
+  // Returns the disabled static rule count for the given |extension_id|.
+  size_t GetDisabledStaticRuleCount(const ExtensionId& extension_id) const;
+
+  // Updates the set of disabled rule ids of a static ruleset.
+  UpdateDisabledStaticRulesResult UpdateDisabledStaticRules(
+      const ExtensionId& extension_id,
+      RulesetID ruleset_id,
+      const RuleIdsToUpdate& rule_ids_to_update);
+
+ private:
+  const base::Value::Dict* GetDisabledRuleIdsDict(const ExtensionId&) const;
+  void SetDisabledStaticRuleIds(const ExtensionId& extension_id,
+                                RulesetID ruleset_id,
+                                const base::flat_set<int>& disabled_rule_ids);
+
+  ExtensionPrefs& prefs_;
+};
+
+}  // namespace declarative_net_request
+}  // namespace extensions
+
+#endif  // EXTENSIONS_BROWSER_API_DECLARATIVE_NET_REQUEST_DECLARATIVE_NET_REQUEST_PREFS_HELPER_H_
diff --git a/extensions/browser/api/declarative_net_request/declarative_net_request_prefs_helper_unittest.cc b/extensions/browser/api/declarative_net_request/declarative_net_request_prefs_helper_unittest.cc
new file mode 100644
index 0000000..267ec6c
--- /dev/null
+++ b/extensions/browser/api/declarative_net_request/declarative_net_request_prefs_helper_unittest.cc
@@ -0,0 +1,246 @@
+// 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 "extensions/browser/api/declarative_net_request/declarative_net_request_prefs_helper.h"
+
+#include "components/crx_file/id_util.h"
+#include "extensions/browser/api/declarative_net_request/constants.h"
+#include "extensions/browser/api/declarative_net_request/utils.h"
+#include "extensions/browser/extension_prefs.h"
+#include "extensions/browser/extensions_test.h"
+#include "extensions/common/extension_id.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace extensions::declarative_net_request {
+namespace {
+
+using ::testing::UnorderedElementsAre;
+
+class DeclarativeNetRequestPrefsHelperTest : public ExtensionsTest {
+ public:
+  DeclarativeNetRequestPrefsHelperTest() = default;
+
+  // ExtensionsTest override.
+  void SetUp() override {
+    ExtensionsTest::SetUp();
+
+    prefs_ = ExtensionPrefs::Get(browser_context());
+    ASSERT_TRUE(prefs_);
+    extension_id_ = crx_file::id_util::GenerateId("dummy_extension");
+  }
+
+ protected:
+  using RuleIdsToUpdate = DeclarativeNetRequestPrefsHelper::RuleIdsToUpdate;
+  using UpdateDisabledStaticRulesResult =
+      DeclarativeNetRequestPrefsHelper::UpdateDisabledStaticRulesResult;
+  using ExtensionId = extensions::ExtensionId;
+
+  UpdateDisabledStaticRulesResult UpdateDisabledStaticRules(
+      RulesetID ruleset_id,
+      const RuleIdsToUpdate& ids_to_update) {
+    return DeclarativeNetRequestPrefsHelper(*prefs_).UpdateDisabledStaticRules(
+        extension_id_, ruleset_id, ids_to_update);
+  }
+
+  base::flat_set<int> GetDisabledRuleIds(RulesetID ruleset_id) const {
+    return DeclarativeNetRequestPrefsHelper(*prefs_).GetDisabledStaticRuleIds(
+        extension_id_, ruleset_id);
+  }
+
+  size_t GetDisabledRuleCount() const {
+    return DeclarativeNetRequestPrefsHelper(*prefs_).GetDisabledStaticRuleCount(
+        extension_id_);
+  }
+
+ private:
+  raw_ptr<ExtensionPrefs> prefs_;
+  ExtensionId extension_id_;
+};
+
+TEST_F(DeclarativeNetRequestPrefsHelperTest, UpdateStaticRulesTest) {
+  const RulesetID ruleset1(1);
+  const RulesetID ruleset2(2);
+
+  // Set the disabled static rule limit as 7.
+  ScopedRuleLimitOverride scoped_disabled_static_rule_limit_override =
+      CreateScopedDisabledStaticRuleLimitOverrideForTesting(7);
+
+  // The initial disabled rule ids set is empty.
+  EXPECT_THAT(GetDisabledRuleIds(ruleset1), testing::IsEmpty());
+  EXPECT_THAT(GetDisabledRuleIds(ruleset2), testing::IsEmpty());
+  EXPECT_EQ(0u, GetDisabledRuleCount());
+
+  // Updating disabled rule ids with empty set doesn't make any change.
+  {
+    RuleIdsToUpdate ids_to_update(std::vector<int>() /* ids_to_disable */,
+                                  absl::nullopt /* ids_to_enable */);
+    EXPECT_TRUE(ids_to_update.Empty());
+
+    auto result = UpdateDisabledStaticRules(ruleset1, ids_to_update);
+    EXPECT_FALSE(result.changed);
+    EXPECT_THAT(result.disabled_rule_ids_after_update, testing::IsEmpty());
+    EXPECT_EQ(absl::nullopt, result.error);
+  }
+  EXPECT_THAT(GetDisabledRuleIds(ruleset1), testing::IsEmpty());
+  EXPECT_THAT(GetDisabledRuleIds(ruleset2), testing::IsEmpty());
+  EXPECT_EQ(0u, GetDisabledRuleCount());
+
+  // Disable rule 1, rule 2 and rule 3 of ruleset1.
+  {
+    RuleIdsToUpdate ids_to_update(
+        std::vector<int>({1, 2, 3}) /* ids_to_disable */,
+        absl::nullopt /* ids_to_enable */);
+    EXPECT_FALSE(ids_to_update.Empty());
+
+    auto result = UpdateDisabledStaticRules(ruleset1, ids_to_update);
+    EXPECT_TRUE(result.changed);
+    EXPECT_THAT(result.disabled_rule_ids_after_update,
+                UnorderedElementsAre(1, 2, 3));
+    EXPECT_EQ(absl::nullopt, result.error);
+  }
+  EXPECT_THAT(GetDisabledRuleIds(ruleset1), UnorderedElementsAre(1, 2, 3));
+  EXPECT_THAT(GetDisabledRuleIds(ruleset2), testing::IsEmpty());
+  EXPECT_EQ(3u, GetDisabledRuleCount());
+
+  // Disable rule 3, rule 4 and rule 5 of ruleset2.
+  {
+    RuleIdsToUpdate ids_to_update(
+        std::vector<int>({3, 4, 5}) /* ids_to_disable */,
+        absl::nullopt /* ids_to_enable */);
+    EXPECT_FALSE(ids_to_update.Empty());
+
+    auto result = UpdateDisabledStaticRules(ruleset2, ids_to_update);
+    EXPECT_TRUE(result.changed);
+    EXPECT_THAT(result.disabled_rule_ids_after_update,
+                UnorderedElementsAre(3, 4, 5));
+    EXPECT_EQ(absl::nullopt, result.error);
+  }
+
+  EXPECT_THAT(GetDisabledRuleIds(ruleset1), UnorderedElementsAre(1, 2, 3));
+  EXPECT_THAT(GetDisabledRuleIds(ruleset2), UnorderedElementsAre(3, 4, 5));
+  EXPECT_EQ(6u, GetDisabledRuleCount());
+
+  // Updating disabled rule ids with null set doesn't make any change.
+  {
+    RuleIdsToUpdate ids_to_update(absl::nullopt /* ids_to_disable */,
+                                  absl::nullopt /* ids_to_enable */);
+    EXPECT_TRUE(ids_to_update.Empty());
+
+    auto result = UpdateDisabledStaticRules(ruleset2, ids_to_update);
+    EXPECT_FALSE(result.changed);
+    EXPECT_THAT(result.disabled_rule_ids_after_update, testing::IsEmpty());
+    EXPECT_EQ(absl::nullopt, result.error);
+  }
+  EXPECT_THAT(GetDisabledRuleIds(ruleset1), UnorderedElementsAre(1, 2, 3));
+  EXPECT_THAT(GetDisabledRuleIds(ruleset2), UnorderedElementsAre(3, 4, 5));
+  EXPECT_EQ(6u, GetDisabledRuleCount());
+
+  // Disable rule 4 and rule 5 of ruleset2 but it doesn't make any change since
+  // they are already disabled. Ignore enabling rule 5 since |ids_to_disable|
+  // takes priority over |ids_to_enable|.
+  {
+    RuleIdsToUpdate ids_to_update(std::vector<int>({4, 5}) /* ids_to_disable */,
+                                  std::vector<int>({5}) /* ids_to_enable */);
+    EXPECT_FALSE(ids_to_update.Empty());
+
+    auto result = UpdateDisabledStaticRules(ruleset2, ids_to_update);
+    EXPECT_FALSE(result.changed);
+    EXPECT_THAT(result.disabled_rule_ids_after_update, testing::IsEmpty());
+    EXPECT_EQ(absl::nullopt, result.error);
+  }
+  EXPECT_THAT(GetDisabledRuleIds(ruleset1), UnorderedElementsAre(1, 2, 3));
+  EXPECT_THAT(GetDisabledRuleIds(ruleset2), UnorderedElementsAre(3, 4, 5));
+  EXPECT_EQ(6u, GetDisabledRuleCount());
+
+  // Enable rule 4 and disable rule 5, rule 6 and rule 7 of ruleset2. Ignore
+  // enabling rule 5 since |ids_to_disable| takes priority over |ids_to_enable|.
+  // Disabling rule 5 doesn't make any change since rule 5 is already disabled.
+  {
+    RuleIdsToUpdate ids_to_update(
+        std::vector<int>({5, 6, 7}) /* ids_to_disable */,
+        std::vector<int>({4, 5}) /* ids_to_enable */);
+    EXPECT_FALSE(ids_to_update.Empty());
+
+    auto result = UpdateDisabledStaticRules(ruleset2, ids_to_update);
+    EXPECT_TRUE(result.changed);
+    EXPECT_THAT(result.disabled_rule_ids_after_update,
+                UnorderedElementsAre(3, 5, 6, 7));
+    EXPECT_EQ(absl::nullopt, result.error);
+  }
+  EXPECT_THAT(GetDisabledRuleIds(ruleset1), UnorderedElementsAre(1, 2, 3));
+  EXPECT_THAT(GetDisabledRuleIds(ruleset2), UnorderedElementsAre(3, 5, 6, 7));
+  EXPECT_EQ(7u, GetDisabledRuleCount());
+
+  // Enable rule 1 and disable rule 3, rule 4 and rule 5 of ruleset2. Ignore
+  // enabling rule 3 since |ids_to_disable| takes priority over |ids_to_enable|.
+  // This operation fails since it exceeds the disabled static rule count limit.
+  {
+    RuleIdsToUpdate ids_to_update(
+        std::vector<int>({3, 4, 5}) /* ids_to_disable */,
+        std::vector<int>({1, 3}) /* ids_to_enable */);
+    EXPECT_FALSE(ids_to_update.Empty());
+
+    auto result = UpdateDisabledStaticRules(ruleset1, ids_to_update);
+    EXPECT_FALSE(result.changed);
+    EXPECT_THAT(result.disabled_rule_ids_after_update, testing::IsEmpty());
+    EXPECT_EQ(kDisabledStaticRuleCountExceeded, result.error);
+  }
+  EXPECT_THAT(GetDisabledRuleIds(ruleset1), UnorderedElementsAre(1, 2, 3));
+  EXPECT_THAT(GetDisabledRuleIds(ruleset2), UnorderedElementsAre(3, 5, 6, 7));
+  EXPECT_EQ(7u, GetDisabledRuleCount());
+
+  // Enable rule 1, rule 2 rule 3 and rule 4 of ruleset1. Enabling rule 4
+  // doesn't make any change since rule 4 is not disabled.
+  {
+    RuleIdsToUpdate ids_to_update(
+        absl::nullopt /* ids_to_disable */,
+        std::vector<int>({1, 2, 3, 4}) /* ids_to_enable */);
+    EXPECT_FALSE(ids_to_update.Empty());
+
+    auto result = UpdateDisabledStaticRules(ruleset1, ids_to_update);
+    EXPECT_TRUE(result.changed);
+    EXPECT_THAT(result.disabled_rule_ids_after_update, testing::IsEmpty());
+    EXPECT_EQ(absl::nullopt, result.error);
+  }
+  EXPECT_THAT(GetDisabledRuleIds(ruleset1), testing::IsEmpty());
+  EXPECT_THAT(GetDisabledRuleIds(ruleset2), UnorderedElementsAre(3, 5, 6, 7));
+  EXPECT_EQ(4u, GetDisabledRuleCount());
+
+  // Enable rule 3, rule 4, rule 5, rule 6 and rule 7 of ruleset2. Enabling
+  // rule 4 doesn't make any change since rule 4 is not disabled.
+  {
+    RuleIdsToUpdate ids_to_update(
+        absl::nullopt /* ids_to_disable */,
+        std::vector<int>({3, 4, 5, 6, 7}) /* ids_to_enable */);
+    EXPECT_FALSE(ids_to_update.Empty());
+
+    auto result = UpdateDisabledStaticRules(ruleset2, ids_to_update);
+    EXPECT_TRUE(result.changed);
+    EXPECT_THAT(result.disabled_rule_ids_after_update, testing::IsEmpty());
+    EXPECT_EQ(absl::nullopt, result.error);
+  }
+  EXPECT_THAT(GetDisabledRuleIds(ruleset1), testing::IsEmpty());
+  EXPECT_THAT(GetDisabledRuleIds(ruleset2), testing::IsEmpty());
+  EXPECT_EQ(0u, GetDisabledRuleCount());
+
+  // Enable rule 3, rule 4 and rule 5 of ruleset2. It doesn't make any change
+  // since there is no disabled rules.
+  {
+    RuleIdsToUpdate ids_to_update(
+        absl::nullopt /* ids_to_disable */,
+        std::vector<int>({3, 4, 5}) /* ids_to_enable */);
+    EXPECT_FALSE(ids_to_update.Empty());
+
+    auto result = UpdateDisabledStaticRules(ruleset2, ids_to_update);
+    EXPECT_FALSE(result.changed);
+    EXPECT_THAT(result.disabled_rule_ids_after_update, testing::IsEmpty());
+    EXPECT_EQ(absl::nullopt, result.error);
+  }
+  EXPECT_THAT(GetDisabledRuleIds(ruleset1), testing::IsEmpty());
+  EXPECT_THAT(GetDisabledRuleIds(ruleset2), testing::IsEmpty());
+  EXPECT_EQ(0u, GetDisabledRuleCount());
+}
+
+}  // namespace
+}  // namespace extensions::declarative_net_request
\ No newline at end of file
diff --git a/extensions/browser/api/declarative_net_request/utils.cc b/extensions/browser/api/declarative_net_request/utils.cc
index 79d48de2..b4894bd 100644
--- a/extensions/browser/api/declarative_net_request/utils.cc
+++ b/extensions/browser/api/declarative_net_request/utils.cc
@@ -68,6 +68,7 @@
 int g_global_static_rule_limit_for_testing = kInvalidRuleLimit;
 int g_regex_rule_limit_for_testing = kInvalidRuleLimit;
 int g_dynamic_and_session_rule_limit_for_testing = kInvalidRuleLimit;
+int g_disabled_static_rule_limit_for_testing = kInvalidRuleLimit;
 
 int GetIndexedRulesetFormatVersion() {
   return g_indexed_ruleset_format_version_for_testing ==
@@ -389,6 +390,12 @@
              : g_regex_rule_limit_for_testing;
 }
 
+int GetDisabledStaticRuleLimit() {
+  return g_disabled_static_rule_limit_for_testing == kInvalidRuleLimit
+             ? kMaxDisabledStaticRules
+             : g_disabled_static_rule_limit_for_testing;
+}
+
 ScopedRuleLimitOverride CreateScopedStaticGuaranteedMinimumOverrideForTesting(
     int minimum) {
   return base::AutoReset<int>(&g_static_guaranteed_minimum_for_testing,
@@ -411,6 +418,11 @@
                               limit);
 }
 
+ScopedRuleLimitOverride CreateScopedDisabledStaticRuleLimitOverrideForTesting(
+    int limit) {
+  return base::AutoReset<int>(&g_disabled_static_rule_limit_for_testing, limit);
+}
+
 size_t GetEnabledStaticRuleCount(const CompositeMatcher* composite_matcher) {
   if (!composite_matcher)
     return 0;
diff --git a/extensions/browser/api/declarative_net_request/utils.h b/extensions/browser/api/declarative_net_request/utils.h
index 5b93b2a..bae6323 100644
--- a/extensions/browser/api/declarative_net_request/utils.h
+++ b/extensions/browser/api/declarative_net_request/utils.h
@@ -121,6 +121,9 @@
 // static and dynamic rulesets.
 int GetRegexRuleLimit();
 
+// Returns the per-extension maximum amount of disabled static rules.
+int GetDisabledStaticRuleLimit();
+
 // Test helpers to override the various rule limits until the returned value is
 // in scope.
 using ScopedRuleLimitOverride = base::AutoReset<int>;
@@ -131,6 +134,8 @@
 ScopedRuleLimitOverride CreateScopedRegexRuleLimitOverrideForTesting(int limit);
 ScopedRuleLimitOverride
 CreateScopedDynamicAndSessionRuleLimitOverrideForTesting(int limit);
+ScopedRuleLimitOverride CreateScopedDisabledStaticRuleLimitOverrideForTesting(
+    int limit);
 
 // Helper to convert a flatbufffers::String to a string-like object with type T.
 template <typename T>
diff --git a/extensions/browser/api/hid/hid_device_manager.cc b/extensions/browser/api/hid/hid_device_manager.cc
index 856fbe9..d3c2ddba 100644
--- a/extensions/browser/api/hid/hid_device_manager.cc
+++ b/extensions/browser/api/hid/hid_device_manager.cc
@@ -78,7 +78,7 @@
     content::BrowserContext* browser_context,
     Feature::Context target_context,
     const Extension* extension,
-    const base::DictionaryValue* listener_filter,
+    const base::Value::Dict* listener_filter,
     std::unique_ptr<base::Value::List>* event_args_out,
     mojom::EventFilteringInfoPtr* event_filtering_info_out) {
   if (device_manager && extension) {
diff --git a/extensions/browser/api/printer_provider/printer_provider_api.cc b/extensions/browser/api/printer_provider/printer_provider_api.cc
index 19d870711..1477310f 100644
--- a/extensions/browser/api/printer_provider/printer_provider_api.cc
+++ b/extensions/browser/api/printer_provider/printer_provider_api.cc
@@ -302,7 +302,7 @@
       content::BrowserContext* browser_context,
       Feature::Context target_context,
       const Extension* extension,
-      const base::DictionaryValue* listener_filter,
+      const base::Value::Dict* listener_filter,
       std::unique_ptr<base::Value::List>* event_args_out,
       mojom::EventFilteringInfoPtr* event_filtering_info_out);
 
@@ -758,7 +758,7 @@
     content::BrowserContext* browser_context,
     Feature::Context target_context,
     const Extension* extension,
-    const base::DictionaryValue* listener_filter,
+    const base::Value::Dict* listener_filter,
     std::unique_ptr<base::Value::List>* event_args_out,
     mojom::EventFilteringInfoPtr* event_filtering_info_out) {
   if (!extension)
diff --git a/extensions/browser/api/usb/usb_device_manager.cc b/extensions/browser/api/usb/usb_device_manager.cc
index 7ed65f9..bc2c521 100644
--- a/extensions/browser/api/usb/usb_device_manager.cc
+++ b/extensions/browser/api/usb/usb_device_manager.cc
@@ -71,7 +71,7 @@
     content::BrowserContext* browser_context,
     Feature::Context target_context,
     const Extension* extension,
-    const base::DictionaryValue* listener_filter,
+    const base::Value::Dict* listener_filter,
     std::unique_ptr<base::Value::List>* event_args_out,
     mojom::EventFilteringInfoPtr* event_filtering_info_out) {
   // Check install-time and optional permissions.
diff --git a/extensions/browser/app_window/app_window_geometry_cache.cc b/extensions/browser/app_window/app_window_geometry_cache.cc
index eba2594..486d517 100644
--- a/extensions/browser/app_window/app_window_geometry_cache.cc
+++ b/extensions/browser/app_window/app_window_geometry_cache.cc
@@ -10,6 +10,7 @@
 
 #include "base/bind.h"
 #include "base/containers/contains.h"
+#include "base/json/values_util.h"
 #include "base/observer_list.h"
 #include "base/strings/string_number_conversions.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
@@ -100,31 +101,27 @@
     const std::string& extension_id = *sync_it;
     const ExtensionData& extension_data = cache_[extension_id];
 
-    std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
+    base::Value::Dict dict;
     for (auto data_it = extension_data.cbegin(),
               data_eit = extension_data.cend();
          data_it != data_eit; ++data_it) {
-      std::unique_ptr<base::DictionaryValue> value =
-          std::make_unique<base::DictionaryValue>();
+      base::Value::Dict value;
       const gfx::Rect& bounds = data_it->second.bounds;
       const gfx::Rect& screen_bounds = data_it->second.screen_bounds;
       DCHECK(!bounds.IsEmpty());
       DCHECK(!screen_bounds.IsEmpty());
       DCHECK(data_it->second.window_state != ui::SHOW_STATE_DEFAULT);
-      value->SetIntKey("x", bounds.x());
-      value->SetIntKey("y", bounds.y());
-      value->SetIntKey("w", bounds.width());
-      value->SetIntKey("h", bounds.height());
-      value->SetIntKey("screen_bounds_x", screen_bounds.x());
-      value->SetIntKey("screen_bounds_y", screen_bounds.y());
-      value->SetIntKey("screen_bounds_w", screen_bounds.width());
-      value->SetIntKey("screen_bounds_h", screen_bounds.height());
-      value->SetIntKey("state", data_it->second.window_state);
-      value->SetStringKey(
-          "ts",
-          base::NumberToString(data_it->second.last_change.ToInternalValue()));
-      dict->SetKey(data_it->first,
-                   base::Value::FromUniquePtrValue(std::move(value)));
+      value.Set("x", bounds.x());
+      value.Set("y", bounds.y());
+      value.Set("w", bounds.width());
+      value.Set("h", bounds.height());
+      value.Set("screen_bounds_x", screen_bounds.x());
+      value.Set("screen_bounds_y", screen_bounds.y());
+      value.Set("screen_bounds_w", screen_bounds.width());
+      value.Set("screen_bounds_h", screen_bounds.height());
+      value.Set("state", data_it->second.window_state);
+      value.Set("ts", base::TimeToValue(data_it->second.last_change));
+      dict.Set(data_it->first, std::move(value));
 
       for (auto& observer : observers_)
         observer.OnGeometryCacheChanged(extension_id, data_it->first, bounds);
@@ -202,12 +199,12 @@
     const std::string& extension_id) {
   ExtensionData& extension_data = cache_[extension_id];
 
-  const base::DictionaryValue* stored_windows =
+  const base::Value::Dict* stored_windows =
       prefs_->GetGeometryCache(extension_id);
   if (!stored_windows)
     return;
 
-  for (const auto item : stored_windows->GetDict()) {
+  for (const auto item : *stored_windows) {
     // If the cache already contains geometry for this window, don't
     // overwrite that information since it is probably the result of an
     // application starting up very quickly.
diff --git a/extensions/browser/app_window/app_window_geometry_cache_unittest.cc b/extensions/browser/app_window/app_window_geometry_cache_unittest.cc
index 2b476c3..0768134 100644
--- a/extensions/browser/app_window/app_window_geometry_cache_unittest.cc
+++ b/extensions/browser/app_window/app_window_geometry_cache_unittest.cc
@@ -82,20 +82,18 @@
     const gfx::Rect& bounds,
     const gfx::Rect& screen_bounds,
     ui::WindowShowState state) {
-  std::unique_ptr<base::DictionaryValue> dict =
-      std::make_unique<base::DictionaryValue>();
-  std::unique_ptr<base::DictionaryValue> value =
-      std::make_unique<base::DictionaryValue>();
-  value->SetIntKey("x", bounds.x());
-  value->SetIntKey("y", bounds.y());
-  value->SetIntKey("w", bounds.width());
-  value->SetIntKey("h", bounds.height());
-  value->SetIntKey("screen_bounds_x", screen_bounds.x());
-  value->SetIntKey("screen_bounds_y", screen_bounds.y());
-  value->SetIntKey("screen_bounds_w", screen_bounds.width());
-  value->SetIntKey("screen_bounds_h", screen_bounds.height());
-  value->SetIntKey("state", state);
-  dict->SetKey(window_id, base::Value::FromUniquePtrValue(std::move(value)));
+  base::Value::Dict dict;
+  base::Value::Dict value;
+  value.Set("x", bounds.x());
+  value.Set("y", bounds.y());
+  value.Set("w", bounds.width());
+  value.Set("h", bounds.height());
+  value.Set("screen_bounds_x", screen_bounds.x());
+  value.Set("screen_bounds_y", screen_bounds.y());
+  value.Set("screen_bounds_w", screen_bounds.width());
+  value.Set("screen_bounds_h", screen_bounds.height());
+  value.Set("state", state);
+  dict.Set(window_id, std::move(value));
   extension_prefs_->SetGeometryCache(extension_id, std::move(dict));
   LoadExtension(extension_id);
 }
@@ -269,25 +267,25 @@
   UnloadExtension(extension_id);
 
   // check if geometry got stored correctly in the state store
-  const base::DictionaryValue* dict =
+  const base::Value::Dict* dict =
       extension_prefs_->GetGeometryCache(extension_id);
   ASSERT_TRUE(dict);
 
-  ASSERT_TRUE(dict->FindKey(window_id));
+  ASSERT_TRUE(dict->Find(window_id));
 
-  ASSERT_EQ(bounds.x(), dict->FindIntPath(window_id + ".x"));
-  ASSERT_EQ(bounds.y(), dict->FindIntPath(window_id + ".y"));
-  ASSERT_EQ(bounds.width(), dict->FindIntPath(window_id + ".w"));
-  ASSERT_EQ(bounds.height(), dict->FindIntPath(window_id + ".h"));
+  ASSERT_EQ(bounds.x(), dict->FindIntByDottedPath(window_id + ".x"));
+  ASSERT_EQ(bounds.y(), dict->FindIntByDottedPath(window_id + ".y"));
+  ASSERT_EQ(bounds.width(), dict->FindIntByDottedPath(window_id + ".w"));
+  ASSERT_EQ(bounds.height(), dict->FindIntByDottedPath(window_id + ".h"));
   ASSERT_EQ(screen_bounds.x(),
-            dict->FindIntPath(window_id + ".screen_bounds_x"));
+            dict->FindIntByDottedPath(window_id + ".screen_bounds_x"));
   ASSERT_EQ(screen_bounds.y(),
-            dict->FindIntPath(window_id + ".screen_bounds_y"));
+            dict->FindIntByDottedPath(window_id + ".screen_bounds_y"));
   ASSERT_EQ(screen_bounds.width(),
-            dict->FindIntPath(window_id + ".screen_bounds_w"));
+            dict->FindIntByDottedPath(window_id + ".screen_bounds_w"));
   ASSERT_EQ(screen_bounds.height(),
-            dict->FindIntPath(window_id + ".screen_bounds_h"));
-  ASSERT_EQ(state, dict->FindIntPath(window_id + ".state"));
+            dict->FindIntByDottedPath(window_id + ".screen_bounds_h"));
+  ASSERT_EQ(state, dict->FindIntByDottedPath(window_id + ".state"));
 
   // reload extension
   LoadExtension(extension_id);
diff --git a/extensions/browser/event_listener_map.cc b/extensions/browser/event_listener_map.cc
index 72f9018..c35dcf2 100644
--- a/extensions/browser/event_listener_map.cc
+++ b/extensions/browser/event_listener_map.cc
@@ -10,7 +10,6 @@
 
 #include "base/containers/contains.h"
 #include "base/memory/ptr_util.h"
-#include "base/values.h"
 #include "content/public/browser/render_process_host.h"
 #include "extensions/browser/event_router.h"
 #include "extensions/common/constants.h"
@@ -18,8 +17,6 @@
 #include "url/gurl.h"
 #include "url/origin.h"
 
-using base::DictionaryValue;
-
 namespace extensions {
 
 typedef EventFilter::MatcherID MatcherID;
@@ -29,7 +26,7 @@
     const std::string& event_name,
     const std::string& extension_id,
     content::RenderProcessHost* process,
-    std::unique_ptr<base::DictionaryValue> filter) {
+    std::unique_ptr<base::Value::Dict> filter) {
   // The process parameter is nullptr when creating lazy listener.
   // TODO(richardzh): Update lazy listener creation to either calling
   // ForExtensionServiceWorker instead, or update this method signature to add a
@@ -48,7 +45,7 @@
     const std::string& event_name,
     const GURL& listener_url,
     content::RenderProcessHost* process,
-    std::unique_ptr<base::DictionaryValue> filter) {
+    std::unique_ptr<base::Value::Dict> filter) {
   // Use only the origin to identify the event listener, e.g. chrome://settings
   // for chrome://settings/accounts, to avoid multiple events being triggered
   // for the same process. See crbug.com/536858 for details. // TODO(devlin): If
@@ -68,7 +65,7 @@
     const GURL& service_worker_scope,
     int64_t service_worker_version_id,
     int worker_thread_id,
-    std::unique_ptr<base::DictionaryValue> filter) {
+    std::unique_ptr<base::Value::Dict> filter) {
   return base::WrapUnique(new EventListener(
       event_name, extension_id, service_worker_scope, process, browser_context,
       true, service_worker_version_id, worker_thread_id, std::move(filter)));
@@ -96,10 +93,10 @@
 }
 
 std::unique_ptr<EventListener> EventListener::Copy() const {
-  std::unique_ptr<DictionaryValue> filter_copy;
-  if (filter_)
-    filter_copy = base::DictionaryValue::From(
-        base::Value::ToUniquePtrValue(filter_->Clone()));
+  std::unique_ptr<base::Value::Dict> filter_copy;
+  if (filter_) {
+    filter_copy = std::make_unique<base::Value::Dict>(filter_->Clone());
+  }
   return base::WrapUnique(new EventListener(
       event_name_, extension_id_, listener_url_, process_, browser_context_,
       is_for_service_worker_, service_worker_version_id_, worker_thread_id_,
@@ -129,7 +126,7 @@
                              bool is_for_service_worker,
                              int64_t service_worker_version_id,
                              int worker_thread_id,
-                             std::unique_ptr<DictionaryValue> filter)
+                             std::unique_ptr<base::Value::Dict> filter)
     : event_name_(event_name),
       extension_id_(extension_id),
       listener_url_(listener_url),
@@ -138,8 +135,7 @@
       is_for_service_worker_(is_for_service_worker),
       service_worker_version_id_(service_worker_version_id),
       worker_thread_id_(worker_thread_id),
-      filter_(std::move(filter)),
-      matcher_id_(-1) {
+      filter_(std::move(filter)) {
   if (!IsLazy()) {
     DCHECK_EQ(is_for_service_worker, worker_thread_id != kMainThreadId);
     DCHECK_EQ(is_for_service_worker,
@@ -159,7 +155,7 @@
     return false;
   if (listener->filter()) {
     std::unique_ptr<EventMatcher> matcher(
-        ParseEventMatcher(listener->filter()));
+        ParseEventMatcher(*listener->filter()));
     MatcherID id = event_filter_.AddEventMatcher(listener->event_name(),
                                                  std::move(matcher));
     listener->set_matcher_id(id);
@@ -175,10 +171,9 @@
 }
 
 std::unique_ptr<EventMatcher> EventListenerMap::ParseEventMatcher(
-    DictionaryValue* filter_dict) {
+    const base::Value::Dict& filter_dict) {
   return std::make_unique<EventMatcher>(
-      base::DictionaryValue::From(
-          base::Value::ToUniquePtrValue(filter_dict->Clone())),
+      std::make_unique<base::Value::Dict>(filter_dict.Clone()),
       MSG_ROUTING_NONE);
 }
 
@@ -290,8 +285,7 @@
     const std::string& extension_id,
     const std::set<std::string>& event_names) {
   for (const auto& name : event_names) {
-    AddListener(EventListener::ForExtension(
-        name, extension_id, nullptr, std::unique_ptr<DictionaryValue>()));
+    AddListener(EventListener::ForExtension(name, extension_id, nullptr, {}));
   }
 }
 
@@ -314,16 +308,14 @@
     content::BrowserContext* browser_context,
     const std::string& extension_id,
     bool is_for_service_worker,
-    const DictionaryValue& filtered) {
-  for (const auto item : filtered.GetDict()) {
+    const base::Value::Dict& filtered) {
+  for (const auto item : filtered) {
     // We skip entries if they are malformed.
     if (!item.second.is_list())
       continue;
     for (const base::Value& filter_value : item.second.GetList()) {
       if (!filter_value.is_dict())
         continue;
-      const base::DictionaryValue* filter =
-          static_cast<const base::DictionaryValue*>(&filter_value);
       if (is_for_service_worker) {
         AddListener(EventListener::ForExtensionServiceWorker(
             item.first, extension_id, nullptr, browser_context,
@@ -333,13 +325,13 @@
             // https://crbug.com/773103.
             Extension::GetBaseURLFromExtensionId(extension_id),
             blink::mojom::kInvalidServiceWorkerVersionId, kMainThreadId,
-            base::DictionaryValue::From(
-                base::Value::ToUniquePtrValue(filter->Clone()))));
+            std::make_unique<base::Value::Dict>(
+                filter_value.GetDict().Clone())));
       } else {
-        AddListener(EventListener::ForExtension(
-            item.first, extension_id, nullptr,
-            base::DictionaryValue::From(
-                base::Value::ToUniquePtrValue(filter->Clone()))));
+        AddListener(
+            EventListener::ForExtension(item.first, extension_id, nullptr,
+                                        std::make_unique<base::Value::Dict>(
+                                            filter_value.GetDict().Clone())));
       }
     }
   }
diff --git a/extensions/browser/event_listener_map.h b/extensions/browser/event_listener_map.h
index 0073399..95e37d2 100644
--- a/extensions/browser/event_listener_map.h
+++ b/extensions/browser/event_listener_map.h
@@ -13,15 +13,12 @@
 #include <vector>
 
 #include "base/memory/raw_ptr.h"
+#include "base/values.h"
 #include "extensions/common/event_filter.h"
 #include "extensions/common/extension_id.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_database.mojom-forward.h"
 #include "url/gurl.h"
 
-namespace base {
-class DictionaryValue;
-}
-
 namespace content {
 class BrowserContext;
 class RenderProcessHost;
@@ -55,12 +52,12 @@
       const std::string& event_name,
       const std::string& extension_id,
       content::RenderProcessHost* process,
-      std::unique_ptr<base::DictionaryValue> filter);
+      std::unique_ptr<base::Value::Dict> filter);
   static std::unique_ptr<EventListener> ForURL(
       const std::string& event_name,
       const GURL& listener_url,
       content::RenderProcessHost* process,
-      std::unique_ptr<base::DictionaryValue> filter);
+      std::unique_ptr<base::Value::Dict> filter);
   // Constructs EventListener for an Extension service worker.
   // Similar to ForExtension above with the only difference that
   // |worker_thread_id_| contains a valid worker thread, as opposed to
@@ -74,7 +71,7 @@
       const GURL& service_worker_scope,
       int64_t service_worker_version_id,
       int worker_thread_id,
-      std::unique_ptr<base::DictionaryValue> filter);
+      std::unique_ptr<base::Value::Dict> filter);
 
   EventListener(const EventListener&) = delete;
   EventListener& operator=(const EventListener&) = delete;
@@ -101,7 +98,7 @@
   const GURL& listener_url() const { return listener_url_; }
   content::RenderProcessHost* process() const { return process_; }
   content::BrowserContext* browser_context() const { return browser_context_; }
-  base::DictionaryValue* filter() const { return filter_.get(); }
+  base::Value::Dict* filter() const { return filter_.get(); }
   EventFilter::MatcherID matcher_id() const { return matcher_id_; }
   void set_matcher_id(EventFilter::MatcherID id) { matcher_id_ = id; }
   int64_t service_worker_version_id() const {
@@ -118,7 +115,7 @@
                 bool is_for_service_worker,
                 int64_t service_worker_version_id,
                 int worker_thread_id,
-                std::unique_ptr<base::DictionaryValue> filter);
+                std::unique_ptr<base::Value::Dict> filter);
 
   const std::string event_name_;
   const std::string extension_id_;
@@ -137,8 +134,8 @@
   // worker events, this will be kMainThreadId.
   int worker_thread_id_;
 
-  std::unique_ptr<base::DictionaryValue> filter_;
-  EventFilter::MatcherID matcher_id_;  // -1 if unset.
+  std::unique_ptr<base::Value::Dict> filter_;
+  EventFilter::MatcherID matcher_id_ = -1;
 };
 
 // Holds listeners for extension events and can answer questions about which
@@ -231,14 +228,14 @@
   void LoadFilteredLazyListeners(content::BrowserContext* browser_context,
                                  const std::string& extension_id,
                                  bool is_for_service_worker,
-                                 const base::DictionaryValue& filtered);
+                                 const base::Value::Dict& filtered);
 
  private:
 
   void CleanupListener(EventListener* listener);
   bool IsFilteredEvent(const Event& event) const;
   std::unique_ptr<EventMatcher> ParseEventMatcher(
-      base::DictionaryValue* filter_dict);
+      const base::Value::Dict& filter_dict);
 
   // Listens for removals from this map.
   const raw_ptr<Delegate> delegate_;
diff --git a/extensions/browser/event_listener_map_unittest.cc b/extensions/browser/event_listener_map_unittest.cc
index 48977ac..6b7bda2f 100644
--- a/extensions/browser/event_listener_map_unittest.cc
+++ b/extensions/browser/event_listener_map_unittest.cc
@@ -17,10 +17,6 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
-using base::DictionaryValue;
-using base::ListValue;
-using base::Value;
-
 namespace extensions {
 
 namespace {
@@ -48,7 +44,7 @@
     base::RepeatingCallback<std::unique_ptr<EventListener>(
         const std::string& /* event_name */,
         content::RenderProcessHost* /* process */,
-        std::unique_ptr<base::DictionaryValue> /* filter */)>;
+        std::unique_ptr<base::Value::Dict> /* filter */)>;
 
 class EmptyDelegate : public EventListenerMap::Delegate {
   void OnListenerAdded(const EventListener* listener) override {}
@@ -76,7 +72,7 @@
     ExtensionsTest::TearDown();
   }
 
-  std::unique_ptr<DictionaryValue> CreateHostSuffixFilter(
+  std::unique_ptr<base::Value::Dict> CreateHostSuffixFilter(
       const std::string& suffix) {
     base::Value::Dict filter_dict;
     filter_dict.Set("hostSuffix", suffix);
@@ -84,8 +80,8 @@
     base::Value::List filter_list;
     filter_list.Append(std::move(filter_dict));
 
-    auto filter = std::make_unique<DictionaryValue>();
-    filter->GetDict().Set("url", base::Value(std::move(filter_list)));
+    auto filter = std::make_unique<base::Value::Dict>();
+    filter->Set("url", std::move(filter_list));
     return filter;
   }
 
@@ -105,7 +101,7 @@
   std::unique_ptr<EventListener> CreateLazyListener(
       const std::string& event_name,
       const ExtensionId& extension_id,
-      std::unique_ptr<base::DictionaryValue> filter,
+      std::unique_ptr<base::Value::Dict> filter,
       bool is_for_service_worker) {
     if (is_for_service_worker) {
       return EventListener::ForExtensionServiceWorker(
@@ -140,7 +136,7 @@
     const std::string& extension_id,
     const std::string& event_name,
     content::RenderProcessHost* process,
-    std::unique_ptr<base::DictionaryValue> filter) {
+    std::unique_ptr<base::Value::Dict> filter) {
   return EventListener::ForExtension(event_name, extension_id, process,
                                      std::move(filter));
 }
@@ -149,7 +145,7 @@
     const GURL& listener_url,
     const std::string& event_name,
     content::RenderProcessHost* process,
-    std::unique_ptr<base::DictionaryValue> filter) {
+    std::unique_ptr<base::Value::Dict> filter) {
   return EventListener::ForURL(event_name, listener_url, process,
                                std::move(filter));
 }
@@ -158,7 +154,7 @@
     const std::string& extension_id,
     const std::string& event_name,
     content::RenderProcessHost* process,
-    std::unique_ptr<base::DictionaryValue> filter) {
+    std::unique_ptr<base::Value::Dict> filter) {
   content::BrowserContext* browser_context =
       process ? process->GetBrowserContext() : nullptr;
   return EventListener::ForExtensionServiceWorker(
@@ -170,7 +166,7 @@
 void EventListenerMapTest::TestUnfilteredEventsGoToAllListeners(
     const EventListenerConstructor& constructor) {
   listeners_->AddListener(constructor.Run(
-      kEvent1Name, process_.get(), std::make_unique<base::DictionaryValue>()));
+      kEvent1Name, process_.get(), std::make_unique<base::Value::Dict>()));
   std::unique_ptr<Event> event(CreateNamedEvent(kEvent1Name));
   ASSERT_EQ(1u, listeners_->GetEventListeners(*event).size());
 }
@@ -196,7 +192,7 @@
     return CreateHostSuffixFilter(filter_str);
   };
   auto create_empty_filter = []() {
-    return std::make_unique<base::DictionaryValue>();
+    return std::make_unique<base::Value::Dict>();
   };
 
   for (bool is_for_service_worker : {false, true}) {
@@ -362,9 +358,9 @@
 }
 
 TEST_F(EventListenerMapTest, HostSuffixFilterEquality) {
-  std::unique_ptr<DictionaryValue> filter1(
+  std::unique_ptr<base::Value::Dict> filter1(
       CreateHostSuffixFilter("google.com"));
-  std::unique_ptr<DictionaryValue> filter2(
+  std::unique_ptr<base::Value::Dict> filter2(
       CreateHostSuffixFilter("google.com"));
   ASSERT_EQ(*filter1, *filter2);
 }
@@ -410,12 +406,12 @@
 void EventListenerMapTest::TestAddExistingUnfilteredListener(
     const EventListenerConstructor& constructor) {
   bool first_add = listeners_->AddListener(constructor.Run(
-      kEvent1Name, process_.get(), std::make_unique<base::DictionaryValue>()));
+      kEvent1Name, process_.get(), std::make_unique<base::Value::Dict>()));
   bool second_add = listeners_->AddListener(constructor.Run(
-      kEvent1Name, process_.get(), std::make_unique<base::DictionaryValue>()));
+      kEvent1Name, process_.get(), std::make_unique<base::Value::Dict>()));
 
   std::unique_ptr<EventListener> listener(constructor.Run(
-      kEvent1Name, process_.get(), std::make_unique<base::DictionaryValue>()));
+      kEvent1Name, process_.get(), std::make_unique<base::Value::Dict>()));
   bool first_remove = listeners_->RemoveListener(listener.get());
   bool second_remove = listeners_->RemoveListener(listener.get());
 
@@ -444,13 +440,13 @@
 TEST_F(EventListenerMapTest, RemovingRouters) {
   listeners_->AddListener(
       EventListener::ForExtension(kEvent1Name, kExt1Id, process_.get(),
-                                  std::unique_ptr<DictionaryValue>()));
+                                  std::unique_ptr<base::Value::Dict>()));
   listeners_->AddListener(
       EventListener::ForURL(kEvent1Name, GURL(kURL), process_.get(),
-                            std::unique_ptr<DictionaryValue>()));
+                            std::unique_ptr<base::Value::Dict>()));
   listeners_->AddListener(CreateEventListenerForExtensionServiceWorker(
       kExt1Id, kEvent1Name, process_.get(),
-      std::unique_ptr<base::DictionaryValue>()));
+      std::unique_ptr<base::Value::Dict>()));
   listeners_->RemoveListenersForProcess(process_.get());
   ASSERT_FALSE(listeners_->HasListenerForEvent(kEvent1Name));
 }
@@ -460,7 +456,7 @@
   ASSERT_FALSE(listeners_->HasListenerForEvent(kEvent1Name));
 
   listeners_->AddListener(constructor.Run(
-      kEvent1Name, process_.get(), std::make_unique<base::DictionaryValue>()));
+      kEvent1Name, process_.get(), std::make_unique<base::Value::Dict>()));
 
   ASSERT_FALSE(listeners_->HasListenerForEvent(kEvent2Name));
   ASSERT_TRUE(listeners_->HasListenerForEvent(kEvent1Name));
@@ -487,7 +483,7 @@
   ASSERT_FALSE(listeners_->HasListenerForExtension(kExt1Id, kEvent1Name));
 
   auto create_event_listener = [&](bool is_for_service_worker, bool lazy) {
-    auto filter = std::unique_ptr<base::DictionaryValue>();
+    auto filter = std::unique_ptr<base::Value::Dict>();
     if (is_for_service_worker) {
       return EventListener::ForExtensionServiceWorker(
           kEvent1Name, kExt1Id, lazy ? nullptr : process_.get(),
@@ -526,12 +522,13 @@
       {"google.com", "http://www.google.com"},
       {"yahoo.com", "http://www.yahoo.com"},
   };
-  auto filter_list = std::make_unique<ListValue>();
-  for (const TestCase& test_case : kTestCases)
-    filter_list->Append(base::Value::FromUniquePtrValue(
-        CreateHostSuffixFilter(test_case.filter_host_suffix)));
+  base::Value::List filter_list;
+  for (const TestCase& test_case : kTestCases) {
+    filter_list.Append(
+        std::move(*CreateHostSuffixFilter(test_case.filter_host_suffix)));
+  }
 
-  DictionaryValue filtered_listeners;
+  base::Value::Dict filtered_listeners;
   filtered_listeners.Set(kEvent1Name, std::move(filter_list));
   listeners_->LoadFilteredLazyListeners(
       browser_context(), kExt1Id, is_for_service_worker, filtered_listeners);
@@ -564,9 +561,10 @@
 }
 
 TEST_F(EventListenerMapTest, CorruptedExtensionPrefsShouldntCrash) {
-  DictionaryValue filtered_listeners;
+  base::Value::Dict filtered_listeners;
   // kEvent1Name should be associated with a list, not a dictionary.
-  filtered_listeners.Set(kEvent1Name, CreateHostSuffixFilter("google.com"));
+  filtered_listeners.Set(kEvent1Name,
+                         std::move(*CreateHostSuffixFilter("google.com")));
 
   listeners_->LoadFilteredLazyListeners(browser_context(), kExt1Id, false,
                                         filtered_listeners);
diff --git a/extensions/browser/event_router.cc b/extensions/browser/event_router.cc
index b37db861..30b720b 100644
--- a/extensions/browser/event_router.cc
+++ b/extensions/browser/event_router.cc
@@ -14,7 +14,6 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/observer_list.h"
 #include "base/ranges/algorithm.h"
-#include "base/values.h"
 #include "components/crx_file/id_util.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_task_traits.h"
@@ -45,7 +44,6 @@
 #include "extensions/common/permissions/permissions_data.h"
 #include "ipc/ipc_channel_proxy.h"
 
-using base::DictionaryValue;
 using base::ListValue;
 using content::BrowserContext;
 using content::BrowserThread;
@@ -361,7 +359,7 @@
 void EventRouter::AddFilteredListenerForMainThread(
     mojom::EventListenerParamPtr param,
     const std::string& event_name,
-    base::Value filter,
+    base::Value::Dict filter,
     bool add_lazy_listener) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   auto* process = RenderProcessHost::FromID(receivers_.current_context());
@@ -369,8 +367,7 @@
     return;
 
   AddFilteredEventListener(event_name, process, std::move(param), absl::nullopt,
-                           base::Value::AsDictionaryValue(filter),
-                           add_lazy_listener);
+                           std::move(filter), add_lazy_listener);
 }
 
 void EventRouter::AddFilteredListenerForServiceWorker(
@@ -379,7 +376,7 @@
     const std::string& event_name,
     int64_t service_worker_version_id,
     int32_t worker_thread_id,
-    base::Value filter,
+    base::Value::Dict filter,
     bool add_lazy_listener) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   auto* process = RenderProcessHost::FromID(receivers_.current_context());
@@ -394,7 +391,7 @@
   AddFilteredEventListener(
       event_name, process,
       mojom::EventListenerParam::NewExtensionId(extension_id), sw_identifier,
-      base::Value::AsDictionaryValue(filter), add_lazy_listener);
+      std::move(filter), add_lazy_listener);
 }
 
 void EventRouter::RemoveListenerForMainThread(
@@ -468,16 +465,16 @@
 void EventRouter::RemoveFilteredListenerForMainThread(
     mojom::EventListenerParamPtr param,
     const std::string& event_name,
-    base::Value filter,
+    base::Value::Dict filter,
     bool remove_lazy_listener) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   auto* process = RenderProcessHost::FromID(receivers_.current_context());
   if (!process)
     return;
 
-  RemoveFilteredEventListener(
-      event_name, process, std::move(param), absl::nullopt,
-      base::Value::AsDictionaryValue(filter), remove_lazy_listener);
+  RemoveFilteredEventListener(event_name, process, std::move(param),
+                              absl::nullopt, std::move(filter),
+                              remove_lazy_listener);
 }
 
 void EventRouter::RemoveFilteredListenerForServiceWorker(
@@ -486,7 +483,7 @@
     const std::string& event_name,
     int64_t service_worker_version_id,
     int32_t worker_thread_id,
-    base::Value filter,
+    base::Value::Dict filter,
     bool remove_lazy_listener) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   auto* process = RenderProcessHost::FromID(receivers_.current_context());
@@ -501,7 +498,7 @@
   RemoveFilteredEventListener(
       event_name, process,
       mojom::EventListenerParam::NewExtensionId(extension_id), sw_identifier,
-      base::Value::AsDictionaryValue(filter), remove_lazy_listener);
+      std::move(filter), remove_lazy_listener);
 }
 
 void EventRouter::AddEventListener(const std::string& event_name,
@@ -659,7 +656,7 @@
     RenderProcessHost* process,
     mojom::EventListenerParamPtr param,
     absl::optional<ServiceWorkerIdentifier> sw_identifier,
-    const base::DictionaryValue& filter,
+    const base::Value::Dict& filter,
     bool add_lazy_listener) {
   const bool is_for_service_worker = sw_identifier.has_value();
   std::unique_ptr<EventListener> regular_listener;
@@ -669,8 +666,7 @@
         event_name, param->get_extension_id(), process,
         process->GetBrowserContext(), sw_identifier->scope,
         sw_identifier->version_id, sw_identifier->thread_id,
-        base::DictionaryValue::From(
-            base::Value::ToUniquePtrValue(filter.Clone())));
+        std::make_unique<base::Value::Dict>(filter.Clone()));
     if (add_lazy_listener) {
       // TODO(richardzh): take browser context from the process instead of the
       // regular browser context attached to the event router. Browser context
@@ -684,26 +680,22 @@
           sw_identifier->scope,
           // Lazy listener, without worker version id and thread id.
           blink::mojom::kInvalidServiceWorkerVersionId, kMainThreadId,
-          base::DictionaryValue::From(
-              base::Value::ToUniquePtrValue(filter.Clone())));
+          std::make_unique<base::Value::Dict>(filter.Clone()));
     }
   } else if (param->is_extension_id()) {
     regular_listener = EventListener::ForExtension(
         event_name, param->get_extension_id(), process,
-        base::DictionaryValue::From(
-            base::Value::ToUniquePtrValue(filter.Clone())));
+        std::make_unique<base::Value::Dict>(filter.Clone()));
     if (add_lazy_listener) {
       lazy_listener = EventListener::ForExtension(
           event_name, param->get_extension_id(),
           nullptr,  // Lazy, without process.
-          base::DictionaryValue::From(
-              base::Value::ToUniquePtrValue(filter.Clone())));
+          std::make_unique<base::Value::Dict>(filter.Clone()));
     }
   } else if (param->is_listener_url() && !add_lazy_listener) {
     regular_listener = EventListener::ForURL(
         event_name, param->get_listener_url(), process,
-        base::DictionaryValue::From(
-            base::Value::ToUniquePtrValue(filter.Clone())));
+        std::make_unique<base::Value::Dict>(filter.Clone()));
   } else {
     mojo::ReportBadMessage(kAddEventListenerWithInvalidParam);
     return;
@@ -725,7 +717,7 @@
     RenderProcessHost* process,
     mojom::EventListenerParamPtr param,
     absl::optional<ServiceWorkerIdentifier> sw_identifier,
-    const base::DictionaryValue& filter,
+    const base::Value::Dict& filter,
     bool remove_lazy_listener) {
   const bool is_for_service_worker = sw_identifier.has_value();
   std::unique_ptr<EventListener> listener;
@@ -734,19 +726,16 @@
         event_name, param->get_extension_id(), process,
         process->GetBrowserContext(), sw_identifier->scope,
         sw_identifier->version_id, sw_identifier->thread_id,
-        base::DictionaryValue::From(
-            base::Value::ToUniquePtrValue(filter.Clone())));
+        std::make_unique<base::Value::Dict>(filter.Clone()));
   } else if (param->is_extension_id()) {
     listener = EventListener::ForExtension(
         event_name, param->get_extension_id(), process,
-        base::DictionaryValue::From(
-            base::Value::ToUniquePtrValue(filter.Clone())));
+        std::make_unique<base::Value::Dict>(filter.Clone()));
 
   } else if (param->is_listener_url() && !remove_lazy_listener) {
     listener = EventListener::ForURL(
         event_name, param->get_listener_url(), process,
-        base::DictionaryValue::From(
-            base::Value::ToUniquePtrValue(filter.Clone())));
+        std::make_unique<base::Value::Dict>(filter.Clone()));
   } else {
     mojo::ReportBadMessage(kRemoveEventListenerWithInvalidParam);
     return;
@@ -834,7 +823,7 @@
 void EventRouter::RemoveFilterFromEvent(const std::string& event_name,
                                         const std::string& extension_id,
                                         bool is_for_service_worker,
-                                        const DictionaryValue* filter) {
+                                        const base::Value::Dict* filter) {
   ExtensionPrefs::ScopedDictionaryUpdate update(
       extension_prefs_, extension_id,
       is_for_service_worker ? kFilteredServiceWorkerEvents : kFilteredEvents);
@@ -847,15 +836,13 @@
   filter_list->erase(base::ranges::find(*filter_list, *filter));
 }
 
-const DictionaryValue* EventRouter::GetFilteredEvents(
+const base::Value::Dict* EventRouter::GetFilteredEvents(
     const std::string& extension_id,
     RegisteredEventType type) {
-  const DictionaryValue* events = nullptr;
   const char* pref_key = type == RegisteredEventType::kLazy
                              ? kFilteredEvents
                              : kFilteredServiceWorkerEvents;
-  extension_prefs_->ReadPrefAsDictionary(extension_id, pref_key, &events);
-  return events;
+  return extension_prefs_->ReadPrefAsDict(extension_id, pref_key);
 }
 
 void EventRouter::BroadcastEvent(std::unique_ptr<Event> event) {
@@ -1006,7 +993,7 @@
     int64_t service_worker_version_id,
     int worker_thread_id,
     const Event& event,
-    const base::DictionaryValue* listener_filter,
+    const base::Value::Dict* listener_filter,
     bool did_enqueue) {
   BrowserContext* listener_context = process->GetBrowserContext();
   ProcessMap* process_map = ProcessMap::Get(listener_context);
@@ -1095,6 +1082,12 @@
                            std::move(event_args_to_use), event.user_gesture,
                            std::move(filter_info));
 
+  if (!event.did_dispatch_callback.is_null()) {
+    event.did_dispatch_callback.Run(EventTarget{extension_id, process->GetID(),
+                                                service_worker_version_id,
+                                                worker_thread_id});
+  }
+
   for (TestObserver& observer : test_observers_)
     observer.OnDidDispatchEventToProcess(event);
 
@@ -1278,7 +1271,7 @@
 void EventRouter::AddFilterToEvent(const std::string& event_name,
                                    const std::string& extension_id,
                                    bool is_for_service_worker,
-                                   const DictionaryValue* filter) {
+                                   const base::Value::Dict* filter) {
   ExtensionPrefs::ScopedDictionaryUpdate update(
       extension_prefs_, extension_id,
       is_for_service_worker ? kFilteredServiceWorkerEvents : kFilteredEvents);
@@ -1309,14 +1302,14 @@
   listeners_.LoadUnfilteredWorkerListeners(browser_context, extension->id(),
                                            registered_worker_events);
 
-  const DictionaryValue* filtered_events =
+  const base::Value::Dict* filtered_events =
       GetFilteredEvents(extension->id(), RegisteredEventType::kLazy);
   if (filtered_events)
     listeners_.LoadFilteredLazyListeners(browser_context, extension->id(),
                                          false /* is_for_service_worker */,
                                          *filtered_events);
 
-  const DictionaryValue* filtered_worker_events =
+  const base::Value::Dict* filtered_worker_events =
       GetFilteredEvents(extension->id(), RegisteredEventType::kServiceWorker);
   if (filtered_worker_events)
     listeners_.LoadFilteredLazyListeners(browser_context, extension->id(),
@@ -1406,6 +1399,7 @@
                               restrict_to_browser_context, event_url,
                               user_gesture, filter_info.Clone());
   copy->will_dispatch_callback = will_dispatch_callback;
+  copy->did_dispatch_callback = did_dispatch_callback;
   return copy;
 }
 
diff --git a/extensions/browser/event_router.h b/extensions/browser/event_router.h
index 28f90f7..0e06a12 100644
--- a/extensions/browser/event_router.h
+++ b/extensions/browser/event_router.h
@@ -168,7 +168,7 @@
 
   void AddFilteredListenerForMainThread(mojom::EventListenerParamPtr param,
                                         const std::string& name,
-                                        base::Value filter,
+                                        base::Value::Dict filter,
                                         bool add_lazy_listener) override;
 
   void AddFilteredListenerForServiceWorker(const std::string& extension_id,
@@ -176,7 +176,7 @@
                                            const std::string& name,
                                            int64_t service_worker_version_id,
                                            int32_t worker_thread_id,
-                                           base::Value filter,
+                                           base::Value::Dict filter,
                                            bool add_lazy_listener) override;
 
   void RemoveListenerForMainThread(mojom::EventListenerParamPtr param,
@@ -197,7 +197,7 @@
 
   void RemoveFilteredListenerForMainThread(mojom::EventListenerParamPtr param,
                                            const std::string& name,
-                                           base::Value filter,
+                                           base::Value::Dict filter,
                                            bool remove_lazy_listener) override;
 
   void RemoveFilteredListenerForServiceWorker(
@@ -206,7 +206,7 @@
       const std::string& name,
       int64_t service_worker_version_id,
       int32_t worker_thread_id,
-      base::Value filter,
+      base::Value::Dict filter,
       bool remove_lazy_listener) override;
 
   // Removes an extension as an event listener for |event_name|.
@@ -261,7 +261,7 @@
       content::RenderProcessHost* process,
       mojom::EventListenerParamPtr param,
       absl::optional<ServiceWorkerIdentifier> sw_identifier,
-      const base::DictionaryValue& filter,
+      const base::Value::Dict& filter,
       bool add_lazy_listener);
 
   // If |remove_lazy_listener| is true also remove the lazy version of this
@@ -271,7 +271,7 @@
       content::RenderProcessHost* process,
       mojom::EventListenerParamPtr param,
       absl::optional<ServiceWorkerIdentifier> sw_identifier,
-      const base::DictionaryValue& filter,
+      const base::Value::Dict& filter,
       bool remove_lazy_listener);
 
   // Returns true if there is at least one listener for the given event.
@@ -346,6 +346,7 @@
   friend class SystemInfoAPITest;
   FRIEND_TEST_ALL_PREFIXES(EventRouterTest, MultipleEventRouterObserver);
   FRIEND_TEST_ALL_PREFIXES(EventRouterDispatchTest, TestDispatch);
+  FRIEND_TEST_ALL_PREFIXES(EventRouterDispatchTest, TestDispatchCallback);
   FRIEND_TEST_ALL_PREFIXES(
       DeveloperPrivateApiUnitTest,
       UpdateHostAccess_UnrequestedHostsDispatchUpdateEvents);
@@ -439,26 +440,25 @@
                               int64_t service_worker_version_id,
                               int worker_thread_id,
                               const Event& event,
-                              const base::DictionaryValue* listener_filter,
+                              const base::Value::Dict* listener_filter,
                               bool did_enqueue);
 
   // Adds a filter to an event.
   void AddFilterToEvent(const std::string& event_name,
                         const std::string& extension_id,
                         bool is_for_service_worker,
-                        const base::DictionaryValue* filter);
+                        const base::Value::Dict* filter);
 
   // Removes a filter from an event.
   void RemoveFilterFromEvent(const std::string& event_name,
                              const std::string& extension_id,
                              bool is_for_service_worker,
-                             const base::DictionaryValue* filter);
+                             const base::Value::Dict* filter);
 
   // Returns the dictionary of event filters that the given extension has
   // registered.
-  const base::DictionaryValue* GetFilteredEvents(
-      const std::string& extension_id,
-      RegisteredEventType type);
+  const base::Value::Dict* GetFilteredEvents(const std::string& extension_id,
+                                             RegisteredEventType type);
 
   // Track the dispatched events that have not yet sent an ACK from the
   // renderer.
@@ -534,6 +534,14 @@
   base::WeakPtrFactory<EventRouter> weak_factory_{this};
 };
 
+// Describes the process an |Event| was dispatched to.
+struct EventTarget {
+  ExtensionId extension_id;
+  int render_process_id;
+  int64_t service_worker_version_id;
+  int worker_thread_id;
+};
+
 struct Event {
   // This callback should return true if the event should be dispatched to the
   // given context and extension, and false otherwise.
@@ -541,10 +549,12 @@
       content::BrowserContext*,
       Feature::Context,
       const Extension*,
-      const base::DictionaryValue*,
+      const base::Value::Dict*,
       std::unique_ptr<base::Value::List>* event_args_out,
       mojom::EventFilteringInfoPtr* event_filtering_info_out)>;
 
+  using DidDispatchCallback = base::RepeatingCallback<void(const EventTarget&)>;
+
   // The identifier for the event, for histograms. In most cases this
   // correlates 1:1 with |event_name|, in some cases events will generate
   // their own names, but they cannot generate their own identifier.
@@ -582,6 +592,9 @@
   // this event to be dispatched to non-extension processes, like WebUI.
   WillDispatchCallback will_dispatch_callback;
 
+  // If specified, this is called after dispatching an event to each target.
+  DidDispatchCallback did_dispatch_callback;
+
   // TODO(lazyboy): This sets |restrict_to_browser_context| to nullptr, this
   // will dispatch the event to unrelated profiles, not just incognito. Audit
   // and limit usages of this constructor and introduce "include incognito"
diff --git a/extensions/browser/event_router_unittest.cc b/extensions/browser/event_router_unittest.cc
index 5ec5087..5a79b3a 100644
--- a/extensions/browser/event_router_unittest.cc
+++ b/extensions/browser/event_router_unittest.cc
@@ -10,6 +10,7 @@
 
 #include "base/bind.h"
 #include "base/compiler_specific.h"
+#include "base/test/bind.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/values.h"
 #include "content/public/browser/browser_context.h"
@@ -17,12 +18,14 @@
 #include "extensions/browser/event_listener_map.h"
 #include "extensions/browser/extensions_test.h"
 #include "extensions/browser/test_event_router_observer.h"
+#include "extensions/common/constants.h"
 #include "extensions/common/extension_api.h"
 #include "extensions/common/extension_builder.h"
 #include "extensions/common/extension_messages.h"
 #include "extensions/common/features/feature_provider.h"
 #include "extensions/common/features/simple_feature.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_database.mojom-blink-forward.h"
 
 using base::DictionaryValue;
 using base::ListValue;
@@ -75,13 +78,13 @@
     base::RepeatingCallback<std::unique_ptr<EventListener>(
         const std::string& /* event_name */,
         content::RenderProcessHost* /* process */,
-        std::unique_ptr<base::DictionaryValue> /* filter */)>;
+        std::unique_ptr<base::Value::Dict> /* filter */)>;
 
 std::unique_ptr<EventListener> CreateEventListenerForExtension(
     const std::string& extension_id,
     const std::string& event_name,
     content::RenderProcessHost* process,
-    std::unique_ptr<base::DictionaryValue> filter) {
+    std::unique_ptr<base::Value::Dict> filter) {
   return EventListener::ForExtension(event_name, extension_id, process,
                                      std::move(filter));
 }
@@ -90,7 +93,7 @@
     const GURL& listener_url,
     const std::string& event_name,
     content::RenderProcessHost* process,
-    std::unique_ptr<base::DictionaryValue> filter) {
+    std::unique_ptr<base::Value::Dict> filter) {
   return EventListener::ForURL(event_name, listener_url, process,
                                std::move(filter));
 }
@@ -101,7 +104,7 @@
     int worker_thread_id,
     const std::string& event_name,
     content::RenderProcessHost* process,
-    std::unique_ptr<base::DictionaryValue> filter) {
+    std::unique_ptr<base::Value::Dict> filter) {
   content::BrowserContext* browser_context =
       process ? process->GetBrowserContext() : nullptr;
   return EventListener::ForExtensionServiceWorker(
@@ -141,21 +144,41 @@
   return builder.Build();
 }
 
-std::unique_ptr<DictionaryValue> CreateHostSuffixFilter(
+std::unique_ptr<base::Value::Dict> CreateHostSuffixFilter(
     const std::string& suffix) {
-  auto filter_dict = std::make_unique<DictionaryValue>();
-  filter_dict->SetKey("hostSuffix", Value(suffix));
+  auto filter_dict = std::make_unique<base::Value::Dict>();
+  filter_dict->Set("hostSuffix", suffix);
 
-  Value filter_list(Value::Type::LIST);
+  base::Value::List filter_list;
   filter_list.Append(std::move(*filter_dict));
 
-  auto filter = std::make_unique<DictionaryValue>();
-  filter->SetKey("url", std::move(filter_list));
+  auto filter = std::make_unique<base::Value::Dict>();
+  filter->Set("url", std::move(filter_list));
   return filter;
 }
 
 }  // namespace
 
+bool operator<(const EventTarget& e1, const EventTarget& e2) {
+  return std::tie(e1.extension_id, e1.render_process_id,
+                  e1.service_worker_version_id, e1.worker_thread_id) <
+         std::tie(e2.extension_id, e2.render_process_id,
+                  e2.service_worker_version_id, e2.worker_thread_id);
+}
+
+bool operator==(const EventTarget& e1, const EventTarget& e2) {
+  return std::tie(e1.extension_id, e1.render_process_id,
+                  e1.service_worker_version_id, e1.worker_thread_id) ==
+         std::tie(e2.extension_id, e2.render_process_id,
+                  e2.service_worker_version_id, e2.worker_thread_id);
+}
+
+std::ostream& operator<<(std::ostream& os, const EventTarget& e) {
+  return os << "EventTarget{" << e.extension_id << "," << e.render_process_id
+            << "," << e.service_worker_version_id << "," << e.worker_thread_id
+            << "}";
+}
+
 class EventRouterTest : public ExtensionsTest {
  public:
   EventRouterTest() = default;
@@ -242,7 +265,7 @@
 
   EventRouter* event_router() { return EventRouter::Get(browser_context()); }
 
-  const DictionaryValue* GetFilteredEvents(const std::string& extension_id) {
+  const base::Value::Dict* GetFilteredEvents(const std::string& extension_id) {
     return event_router()->GetFilteredEvents(
         extension_id, is_for_service_worker()
                           ? EventRouter::RegisteredEventType::kServiceWorker
@@ -251,19 +274,20 @@
 
   bool ContainsFilter(const std::string& extension_id,
                       const std::string& event_name,
-                      const DictionaryValue& to_check) {
-    const Value* filter_list = GetFilterList(extension_id, event_name);
+                      const base::Value::Dict& to_check) {
+    const base::Value::List* filter_list =
+        GetFilterList(extension_id, event_name);
     if (!filter_list) {
       ADD_FAILURE();
       return false;
     }
 
-    for (const base::Value& filter : filter_list->GetList()) {
+    for (const base::Value& filter : *filter_list) {
       if (!filter.is_dict()) {
         ADD_FAILURE();
         return false;
       }
-      if (filter == to_check)
+      if (filter.GetDict() == to_check)
         return true;
     }
     return false;
@@ -272,15 +296,14 @@
   bool is_for_service_worker() const { return GetParam(); }
 
  private:
-  const Value* GetFilterList(const std::string& extension_id,
-                             const std::string& event_name) {
-    const base::DictionaryValue* filtered_events =
-        GetFilteredEvents(extension_id);
-    const auto iter = filtered_events->GetDict().begin();
+  const base::Value::List* GetFilterList(const std::string& extension_id,
+                                         const std::string& event_name) {
+    const base::Value::Dict* filtered_events = GetFilteredEvents(extension_id);
+    const auto iter = filtered_events->begin();
     if (iter->first != event_name)
       return nullptr;
 
-    return iter->second.is_list() ? &iter->second : nullptr;
+    return iter->second.is_list() ? &iter->second.GetList() : nullptr;
   }
 
   std::unique_ptr<content::RenderProcessHost> render_process_host_;
@@ -300,7 +323,7 @@
   EventRouter router(nullptr, nullptr);
   std::unique_ptr<EventListener> listener =
       constructor.Run("event_name", render_process_host(),
-                      std::make_unique<base::DictionaryValue>());
+                      std::make_unique<base::Value::Dict>());
 
   // Add/remove works without any observers.
   router.OnListenerAdded(listener.get());
@@ -337,7 +360,7 @@
   matching_observer.Reset();
   std::unique_ptr<EventListener> sub_event_listener =
       constructor.Run("event_name/1", render_process_host(),
-                      std::make_unique<base::DictionaryValue>());
+                      std::make_unique<base::Value::Dict>());
   router.OnListenerAdded(sub_event_listener.get());
   EXPECT_EQ(1, matching_observer.listener_added_count());
   EXPECT_EQ(0, matching_observer.listener_removed_count());
@@ -372,7 +395,7 @@
   EventRouter router(nullptr, nullptr);
   std::unique_ptr<EventListener> listener = EventListener::ForURL(
       "event_name", GURL("http://google.com/path"), render_process_host(),
-      std::make_unique<base::DictionaryValue>());
+      std::make_unique<base::Value::Dict>());
 
   // Add/remove works without any observers.
   router.OnListenerAdded(listener.get());
@@ -451,7 +474,8 @@
 // Tests adding and removing events with filters.
 TEST_P(EventRouterFilterTest, Basic) {
   // For the purpose of this test, "." is important in |event_name| as it
-  // exercises the code path that uses |event_name| as a key in DictionaryValue.
+  // exercises the code path that uses |event_name| as a key in
+  // base::Value::Dict.
   const std::string kEventName = "webNavigation.onBeforeNavigate";
 
   const std::string kExtensionId = "mbflcebpggnecokmikipoihdbecnjfoj";
@@ -467,22 +491,21 @@
     worker_identifier =
         absl::make_optional<ServiceWorkerIdentifier>(std::move(identifier));
   }
-  std::vector<std::unique_ptr<DictionaryValue>> filters;
-  for (size_t i = 0; i < std::size(kHostSuffixes); ++i) {
-    std::unique_ptr<base::DictionaryValue> filter =
-        CreateHostSuffixFilter(kHostSuffixes[i]);
+  std::vector<std::unique_ptr<base::Value::Dict>> filters;
+  for (const std::string& host_suffix : kHostSuffixes) {
+    std::unique_ptr<base::Value::Dict> filter =
+        CreateHostSuffixFilter(host_suffix);
     event_router()->AddFilteredEventListener(kEventName, render_process_host(),
                                              param.Clone(), worker_identifier,
                                              *filter, true);
     filters.push_back(std::move(filter));
   }
 
-  const base::DictionaryValue* filtered_events =
-      GetFilteredEvents(kExtensionId);
+  const base::Value::Dict* filtered_events = GetFilteredEvents(kExtensionId);
   ASSERT_TRUE(filtered_events);
-  ASSERT_EQ(1u, filtered_events->DictSize());
+  ASSERT_EQ(1u, filtered_events->size());
 
-  const auto iter = filtered_events->GetDict().begin();
+  const auto iter = filtered_events->begin();
   ASSERT_EQ(kEventName, iter->first);
   ASSERT_TRUE(iter->second.is_list());
   ASSERT_EQ(3u, iter->second.GetList().size());
@@ -520,7 +543,7 @@
   const std::string kEventName = "windows.onRemoved";
   const GURL kUrl("chrome-untrusted://terminal");
   absl::optional<ServiceWorkerIdentifier> worker_identifier = absl::nullopt;
-  auto filter = std::make_unique<DictionaryValue>();
+  auto filter = std::make_unique<base::Value::Dict>();
   bool lazy = false;
   EXPECT_FALSE(event_router()->HasEventListener(kEventName));
   event_router()->AddFilteredEventListener(
@@ -627,4 +650,111 @@
   EXPECT_EQ(0u, observer.dispatched_events().size());
 }
 
+TEST_F(EventRouterDispatchTest, TestDispatchCallback) {
+  std::string ext1 = "ext1";
+  std::string ext2 = "ext2";
+  std::string ext3 = "ext3";
+  std::string event_name = "testapi.onEvent";
+  FeatureProvider provider;
+  auto feature = std::make_unique<SimpleFeature>();
+  feature->set_name("test feature");
+  provider.AddFeature(event_name, std::move(feature));
+  ExtensionAPI::GetSharedInstance()->RegisterDependencyProvider("api",
+                                                                &provider);
+  auto add_extension = [&](const std::string& id) {
+    scoped_refptr<const Extension> extension =
+        ExtensionBuilder("test extension")
+            .SetManifestVersion(3)
+            .SetID(id)
+            .Build();
+    ExtensionRegistry::Get(browser_context())->AddEnabled(extension);
+  };
+  add_extension(ext1);
+  add_extension(ext2);
+  add_extension(ext3);
+
+  std::vector<extensions::EventTarget> dispatched;
+  auto create_event = [&](const std::string& name) {
+    auto event = std::make_unique<extensions::Event>(
+        extensions::events::FOR_TEST, name, base::Value::List());
+    return event;
+  };
+
+  auto create_event_with_callback = [&](const std::string& name) {
+    auto e = create_event(name);
+    e->did_dispatch_callback =
+        base::BindLambdaForTesting([&](const extensions::EventTarget& target) {
+          dispatched.push_back(target);
+        });
+    // To ensure did_dispatch_callback is copied properly.
+    return e->DeepCopy();
+  };
+
+  auto process1 =
+      std::make_unique<content::MockRenderProcessHost>(browser_context());
+  auto process2 =
+      std::make_unique<content::MockRenderProcessHost>(browser_context());
+  auto process3 =
+      std::make_unique<content::MockRenderProcessHost>(browser_context());
+  auto process4 =
+      std::make_unique<content::MockRenderProcessHost>(browser_context());
+
+  // Register all extensions for the event:
+  // 1) single listener for ext1
+  event_router()->AddEventListener(event_name, process1.get(), ext1);
+  // 2) two listeners for two processes for ext2
+  event_router()->AddEventListener(event_name, process2.get(), ext2);
+  event_router()->AddEventListener(event_name, process3.get(), ext2);
+  // 3) service worker listeners for ext3
+  const int sw_version_id = 10;
+  const int sw_thread_id = 100;
+  event_router()->AddServiceWorkerEventListener(
+      event_name, process4.get(), ext3, GURL(), sw_version_id, sw_thread_id);
+
+  // Dispatch without callback set.
+  event_router()->DispatchEventToExtension(ext1, create_event(event_name));
+  event_router()->DispatchEventToExtension(ext2, create_event(event_name));
+  event_router()->DispatchEventToExtension(ext3, create_event(event_name));
+
+  EXPECT_EQ(0u, dispatched.size());
+  dispatched.clear();
+
+  // Dispatch with a post-dispatch callback set.
+  event_router()->DispatchEventToExtension(
+      ext1, create_event_with_callback(event_name));
+  event_router()->DispatchEventToExtension(
+      ext2, create_event_with_callback(event_name));
+  event_router()->DispatchEventToExtension(
+      ext3, create_event_with_callback(event_name));
+
+  const int sw_invalid_version_id =
+      blink::mojom::kInvalidServiceWorkerVersionId;
+  std::vector<EventTarget> expected{
+      {ext1, process1->GetID(), sw_invalid_version_id, kMainThreadId},
+      {ext2, process2->GetID(), sw_invalid_version_id, kMainThreadId},
+      {ext2, process3->GetID(), sw_invalid_version_id, kMainThreadId},
+      {ext3, process4->GetID(), sw_version_id, sw_thread_id},
+  };
+  std::sort(std::begin(dispatched), std::end(dispatched));
+  EXPECT_EQ(dispatched, expected);
+  dispatched.clear();
+
+  // Repeat the same event, but with broadcast: should have the same dispatch
+  // targets.
+  event_router()->BroadcastEvent(create_event_with_callback(event_name));
+
+  std::sort(std::begin(dispatched), std::end(dispatched));
+  EXPECT_EQ(dispatched, expected);
+  dispatched.clear();
+
+  // No listeners registered for 'api.other' event.
+  event_router()->DispatchEventToExtension(
+      ext1, create_event_with_callback("api.other"));
+  event_router()->DispatchEventToExtension(
+      ext2, create_event_with_callback("api.other"));
+  event_router()->DispatchEventToExtension(
+      ext3, create_event_with_callback("api.other"));
+  EXPECT_EQ(0u, dispatched.size());
+}
+
 }  // namespace extensions
diff --git a/extensions/browser/events/lazy_event_dispatcher.cc b/extensions/browser/events/lazy_event_dispatcher.cc
index e71eb500..5417f08 100644
--- a/extensions/browser/events/lazy_event_dispatcher.cc
+++ b/extensions/browser/events/lazy_event_dispatcher.cc
@@ -23,10 +23,9 @@
 
 LazyEventDispatcher::~LazyEventDispatcher() {}
 
-void LazyEventDispatcher::Dispatch(
-    const Event& event,
-    const LazyContextId& dispatch_context,
-    const base::DictionaryValue* listener_filter) {
+void LazyEventDispatcher::Dispatch(const Event& event,
+                                   const LazyContextId& dispatch_context,
+                                   const base::Value::Dict* listener_filter) {
   const Extension* extension = ExtensionRegistry::Get(browser_context_)
                                    ->enabled_extensions()
                                    .GetByID(dispatch_context.extension_id());
@@ -49,7 +48,7 @@
     const Event& event,
     const LazyContextId& dispatch_context,
     const Extension* extension,
-    const base::DictionaryValue* listener_filter) {
+    const base::Value::Dict* listener_filter) {
   if (!EventRouter::CanDispatchEventToBrowserContext(
           dispatch_context.browser_context(), extension, event)) {
     return false;
diff --git a/extensions/browser/events/lazy_event_dispatcher.h b/extensions/browser/events/lazy_event_dispatcher.h
index 3a7bece..d0f8fa8 100644
--- a/extensions/browser/events/lazy_event_dispatcher.h
+++ b/extensions/browser/events/lazy_event_dispatcher.h
@@ -10,14 +10,11 @@
 
 #include "base/callback.h"
 #include "base/memory/raw_ptr.h"
+#include "base/values.h"
 #include "extensions/browser/lazy_context_id.h"
 #include "extensions/browser/lazy_context_task_queue.h"
 #include "extensions/common/extension_id.h"
 
-namespace base {
-class DictionaryValue;
-}
-
 namespace content {
 class BrowserContext;
 }
@@ -53,7 +50,7 @@
   // started before dispatching the  event.
   void Dispatch(const Event& event,
                 const LazyContextId& dispatch_context,
-                const base::DictionaryValue* listener_filter);
+                const base::Value::Dict* listener_filter);
 
   // Returns whether or not an event listener identical for |dispatch_context|
   // is already queued for dispatch.
@@ -66,7 +63,7 @@
   bool QueueEventDispatch(const Event& event,
                           const LazyContextId& dispatch_context,
                           const Extension* extension,
-                          const base::DictionaryValue* listener_filter);
+                          const base::Value::Dict* listener_filter);
 
   void RecordAlreadyDispatched(const LazyContextId& dispatch_context);
 
diff --git a/extensions/browser/extension_prefs.cc b/extensions/browser/extension_prefs.cc
index a57af84..78f45a9f 100644
--- a/extensions/browser/extension_prefs.cc
+++ b/extensions/browser/extension_prefs.cc
@@ -225,10 +225,6 @@
 // that need to be synced. Default value is false.
 constexpr const char kPrefNeedsSync[] = "needs_sync";
 
-// Stores preferences corresponding to static indexed rulesets for the
-// Declarative Net Request API.
-constexpr const char kDNRStaticRulesetPref[] = "dnr_static_ruleset";
-
 // Stores preferences corresponding to dynamic indexed ruleset for the
 // Declarative Net Request API. Note: we use a separate preference key for
 // dynamic rulesets instead of using the |kDNRStaticRulesetPref| dictionary.
@@ -287,6 +283,28 @@
   }
 }
 
+// Serializes |time| as a string value mapped to |key| in |dictionary|.
+void SaveTime(prefs::DictionaryValueUpdate* dictionary,
+              const char* key,
+              const base::Time& time) {
+  if (!dictionary)
+    return;
+
+  dictionary->Set(key, base::TimeToValue(time));
+}
+
+// The opposite of SaveTime. If |key| is not found, this returns an empty Time
+// (is_null() will return true).
+base::Time ReadTime(const base::Value::Dict* dictionary, const char* key) {
+  if (!dictionary)
+    return base::Time();
+
+  if (const base::Value* time_value = dictionary->FindByDottedPath(key))
+    return base::ValueToTime(time_value).value_or(base::Time());
+
+  return base::Time();
+}
+
 // Provider of write access to a dictionary storing extension prefs.
 class ScopedExtensionPrefUpdate : public prefs::ScopedDictionaryPrefUpdate {
  public:
@@ -319,10 +337,6 @@
   const std::string extension_id_;
 };
 
-std::string JoinPrefs(const std::vector<base::StringPiece>& parts) {
-  return base::JoinString(parts, ".");
-}
-
 // Whether SetAlertSystemFirstRun() should always return true, so that alerts
 // are triggered, even in first run.
 bool g_run_alerts_in_first_run_for_testing = false;
@@ -484,7 +498,7 @@
   }
 }
 
-const base::DictionaryValue* ExtensionPrefs::GetExtensionPref(
+const base::Value::Dict* ExtensionPrefs::GetExtensionPref(
     const std::string& extension_id) const {
   // TODO(https://1297144): Should callers of this method proactively filter out
   // extension IDs? Previously, this function would (potentially surprisingly)
@@ -493,15 +507,9 @@
   if (extension_id.empty()) {
     return nullptr;
   }
-  // TODO (https://crbug.com/1342019) This should call
-  // `PrefService::GetDict`, which will in turn require the return type to
-  // be `base::Value::Dict`.
-  const base::Value& extensions = prefs_->GetValue(pref_names::kExtensions);
-  if (!extensions.is_dict())
-    return nullptr;
-  const base::Value* extension_dict = extensions.FindDictPath(extension_id);
-  return extension_dict ? &base::Value::AsDictionaryValue(*extension_dict)
-                        : nullptr;
+
+  return prefs_->GetDict(pref_names::kExtensions)
+      .FindDictByDottedPath(extension_id);
 }
 
 void ExtensionPrefs::SetIntegerPref(const std::string& id,
@@ -533,13 +541,11 @@
   UpdateExtensionPrefInternal(id, pref, std::move(value));
 }
 
-void ExtensionPrefs::SetDictionaryPref(
-    const std::string& id,
-    const PrefMap& pref,
-    std::unique_ptr<base::DictionaryValue> value) {
+void ExtensionPrefs::SetDictionaryPref(const std::string& id,
+                                       const PrefMap& pref,
+                                       base::Value::Dict value) {
   DCHECK_EQ(pref.type, PrefType::kDictionary);
-  DCHECK_EQ(base::Value::Type::DICTIONARY, value->type());
-  UpdateExtensionPrefInternal(id, pref, std::move(*value));
+  UpdateExtensionPrefInternal(id, pref, base::Value(std::move(value)));
 }
 
 void ExtensionPrefs::SetTimePref(const std::string& id,
@@ -585,8 +591,8 @@
 
 void ExtensionPrefs::DeleteExtensionPrefsIfPrefEmpty(
     const std::string& extension_id) {
-  const base::DictionaryValue* dict = GetExtensionPref(extension_id);
-  if (dict && dict->DictEmpty())
+  const base::Value::Dict* dict = GetExtensionPref(extension_id);
+  if (dict && dict->empty())
     DeleteExtensionPrefs(extension_id);
 }
 
@@ -595,12 +601,13 @@
                                        bool* out_value) const {
   DCHECK_EQ(PrefScope::kExtensionSpecific, pref.scope);
   DCHECK_EQ(PrefType::kBool, pref.type);
+  DCHECK(out_value);
 
-  const base::DictionaryValue* ext = GetExtensionPref(extension_id);
+  const base::Value::Dict* ext = GetExtensionPref(extension_id);
   if (!ext)
     return false;
 
-  absl::optional<bool> value = ext->FindBoolPath(pref.name);
+  absl::optional<bool> value = ext->FindBoolByDottedPath(pref.name);
   if (!value)
     return false;
 
@@ -613,10 +620,11 @@
                                        int* out_value) const {
   DCHECK_EQ(PrefScope::kExtensionSpecific, pref.scope);
   DCHECK_EQ(PrefType::kInteger, pref.type);
-  const base::DictionaryValue* ext = GetExtensionPref(extension_id);
+  DCHECK(out_value);
+  const base::Value::Dict* ext = GetExtensionPref(extension_id);
   if (!ext)
     return false;
-  absl::optional<int> value = ext->FindIntPath(pref.name);
+  absl::optional<int> value = ext->FindIntByDottedPath(pref.name);
   if (!value)
     return false;
   *out_value = *value;
@@ -628,63 +636,56 @@
                                       std::string* out_value) const {
   DCHECK_EQ(PrefScope::kExtensionSpecific, pref.scope);
   DCHECK_EQ(PrefType::kString, pref.type);
-  const base::DictionaryValue* ext = GetExtensionPref(extension_id);
-  if (!ext || !ext->GetString(pref.name, out_value))
-    return false;
-
-  return true;
-}
-
-bool ExtensionPrefs::ReadPrefAsList(const std::string& extension_id,
-                                    const PrefMap& pref,
-                                    const base::ListValue** out_value) const {
-  DCHECK_EQ(PrefScope::kExtensionSpecific, pref.scope);
-  DCHECK_EQ(PrefType::kList, pref.type);
   DCHECK(out_value);
-  const base::DictionaryValue* ext = GetExtensionPref(extension_id);
-  if (!ext || !ext->GetList(pref.name, out_value))
-    return false;
-  return true;
-}
-
-bool ExtensionPrefs::ReadPrefAsDictionary(
-    const std::string& extension_id,
-    const PrefMap& pref,
-    const base::DictionaryValue** out_value) const {
-  DCHECK_EQ(PrefScope::kExtensionSpecific, pref.scope);
-  DCHECK_EQ(PrefType::kDictionary, pref.type);
-  DCHECK(out_value);
-  const base::DictionaryValue* ext = GetExtensionPref(extension_id);
+  const base::Value::Dict* ext = GetExtensionPref(extension_id);
   if (!ext)
     return false;
-  const base::Value* dict = ext->FindDictPath(pref.name);
-  if (!dict)
+
+  const std::string* str = ext->FindStringByDottedPath(pref.name);
+  if (!str)
     return false;
-  *out_value = &base::Value::AsDictionaryValue(*dict);
+
+  *out_value = *str;
   return true;
 }
 
+const base::Value::List* ExtensionPrefs::ReadPrefAsList(
+    const std::string& extension_id,
+    const PrefMap& pref) const {
+  DCHECK_EQ(PrefScope::kExtensionSpecific, pref.scope);
+  DCHECK_EQ(PrefType::kList, pref.type);
+  const base::Value::Dict* ext = GetExtensionPref(extension_id);
+  if (!ext)
+    return nullptr;
+  return ext->FindListByDottedPath(pref.name);
+}
+
+const base::Value::Dict* ExtensionPrefs::ReadPrefAsDictionary(
+    const std::string& extension_id,
+    const PrefMap& pref) const {
+  DCHECK_EQ(PrefScope::kExtensionSpecific, pref.scope);
+  DCHECK_EQ(PrefType::kDictionary, pref.type);
+  const base::Value::Dict* ext = GetExtensionPref(extension_id);
+  if (!ext)
+    return nullptr;
+  return ext->FindDictByDottedPath(pref.name);
+}
+
 base::Time ExtensionPrefs::ReadPrefAsTime(const std::string& extension_id,
                                           const PrefMap& pref) const {
   DCHECK_EQ(PrefScope::kExtensionSpecific, pref.scope);
   DCHECK_EQ(PrefType::kTime, pref.type);
-  const base::DictionaryValue* ext = GetExtensionPref(extension_id);
-  const base::Value* value;
-  if (!ext || !ext->Get(pref.name, &value))
-    return base::Time();
-  absl::optional<base::Time> time = ::base::ValueToTime(value);
-  DCHECK(time);
-  return time.value_or(base::Time());
+  return ReadTime(GetExtensionPref(extension_id), pref.name);
 }
 
 bool ExtensionPrefs::ReadPrefAsBoolean(const std::string& extension_id,
                                        base::StringPiece pref_key,
                                        bool* out_value) const {
-  const base::DictionaryValue* ext = GetExtensionPref(extension_id);
+  const base::Value::Dict* ext = GetExtensionPref(extension_id);
   if (!ext)
     return false;
 
-  absl::optional<bool> value = ext->FindBoolPath(pref_key);
+  absl::optional<bool> value = ext->FindBoolByDottedPath(pref_key);
   if (!value)
     return false;
 
@@ -695,11 +696,11 @@
 bool ExtensionPrefs::ReadPrefAsInteger(const std::string& extension_id,
                                        base::StringPiece pref_key,
                                        int* out_value) const {
-  const base::DictionaryValue* ext = GetExtensionPref(extension_id);
+  const base::Value::Dict* ext = GetExtensionPref(extension_id);
   if (!ext)
     return false;
 
-  absl::optional<int> value = ext->FindIntPath(pref_key);
+  absl::optional<int> value = ext->FindIntByDottedPath(pref_key);
   if (!value)
     return false;
 
@@ -710,27 +711,36 @@
 bool ExtensionPrefs::ReadPrefAsString(const std::string& extension_id,
                                       base::StringPiece pref_key,
                                       std::string* out_value) const {
-  const base::DictionaryValue* ext = GetExtensionPref(extension_id);
-  if (!ext || !ext->GetString(pref_key, out_value))
+  DCHECK(out_value);
+  const base::Value::Dict* ext = GetExtensionPref(extension_id);
+  if (!ext)
     return false;
 
+  const std::string* str = ext->FindStringByDottedPath(pref_key);
+  if (!str)
+    return false;
+
+  *out_value = *str;
   return true;
 }
 
 const base::Value::List* ExtensionPrefs::ReadPrefAsList(
     const std::string& extension_id,
     base::StringPiece pref_key) const {
-  const base::DictionaryValue* ext = GetExtensionPref(extension_id);
+  const base::Value::Dict* ext = GetExtensionPref(extension_id);
   if (!ext)
     return nullptr;
-  return ext->GetDict().FindListByDottedPath(pref_key);
+  return ext->FindListByDottedPath(pref_key);
 }
 
 const base::Value* ExtensionPrefs::GetPrefAsValue(
     const std::string& extension_id,
     base::StringPiece pref_key) const {
-  const base::DictionaryValue* ext = GetExtensionPref(extension_id);
-  return ext ? ext->FindDictPath(pref_key) : nullptr;
+  const base::Value::Dict* ext = GetExtensionPref(extension_id);
+  if (!ext)
+    return nullptr;
+  const base::Value* value = ext->FindByDottedPath(pref_key);
+  return value && value->is_dict() ? value : nullptr;
 }
 
 bool ExtensionPrefs::ReadPrefAsDictionary(
@@ -765,10 +775,10 @@
   const base::Value::List* value = ReadPrefAsList(extension_id, pref_key);
   if (!value)
     return false;
-  const base::DictionaryValue* extension = GetExtensionPref(extension_id);
+  const base::Value::Dict* extension = GetExtensionPref(extension_id);
   if (!extension)
     return false;
-  absl::optional<int> location = extension->FindIntKey(kPrefLocation);
+  absl::optional<int> location = extension->FindInt(kPrefLocation);
   if (location && static_cast<ManifestLocation>(*location) ==
                       ManifestLocation::kComponent) {
     valid_schemes |= URLPattern::SCHEME_CHROMEUI;
@@ -1106,52 +1116,6 @@
   }
 }
 
-namespace {
-
-// Serializes a 64bit integer as a string value.
-void SaveInt64(prefs::DictionaryValueUpdate* dictionary,
-               const char* key,
-               const int64_t value) {
-  if (!dictionary)
-    return;
-
-  std::string string_value = base::NumberToString(value);
-  dictionary->SetString(key, string_value);
-}
-
-// Deserializes a 64bit integer stored as a string value.
-bool ReadInt64(const base::DictionaryValue* dictionary,
-               const char* key,
-               int64_t* value) {
-  if (!dictionary)
-    return false;
-
-  std::string string_value;
-  if (!dictionary->GetString(key, &string_value))
-    return false;
-
-  return base::StringToInt64(string_value, value);
-}
-
-// Serializes |time| as a string value mapped to |key| in |dictionary|.
-void SaveTime(prefs::DictionaryValueUpdate* dictionary,
-              const char* key,
-              const base::Time& time) {
-  SaveInt64(dictionary, key, time.ToDeltaSinceWindowsEpoch().InMicroseconds());
-}
-
-// The opposite of SaveTime. If |key| is not found, this returns an empty Time
-// (is_null() will return true).
-base::Time ReadTime(const base::DictionaryValue* dictionary, const char* key) {
-  int64_t value;
-  if (ReadInt64(dictionary, key, &value))
-    return base::Time::FromDeltaSinceWindowsEpoch(base::Microseconds(value));
-
-  return base::Time();
-}
-
-}  // namespace
-
 base::Time ExtensionPrefs::LastPingDay(const std::string& extension_id) const {
   DCHECK(crx_file::id_util::IdIsValid(extension_id));
   return ReadTime(GetExtensionPref(extension_id), kLastPingDay);
@@ -1165,12 +1129,7 @@
 }
 
 base::Time ExtensionPrefs::BlocklistLastPingDay() const {
-  // TODO (https://crbug.com/1342019) This should call
-  // `PrefService::GetDict`, which will in turn require the return type to
-  // be `base::Value::Dict`.
-  return ReadTime(&base::Value::AsDictionaryValue(
-                      prefs_->GetValue(kExtensionsBlocklistUpdate)),
-                  kLastPingDay);
+  return ReadTime(&prefs_->GetDict(kExtensionsBlocklistUpdate), kLastPingDay);
 }
 
 void ExtensionPrefs::SetBlocklistLastPingDay(const base::Time& time) {
@@ -1192,9 +1151,9 @@
 }
 
 bool ExtensionPrefs::GetActiveBit(const std::string& extension_id) const {
-  const base::DictionaryValue* dictionary = GetExtensionPref(extension_id);
+  const base::Value::Dict* dictionary = GetExtensionPref(extension_id);
   if (dictionary)
-    return dictionary->FindBoolKey(kActiveBit).value_or(false);
+    return dictionary->FindBool(kActiveBit).value_or(false);
   return false;
 }
 
@@ -1269,8 +1228,8 @@
 
 bool ExtensionPrefs::HasWithholdingPermissionsSetting(
     const ExtensionId& extension_id) const {
-  const base::DictionaryValue* ext = GetExtensionPref(extension_id);
-  return ext && ext->FindKey(kPrefWithholdingPermissions);
+  const base::Value::Dict* ext = GetExtensionPref(extension_id);
+  return ext && ext->Find(kPrefWithholdingPermissions);
 }
 
 std::unique_ptr<PermissionSet> ExtensionPrefs::GetRuntimeGrantedPermissions(
@@ -1304,9 +1263,9 @@
 }
 
 bool ExtensionPrefs::IsExtensionRunning(const std::string& extension_id) const {
-  const base::DictionaryValue* extension = GetExtensionPref(extension_id);
+  const base::Value::Dict* extension = GetExtensionPref(extension_id);
   if (extension)
-    return extension->FindBoolKey(kPrefRunning).value_or(false);
+    return extension->FindBool(kPrefRunning).value_or(false);
   return false;
 }
 
@@ -1317,9 +1276,9 @@
 }
 
 bool ExtensionPrefs::IsActive(const std::string& extension_id) const {
-  const base::DictionaryValue* extension = GetExtensionPref(extension_id);
+  const base::Value::Dict* extension = GetExtensionPref(extension_id);
   if (extension)
-    return extension->FindBoolKey(kIsActive).value_or(false);
+    return extension->FindBool(kIsActive).value_or(false);
   return false;
 }
 
@@ -1346,18 +1305,18 @@
 
 bool ExtensionPrefs::HasAllowFileAccessSetting(
     const std::string& extension_id) const {
-  const base::DictionaryValue* ext = GetExtensionPref(extension_id);
-  return ext && ext->FindKey(kPrefAllowFileAccess);
+  const base::Value::Dict* ext = GetExtensionPref(extension_id);
+  return ext && ext->Find(kPrefAllowFileAccess);
 }
 
 bool ExtensionPrefs::DoesExtensionHaveState(
     const std::string& id,
     Extension::State check_state) const {
-  const base::DictionaryValue* extension = GetExtensionPref(id);
+  const base::Value::Dict* extension = GetExtensionPref(id);
   if (!extension)
     return false;
 
-  absl::optional<int> state = extension->FindIntKey(kPrefState);
+  absl::optional<int> state = extension->FindInt(kPrefState);
   if (!state)
     return false;
 
@@ -1470,26 +1429,25 @@
 
 std::string ExtensionPrefs::GetVersionString(
     const std::string& extension_id) const {
-  const base::DictionaryValue* extension = GetExtensionPref(extension_id);
+  const base::Value::Dict* extension = GetExtensionPref(extension_id);
   if (!extension)
     return std::string();
 
-  std::string version;
-  extension->GetString(kPrefManifestVersion, &version);
-
-  return version;
+  const std::string* version =
+      extension->FindStringByDottedPath(kPrefManifestVersion);
+  return version ? *version : std::string();
 }
 
 void ExtensionPrefs::UpdateManifest(const Extension* extension) {
   if (!Manifest::IsUnpackedLocation(extension->location())) {
-    const base::DictionaryValue* extension_dict =
-        GetExtensionPref(extension->id());
+    const base::Value::Dict* extension_dict = GetExtensionPref(extension->id());
     if (!extension_dict)
       return;
-    const base::Value* old_manifest =
-        extension_dict->FindDictKey(kPrefManifest);
+    const base::Value::Dict* old_manifest =
+        extension_dict->FindDict(kPrefManifest);
     bool update_required =
-        !old_manifest || *extension->manifest()->value() != *old_manifest;
+        !old_manifest ||
+        extension->manifest()->value()->GetDict() != *old_manifest;
     if (update_required) {
       UpdateExtensionPref(
           extension->id(), kPrefManifest,
@@ -1678,29 +1636,29 @@
 
 std::unique_ptr<ExtensionInfo> ExtensionPrefs::GetDelayedInstallInfo(
     const std::string& extension_id) const {
-  const base::DictionaryValue* extension_prefs = GetExtensionPref(extension_id);
+  const base::Value::Dict* extension_prefs = GetExtensionPref(extension_id);
   if (!extension_prefs)
     return nullptr;
 
-  const base::Value* ext = extension_prefs->FindDictKey(kDelayedInstallInfo);
+  const base::Value::Dict* ext = extension_prefs->FindDict(kDelayedInstallInfo);
   if (!ext)
     return nullptr;
 
-  return GetInstalledInfoHelper(extension_id, ext->GetDict(),
+  return GetInstalledInfoHelper(extension_id, *ext,
                                 /*include_component_extensions = */ false);
 }
 
 ExtensionPrefs::DelayReason ExtensionPrefs::GetDelayedInstallReason(
     const std::string& extension_id) const {
-  const base::DictionaryValue* extension_prefs = GetExtensionPref(extension_id);
+  const base::Value::Dict* extension_prefs = GetExtensionPref(extension_id);
   if (!extension_prefs)
     return DELAY_REASON_NONE;
 
-  const base::Value* ext = extension_prefs->FindDictKey(kDelayedInstallInfo);
+  const base::Value::Dict* ext = extension_prefs->FindDict(kDelayedInstallInfo);
   if (!ext)
     return DELAY_REASON_NONE;
 
-  absl::optional<int> delay_reason = ext->FindIntKey(kDelayedInstallReason);
+  absl::optional<int> delay_reason = ext->FindInt(kDelayedInstallReason);
   if (!delay_reason)
     return DELAY_REASON_NONE;
 
@@ -1726,9 +1684,9 @@
 }
 
 bool ExtensionPrefs::IsFromWebStore(const std::string& extension_id) const {
-  const base::DictionaryValue* dictionary = GetExtensionPref(extension_id);
+  const base::Value::Dict* dictionary = GetExtensionPref(extension_id);
   if (dictionary)
-    return dictionary->FindBoolKey(kPrefFromWebStore).value_or(false);
+    return dictionary->FindBool(kPrefFromWebStore).value_or(false);
   return false;
 }
 
@@ -1762,32 +1720,22 @@
 
 bool ExtensionPrefs::WasInstalledByDefault(
     const std::string& extension_id) const {
-  const base::DictionaryValue* dictionary = GetExtensionPref(extension_id);
+  const base::Value::Dict* dictionary = GetExtensionPref(extension_id);
   if (!dictionary)
     return false;
-  return dictionary->FindBoolKey(kPrefWasInstalledByDefault).value_or(false);
+  return dictionary->FindBool(kPrefWasInstalledByDefault).value_or(false);
 }
 
 bool ExtensionPrefs::WasInstalledByOem(const std::string& extension_id) const {
-  const base::DictionaryValue* dictionary = GetExtensionPref(extension_id);
+  const base::Value::Dict* dictionary = GetExtensionPref(extension_id);
   if (dictionary)
-    return dictionary->FindBoolKey(kPrefWasInstalledByOem).value_or(false);
+    return dictionary->FindBool(kPrefWasInstalledByOem).value_or(false);
   return false;
 }
 
 base::Time ExtensionPrefs::GetTimePrefHelper(const std::string& extension_id,
                                              const char* pref_key) const {
-  const base::DictionaryValue* extension = GetExtensionPref(extension_id);
-  if (!extension) {
-    return base::Time();
-  }
-  std::string time_str;
-  if (!extension->GetString(pref_key, &time_str))
-    return base::Time();
-  int64_t time_i64 = 0;
-  if (!base::StringToInt64(time_str, &time_i64))
-    return base::Time();
-  return base::Time::FromDeltaSinceWindowsEpoch(base::Microseconds(time_i64));
+  return ReadTime(GetExtensionPref(extension_id), pref_key);
 }
 
 base::Time ExtensionPrefs::GetFirstInstallTime(
@@ -1842,15 +1790,6 @@
   }
 }
 
-void ExtensionPrefs::SetPref(const PrefMap& pref,
-                             std::unique_ptr<base::Value> value) {
-  DCHECK_EQ(PrefScope::kProfile, pref.scope);
-  DCHECK(CheckPrefType(pref.type, value.get()))
-      << "The value passed in does not match the expected PrefType for "
-      << pref.name;
-  prefs_->Set(pref.name, std::move(*value));
-}
-
 void ExtensionPrefs::SetIntegerPref(const PrefMap& pref, int value) {
   DCHECK_EQ(PrefScope::kProfile, pref.scope);
   DCHECK_EQ(PrefType::kInteger, pref.type);
@@ -1884,12 +1823,11 @@
   prefs_->SetString(pref.name, value.spec());
 }
 
-void ExtensionPrefs::SetDictionaryPref(
-    const PrefMap& pref,
-    std::unique_ptr<base::DictionaryValue> value) {
+void ExtensionPrefs::SetDictionaryPref(const PrefMap& pref,
+                                       base::Value::Dict value) {
   DCHECK_EQ(PrefScope::kProfile, pref.scope);
   DCHECK_EQ(PrefType::kDictionary, pref.type);
-  SetPref(pref, std::move(value));
+  prefs_->SetDict(pref.name, std::move(value));
 }
 
 int ExtensionPrefs::GetPrefAsInteger(const PrefMap& pref) const {
@@ -1922,14 +1860,11 @@
   return GURL(prefs_->GetString(pref.name));
 }
 
-const base::DictionaryValue* ExtensionPrefs::GetPrefAsDictionary(
+const base::Value::Dict& ExtensionPrefs::GetPrefAsDictionary(
     const PrefMap& pref) const {
   DCHECK_EQ(PrefScope::kProfile, pref.scope);
   DCHECK_EQ(PrefType::kDictionary, pref.type);
-  // TODO (https://crbug.com/1342019) This should call
-  // `PrefService::GetDict`, which will in turn require the return type to
-  // be `base::Value::Dict`.
-  return &base::Value::AsDictionaryValue(prefs_->GetValue(pref.name));
+  return prefs_->GetDict(pref.name);
 }
 
 std::unique_ptr<prefs::ScopedDictionaryPrefUpdate>
@@ -2019,23 +1954,20 @@
   return has_incognito_pref_value;
 }
 
-const base::DictionaryValue* ExtensionPrefs::GetGeometryCache(
+const base::Value::Dict* ExtensionPrefs::GetGeometryCache(
     const std::string& extension_id) const {
-  const base::DictionaryValue* extension_prefs = GetExtensionPref(extension_id);
+  const base::Value::Dict* extension_prefs = GetExtensionPref(extension_id);
   if (!extension_prefs)
     return nullptr;
 
-  const base::Value* ext = extension_prefs->FindDictKey(kPrefGeometryCache);
-  if (!ext)
-    return nullptr;
-
-  return &base::Value::AsDictionaryValue(*ext);
+  return extension_prefs->FindDict(kPrefGeometryCache);
 }
 
-void ExtensionPrefs::SetGeometryCache(
-    const std::string& extension_id,
-    std::unique_ptr<base::DictionaryValue> cache) {
-  UpdateExtensionPref(extension_id, kPrefGeometryCache, std::move(cache));
+void ExtensionPrefs::SetGeometryCache(const std::string& extension_id,
+                                      base::Value::Dict cache) {
+  UpdateExtensionPref(
+      extension_id, kPrefGeometryCache,
+      base::Value::ToUniquePtrValue(base::Value(std::move(cache))));
 }
 
 const base::Value::Dict& ExtensionPrefs::GetInstallSignature() const {
@@ -2054,13 +1986,16 @@
 
 std::string ExtensionPrefs::GetInstallParam(
     const std::string& extension_id) const {
-  const base::DictionaryValue* extension = GetExtensionPref(extension_id);
+  const base::Value::Dict* extension = GetExtensionPref(extension_id);
   if (!extension)  // Expected during unit testing.
     return std::string();
-  std::string install_parameter;
-  if (!extension->GetString(kPrefInstallParam, &install_parameter))
-    return std::string();
-  return install_parameter;
+
+  if (const std::string* install_parameter =
+          extension->FindStringByDottedPath(kPrefInstallParam)) {
+    return *install_parameter;
+  }
+
+  return std::string();
 }
 
 void ExtensionPrefs::SetInstallParam(const std::string& extension_id,
@@ -2223,6 +2158,19 @@
 const char ExtensionPrefs::kFakeObsoletePrefForTesting[] =
     "__fake_obsolete_pref_for_testing";
 
+// Stores preferences corresponding to static indexed rulesets for the
+// Declarative Net Request API.
+//
+// TODO(blee@igalia.com) Need to move all the DNR related codes to the helper.
+//                       (DeclarativeNetRequestPrefsHelper)
+const char ExtensionPrefs::kDNRStaticRulesetPref[] = "dnr_static_ruleset";
+
+// static
+std::string ExtensionPrefs::JoinPrefs(
+    const std::vector<base::StringPiece>& parts) {
+  return base::JoinString(parts, ".");
+}
+
 ExtensionPrefs::ExtensionPrefs(
     content::BrowserContext* browser_context,
     PrefService* prefs,
diff --git a/extensions/browser/extension_prefs.h b/extensions/browser/extension_prefs.h
index ca90a267..a88c5e2 100644
--- a/extensions/browser/extension_prefs.h
+++ b/extensions/browser/extension_prefs.h
@@ -271,15 +271,14 @@
   void SetStringPref(const PrefMap& pref, const std::string& value);
   void SetTimePref(const PrefMap& pref, base::Time value);
   void SetGURLPref(const PrefMap& pref, const GURL& value);
-  void SetDictionaryPref(const PrefMap& pref,
-                         std::unique_ptr<base::DictionaryValue> value);
+  void SetDictionaryPref(const PrefMap& pref, base::Value::Dict value);
 
   int GetPrefAsInteger(const PrefMap& pref) const;
   bool GetPrefAsBoolean(const PrefMap& pref) const;
   std::string GetPrefAsString(const PrefMap& pref) const;
   base::Time GetPrefAsTime(const PrefMap& pref) const;
   GURL GetPrefAsGURL(const PrefMap& pref) const;
-  const base::DictionaryValue* GetPrefAsDictionary(const PrefMap& pref) const;
+  const base::Value::Dict& GetPrefAsDictionary(const PrefMap& pref) const;
 
   // Returns a wrapper that allows to update an ExtensionPref with a
   // PrefType::kDictionary.
@@ -303,7 +302,7 @@
                    base::Value value);
   void SetDictionaryPref(const std::string& id,
                          const PrefMap& pref,
-                         std::unique_ptr<base::DictionaryValue> value);
+                         base::Value::Dict value);
   void SetTimePref(const std::string& id,
                    const PrefMap& pref,
                    const base::Time value);
@@ -328,13 +327,11 @@
                         const PrefMap& pref,
                         std::string* out_value) const;
 
-  bool ReadPrefAsList(const std::string& extension_id,
-                      const PrefMap& pref,
-                      const base::ListValue** out_value) const;
+  const base::Value::List* ReadPrefAsList(const std::string& extension_id,
+                                          const PrefMap& pref) const;
 
-  bool ReadPrefAsDictionary(const std::string& extension_id,
-                            const PrefMap& pref,
-                            const base::DictionaryValue** out_value) const;
+  const base::Value::Dict* ReadPrefAsDictionary(const std::string& extension_id,
+                                                const PrefMap& pref) const;
 
   base::Time ReadPrefAsTime(const std::string& extension_id,
                             const PrefMap& pref) const;
@@ -674,10 +671,10 @@
 
   // Used by AppWindowGeometryCache to persist its cache. These methods
   // should not be called directly.
-  const base::DictionaryValue* GetGeometryCache(
+  const base::Value::Dict* GetGeometryCache(
       const std::string& extension_id) const;
   void SetGeometryCache(const std::string& extension_id,
-                        std::unique_ptr<base::DictionaryValue> cache);
+                        base::Value::Dict cache);
 
   // Used for verification of installed extension ids. For the Set method, pass
   // null to remove the preference.
@@ -794,6 +791,13 @@
       const std::string& extension_id,
       const mojom::ManifestLocation location);
 
+  // Join |parts| to get a prefs key
+  static std::string JoinPrefs(const std::vector<base::StringPiece>& parts);
+
+  // TODO(blee@igalia.com) Need to move all the DNR related codes to the helper.
+  //                       (DeclarativeNetRequestPrefsHelper)
+  static const char kDNRStaticRulesetPref[];
+
   // When called before the ExtensionService is created, alerts that are
   // normally suppressed in first run will still trigger.
   static void SetRunAlertsInFirstRunForTest();
@@ -818,9 +822,6 @@
       bool extensions_disabled,
       const std::vector<EarlyExtensionPrefsObserver*>& early_observers);
 
-  // Sets profile wide ExtensionPrefs.
-  void SetPref(const PrefMap& pref, std::unique_ptr<base::Value> value);
-
   // Updates ExtensionPrefs for a specific extension.
   void UpdateExtensionPrefInternal(const std::string& id,
                                    const PrefMap& pref,
@@ -830,10 +831,6 @@
   // install_directory_.
   void MakePathsRelative();
 
-  // Converts internal relative paths to be absolute. Used for export to
-  // consumers who expect full paths.
-  void MakePathsAbsolute(base::DictionaryValue* dict);
-
   // Helper function used by GetInstalledExtensionInfo() and
   // GetDelayedInstallInfo() to construct an ExtensionInfo from the provided
   // |extension| dictionary.
@@ -871,7 +868,7 @@
 
   // Returns an immutable dictionary for extension |id|'s prefs, or NULL if it
   // doesn't exist.
-  const base::DictionaryValue* GetExtensionPref(const std::string& id) const;
+  const base::Value::Dict* GetExtensionPref(const std::string& id) const;
 
   // Returns an immutable base::Value for extension |id|'s prefs, or nullptr if
   // it doesn't exist.
diff --git a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc
index 98bc3a82..50a583c 100644
--- a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc
+++ b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc
@@ -334,7 +334,7 @@
   if (!attached() || !plugin_can_save_)
     return false;
 
-  base::ListValue::List args;
+  base::Value::List args;
   args.Append(stream_->stream_url().spec());
 
   auto event =
diff --git a/extensions/browser/permissions_manager.cc b/extensions/browser/permissions_manager.cc
index 1221bd2d..8e19db9 100644
--- a/extensions/browser/permissions_manager.cc
+++ b/extensions/browser/permissions_manager.cc
@@ -79,15 +79,15 @@
 // Returns sites from `pref` in `extension_prefs`.
 std::set<url::Origin> GetSitesFromPrefs(ExtensionPrefs* extension_prefs,
                                         const char* pref) {
-  const base::Value* user_permissions =
+  const base::Value::Dict& user_permissions =
       extension_prefs->GetPrefAsDictionary(kUserPermissions);
   std::set<url::Origin> sites;
 
-  auto* list = user_permissions->FindListKey(pref);
+  auto* list = user_permissions.FindList(pref);
   if (!list)
     return sites;
 
-  for (const auto& site : list->GetList()) {
+  for (const auto& site : *list) {
     const std::string* site_as_string = site.GetIfString();
     if (!site_as_string)
       continue;
diff --git a/extensions/browser/permissions_manager_unittest.cc b/extensions/browser/permissions_manager_unittest.cc
index d7b6087..0ddb364 100644
--- a/extensions/browser/permissions_manager_unittest.cc
+++ b/extensions/browser/permissions_manager_unittest.cc
@@ -97,15 +97,15 @@
 }
 
 const base::Value* PermissionsManagerUnittest::GetRestrictedSitesFromPrefs() {
-  const base::DictionaryValue* permissions =
+  const base::Value::Dict& permissions =
       extension_prefs_->GetPrefAsDictionary(kUserPermissions);
-  return permissions->FindKey("restricted_sites");
+  return permissions.Find("restricted_sites");
 }
 
 const base::Value* PermissionsManagerUnittest::GetPermittedSitesFromPrefs() {
-  const base::DictionaryValue* permissions =
+  const base::Value::Dict& permissions =
       extension_prefs_->GetPrefAsDictionary(kUserPermissions);
-  return permissions->FindKey("permitted_sites");
+  return permissions.Find("permitted_sites");
 }
 
 std::set<url::Origin>
diff --git a/extensions/common/event_filter_unittest.cc b/extensions/common/event_filter_unittest.cc
index e56219e..487f144 100644
--- a/extensions/common/event_filter_unittest.cc
+++ b/extensions/common/event_filter_unittest.cc
@@ -14,10 +14,6 @@
 #include "ipc/ipc_message.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-using base::DictionaryValue;
-using base::ListValue;
-using base::Value;
-
 namespace extensions {
 
 class EventFilterUnittest : public testing::Test {
@@ -43,8 +39,8 @@
   }
 
   std::unique_ptr<EventMatcher> AllURLs() {
-    return std::make_unique<EventMatcher>(
-        std::make_unique<base::DictionaryValue>(), MSG_ROUTING_NONE);
+    return std::make_unique<EventMatcher>(std::make_unique<base::Value::Dict>(),
+                                          MSG_ROUTING_NONE);
   }
 
   std::unique_ptr<EventMatcher> HostSuffixMatcher(
@@ -55,8 +51,8 @@
 
   std::unique_ptr<EventMatcher> MatcherFromURLFilterList(
       base::Value::List url_filter_list) {
-    auto filter_dict = std::make_unique<DictionaryValue>();
-    filter_dict->SetKey("url", base::Value(std::move(url_filter_list)));
+    auto filter_dict = std::make_unique<base::Value::Dict>();
+    filter_dict->Set("url", base::Value(std::move(url_filter_list)));
     return std::make_unique<EventMatcher>(std::move(filter_dict),
                                           MSG_ROUTING_NONE);
   }
diff --git a/extensions/common/event_matcher.cc b/extensions/common/event_matcher.cc
index 46c5eed9..467ac4e 100644
--- a/extensions/common/event_matcher.cc
+++ b/extensions/common/event_matcher.cc
@@ -18,7 +18,7 @@
 
 const char kEventFilterServiceTypeKey[] = "serviceType";
 
-EventMatcher::EventMatcher(std::unique_ptr<base::DictionaryValue> filter,
+EventMatcher::EventMatcher(std::unique_ptr<base::Value::Dict> filter,
                            int routing_id)
     : filter_(std::move(filter)), routing_id_(routing_id) {}
 
@@ -58,18 +58,16 @@
 }
 
 int EventMatcher::GetURLFilterCount() const {
-  base::ListValue* url_filters = nullptr;
-  if (filter_->GetList(kUrlFiltersKey, &url_filters))
-    return url_filters->GetList().size();
+  base::Value::List* url_filters = filter_->FindList(kUrlFiltersKey);
+  if (url_filters)
+    return url_filters->size();
   return 0;
 }
 
 const base::Value::Dict* EventMatcher::GetURLFilter(int i) {
-  base::ListValue* url_filters = nullptr;
-  if (filter_->GetList(kUrlFiltersKey, &url_filters)) {
-    base::Value& dict = url_filters->GetList()[i];
-    return dict.GetIfDict();
-  }
+  base::Value::List* url_filters = filter_->FindList(kUrlFiltersKey);
+  if (url_filters)
+    return (*url_filters)[i].GetIfDict();
   return nullptr;
 }
 
@@ -80,7 +78,7 @@
 std::string EventMatcher::GetServiceTypeFilter() const {
   std::string service_type_filter;
   if (const std::string* ptr =
-          filter_->FindStringKey(kEventFilterServiceTypeKey)) {
+          filter_->FindString(kEventFilterServiceTypeKey)) {
     if (base::IsStringASCII(*ptr))
       service_type_filter = *ptr;
   }
@@ -88,23 +86,22 @@
 }
 
 int EventMatcher::GetInstanceID() const {
-  return filter_->FindIntKey("instanceId").value_or(0);
+  return filter_->FindInt("instanceId").value_or(0);
 }
 
 int EventMatcher::GetWindowTypeCount() const {
-  base::ListValue* window_type_filters = nullptr;
-  if (filter_->GetList(kWindowTypesKey, &window_type_filters))
-    return window_type_filters->GetList().size();
+  base::Value::List* window_type_filters = filter_->FindList(kWindowTypesKey);
+  if (window_type_filters)
+    return window_type_filters->size();
   return 0;
 }
 
 bool EventMatcher::GetWindowType(int i, std::string* window_type_out) const {
-  base::ListValue* window_types = nullptr;
-  if (filter_->GetList(kWindowTypesKey, &window_types)) {
-    const base::Value::List& types_list = window_types->GetList();
-    if (i >= 0 && static_cast<size_t>(i) < types_list.size() &&
-        types_list[i].is_string()) {
-      *window_type_out = types_list[i].GetString();
+  base::Value::List* window_types = filter_->FindList(kWindowTypesKey);
+  if (window_types) {
+    if (i >= 0 && static_cast<size_t>(i) < window_types->size() &&
+        (*window_types)[i].is_string()) {
+      *window_type_out = (*window_types)[i].GetString();
       return true;
     }
   }
diff --git a/extensions/common/event_matcher.h b/extensions/common/event_matcher.h
index 89bea04..4590785c 100644
--- a/extensions/common/event_matcher.h
+++ b/extensions/common/event_matcher.h
@@ -19,7 +19,7 @@
 // MatchNonURLCriteria() - URL matching is handled by EventFilter.
 class EventMatcher {
  public:
-  EventMatcher(std::unique_ptr<base::DictionaryValue> filter, int routing_id);
+  EventMatcher(std::unique_ptr<base::Value::Dict> filter, int routing_id);
 
   EventMatcher(const EventMatcher&) = delete;
   EventMatcher& operator=(const EventMatcher&) = delete;
@@ -46,9 +46,7 @@
 
   int GetRoutingID() const;
 
-  base::DictionaryValue* value() const {
-    return filter_.get();
-  }
+  base::Value::Dict* value() const { return filter_.get(); }
 
  private:
   // Contains a dictionary that corresponds to a single event filter, eg:
@@ -56,7 +54,7 @@
   // {url: [{hostSuffix: 'google.com'}]}
   //
   // The valid filter keys are event-specific.
-  const std::unique_ptr<base::DictionaryValue> filter_;
+  const std::unique_ptr<base::Value::Dict> filter_;
 
   const int routing_id_;
 };
diff --git a/extensions/common/mojom/event_router.mojom b/extensions/common/mojom/event_router.mojom
index b63e314..4cf2600 100644
--- a/extensions/common/mojom/event_router.mojom
+++ b/extensions/common/mojom/event_router.mojom
@@ -49,7 +49,7 @@
   AddFilteredListenerForMainThread(
       EventListenerParam param,
       string event_name,
-      mojo_base.mojom.DeprecatedDictionaryValue filter,
+      mojo_base.mojom.DictionaryValue filter,
       bool add_lazy_listener);
 
   // Notifies the browser that the given extension added a listener for a
@@ -60,7 +60,7 @@
       string event_name,
       int64 service_worker_version_id,
       int32 worker_thread_id,
-      mojo_base.mojom.DeprecatedDictionaryValue filter,
+      mojo_base.mojom.DictionaryValue filter,
       bool add_lazy_listener);
 
   // Notifies the browser that the given |extension_id| or |listener_url|
@@ -97,7 +97,7 @@
   RemoveFilteredListenerForMainThread(
       EventListenerParam param,
       string event_name,
-      mojo_base.mojom.DeprecatedDictionaryValue filter,
+      mojo_base.mojom.DictionaryValue filter,
       bool remove_lazy_listener);
 
   // Notifies the browser that the given extension is no longer interested in
@@ -109,7 +109,7 @@
       string event_name,
       int64 service_worker_version_id,
       int32 worker_thread_id,
-      mojo_base.mojom.DeprecatedDictionaryValue filter,
+      mojo_base.mojom.DictionaryValue filter,
       bool remove_lazy_listener);
 
 };
diff --git a/extensions/renderer/bindings/api_binding_js_util.cc b/extensions/renderer/bindings/api_binding_js_util.cc
index 0768953d..7a68ed17 100644
--- a/extensions/renderer/bindings/api_binding_js_util.cc
+++ b/extensions/renderer/bindings/api_binding_js_util.cc
@@ -87,7 +87,6 @@
     options_dict.Get("customCallback", &custom_callback);
   }
 
-  std::unique_ptr<base::ListValue> converted_arguments;
   v8::Local<v8::Function> callback;
 
   // Some APIs (like fileSystem and contextMenus) don't provide arguments that
diff --git a/extensions/renderer/bindings/api_binding_unittest.cc b/extensions/renderer/bindings/api_binding_unittest.cc
index e308e6df..8e621cc 100644
--- a/extensions/renderer/bindings/api_binding_unittest.cc
+++ b/extensions/renderer/bindings/api_binding_unittest.cc
@@ -147,7 +147,7 @@
 
 void OnEventListenersChanged(const std::string& event_name,
                              binding::EventListenersChanged change,
-                             const base::DictionaryValue* filter,
+                             const base::Value::Dict* filter,
                              bool was_manual,
                              v8::Local<v8::Context> context) {}
 
@@ -1821,7 +1821,7 @@
          const APITypeReferenceMap& map) {
         handler->StartRequest(
             context, "test.handleAndSendRequest",
-            std::make_unique<base::ListValue>(),
+            std::make_unique<base::Value::List>(),
             binding::AsyncResponseType::kNone, v8::Local<v8::Function>(),
             v8::Local<v8::Function>(), binding::ResultModifierFunction());
         return RequestResult(RequestResult::HANDLED);
diff --git a/extensions/renderer/bindings/api_bindings_system_unittest.cc b/extensions/renderer/bindings/api_bindings_system_unittest.cc
index 5700227..b0fc25b 100644
--- a/extensions/renderer/bindings/api_bindings_system_unittest.cc
+++ b/extensions/renderer/bindings/api_bindings_system_unittest.cc
@@ -8,7 +8,6 @@
 #include "base/callback_helpers.h"
 #include "base/containers/contains.h"
 #include "base/strings/stringprintf.h"
-#include "base/values.h"
 #include "extensions/common/mojom/event_dispatcher.mojom.h"
 #include "extensions/renderer/bindings/api_binding.h"
 #include "extensions/renderer/bindings/api_binding_hooks.h"
@@ -208,7 +207,7 @@
 void APIBindingsSystemTest::OnEventListenersChanged(
     const std::string& event_name,
     binding::EventListenersChanged changed,
-    const base::DictionaryValue* filter,
+    const base::Value::Dict* filter,
     bool was_manual,
     v8::Local<v8::Context> context) {}
 
diff --git a/extensions/renderer/bindings/api_bindings_system_unittest.h b/extensions/renderer/bindings/api_bindings_system_unittest.h
index fe97732..b5da9637 100644
--- a/extensions/renderer/bindings/api_bindings_system_unittest.h
+++ b/extensions/renderer/bindings/api_bindings_system_unittest.h
@@ -9,15 +9,12 @@
 #include <memory>
 #include <string>
 
+#include "base/values.h"
 #include "extensions/renderer/bindings/api_binding_test.h"
 #include "extensions/renderer/bindings/api_binding_types.h"
 #include "extensions/renderer/bindings/api_request_handler.h"
 #include "v8/include/v8.h"
 
-namespace base {
-class DictionaryValue;
-}
-
 namespace extensions {
 class APIBindingsSystem;
 
@@ -60,14 +57,14 @@
   void AddConsoleError(v8::Local<v8::Context> context,
                        const std::string& error);
 
-  // Returns the DictionaryValue representing the schema with the given API
+  // Returns the base::Value::Dict representing the schema with the given API
   // name.
   const base::Value::Dict& GetAPISchema(const std::string& api_name);
 
   // Callback for event listeners changing.
   void OnEventListenersChanged(const std::string& event_name,
                                binding::EventListenersChanged changed,
-                               const base::DictionaryValue* filter,
+                               const base::Value::Dict* filter,
                                bool was_manual,
                                v8::Local<v8::Context> context);
 
diff --git a/extensions/renderer/bindings/api_event_handler_unittest.cc b/extensions/renderer/bindings/api_event_handler_unittest.cc
index 5c923baf..446b4ad 100644
--- a/extensions/renderer/bindings/api_event_handler_unittest.cc
+++ b/extensions/renderer/bindings/api_event_handler_unittest.cc
@@ -910,10 +910,10 @@
   v8::HandleScope handle_scope(isolate());
   v8::Local<v8::Context> context = MainContext();
 
-  auto fail_on_notified =
-      [](const std::string& event_name, binding::EventListenersChanged changed,
-         const base::DictionaryValue* filter, bool was_manual,
-         v8::Local<v8::Context> context) { ADD_FAILURE(); };
+  auto fail_on_notified = [](const std::string& event_name,
+                             binding::EventListenersChanged changed,
+                             const base::Value::Dict* filter, bool was_manual,
+                             v8::Local<v8::Context> context) { ADD_FAILURE(); };
 
   APIEventHandler handler(base::BindRepeating(fail_on_notified),
                           base::BindRepeating(&GetContextOwner), nullptr);
diff --git a/extensions/renderer/bindings/api_event_listeners.cc b/extensions/renderer/bindings/api_event_listeners.cc
index bc51084..8a1ea84 100644
--- a/extensions/renderer/bindings/api_event_listeners.cc
+++ b/extensions/renderer/bindings/api_event_listeners.cc
@@ -26,19 +26,19 @@
 const char kErrorTooManyListeners[] = "Too many listeners.";
 
 // Pseudo-validates the given |filter| and converts it into a
-// base::DictionaryValue. Returns true on success.
+// base::Value::Dict. Returns true on success.
 // TODO(devlin): This "validation" is pretty terrible. It matches the JS
 // equivalent, but it's lousy and makes it easy for users to get it wrong.
 // We should generate an argument spec for it and match it exactly.
 bool ValidateFilter(v8::Local<v8::Context> context,
                     v8::Local<v8::Object> filter,
-                    std::unique_ptr<base::DictionaryValue>* filter_dict,
+                    std::unique_ptr<base::Value::Dict>* filter_dict,
                     std::string* error) {
   v8::Isolate* isolate = context->GetIsolate();
   v8::HandleScope handle_scope(isolate);
 
   if (filter.IsEmpty()) {
-    *filter_dict = std::make_unique<base::DictionaryValue>();
+    *filter_dict = std::make_unique<base::Value::Dict>();
     return true;
   }
 
@@ -71,7 +71,7 @@
     return false;
   }
 
-  *filter_dict = base::DictionaryValue::From(std::move(value));
+  *filter_dict = std::make_unique<base::Value::Dict>(value->GetDict().Clone());
   return true;
 }
 
@@ -258,11 +258,11 @@
     return false;
   }
 
-  std::unique_ptr<base::DictionaryValue> filter_dict;
+  std::unique_ptr<base::Value::Dict> filter_dict;
   if (!ValidateFilter(context, filter, &filter_dict, error))
     return false;
 
-  base::DictionaryValue* filter_weak = filter_dict.get();
+  base::Value::Dict* filter_weak = filter_dict.get();
   int filter_id = -1;
   bool was_first_of_kind = false;
   LazilySetContextOwner(context);
@@ -348,7 +348,7 @@
       << "The context owner must be instantiated if listeners were removed.";
 
   bool was_last_of_kind = false;
-  std::unique_ptr<base::DictionaryValue> filter;
+  std::unique_ptr<base::Value::Dict> filter;
   std::tie(was_last_of_kind, filter) =
       listener_tracker_->RemoveFilteredListener(context_owner_id_, event_name_,
                                                 listener.filter_id);
diff --git a/extensions/renderer/bindings/api_event_listeners.h b/extensions/renderer/bindings/api_event_listeners.h
index 851c3e8..910fbcc 100644
--- a/extensions/renderer/bindings/api_event_listeners.h
+++ b/extensions/renderer/bindings/api_event_listeners.h
@@ -9,14 +9,11 @@
 #include <vector>
 
 #include "base/callback.h"
+#include "base/values.h"
 #include "extensions/common/mojom/event_dispatcher.mojom-forward.h"
 #include "extensions/renderer/bindings/api_binding_types.h"
 #include "v8/include/v8.h"
 
-namespace base {
-class DictionaryValue;
-}
-
 namespace extensions {
 class ListenerTracker;
 
@@ -33,7 +30,7 @@
   using ListenersUpdated =
       base::RepeatingCallback<void(const std::string& event_name,
                                    binding::EventListenersChanged,
-                                   const base::DictionaryValue* filter,
+                                   const base::Value::Dict* filter,
                                    bool update_lazy_listeners,
                                    v8::Local<v8::Context> context)>;
 
diff --git a/extensions/renderer/bindings/api_request_handler.cc b/extensions/renderer/bindings/api_request_handler.cc
index a7afe4d..04de816 100644
--- a/extensions/renderer/bindings/api_request_handler.cc
+++ b/extensions/renderer/bindings/api_request_handler.cc
@@ -443,7 +443,7 @@
 v8::Local<v8::Promise> APIRequestHandler::StartRequest(
     v8::Local<v8::Context> context,
     const std::string& method,
-    std::unique_ptr<base::Value> arguments_list,
+    std::unique_ptr<base::Value::List> arguments_list,
     binding::AsyncResponseType async_type,
     v8::Local<v8::Function> callback,
     v8::Local<v8::Function> custom_callback,
diff --git a/extensions/renderer/bindings/api_request_handler.h b/extensions/renderer/bindings/api_request_handler.h
index 289c8e5..b200775 100644
--- a/extensions/renderer/bindings/api_request_handler.h
+++ b/extensions/renderer/bindings/api_request_handler.h
@@ -41,7 +41,7 @@
     std::string method_name;
     bool has_async_response_handler = false;
     bool has_user_gesture = false;
-    std::unique_ptr<base::Value> arguments_list;
+    std::unique_ptr<base::Value::List> arguments_list;
   };
 
   // Details about a newly-added request to provide as a return to callers.
@@ -75,7 +75,7 @@
   v8::Local<v8::Promise> StartRequest(
       v8::Local<v8::Context> context,
       const std::string& method,
-      std::unique_ptr<base::Value> arguments_list,
+      std::unique_ptr<base::Value::List> arguments_list,
       binding::AsyncResponseType async_type,
       v8::Local<v8::Function> callback,
       v8::Local<v8::Function> custom_callback,
diff --git a/extensions/renderer/bindings/api_request_handler_unittest.cc b/extensions/renderer/bindings/api_request_handler_unittest.cc
index 4f81574..233a6aa 100644
--- a/extensions/renderer/bindings/api_request_handler_unittest.cc
+++ b/extensions/renderer/bindings/api_request_handler_unittest.cc
@@ -104,7 +104,7 @@
   ASSERT_FALSE(function.IsEmpty());
 
   request_handler->StartRequest(
-      context, kMethod, std::make_unique<base::ListValue>(),
+      context, kMethod, std::make_unique<base::Value::List>(),
       binding::AsyncResponseType::kCallback, function,
       v8::Local<v8::Function>(), binding::ResultModifierFunction());
   int request_id = request_handler->last_sent_request_id();
@@ -122,7 +122,7 @@
   EXPECT_TRUE(request_handler->GetPendingRequestIdsForTesting().empty());
 
   request_handler->StartRequest(
-      context, kMethod, std::make_unique<base::ListValue>(),
+      context, kMethod, std::make_unique<base::Value::List>(),
       binding::AsyncResponseType::kNone, v8::Local<v8::Function>(),
       v8::Local<v8::Function>(), binding::ResultModifierFunction());
   request_id = request_handler->last_sent_request_id();
@@ -142,7 +142,7 @@
   ASSERT_FALSE(function.IsEmpty());
 
   request_handler->StartRequest(
-      context, kMethod, std::make_unique<base::ListValue>(),
+      context, kMethod, std::make_unique<base::Value::List>(),
       binding::AsyncResponseType::kCallback, function,
       v8::Local<v8::Function>(), binding::ResultModifierFunction());
   int request_id = request_handler->last_sent_request_id();
@@ -178,12 +178,12 @@
       context_b, "(function(res) { this.result = res + 'beta'; })");
 
   request_handler->StartRequest(
-      context_a, kMethod, std::make_unique<base::ListValue>(),
+      context_a, kMethod, std::make_unique<base::Value::List>(),
       binding::AsyncResponseType::kCallback, function_a,
       v8::Local<v8::Function>(), binding::ResultModifierFunction());
   int request_a = request_handler->last_sent_request_id();
   request_handler->StartRequest(
-      context_b, kMethod, std::make_unique<base::ListValue>(),
+      context_b, kMethod, std::make_unique<base::Value::List>(),
       binding::AsyncResponseType::kCallback, function_b,
       v8::Local<v8::Function>(), binding::ResultModifierFunction());
   int request_b = request_handler->last_sent_request_id();
@@ -224,7 +224,7 @@
   ASSERT_FALSE(custom_callback.IsEmpty());
 
   request_handler->StartRequest(
-      context, "method", std::make_unique<base::ListValue>(),
+      context, "method", std::make_unique<base::Value::List>(),
       binding::AsyncResponseType::kCallback, callback, custom_callback,
       binding::ResultModifierFunction());
   int request_id = request_handler->last_sent_request_id();
@@ -297,7 +297,7 @@
   ASSERT_FALSE(custom_callback.IsEmpty());
 
   request_handler.StartRequest(
-      context, "method", std::make_unique<base::ListValue>(),
+      context, "method", std::make_unique<base::Value::List>(),
       binding::AsyncResponseType::kCallback, callback_throwing_error,
       custom_callback, binding::ResultModifierFunction());
   int request_id = request_handler.last_sent_request_id();
@@ -340,7 +340,7 @@
   ASSERT_FALSE(custom_callback.IsEmpty());
 
   v8::Local<v8::Promise> promise = request_handler->StartRequest(
-      context, "method", std::make_unique<base::ListValue>(),
+      context, "method", std::make_unique<base::Value::List>(),
       binding::AsyncResponseType::kPromise, v8::Local<v8::Function>(),
       custom_callback, binding::ResultModifierFunction());
   ASSERT_FALSE(promise.IsEmpty());
@@ -391,7 +391,7 @@
 
   v8::Local<v8::Function> empty_callback;
   request_handler->StartRequest(
-      context, "method", std::make_unique<base::ListValue>(),
+      context, "method", std::make_unique<base::Value::List>(),
       binding::AsyncResponseType::kNone, empty_callback, custom_callback,
       binding::ResultModifierFunction());
   int request_id = request_handler->last_sent_request_id();
@@ -445,7 +445,7 @@
   ASSERT_FALSE(callback.IsEmpty());
 
   request_handler->StartRequest(
-      context, "method", std::make_unique<base::ListValue>(),
+      context, "method", std::make_unique<base::Value::List>(),
       binding::AsyncResponseType::kCallback, callback,
       v8::Local<v8::Function>(), std::move(result_modifier));
   int request_id = request_handler->last_sent_request_id();
@@ -486,7 +486,7 @@
 
   // Try first without a user gesture.
   request_handler->StartRequest(
-      context, kMethod, std::make_unique<base::ListValue>(),
+      context, kMethod, std::make_unique<base::Value::List>(),
       binding::AsyncResponseType::kCallback, v8_callback,
       v8::Local<v8::Function>(), binding::ResultModifierFunction());
   int request_id = request_handler->last_sent_request_id();
@@ -508,7 +508,7 @@
   EXPECT_TRUE(interaction_provider()->HasActiveInteraction(context));
 
   request_handler->StartRequest(
-      context, kMethod, std::make_unique<base::ListValue>(),
+      context, kMethod, std::make_unique<base::Value::List>(),
       binding::AsyncResponseType::kCallback, v8_callback,
       v8::Local<v8::Function>(), binding::ResultModifierFunction());
   request_id = request_handler->last_sent_request_id();
@@ -557,7 +557,7 @@
     v8::Local<v8::Function> callback =
         FunctionFromString(context, kReportExposedLastError);
     request_handler.StartRequest(
-        context, kMethod, std::make_unique<base::ListValue>(),
+        context, kMethod, std::make_unique<base::Value::List>(),
         binding::AsyncResponseType::kCallback, callback,
         v8::Local<v8::Function>(), binding::ResultModifierFunction());
     int request_id = request_handler.last_sent_request_id();
@@ -575,7 +575,7 @@
     v8::Local<v8::Function> callback =
         FunctionFromString(context, kReportExposedLastError);
     request_handler.StartRequest(
-        context, kMethod, std::make_unique<base::ListValue>(),
+        context, kMethod, std::make_unique<base::Value::List>(),
         binding::AsyncResponseType::kCallback, callback,
         v8::Local<v8::Function>(), binding::ResultModifierFunction());
     int request_id = request_handler.last_sent_request_id();
@@ -592,7 +592,7 @@
     v8::Local<v8::Function> callback =
         FunctionFromString(context, "(function() {})");
     request_handler.StartRequest(
-        context, kMethod, std::make_unique<base::ListValue>(),
+        context, kMethod, std::make_unique<base::Value::List>(),
         binding::AsyncResponseType::kCallback, callback,
         v8::Local<v8::Function>(), binding::ResultModifierFunction());
     int request_id = request_handler.last_sent_request_id();
@@ -609,7 +609,7 @@
     v8::Local<v8::Function> custom_callback =
         FunctionFromString(context, "(function() {})");
     request_handler.StartRequest(
-        context, kMethod, std::make_unique<base::ListValue>(),
+        context, kMethod, std::make_unique<base::Value::List>(),
         binding::AsyncResponseType::kNone, v8::Local<v8::Function>(),
         custom_callback, binding::ResultModifierFunction());
     int request_id = request_handler.last_sent_request_id();
@@ -624,7 +624,7 @@
     // Test a function call resulting in an error that does not have an
     // associated callback callback. The error should be logged.
     request_handler.StartRequest(
-        context, kMethod, std::make_unique<base::ListValue>(),
+        context, kMethod, std::make_unique<base::Value::List>(),
         binding::AsyncResponseType::kNone, v8::Local<v8::Function>(),
         v8::Local<v8::Function>(), binding::ResultModifierFunction());
     int request_id = request_handler.last_sent_request_id();
@@ -652,7 +652,7 @@
     v8::Local<v8::Function> callback =
         FunctionFromString(context, kReportExposedLastError);
     request_handler.StartRequest(
-        context, kMethod, std::make_unique<base::ListValue>(),
+        context, kMethod, std::make_unique<base::Value::List>(),
         binding::AsyncResponseType::kCallback, callback,
         v8::Local<v8::Function>(), base::BindLambdaForTesting(result_modifier));
     int request_id = request_handler.last_sent_request_id();
@@ -842,7 +842,7 @@
   EXPECT_TRUE(request_handler->GetPendingRequestIdsForTesting().empty());
 
   v8::Local<v8::Promise> promise = request_handler->StartRequest(
-      context, kMethod, std::make_unique<base::ListValue>(),
+      context, kMethod, std::make_unique<base::Value::List>(),
       binding::AsyncResponseType::kPromise, v8::Local<v8::Function>(),
       v8::Local<v8::Function>(), binding::ResultModifierFunction());
   ASSERT_FALSE(promise.IsEmpty());
@@ -872,7 +872,7 @@
   EXPECT_TRUE(request_handler->GetPendingRequestIdsForTesting().empty());
 
   v8::Local<v8::Promise> promise = request_handler->StartRequest(
-      context, kMethod, std::make_unique<base::ListValue>(),
+      context, kMethod, std::make_unique<base::Value::List>(),
       binding::AsyncResponseType::kPromise, v8::Local<v8::Function>(),
       v8::Local<v8::Function>(), binding::ResultModifierFunction());
   ASSERT_FALSE(promise.IsEmpty());
diff --git a/extensions/renderer/bindings/api_signature.cc b/extensions/renderer/bindings/api_signature.cc
index 92a66c2..4a44a59c2 100644
--- a/extensions/renderer/bindings/api_signature.cc
+++ b/extensions/renderer/bindings/api_signature.cc
@@ -441,7 +441,7 @@
     result.error = TakeError();
   } else {
     result.arguments_list =
-        std::make_unique<base::Value>(std::move(list_value_));
+        std::make_unique<base::Value::List>(std::move(list_value_));
     result.callback = callback_;
     result.async_type = async_type();
   }
@@ -662,7 +662,7 @@
     json.Append(base::Value::FromUniquePtrValue(std::move(converted)));
   }
 
-  result.arguments_list = std::make_unique<base::Value>(std::move(json));
+  result.arguments_list = std::make_unique<base::Value::List>(std::move(json));
   return result;
 }
 
diff --git a/extensions/renderer/bindings/api_signature.h b/extensions/renderer/bindings/api_signature.h
index 2cc38f7..af09d98 100644
--- a/extensions/renderer/bindings/api_signature.h
+++ b/extensions/renderer/bindings/api_signature.h
@@ -9,15 +9,12 @@
 #include <string>
 #include <vector>
 
+#include "base/values.h"
 #include "extensions/renderer/bindings/api_binding_types.h"
 #include "extensions/renderer/bindings/binding_access_checker.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "v8/include/v8.h"
 
-namespace base {
-class Value;
-}
-
 namespace extensions {
 class APITypeReferenceMap;
 class ArgumentSpec;
@@ -108,7 +105,7 @@
     // The parsed JSON arguments, with null-filled optional arguments filled in.
     // Populated if parsing was successful. Does not include the callback (if
     // any).
-    std::unique_ptr<base::Value> arguments_list;
+    std::unique_ptr<base::Value::List> arguments_list;
 
     // The callback, if one was provided.
     v8::Local<v8::Function> callback;
diff --git a/extensions/renderer/bindings/api_signature_unittest.cc b/extensions/renderer/bindings/api_signature_unittest.cc
index 91c9a8e..3a302951 100644
--- a/extensions/renderer/bindings/api_signature_unittest.cc
+++ b/extensions/renderer/bindings/api_signature_unittest.cc
@@ -531,7 +531,6 @@
     std::vector<v8::Local<v8::Value>> v8_args =
         StringToV8Vector(context, "[1, null]");
     v8::Local<v8::Function> callback;
-    std::unique_ptr<base::ListValue> parsed;
     APISignature::JSONParseResult parse_result =
         signature->ConvertArgumentsIgnoringSchema(context, v8_args);
     EXPECT_FALSE(parse_result.error);
@@ -627,7 +626,6 @@
     std::vector<v8::Local<v8::Value>> v8_args =
         StringToV8Vector(context, "[1, null]");
     v8::Local<v8::Function> callback;
-    std::unique_ptr<base::ListValue> parsed;
     APISignature::JSONParseResult parse_result =
         int_and_optional_callback->ConvertArgumentsIgnoringSchema(context,
                                                                   v8_args);
@@ -661,7 +659,6 @@
     std::vector<v8::Local<v8::Value>> v8_args =
         StringToV8Vector(context, "[1, null]");
     v8::Local<v8::Function> callback;
-    std::unique_ptr<base::ListValue> parsed;
     APISignature::JSONParseResult parse_result =
         int_and_optional_callback->ConvertArgumentsIgnoringSchema(context,
                                                                   v8_args);
diff --git a/extensions/renderer/bindings/listener_tracker.cc b/extensions/renderer/bindings/listener_tracker.cc
index 097e8e1..e7d703b 100644
--- a/extensions/renderer/bindings/listener_tracker.cc
+++ b/extensions/renderer/bindings/listener_tracker.cc
@@ -5,7 +5,6 @@
 #include "extensions/renderer/bindings/listener_tracker.h"
 
 #include "base/check.h"
-#include "base/values.h"
 #include "extensions/common/mojom/event_dispatcher.mojom.h"
 #include "extensions/common/value_counter.h"
 
@@ -36,7 +35,7 @@
 std::pair<bool, int> ListenerTracker::AddFilteredListener(
     const std::string& context_owner_id,
     const std::string& event_name,
-    std::unique_ptr<base::DictionaryValue> filter,
+    std::unique_ptr<base::Value::Dict> filter,
     int routing_id) {
   int filter_id = event_filter_.AddEventMatcher(
       event_name,
@@ -50,26 +49,24 @@
     counts = std::make_unique<ValueCounter>();
 
   const EventMatcher* matcher = event_filter_.GetEventMatcher(filter_id);
-  bool was_first_of_kind = counts->Add(*matcher->value());
+  bool was_first_of_kind = counts->Add(base::Value(matcher->value()->Clone()));
   return std::make_pair(was_first_of_kind, filter_id);
 }
 
-std::pair<bool, std::unique_ptr<base::DictionaryValue>>
+std::pair<bool, std::unique_ptr<base::Value::Dict>>
 ListenerTracker::RemoveFilteredListener(const std::string& context_owner_id,
                                         const std::string& event_name,
                                         int filter_id) {
   EventMatcher* matcher = event_filter_.GetEventMatcher(filter_id);
   DCHECK(matcher);
-  std::unique_ptr<base::DictionaryValue> filter_copy =
-      base::DictionaryValue::From(
-          base::Value::ToUniquePtrValue(matcher->value()->Clone()));
 
   FilteredEventListenerKey key(context_owner_id, event_name);
   FilteredListeners::const_iterator counts = filtered_listeners_.find(key);
 
   bool was_last_of_kind = false;
   DCHECK(counts != filtered_listeners_.end());
-  if (counts->second->Remove(*matcher->value())) {
+  base::Value filter_copy = base::Value(matcher->value()->Clone());
+  if (counts->second->Remove(filter_copy)) {
     if (counts->second->is_empty()) {
       // Clean up if there are no more filters.
       filtered_listeners_.erase(counts);
@@ -78,7 +75,9 @@
   }
 
   event_filter_.RemoveEventMatcher(filter_id);
-  return std::make_pair(was_last_of_kind, std::move(filter_copy));
+  return std::make_pair(
+      was_last_of_kind,
+      std::make_unique<base::Value::Dict>(std::move(filter_copy).TakeDict()));
 }
 
 std::set<int> ListenerTracker::GetMatchingFilteredListeners(
diff --git a/extensions/renderer/bindings/listener_tracker.h b/extensions/renderer/bindings/listener_tracker.h
index 29e7c7a4..d6f4ec5 100644
--- a/extensions/renderer/bindings/listener_tracker.h
+++ b/extensions/renderer/bindings/listener_tracker.h
@@ -10,13 +10,10 @@
 #include <string>
 #include <utility>
 
+#include "base/values.h"
 #include "extensions/common/event_filter.h"
 #include "extensions/common/mojom/event_dispatcher.mojom-forward.h"
 
-namespace base {
-class DictionaryValue;
-}
-
 namespace extensions {
 class EventFilter;
 class ValueCounter;
@@ -68,7 +65,7 @@
   std::pair<bool, int> AddFilteredListener(
       const std::string& context_owner_id,
       const std::string& event_name,
-      std::unique_ptr<base::DictionaryValue> filter,
+      std::unique_ptr<base::Value::Dict> filter,
       int routing_id);
 
   // Removes a record of a filtered listener for the given |event_name|,
@@ -77,10 +74,10 @@
   // Returns a pair, with the bool indicating if this was the last listener
   // added for this event and |context_owner_id| with this specific filter, and
   // a copy of the filter value.
-  std::pair<bool, std::unique_ptr<base::DictionaryValue>>
-  RemoveFilteredListener(const std::string& context_owner_id,
-                         const std::string& event_name,
-                         int filter_id);
+  std::pair<bool, std::unique_ptr<base::Value::Dict>> RemoveFilteredListener(
+      const std::string& context_owner_id,
+      const std::string& event_name,
+      int filter_id);
 
   // Returns a set of filter IDs to that correspond to the given |event_name|,
   // |filter|, and |routing_id|.
diff --git a/extensions/renderer/bindings/listener_tracker_unittest.cc b/extensions/renderer/bindings/listener_tracker_unittest.cc
index 80480d8..8ef090d 100644
--- a/extensions/renderer/bindings/listener_tracker_unittest.cc
+++ b/extensions/renderer/bindings/listener_tracker_unittest.cc
@@ -43,27 +43,21 @@
 }
 
 TEST(ListenerTrackerTest, FilteredListenersWithMultipleFilters) {
-  std::unique_ptr<base::DictionaryValue> filter1 =
-      DeprecatedDictionaryValueFromString(
-          R"({"url": [{"hostSuffix": "example.com"}]})");
-  std::unique_ptr<base::DictionaryValue> filter2 =
-      DeprecatedDictionaryValueFromString(
-          R"({"url": [{"hostSuffix": "google.com"}]})");
+  base::Value::Dict filter1 =
+      DictValueFromString(R"({"url": [{"hostSuffix": "example.com"}]})");
+  base::Value::Dict filter2 =
+      DictValueFromString(R"({"url": [{"hostSuffix": "google.com"}]})");
 
   ListenerTracker tracker;
   auto [was_first_of_kind, filter_id1] = tracker.AddFilteredListener(
-      kOwner1, kEvent1,
-      base::DictionaryValue::From(
-          base::Value::ToUniquePtrValue(filter1->Clone())),
+      kOwner1, kEvent1, std::make_unique<base::Value::Dict>(filter1.Clone()),
       kRoutingId);
   EXPECT_TRUE(was_first_of_kind);
   EXPECT_NE(-1, filter_id1);
 
   int filter_id2 = -1;
   std::tie(was_first_of_kind, filter_id2) = tracker.AddFilteredListener(
-      kOwner1, kEvent1,
-      base::DictionaryValue::From(
-          base::Value::ToUniquePtrValue(filter1->Clone())),
+      kOwner1, kEvent1, std::make_unique<base::Value::Dict>(filter1.Clone()),
       kRoutingId);
   EXPECT_FALSE(was_first_of_kind);
   EXPECT_NE(-1, filter_id2);
@@ -71,9 +65,7 @@
 
   int filter_id3 = -1;
   std::tie(was_first_of_kind, filter_id3) = tracker.AddFilteredListener(
-      kOwner1, kEvent1,
-      base::DictionaryValue::From(
-          base::Value::ToUniquePtrValue(filter2->Clone())),
+      kOwner1, kEvent1, std::make_unique<base::Value::Dict>(filter2.Clone()),
       kRoutingId);
   EXPECT_TRUE(was_first_of_kind);
   EXPECT_NE(-1, filter_id3);
@@ -82,40 +74,35 @@
       tracker.RemoveFilteredListener(kOwner1, kEvent1, filter_id1);
   EXPECT_FALSE(was_last_of_kind);
   ASSERT_TRUE(removed_filter);
-  EXPECT_EQ(ValueToString(*removed_filter), ValueToString(*filter1));
+  EXPECT_EQ(ValueToString(*removed_filter), ValueToString(filter1));
 
   std::tie(was_last_of_kind, removed_filter) =
       tracker.RemoveFilteredListener(kOwner1, kEvent1, filter_id2);
   EXPECT_TRUE(was_last_of_kind);
   ASSERT_TRUE(removed_filter);
-  EXPECT_EQ(ValueToString(*removed_filter), ValueToString(*filter1));
+  EXPECT_EQ(ValueToString(*removed_filter), ValueToString(filter1));
 
   std::tie(was_last_of_kind, removed_filter) =
       tracker.RemoveFilteredListener(kOwner1, kEvent1, filter_id3);
   EXPECT_TRUE(was_last_of_kind);
   ASSERT_TRUE(removed_filter);
-  EXPECT_EQ(ValueToString(*removed_filter), ValueToString(*filter2));
+  EXPECT_EQ(ValueToString(*removed_filter), ValueToString(filter2));
 }
 
 TEST(ListenerTrackerTest, FilteredListenersWithMultipleOwners) {
-  std::unique_ptr<base::DictionaryValue> filter =
-      DeprecatedDictionaryValueFromString(
-          R"({"url": [{"hostSuffix": "example.com"}]})");
+  base::Value::Dict filter =
+      DictValueFromString(R"({"url": [{"hostSuffix": "example.com"}]})");
 
   ListenerTracker tracker;
   auto [was_first_of_kind, filter_id1] = tracker.AddFilteredListener(
-      kOwner1, kEvent1,
-      base::DictionaryValue::From(
-          base::Value::ToUniquePtrValue(filter->Clone())),
+      kOwner1, kEvent1, std::make_unique<base::Value::Dict>(filter.Clone()),
       kRoutingId);
   EXPECT_TRUE(was_first_of_kind);
   EXPECT_NE(-1, filter_id1);
 
   int filter_id2 = -1;
   std::tie(was_first_of_kind, filter_id2) = tracker.AddFilteredListener(
-      kOwner2, kEvent1,
-      base::DictionaryValue::From(
-          base::Value::ToUniquePtrValue(filter->Clone())),
+      kOwner2, kEvent1, std::make_unique<base::Value::Dict>(filter.Clone()),
       kRoutingId);
   EXPECT_TRUE(was_first_of_kind);
   EXPECT_NE(-1, filter_id2);
@@ -125,34 +112,29 @@
       tracker.RemoveFilteredListener(kOwner1, kEvent1, filter_id1);
   EXPECT_TRUE(was_last_of_kind);
   ASSERT_TRUE(removed_filter);
-  EXPECT_EQ(ValueToString(*removed_filter), ValueToString(*filter));
+  EXPECT_EQ(ValueToString(*removed_filter), ValueToString(filter));
 
   std::tie(was_last_of_kind, removed_filter) =
       tracker.RemoveFilteredListener(kOwner2, kEvent1, filter_id2);
   EXPECT_TRUE(was_last_of_kind);
   ASSERT_TRUE(removed_filter);
-  EXPECT_EQ(ValueToString(*removed_filter), ValueToString(*filter));
+  EXPECT_EQ(ValueToString(*removed_filter), ValueToString(filter));
 }
 
 TEST(ListenerTrackerTest, FilteredListenersWithMultipleEvents) {
-  std::unique_ptr<base::DictionaryValue> filter =
-      DeprecatedDictionaryValueFromString(
-          R"({"url": [{"hostSuffix": "example.com"}]})");
+  base::Value::Dict filter =
+      DictValueFromString(R"({"url": [{"hostSuffix": "example.com"}]})");
 
   ListenerTracker tracker;
   auto [was_first_of_kind, filter_id1] = tracker.AddFilteredListener(
-      kOwner1, kEvent1,
-      base::DictionaryValue::From(
-          base::Value::ToUniquePtrValue(filter->Clone())),
+      kOwner1, kEvent1, std::make_unique<base::Value::Dict>(filter.Clone()),
       kRoutingId);
   EXPECT_TRUE(was_first_of_kind);
   EXPECT_NE(-1, filter_id1);
 
   int filter_id2 = -1;
   std::tie(was_first_of_kind, filter_id2) = tracker.AddFilteredListener(
-      kOwner1, kEvent2,
-      base::DictionaryValue::From(
-          base::Value::ToUniquePtrValue(filter->Clone())),
+      kOwner1, kEvent2, std::make_unique<base::Value::Dict>(filter.Clone()),
       kRoutingId);
   EXPECT_TRUE(was_first_of_kind);
   EXPECT_NE(-1, filter_id2);
@@ -162,58 +144,50 @@
       tracker.RemoveFilteredListener(kOwner1, kEvent1, filter_id1);
   EXPECT_TRUE(was_last_of_kind);
   ASSERT_TRUE(removed_filter);
-  EXPECT_EQ(ValueToString(*removed_filter), ValueToString(*filter));
+  EXPECT_EQ(ValueToString(*removed_filter), ValueToString(filter));
 
   std::tie(was_last_of_kind, removed_filter) =
       tracker.RemoveFilteredListener(kOwner1, kEvent2, filter_id2);
   EXPECT_TRUE(was_last_of_kind);
   ASSERT_TRUE(removed_filter);
-  EXPECT_EQ(ValueToString(*removed_filter), ValueToString(*filter));
+  EXPECT_EQ(ValueToString(*removed_filter), ValueToString(filter));
 }
 
 TEST(ListenerTrackerTest, InvalidFilteredListener) {
   ListenerTracker tracker;
 
-  std::unique_ptr<base::DictionaryValue> filter =
-      DeprecatedDictionaryValueFromString(R"({"url": ["Not a dictionary"]})");
   auto [was_first_of_kind, filter_id] = tracker.AddFilteredListener(
-      kOwner1, kEvent1, std::move(filter), kRoutingId);
+      kOwner1, kEvent1,
+      std::make_unique<base::Value::Dict>(
+          DictValueFromString(R"({"url": ["Not a dictionary"]})")),
+      kRoutingId);
   EXPECT_EQ(-1, filter_id);
   EXPECT_FALSE(was_first_of_kind);
 }
 
 TEST(ListenerTrackerTest, GetMatchingFilters) {
-  std::unique_ptr<base::DictionaryValue> filter1 =
-      DeprecatedDictionaryValueFromString(
-          R"({"url": [{"hostSuffix": "example.com"}]})");
-  std::unique_ptr<base::DictionaryValue> filter2 =
-      DeprecatedDictionaryValueFromString(
-          R"({"url": [{"hostContains": "google"}]})");
-  std::unique_ptr<base::DictionaryValue> filter3 =
-      DeprecatedDictionaryValueFromString(
-          R"({"url": [{"hostContains": "example"}]})");
+  base::Value::Dict filter1 =
+      DictValueFromString(R"({"url": [{"hostSuffix": "example.com"}]})");
+  base::Value::Dict filter2 =
+      DictValueFromString(R"({"url": [{"hostContains": "google"}]})");
+  base::Value::Dict filter3 =
+      DictValueFromString(R"({"url": [{"hostContains": "example"}]})");
 
   ListenerTracker tracker;
   auto [was_first_of_kind, filter_id1] = tracker.AddFilteredListener(
-      kOwner1, kEvent1,
-      base::DictionaryValue::From(
-          base::Value::ToUniquePtrValue(filter1->Clone())),
+      kOwner1, kEvent1, std::make_unique<base::Value::Dict>(filter1.Clone()),
       kRoutingId);
   EXPECT_NE(-1, filter_id1);
 
   int filter_id2 = -1;
   std::tie(was_first_of_kind, filter_id2) = tracker.AddFilteredListener(
-      kOwner1, kEvent1,
-      base::DictionaryValue::From(
-          base::Value::ToUniquePtrValue(filter2->Clone())),
+      kOwner1, kEvent1, std::make_unique<base::Value::Dict>(filter2.Clone()),
       kRoutingId);
   EXPECT_NE(-1, filter_id2);
 
   int filter_id3 = -1;
   std::tie(was_first_of_kind, filter_id3) = tracker.AddFilteredListener(
-      kOwner2, kEvent1,
-      base::DictionaryValue::From(
-          base::Value::ToUniquePtrValue(filter3->Clone())),
+      kOwner2, kEvent1, std::make_unique<base::Value::Dict>(filter3.Clone()),
       kRoutingId);
   EXPECT_NE(-1, filter_id3);
 
diff --git a/extensions/renderer/chrome_setting.cc b/extensions/renderer/chrome_setting.cc
index bf285c6..85d7fd5 100644
--- a/extensions/renderer/chrome_setting.cc
+++ b/extensions/renderer/chrome_setting.cc
@@ -164,7 +164,6 @@
   if (!access_checker_->HasAccessOrThrowError(context, full_name))
     return;
 
-  std::unique_ptr<base::ListValue> converted_arguments;
   v8::Local<v8::Function> callback;
   std::string error;
   const APISignature* signature = type_refs_->GetTypeMethodSignature(full_name);
@@ -176,8 +175,8 @@
     return;
   }
 
-  parse_result.arguments_list->GetList().Insert(
-      parse_result.arguments_list->GetList().begin(), base::Value(pref_name_));
+  parse_result.arguments_list->Insert(parse_result.arguments_list->begin(),
+                                      base::Value(pref_name_));
 
   v8::Local<v8::Promise> promise = request_handler_->StartRequest(
       context, full_name, std::move(parse_result.arguments_list),
diff --git a/extensions/renderer/content_setting.cc b/extensions/renderer/content_setting.cc
index 21c2f0d..4e78bde 100644
--- a/extensions/renderer/content_setting.cc
+++ b/extensions/renderer/content_setting.cc
@@ -211,8 +211,8 @@
     }
   }
 
-  parse_result.arguments_list->GetList().Insert(
-      parse_result.arguments_list->GetList().begin(), base::Value(pref_name_));
+  parse_result.arguments_list->Insert(parse_result.arguments_list->begin(),
+                                      base::Value(pref_name_));
 
   v8::Local<v8::Promise> promise = request_handler_->StartRequest(
       context, "contentSettings." + method_name,
diff --git a/extensions/renderer/ipc_message_sender.cc b/extensions/renderer/ipc_message_sender.cc
index 6120aff..dde39ee37 100644
--- a/extensions/renderer/ipc_message_sender.cc
+++ b/extensions/renderer/ipc_message_sender.cc
@@ -110,7 +110,7 @@
 
   void SendAddFilteredEventListenerIPC(ScriptContext* context,
                                        const std::string& event_name,
-                                       const base::DictionaryValue& filter,
+                                       const base::Value::Dict& filter,
                                        bool is_lazy) override {
     DCHECK(!context->IsForServiceWorker());
     DCHECK_EQ(kMainThreadId, content::WorkerThread::GetCurrentId());
@@ -121,7 +121,7 @@
 
   void SendRemoveFilteredEventListenerIPC(ScriptContext* context,
                                           const std::string& event_name,
-                                          const base::DictionaryValue& filter,
+                                          const base::Value::Dict& filter,
                                           bool remove_lazy_listener) override {
     DCHECK(!context->IsForServiceWorker());
     DCHECK_EQ(kMainThreadId, content::WorkerThread::GetCurrentId());
@@ -339,7 +339,7 @@
 
   void SendAddFilteredEventListenerIPC(ScriptContext* context,
                                        const std::string& event_name,
-                                       const base::DictionaryValue& filter,
+                                       const base::Value::Dict& filter,
                                        bool is_lazy) override {
     DCHECK(context->IsForServiceWorker());
     DCHECK_NE(kMainThreadId, content::WorkerThread::GetCurrentId());
@@ -354,7 +354,7 @@
 
   void SendRemoveFilteredEventListenerIPC(ScriptContext* context,
                                           const std::string& event_name,
-                                          const base::DictionaryValue& filter,
+                                          const base::Value::Dict& filter,
                                           bool remove_lazy_listener) override {
     DCHECK(context->IsForServiceWorker());
     DCHECK_NE(kMainThreadId, content::WorkerThread::GetCurrentId());
diff --git a/extensions/renderer/ipc_message_sender.h b/extensions/renderer/ipc_message_sender.h
index 1ead29c..aead625c4 100644
--- a/extensions/renderer/ipc_message_sender.h
+++ b/extensions/renderer/ipc_message_sender.h
@@ -8,16 +8,13 @@
 #include <memory>
 #include <string>
 
+#include "base/values.h"
 #include "extensions/common/extension_id.h"
 #include "extensions/common/mojom/frame.mojom-forward.h"
 #include "extensions/renderer/bindings/api_binding_types.h"
 
 struct ExtensionHostMsg_APIActionOrEvent_Params;
 
-namespace base {
-class DictionaryValue;
-}
-
 namespace extensions {
 class ScriptContext;
 class WorkerThreadDispatcher;
@@ -62,15 +59,14 @@
       const std::string& event_name) = 0;
 
   // Sends a message to add/remove a filtered listener.
-  virtual void SendAddFilteredEventListenerIPC(
-      ScriptContext* context,
-      const std::string& event_name,
-      const base::DictionaryValue& filter,
-      bool is_lazy) = 0;
+  virtual void SendAddFilteredEventListenerIPC(ScriptContext* context,
+                                               const std::string& event_name,
+                                               const base::Value::Dict& filter,
+                                               bool is_lazy) = 0;
   virtual void SendRemoveFilteredEventListenerIPC(
       ScriptContext* context,
       const std::string& event_name,
-      const base::DictionaryValue& filter,
+      const base::Value::Dict& filter,
       bool remove_lazy_listener) = 0;
 
   // Opens a message channel to the specified target.
diff --git a/extensions/renderer/native_extension_bindings_system.cc b/extensions/renderer/native_extension_bindings_system.cc
index 5cb06cf..cb105b2 100644
--- a/extensions/renderer/native_extension_bindings_system.cc
+++ b/extensions/renderer/native_extension_bindings_system.cc
@@ -850,8 +850,7 @@
 
   auto params = mojom::RequestParams::New();
   params->name = request->method_name;
-  base::Value::List args = std::move(*request->arguments_list).TakeList();
-  params->arguments = std::move(args);
+  params->arguments = std::move(*request->arguments_list);
   params->extension_id = script_context->GetExtensionID();
   params->source_url = url;
   params->request_id = request->request_id;
@@ -868,7 +867,7 @@
 void NativeExtensionBindingsSystem::OnEventListenerChanged(
     const std::string& event_name,
     binding::EventListenersChanged change,
-    const base::DictionaryValue* filter,
+    const base::Value::Dict* filter,
     bool update_lazy_listeners,
     v8::Local<v8::Context> context) {
   ScriptContext* script_context = GetScriptContextFromV8ContextChecked(context);
diff --git a/extensions/renderer/native_extension_bindings_system.h b/extensions/renderer/native_extension_bindings_system.h
index b0cb485..31785e4 100644
--- a/extensions/renderer/native_extension_bindings_system.h
+++ b/extensions/renderer/native_extension_bindings_system.h
@@ -9,6 +9,7 @@
 #include <string>
 
 #include "base/memory/weak_ptr.h"
+#include "base/values.h"
 #include "extensions/common/mojom/event_dispatcher.mojom-forward.h"
 #include "extensions/renderer/api/messaging/native_renderer_messaging_service.h"
 #include "extensions/renderer/bindings/api_binding_types.h"
@@ -108,7 +109,7 @@
   // to |send_event_listener_ipc_|.
   void OnEventListenerChanged(const std::string& event_name,
                               binding::EventListenersChanged change,
-                              const base::DictionaryValue* filter,
+                              const base::Value::Dict* filter,
                               bool was_manual,
                               v8::Local<v8::Context> context);
 
diff --git a/extensions/renderer/native_extension_bindings_system_test_base.h b/extensions/renderer/native_extension_bindings_system_test_base.h
index f7e6718..ea02577 100644
--- a/extensions/renderer/native_extension_bindings_system_test_base.h
+++ b/extensions/renderer/native_extension_bindings_system_test_base.h
@@ -8,6 +8,7 @@
 #include <memory>
 #include <string>
 
+#include "base/values.h"
 #include "extensions/common/api/messaging/message.h"
 #include "extensions/common/api/messaging/port_id.h"
 #include "extensions/common/extension.h"
@@ -26,10 +27,6 @@
 
 struct ExtensionHostMsg_APIActionOrEvent_Params;
 
-namespace base {
-class DictionaryValue;
-}
-
 namespace content {
 class MockRenderThread;
 }
@@ -74,12 +71,12 @@
   MOCK_METHOD4(SendAddFilteredEventListenerIPC,
                void(ScriptContext* context,
                     const std::string& event_name,
-                    const base::DictionaryValue& filter,
+                    const base::Value::Dict& filter,
                     bool is_lazy));
   MOCK_METHOD4(SendRemoveFilteredEventListenerIPC,
                void(ScriptContext* context,
                     const std::string& event_name,
-                    const base::DictionaryValue& filter,
+                    const base::Value::Dict& filter,
                     bool remove_lazy_listener));
 
   MOCK_METHOD4(SendOpenMessageChannel,
diff --git a/extensions/renderer/storage_area.cc b/extensions/renderer/storage_area.cc
index 4ec1187..d58db618 100644
--- a/extensions/renderer/storage_area.cc
+++ b/extensions/renderer/storage_area.cc
@@ -303,8 +303,8 @@
     return;
   }
 
-  parse_result.arguments_list->GetList().Insert(
-      parse_result.arguments_list->GetList().begin(), base::Value(name_));
+  parse_result.arguments_list->Insert(parse_result.arguments_list->begin(),
+                                      base::Value(name_));
 
   v8::Local<v8::Promise> promise = request_handler_->StartRequest(
       context, full_method_name, std::move(parse_result.arguments_list),
diff --git a/extensions/renderer/worker_thread_dispatcher.cc b/extensions/renderer/worker_thread_dispatcher.cc
index 4c99193..f7c10bb4 100644
--- a/extensions/renderer/worker_thread_dispatcher.cc
+++ b/extensions/renderer/worker_thread_dispatcher.cc
@@ -94,7 +94,7 @@
                                   const std::string& event_name,
                                   int64_t service_worker_version_id,
                                   int worker_thread_id,
-                                  base::Value filter,
+                                  base::Value::Dict filter,
                                   bool add_lazy_listener) {
   auto* dispatcher = WorkerThreadDispatcher::Get();
   dispatcher->GetEventRouterOnIO()->AddFilteredListenerForServiceWorker(
@@ -109,7 +109,7 @@
                                      const std::string& event_name,
                                      int64_t service_worker_version_id,
                                      int worker_thread_id,
-                                     base::Value filter,
+                                     base::Value::Dict filter,
                                      bool remove_lazy_listener) {
   auto* dispatcher = WorkerThreadDispatcher::Get();
   dispatcher->GetEventRouterOnIO()->RemoveFilteredListenerForServiceWorker(
@@ -256,7 +256,7 @@
     const std::string& event_name,
     int64_t service_worker_version_id,
     int worker_thread_id,
-    base::Value filter,
+    base::Value::Dict filter,
     bool add_lazy_listener) {
   io_task_runner_->PostTask(
       FROM_HERE,
@@ -292,7 +292,7 @@
     const std::string& event_name,
     int64_t service_worker_version_id,
     int worker_thread_id,
-    base::Value filter,
+    base::Value::Dict filter,
     bool remove_lazy_listener) {
   io_task_runner_->PostTask(
       FROM_HERE,
diff --git a/extensions/renderer/worker_thread_dispatcher.h b/extensions/renderer/worker_thread_dispatcher.h
index ec0ff819..46882b3 100644
--- a/extensions/renderer/worker_thread_dispatcher.h
+++ b/extensions/renderer/worker_thread_dispatcher.h
@@ -11,6 +11,7 @@
 
 #include "base/synchronization/lock.h"
 #include "base/threading/platform_thread.h"
+#include "base/values.h"
 #include "content/public/renderer/render_thread_observer.h"
 #include "content/public/renderer/worker_thread.h"
 #include "extensions/common/activation_sequence.h"
@@ -119,7 +120,7 @@
                                     const std::string& event_name,
                                     int64_t service_worker_version_id,
                                     int worker_thread_id,
-                                    base::Value filter,
+                                    base::Value::Dict filter,
                                     bool add_lazy_listener);
 
   // Posts mojom::EventRouter::RemoveListenerForServiceWorker to the IO thread
@@ -143,7 +144,7 @@
                                        const std::string& event_name,
                                        int64_t service_worker_version_id,
                                        int worker_thread_id,
-                                       base::Value filter,
+                                       base::Value::Dict filter,
                                        bool remove_lazy_listener);
 
   // NOTE: This must be called on the IO thread because it can call
diff --git a/gpu/command_buffer/client/webgpu_implementation.cc b/gpu/command_buffer/client/webgpu_implementation.cc
index 70a9ca3..8d8bbca 100644
--- a/gpu/command_buffer/client/webgpu_implementation.cc
+++ b/gpu/command_buffer/client/webgpu_implementation.cc
@@ -23,61 +23,60 @@
 namespace webgpu {
 
 #if BUILDFLAG(USE_DAWN)
-class DawnWireServices : public APIChannel {
- private:
-  friend class base::RefCounted<DawnWireServices>;
-  ~DawnWireServices() override { GetProcs().instanceRelease(wgpu_instance_); }
+DawnWireServices::~DawnWireServices() {
+  GetProcs().instanceRelease(wgpu_instance_);
+}
 
- public:
-  DawnWireServices(WebGPUImplementation* webgpu_implementation,
-                   WebGPUCmdHelper* helper,
-                   MappedMemoryManager* mapped_memory,
-                   std::unique_ptr<TransferBuffer> transfer_buffer)
-      : memory_transfer_service_(mapped_memory),
-        serializer_(webgpu_implementation,
-                    helper,
-                    &memory_transfer_service_,
-                    std::move(transfer_buffer)),
-        wire_client_(dawn::wire::WireClientDescriptor{
-            &serializer_,
-            &memory_transfer_service_,
-        }),
-        wgpu_instance_(wire_client_.ReserveInstance().instance) {
-    DCHECK(wgpu_instance_);
-  }
+DawnWireServices::DawnWireServices(
+    WebGPUImplementation* webgpu_implementation,
+    WebGPUCmdHelper* helper,
+    MappedMemoryManager* mapped_memory,
+    std::unique_ptr<TransferBuffer> transfer_buffer)
+    : memory_transfer_service_(mapped_memory),
+      serializer_(webgpu_implementation,
+                  helper,
+                  &memory_transfer_service_,
+                  std::move(transfer_buffer)),
+      wire_client_(dawn::wire::WireClientDescriptor{
+          &serializer_,
+          &memory_transfer_service_,
+      }),
+      wgpu_instance_(wire_client_.ReserveInstance().instance) {
+  DCHECK(wgpu_instance_);
+}
 
-  const DawnProcTable& GetProcs() const override {
-    return dawn::wire::client::GetProcs();
-  }
+const DawnProcTable& DawnWireServices::GetProcs() const {
+  return dawn::wire::client::GetProcs();
+}
 
-  WGPUInstance GetWGPUInstance() const override { return wgpu_instance_; }
+WGPUInstance DawnWireServices::GetWGPUInstance() const {
+  return wgpu_instance_;
+}
 
-  dawn::wire::WireClient* wire_client() { return &wire_client_; }
-  DawnClientSerializer* serializer() { return &serializer_; }
-  DawnClientMemoryTransferService* memory_transfer_service() {
-    return &memory_transfer_service_;
-  }
+dawn::wire::WireClient* DawnWireServices::wire_client() {
+  return &wire_client_;
+}
+DawnClientSerializer* DawnWireServices::serializer() {
+  return &serializer_;
+}
+DawnClientMemoryTransferService* DawnWireServices::memory_transfer_service() {
+  return &memory_transfer_service_;
+}
 
-  void Disconnect() override {
-    disconnected_ = true;
-    wire_client_.Disconnect();
-    serializer_.Disconnect();
-    memory_transfer_service_.Disconnect();
-  }
+void DawnWireServices::Disconnect() {
+  disconnected_ = true;
+  wire_client_.Disconnect();
+  serializer_.Disconnect();
+  memory_transfer_service_.Disconnect();
+}
 
-  bool IsDisconnected() const { return disconnected_; }
+bool DawnWireServices::IsDisconnected() const {
+  return disconnected_;
+}
 
-  void FreeMappedResources(WebGPUCmdHelper* helper) {
-    memory_transfer_service_.FreeHandles(helper);
-  }
-
- private:
-  bool disconnected_ = false;
-  DawnClientMemoryTransferService memory_transfer_service_;
-  DawnClientSerializer serializer_;
-  dawn::wire::WireClient wire_client_;
-  WGPUInstance wgpu_instance_;
-};
+void DawnWireServices::FreeMappedResources(WebGPUCmdHelper* helper) {
+  memory_transfer_service_.FreeHandles(helper);
+}
 #endif
 
 // Include the auto-generated part of this file. We split this because it means
diff --git a/gpu/command_buffer/client/webgpu_implementation.h b/gpu/command_buffer/client/webgpu_implementation.h
index 80f1e6b..b947f59a 100644
--- a/gpu/command_buffer/client/webgpu_implementation.h
+++ b/gpu/command_buffer/client/webgpu_implementation.h
@@ -6,12 +6,15 @@
 #define GPU_COMMAND_BUFFER_CLIENT_WEBGPU_IMPLEMENTATION_H_
 
 #include <dawn/webgpu.h>
+#include <dawn/wire/WireClient.h>
 
 #include <memory>
 #include <utility>
 #include <vector>
 
 #include "base/memory/raw_ptr.h"
+#include "gpu/command_buffer/client/dawn_client_memory_transfer_service.h"
+#include "gpu/command_buffer/client/dawn_client_serializer.h"
 #include "gpu/command_buffer/client/gpu_control_client.h"
 #include "gpu/command_buffer/client/implementation_base.h"
 #include "gpu/command_buffer/client/logging.h"
@@ -24,7 +27,40 @@
 namespace gpu {
 namespace webgpu {
 
-class DawnWireServices;
+#if BUILDFLAG(USE_DAWN)
+class DawnWireServices : public APIChannel {
+ private:
+  friend class base::RefCounted<DawnWireServices>;
+  ~DawnWireServices() override;
+
+ public:
+  DawnWireServices(WebGPUImplementation* webgpu_implementation,
+                   WebGPUCmdHelper* helper,
+                   MappedMemoryManager* mapped_memory,
+                   std::unique_ptr<TransferBuffer> transfer_buffer);
+
+  const DawnProcTable& GetProcs() const override;
+
+  WGPUInstance GetWGPUInstance() const override;
+
+  dawn::wire::WireClient* wire_client();
+  DawnClientSerializer* serializer();
+  DawnClientMemoryTransferService* memory_transfer_service();
+
+  void Disconnect() override;
+
+  bool IsDisconnected() const;
+
+  void FreeMappedResources(WebGPUCmdHelper* helper);
+
+ private:
+  bool disconnected_ = false;
+  DawnClientMemoryTransferService memory_transfer_service_;
+  DawnClientSerializer serializer_;
+  dawn::wire::WireClient wire_client_;
+  WGPUInstance wgpu_instance_;
+};
+#endif
 
 class WEBGPU_EXPORT WebGPUImplementation final : public WebGPUInterface,
                                                  public ImplementationBase {
diff --git a/gpu/command_buffer/service/webgpu_decoder_impl.cc b/gpu/command_buffer/service/webgpu_decoder_impl.cc
index 3a4557f7..1d40775 100644
--- a/gpu/command_buffer/service/webgpu_decoder_impl.cc
+++ b/gpu/command_buffer/service/webgpu_decoder_impl.cc
@@ -1540,7 +1540,12 @@
   dawn_instance_->DiscoverAdapters(&swiftShaderOptions);
 #endif  // BUILDFLAG(ENABLE_VULKAN)
 #else
-  dawn_instance_->DiscoverDefaultAdapters();
+  // Don't call DiscoverDefaultAdapters() in Compat mode. Some drivers (*stares
+  // at NVidia*) are not robust when an EGL context and a Vulkan device are
+  // created in the same process.
+  if (use_webgpu_adapter_ != WebGPUAdapterName::kCompat) {
+    dawn_instance_->DiscoverDefaultAdapters();
+  }
 #endif  // BUILDFLAG(IS_WIN)
 
   std::vector<dawn::native::Adapter> adapters = dawn_instance_->GetAdapters();
diff --git a/gpu/config/gpu_finch_features.cc b/gpu/config/gpu_finch_features.cc
index d2f24ba9..664d58fa 100644
--- a/gpu/config/gpu_finch_features.cc
+++ b/gpu/config/gpu_finch_features.cc
@@ -288,7 +288,8 @@
 const base::FeatureParam<std::string> kDrDcBlockListByDevice{
     &kEnableDrDc, "BlockListByDevice",
     "LF9810_2GB|amber|chopin|secret|a03|SO-51B|on7xelte|j7xelte|F41B|doha|"
-    "rk322x_box|a20s|HWMAR|HWSTK-HF|HWPOT-H"};
+    "rk322x_box|a20s|HWMAR|HWSTK-HF|HWPOT-H|b2q|channel|galahad|a32|ellis|"
+    "dandelion|tonga|RMX3231"};
 
 // crbug.com/1340059, crbug.com/1340064
 const base::FeatureParam<std::string> kDrDcBlockListByModel{
diff --git a/gpu/ipc/common/gpu_memory_buffer_support.cc b/gpu/ipc/common/gpu_memory_buffer_support.cc
index 64473239..2b757d7 100644
--- a/gpu/ipc/common/gpu_memory_buffer_support.cc
+++ b/gpu/ipc/common/gpu_memory_buffer_support.cc
@@ -77,6 +77,9 @@
              format == gfx::BufferFormat::BGRX_8888 ||
              format == gfx::BufferFormat::RGBX_8888 ||
              format == gfx::BufferFormat::R_8 ||
+             format == gfx::BufferFormat::RG_88 ||
+             format == gfx::BufferFormat::R_16 ||
+             format == gfx::BufferFormat::RG_1616 ||
              format == gfx::BufferFormat::RGBA_F16 ||
              format == gfx::BufferFormat::BGRA_1010102 ||
              format == gfx::BufferFormat::YUV_420_BIPLANAR ||
@@ -122,8 +125,7 @@
     case gfx::BufferUsage::GPU_READ:
     case gfx::BufferUsage::SCANOUT:
       return format == gfx::BufferFormat::RGBA_8888 ||
-             format == gfx::BufferFormat::RGBX_8888 ||
-             format == gfx::BufferFormat::YUV_420_BIPLANAR;
+             format == gfx::BufferFormat::RGBX_8888;
     case gfx::BufferUsage::SCANOUT_CPU_READ_WRITE:
     case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE:
     case gfx::BufferUsage::SCANOUT_VDA_WRITE:
diff --git "a/infra/config/generated/builders/ci/Android Release \050Nexus 5X\051/properties.json" "b/infra/config/generated/builders/ci/Android Release \050Nexus 5X\051/properties.json"
index f6b0445..22c603f 100644
--- "a/infra/config/generated/builders/ci/Android Release \050Nexus 5X\051/properties.json"
+++ "b/infra/config/generated/builders/ci/Android Release \050Nexus 5X\051/properties.json"
@@ -49,6 +49,10 @@
           "group": "tryserver.chromium.android"
         },
         {
+          "builder": "android-arm64-rel-inverse-fyi",
+          "group": "tryserver.chromium.android"
+        },
+        {
           "builder": "gpu-try-android-m-nexus-5x-64",
           "group": "tryserver.chromium.android"
         }
diff --git a/infra/config/generated/builders/ci/android-pie-arm64-rel/properties.json b/infra/config/generated/builders/ci/android-pie-arm64-rel/properties.json
index aee6a98..910378f 100644
--- a/infra/config/generated/builders/ci/android-pie-arm64-rel/properties.json
+++ b/infra/config/generated/builders/ci/android-pie-arm64-rel/properties.json
@@ -49,11 +49,7 @@
           "group": "tryserver.chromium.android"
         },
         {
-          "builder": "android-pie-arm64-rel",
-          "group": "tryserver.chromium.android"
-        },
-        {
-          "builder": "android-pie-arm64-rel-inverse-fyi",
+          "builder": "android-arm64-rel-inverse-fyi",
           "group": "tryserver.chromium.android"
         }
       ]
diff --git a/infra/config/generated/builders/try/android-pie-arm64-rel-inverse-fyi/properties.json b/infra/config/generated/builders/try/android-arm64-rel-inverse-fyi/properties.json
similarity index 60%
rename from infra/config/generated/builders/try/android-pie-arm64-rel-inverse-fyi/properties.json
rename to infra/config/generated/builders/try/android-arm64-rel-inverse-fyi/properties.json
index e5384ba..f49df3e 100644
--- a/infra/config/generated/builders/try/android-pie-arm64-rel-inverse-fyi/properties.json
+++ b/infra/config/generated/builders/try/android-arm64-rel-inverse-fyi/properties.json
@@ -1,6 +1,6 @@
 {
   "$build/chromium_orchestrator": {
-    "compilator": "android-pie-arm64-rel-compilator",
+    "compilator": "android-arm64-rel-compilator",
     "compilator_watcher_git_revision": "7809a690bbd935bcb3b4d922e24cabe168aaabc8"
   },
   "$build/chromium_tests_builder_config": {
@@ -10,6 +10,37 @@
           {
             "builder_id": {
               "bucket": "ci",
+              "builder": "Android Release (Nexus 5X)",
+              "project": "chromium"
+            },
+            "builder_spec": {
+              "build_gs_bucket": "chromium-gpu-archive",
+              "builder_group": "chromium.gpu",
+              "execution_mode": "COMPILE_AND_TEST",
+              "legacy_android_config": {
+                "config": "main_builder"
+              },
+              "legacy_chromium_config": {
+                "apply_configs": [
+                  "download_vr_test_apks",
+                  "mb"
+                ],
+                "build_config": "Release",
+                "config": "android",
+                "target_bits": 64,
+                "target_platform": "android"
+              },
+              "legacy_gclient_config": {
+                "apply_configs": [
+                  "android"
+                ],
+                "config": "chromium"
+              }
+            }
+          },
+          {
+            "builder_id": {
+              "bucket": "ci",
               "builder": "android-pie-arm64-rel",
               "project": "chromium"
             },
@@ -43,6 +74,11 @@
       "builder_ids": [
         {
           "bucket": "ci",
+          "builder": "Android Release (Nexus 5X)",
+          "project": "chromium"
+        },
+        {
+          "bucket": "ci",
           "builder": "android-pie-arm64-rel",
           "project": "chromium"
         }
diff --git a/infra/config/generated/builders/try/android-pie-arm64-rel-compilator/properties.json b/infra/config/generated/builders/try/android-pie-arm64-rel-compilator/properties.json
deleted file mode 100644
index 048533b5..0000000
--- a/infra/config/generated/builders/try/android-pie-arm64-rel-compilator/properties.json
+++ /dev/null
@@ -1,68 +0,0 @@
-{
-  "$build/chromium_tests_builder_config": {
-    "builder_config": {
-      "builder_db": {
-        "entries": [
-          {
-            "builder_id": {
-              "bucket": "ci",
-              "builder": "android-pie-arm64-rel",
-              "project": "chromium"
-            },
-            "builder_spec": {
-              "build_gs_bucket": "chromium-android-archive",
-              "builder_group": "chromium.android",
-              "execution_mode": "COMPILE_AND_TEST",
-              "legacy_android_config": {
-                "config": "main_builder"
-              },
-              "legacy_chromium_config": {
-                "apply_configs": [
-                  "download_vr_test_apks",
-                  "mb"
-                ],
-                "build_config": "Release",
-                "config": "android",
-                "target_bits": 64,
-                "target_platform": "android"
-              },
-              "legacy_gclient_config": {
-                "apply_configs": [
-                  "android"
-                ],
-                "config": "chromium"
-              }
-            }
-          }
-        ]
-      },
-      "builder_ids": [
-        {
-          "bucket": "ci",
-          "builder": "android-pie-arm64-rel",
-          "project": "chromium"
-        }
-      ],
-      "rts_config": {
-        "condition": "QUICK_RUN_ONLY"
-      }
-    }
-  },
-  "$build/flakiness": {
-    "check_for_flakiness": true
-  },
-  "$build/reclient": {
-    "instance": "rbe-chromium-untrusted",
-    "jobs": 300,
-    "metrics_project": "chromium-reclient-metrics"
-  },
-  "$recipe_engine/resultdb/test_presentation": {
-    "column_keys": [],
-    "grouping_keys": [
-      "status",
-      "v.test_suite"
-    ]
-  },
-  "builder_group": "tryserver.chromium.android",
-  "recipe": "chromium/compilator"
-}
\ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-pie-arm64-rel/properties.json b/infra/config/generated/builders/try/android-pie-arm64-rel/properties.json
deleted file mode 100644
index e5384ba..0000000
--- a/infra/config/generated/builders/try/android-pie-arm64-rel/properties.json
+++ /dev/null
@@ -1,67 +0,0 @@
-{
-  "$build/chromium_orchestrator": {
-    "compilator": "android-pie-arm64-rel-compilator",
-    "compilator_watcher_git_revision": "7809a690bbd935bcb3b4d922e24cabe168aaabc8"
-  },
-  "$build/chromium_tests_builder_config": {
-    "builder_config": {
-      "builder_db": {
-        "entries": [
-          {
-            "builder_id": {
-              "bucket": "ci",
-              "builder": "android-pie-arm64-rel",
-              "project": "chromium"
-            },
-            "builder_spec": {
-              "build_gs_bucket": "chromium-android-archive",
-              "builder_group": "chromium.android",
-              "execution_mode": "COMPILE_AND_TEST",
-              "legacy_android_config": {
-                "config": "main_builder"
-              },
-              "legacy_chromium_config": {
-                "apply_configs": [
-                  "download_vr_test_apks",
-                  "mb"
-                ],
-                "build_config": "Release",
-                "config": "android",
-                "target_bits": 64,
-                "target_platform": "android"
-              },
-              "legacy_gclient_config": {
-                "apply_configs": [
-                  "android"
-                ],
-                "config": "chromium"
-              }
-            }
-          }
-        ]
-      },
-      "builder_ids": [
-        {
-          "bucket": "ci",
-          "builder": "android-pie-arm64-rel",
-          "project": "chromium"
-        }
-      ],
-      "rts_config": {
-        "condition": "QUICK_RUN_ONLY"
-      }
-    }
-  },
-  "$build/flakiness": {
-    "check_for_flakiness": true
-  },
-  "$recipe_engine/resultdb/test_presentation": {
-    "column_keys": [],
-    "grouping_keys": [
-      "status",
-      "v.test_suite"
-    ]
-  },
-  "builder_group": "tryserver.chromium.android",
-  "recipe": "chromium/orchestrator"
-}
\ No newline at end of file
diff --git a/infra/config/generated/cq-builders.md b/infra/config/generated/cq-builders.md
index ade56e3..5081e99 100644
--- a/infra/config/generated/cq-builders.md
+++ b/infra/config/generated/cq-builders.md
@@ -480,7 +480,7 @@
   * [`//third_party/nearby/README.chromium`](https://cs.chromium.org/search?q=+file:third_party/nearby/README.chromium)
 
 * [linux-chromeos-compile-chrome](https://ci.chromium.org/p/chrome/builders/try/linux-chromeos-compile-chrome) ([definition](https://source.corp.google.com/search?q=+file:/try/.*\.star$+""linux-chromeos-compile-chrome""))
-  * Experiment percentage: 50.0
+  * Experiment percentage: 100.0
 
 * [android-12-x64-rel](https://ci.chromium.org/p/chromium/builders/try/android-12-x64-rel) ([definition](https://cs.chromium.org/search?q=+file:/try/.*\.star$+""android-12-x64-rel""))
   * Experiment percentage: 60.0
diff --git a/infra/config/generated/luci/commit-queue.cfg b/infra/config/generated/luci/commit-queue.cfg
index ffa9c72..90f69bc8 100644
--- a/infra/config/generated/luci/commit-queue.cfg
+++ b/infra/config/generated/luci/commit-queue.cfg
@@ -32,41 +32,48 @@
       builders {
         name: "chrome/try/android-internal-binary-size"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/android-internal-rel"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/chromeos-betty-chrome"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/chromeos-betty-pi-arc-chrome"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/chromeos-eve-chrome"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/chromeos-eve-compile-chrome"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/chromeos-jacuzzi-nearby-chrome-fyi"
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         experiment_percentage: 100
         location_filters {
           gerrit_host_regexp: ".*"
@@ -79,102 +86,119 @@
       builders {
         name: "chrome/try/chromeos-kevin-chrome"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/chromeos-kevin-compile-chrome"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/chromeos-octopus-chrome"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/chromeos-octopus-compile-chrome"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/chromeos-reven-chrome"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/fuchsia-fyi-astro"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/ipad-device"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/iphone-device"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/lacros-amd64-generic-chrome"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/lacros-amd64-generic-chrome-skylab"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/lacros-arm-generic-chrome"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/lacros-arm-generic-chrome-skylab"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/lacros-arm64-generic-chrome-skylab"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/linux-chrome"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/linux-chrome-stable"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/linux-chromeos-chrome"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/linux-chromeos-compile-chrome"
-        experiment_percentage: 50
+        result_visibility: COMMENT_LEVEL_RESTRICTED
+        experiment_percentage: 100
         location_filters {
           gerrit_host_regexp: ".*"
           gerrit_project_regexp: ".*"
@@ -191,78 +215,91 @@
       builders {
         name: "chrome/try/linux-nearby-chrome-fyi"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/linux-pgo"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/mac-arm-pgo"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/mac-chrome"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/mac-chrome-stable"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/mac-pgo"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/test-o-emulator"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/win-chrome"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/win-chrome-stable"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/win32-pgo"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/win64-chrome"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/win64-chrome-stable"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
       builders {
         name: "chrome/try/win64-pgo"
         includable_only: true
+        result_visibility: COMMENT_LEVEL_RESTRICTED
         owner_whitelist_group: "googlers"
         owner_whitelist_group: "project-chromium-robot-committers"
       }
@@ -401,6 +438,10 @@
         includable_only: true
       }
       builders {
+        name: "chromium/try/android-arm64-rel-inverse-fyi"
+        includable_only: true
+      }
+      builders {
         name: "chromium/try/android-asan"
         includable_only: true
       }
@@ -720,18 +761,6 @@
         }
       }
       builders {
-        name: "chromium/try/android-pie-arm64-rel"
-        includable_only: true
-      }
-      builders {
-        name: "chromium/try/android-pie-arm64-rel-compilator"
-        includable_only: true
-      }
-      builders {
-        name: "chromium/try/android-pie-arm64-rel-inverse-fyi"
-        includable_only: true
-      }
-      builders {
         name: "chromium/try/android-pie-arm64-wpt-rel-non-cq"
         includable_only: true
       }
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg
index e2b3adf..470e5eb 100644
--- a/infra/config/generated/luci/cr-buildbucket.cfg
+++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -56945,7 +56945,128 @@
           use_invocation_timestamp: true
         }
       }
-      description_html: "This is the compilator half of an orchestrator + compilator pair of builders. The orchestrator is <a href=\"https://ci.chromium.org/p/chromium/builders/try/android-arm64-rel\">android-arm64-rel</a>."
+      description_html: "This is the compilator half of an orchestrator + compilator pair of builders. The orchestrator is <a href=\"https://ci.chromium.org/p/chromium/builders/try/android-arm64-rel\">android-arm64-rel</a>.<br/>It is also the compilator for experimental orchestrator <a href=\"https://ci.chromium.org/p/chromium/builders/try/android-arm64-rel-inverse-fyi\">android-arm64-rel-inverse-fyi</a>."
+    }
+    builders {
+      name: "android-arm64-rel-inverse-fyi"
+      swarming_host: "chromium-swarm.appspot.com"
+      dimensions: "cores:4"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Ubuntu-18.04"
+      dimensions: "pool:luci.chromium.try.orchestrator"
+      exe {
+        cipd_package: "infra/chromium/bootstrapper/${platform}"
+        cipd_version: "latest"
+        cmd: "bootstrapper"
+      }
+      properties:
+        '{'
+        '  "$bootstrap/exe": {'
+        '    "exe": {'
+        '      "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",'
+        '      "cipd_version": "refs/heads/main",'
+        '      "cmd": ['
+        '        "luciexe"'
+        '      ]'
+        '    }'
+        '  },'
+        '  "$bootstrap/properties": {'
+        '    "properties_file": "infra/config/generated/builders/try/android-arm64-rel-inverse-fyi/properties.json",'
+        '    "top_level_project": {'
+        '      "ref": "refs/heads/main",'
+        '      "repo": {'
+        '        "host": "chromium.googlesource.com",'
+        '        "project": "chromium/src"'
+        '      }'
+        '    }'
+        '  },'
+        '  "builder_group": "tryserver.chromium.android",'
+        '  "led_builder_is_bootstrapped": true,'
+        '  "recipe": "chromium/orchestrator"'
+        '}'
+      execution_timeout_secs: 14400
+      expiration_secs: 7200
+      grace_period {
+        seconds: 120
+      }
+      caches {
+        name: "unused_builder_cache"
+        path: "builder"
+      }
+      caches {
+        name: "win_toolchain"
+        path: "win_toolchain"
+      }
+      build_numbers: YES
+      service_account: "chromium-orchestrator@chops-service-accounts.iam.gserviceaccount.com"
+      task_template_canary_percentage {
+        value: 5
+      }
+      experiments {
+        key: "chromium_rts.inverted_rts"
+        value: 100
+      }
+      experiments {
+        key: "chromium_rts.inverted_rts_bail_early"
+        value: 100
+      }
+      experiments {
+        key: "chromium_swarming.expose_merge_script_failures"
+        value: 100
+      }
+      experiments {
+        key: "enable_weetbix_queries"
+        value: 100
+      }
+      experiments {
+        key: "luci.buildbucket.omit_python2"
+        value: 100
+      }
+      experiments {
+        key: "luci.recipes.use_python3"
+        value: 100
+      }
+      experiments {
+        key: "weetbix.enable_weetbix_exonerations"
+        value: 100
+      }
+      experiments {
+        key: "weetbix.retry_weak_exonerations"
+        value: 100
+      }
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "try_test_results"
+          test_results {}
+        }
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "gpu_try_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+"
+            }
+          }
+        }
+        bq_exports {
+          project: "chrome-luci-data"
+          dataset: "chromium"
+          table: "blink_web_tests_try_test_results"
+          test_results {
+            predicate {
+              test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*blink_wpt_tests/.+)"
+            }
+          }
+        }
+        history_options {
+          use_invocation_timestamp: true
+        }
+      }
+      description_html: "This is an experimental orchestrator making use of compilator <a href=\"https://ci.chromium.org/p/chromium/builders/try/android-arm64-rel-compilator\">android-arm64-rel-compilator</a>."
     }
     builders {
       name: "android-asan"
@@ -60249,348 +60370,6 @@
       }
     }
     builders {
-      name: "android-pie-arm64-rel"
-      swarming_host: "chromium-swarm.appspot.com"
-      dimensions: "builder:android-pie-arm64-rel"
-      dimensions: "cores:4"
-      dimensions: "cpu:x86-64"
-      dimensions: "os:Ubuntu-18.04"
-      dimensions: "pool:luci.chromium.try"
-      exe {
-        cipd_package: "infra/chromium/bootstrapper/${platform}"
-        cipd_version: "latest"
-        cmd: "bootstrapper"
-      }
-      properties:
-        '{'
-        '  "$bootstrap/exe": {'
-        '    "exe": {'
-        '      "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",'
-        '      "cipd_version": "refs/heads/main",'
-        '      "cmd": ['
-        '        "luciexe"'
-        '      ]'
-        '    }'
-        '  },'
-        '  "$bootstrap/properties": {'
-        '    "properties_file": "infra/config/generated/builders/try/android-pie-arm64-rel/properties.json",'
-        '    "top_level_project": {'
-        '      "ref": "refs/heads/main",'
-        '      "repo": {'
-        '        "host": "chromium.googlesource.com",'
-        '        "project": "chromium/src"'
-        '      }'
-        '    }'
-        '  },'
-        '  "builder_group": "tryserver.chromium.android",'
-        '  "led_builder_is_bootstrapped": true,'
-        '  "recipe": "chromium/orchestrator"'
-        '}'
-      execution_timeout_secs: 14400
-      expiration_secs: 7200
-      grace_period {
-        seconds: 120
-      }
-      caches {
-        name: "win_toolchain"
-        path: "win_toolchain"
-      }
-      build_numbers: YES
-      service_account: "chromium-orchestrator@chops-service-accounts.iam.gserviceaccount.com"
-      task_template_canary_percentage {
-        value: 5
-      }
-      experiments {
-        key: "chromium_swarming.expose_merge_script_failures"
-        value: 100
-      }
-      experiments {
-        key: "enable_weetbix_queries"
-        value: 100
-      }
-      experiments {
-        key: "luci.buildbucket.omit_python2"
-        value: 100
-      }
-      experiments {
-        key: "luci.recipes.use_python3"
-        value: 100
-      }
-      experiments {
-        key: "weetbix.enable_weetbix_exonerations"
-        value: 100
-      }
-      experiments {
-        key: "weetbix.retry_weak_exonerations"
-        value: 100
-      }
-      resultdb {
-        enable: true
-        bq_exports {
-          project: "chrome-luci-data"
-          dataset: "chromium"
-          table: "try_test_results"
-          test_results {}
-        }
-        bq_exports {
-          project: "chrome-luci-data"
-          dataset: "chromium"
-          table: "gpu_try_test_results"
-          test_results {
-            predicate {
-              test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+"
-            }
-          }
-        }
-        bq_exports {
-          project: "chrome-luci-data"
-          dataset: "chromium"
-          table: "blink_web_tests_try_test_results"
-          test_results {
-            predicate {
-              test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*blink_wpt_tests/.+)"
-            }
-          }
-        }
-        history_options {
-          use_invocation_timestamp: true
-        }
-      }
-      description_html: "This is the orchestrator half of an orchestrator + compilator pair of builders. The compilator is <a href=\"https://ci.chromium.org/p/chromium/builders/try/android-pie-arm64-rel-compilator\">android-pie-arm64-rel-compilator</a>."
-    }
-    builders {
-      name: "android-pie-arm64-rel-compilator"
-      swarming_host: "chromium-swarm.appspot.com"
-      dimensions: "builder:android-pie-arm64-rel-compilator"
-      dimensions: "cores:16|32"
-      dimensions: "cpu:x86-64"
-      dimensions: "os:Ubuntu-18.04"
-      dimensions: "pool:luci.chromium.try"
-      dimensions: "ssd:1"
-      exe {
-        cipd_package: "infra/chromium/bootstrapper/${platform}"
-        cipd_version: "latest"
-        cmd: "bootstrapper"
-      }
-      properties:
-        '{'
-        '  "$bootstrap/exe": {'
-        '    "exe": {'
-        '      "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",'
-        '      "cipd_version": "refs/heads/main",'
-        '      "cmd": ['
-        '        "luciexe"'
-        '      ]'
-        '    }'
-        '  },'
-        '  "$bootstrap/properties": {'
-        '    "properties_file": "infra/config/generated/builders/try/android-pie-arm64-rel-compilator/properties.json",'
-        '    "top_level_project": {'
-        '      "ref": "refs/heads/main",'
-        '      "repo": {'
-        '        "host": "chromium.googlesource.com",'
-        '        "project": "chromium/src"'
-        '      }'
-        '    }'
-        '  },'
-        '  "builder_group": "tryserver.chromium.android",'
-        '  "led_builder_is_bootstrapped": true,'
-        '  "recipe": "chromium/compilator"'
-        '}'
-      execution_timeout_secs: 14400
-      expiration_secs: 7200
-      grace_period {
-        seconds: 120
-      }
-      caches {
-        name: "win_toolchain"
-        path: "win_toolchain"
-      }
-      build_numbers: YES
-      service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com"
-      task_template_canary_percentage {
-        value: 5
-      }
-      experiments {
-        key: "chromium_swarming.expose_merge_script_failures"
-        value: 100
-      }
-      experiments {
-        key: "enable_weetbix_queries"
-        value: 100
-      }
-      experiments {
-        key: "luci.buildbucket.omit_python2"
-        value: 100
-      }
-      experiments {
-        key: "luci.recipes.use_python3"
-        value: 100
-      }
-      experiments {
-        key: "weetbix.enable_weetbix_exonerations"
-        value: 100
-      }
-      experiments {
-        key: "weetbix.retry_weak_exonerations"
-        value: 100
-      }
-      resultdb {
-        enable: true
-        bq_exports {
-          project: "chrome-luci-data"
-          dataset: "chromium"
-          table: "try_test_results"
-          test_results {}
-        }
-        bq_exports {
-          project: "chrome-luci-data"
-          dataset: "chromium"
-          table: "gpu_try_test_results"
-          test_results {
-            predicate {
-              test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+"
-            }
-          }
-        }
-        bq_exports {
-          project: "chrome-luci-data"
-          dataset: "chromium"
-          table: "blink_web_tests_try_test_results"
-          test_results {
-            predicate {
-              test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*blink_wpt_tests/.+)"
-            }
-          }
-        }
-        history_options {
-          use_invocation_timestamp: true
-        }
-      }
-      description_html: "This is the compilator half of an orchestrator + compilator pair of builders. The orchestrator is <a href=\"https://ci.chromium.org/p/chromium/builders/try/android-pie-arm64-rel\">android-pie-arm64-rel</a>.<br/>It is also the compilator for experimental orchestrator <a href=\"https://ci.chromium.org/p/chromium/builders/try/android-pie-arm64-rel-inverse-fyi\">android-pie-arm64-rel-inverse-fyi</a>."
-    }
-    builders {
-      name: "android-pie-arm64-rel-inverse-fyi"
-      swarming_host: "chromium-swarm.appspot.com"
-      dimensions: "cores:4"
-      dimensions: "cpu:x86-64"
-      dimensions: "os:Ubuntu-18.04"
-      dimensions: "pool:luci.chromium.try.orchestrator"
-      exe {
-        cipd_package: "infra/chromium/bootstrapper/${platform}"
-        cipd_version: "latest"
-        cmd: "bootstrapper"
-      }
-      properties:
-        '{'
-        '  "$bootstrap/exe": {'
-        '    "exe": {'
-        '      "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",'
-        '      "cipd_version": "refs/heads/main",'
-        '      "cmd": ['
-        '        "luciexe"'
-        '      ]'
-        '    }'
-        '  },'
-        '  "$bootstrap/properties": {'
-        '    "properties_file": "infra/config/generated/builders/try/android-pie-arm64-rel-inverse-fyi/properties.json",'
-        '    "top_level_project": {'
-        '      "ref": "refs/heads/main",'
-        '      "repo": {'
-        '        "host": "chromium.googlesource.com",'
-        '        "project": "chromium/src"'
-        '      }'
-        '    }'
-        '  },'
-        '  "builder_group": "tryserver.chromium.android",'
-        '  "led_builder_is_bootstrapped": true,'
-        '  "recipe": "chromium/orchestrator"'
-        '}'
-      execution_timeout_secs: 14400
-      expiration_secs: 7200
-      grace_period {
-        seconds: 120
-      }
-      caches {
-        name: "unused_builder_cache"
-        path: "builder"
-      }
-      caches {
-        name: "win_toolchain"
-        path: "win_toolchain"
-      }
-      build_numbers: YES
-      service_account: "chromium-orchestrator@chops-service-accounts.iam.gserviceaccount.com"
-      task_template_canary_percentage {
-        value: 5
-      }
-      experiments {
-        key: "chromium_rts.inverted_rts"
-        value: 100
-      }
-      experiments {
-        key: "chromium_rts.inverted_rts_bail_early"
-        value: 100
-      }
-      experiments {
-        key: "chromium_swarming.expose_merge_script_failures"
-        value: 100
-      }
-      experiments {
-        key: "enable_weetbix_queries"
-        value: 100
-      }
-      experiments {
-        key: "luci.buildbucket.omit_python2"
-        value: 100
-      }
-      experiments {
-        key: "luci.recipes.use_python3"
-        value: 100
-      }
-      experiments {
-        key: "weetbix.enable_weetbix_exonerations"
-        value: 100
-      }
-      experiments {
-        key: "weetbix.retry_weak_exonerations"
-        value: 100
-      }
-      resultdb {
-        enable: true
-        bq_exports {
-          project: "chrome-luci-data"
-          dataset: "chromium"
-          table: "try_test_results"
-          test_results {}
-        }
-        bq_exports {
-          project: "chrome-luci-data"
-          dataset: "chromium"
-          table: "gpu_try_test_results"
-          test_results {
-            predicate {
-              test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+"
-            }
-          }
-        }
-        bq_exports {
-          project: "chrome-luci-data"
-          dataset: "chromium"
-          table: "blink_web_tests_try_test_results"
-          test_results {
-            predicate {
-              test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*blink_wpt_tests/.+)"
-            }
-          }
-        }
-        history_options {
-          use_invocation_timestamp: true
-        }
-      }
-      description_html: "This is an experimental orchestrator making use of compilator <a href=\"https://ci.chromium.org/p/chromium/builders/try/android-pie-arm64-rel-compilator\">android-pie-arm64-rel-compilator</a>."
-    }
-    builders {
       name: "android-pie-arm64-wpt-rel-non-cq"
       swarming_host: "chromium-swarm.appspot.com"
       dimensions: "builderless:1"
diff --git a/infra/config/generated/luci/luci-milo.cfg b/infra/config/generated/luci/luci-milo.cfg
index bc7455c..11ab7b6 100644
--- a/infra/config/generated/luci/luci-milo.cfg
+++ b/infra/config/generated/luci/luci-milo.cfg
@@ -2561,12 +2561,6 @@
     name: "buildbucket/luci.chromium.try/android-pie-arm64-dbg"
   }
   builders {
-    name: "buildbucket/luci.chromium.try/android-pie-arm64-rel"
-  }
-  builders {
-    name: "buildbucket/luci.chromium.try/android-pie-arm64-rel-compilator"
-  }
-  builders {
     name: "buildbucket/luci.chromium.try/android-x64-cast"
   }
   builders {
@@ -16236,6 +16230,9 @@
     name: "buildbucket/luci.chromium.try/android-arm64-rel-compilator"
   }
   builders {
+    name: "buildbucket/luci.chromium.try/android-arm64-rel-inverse-fyi"
+  }
+  builders {
     name: "buildbucket/luci.chromium.try/android-asan"
   }
   builders {
@@ -16326,15 +16323,6 @@
     name: "buildbucket/luci.chromium.try/android-pie-arm64-dbg"
   }
   builders {
-    name: "buildbucket/luci.chromium.try/android-pie-arm64-rel"
-  }
-  builders {
-    name: "buildbucket/luci.chromium.try/android-pie-arm64-rel-compilator"
-  }
-  builders {
-    name: "buildbucket/luci.chromium.try/android-pie-arm64-rel-inverse-fyi"
-  }
-  builders {
     name: "buildbucket/luci.chromium.try/android-pie-arm64-wpt-rel-non-cq"
   }
   builders {
@@ -17381,6 +17369,9 @@
     name: "buildbucket/luci.chromium.try/android-arm64-rel-compilator"
   }
   builders {
+    name: "buildbucket/luci.chromium.try/android-arm64-rel-inverse-fyi"
+  }
+  builders {
     name: "buildbucket/luci.chromium.try/android-asan"
   }
   builders {
@@ -17462,15 +17453,6 @@
     name: "buildbucket/luci.chromium.try/android-pie-arm64-dbg"
   }
   builders {
-    name: "buildbucket/luci.chromium.try/android-pie-arm64-rel"
-  }
-  builders {
-    name: "buildbucket/luci.chromium.try/android-pie-arm64-rel-compilator"
-  }
-  builders {
-    name: "buildbucket/luci.chromium.try/android-pie-arm64-rel-inverse-fyi"
-  }
-  builders {
     name: "buildbucket/luci.chromium.try/android-pie-arm64-wpt-rel-non-cq"
   }
   builders {
diff --git a/infra/config/lib/orchestrator.star b/infra/config/lib/orchestrator.star
index ceb0d40..362bebdd 100644
--- a/infra/config/lib/orchestrator.star
+++ b/infra/config/lib/orchestrator.star
@@ -36,7 +36,7 @@
 # compilator.
 _EXPERIMENTAL_ORCHESTRATOR_NAMES_BY_COMPILATOR_NAME = {
     "try/android-nougat-x86-rel-compilator": ["try/android-nougat-x86-rel-inverse-fyi"],
-    "try/android-pie-arm64-rel-compilator": ["try/android-pie-arm64-rel-inverse-fyi"],
+    "try/android-arm64-rel-compilator": ["try/android-arm64-rel-inverse-fyi"],
     "try/linux_chromium_asan_rel_ng-compilator": ["try/linux_chromium_asan_rel_ng-inverse-fyi"],
     "try/linux_chromium_tsan_rel_ng-compilator": ["try/linux_chromium_tsan_rel_ng-inverse-fyi"],
     "try/linux-rel-compilator": ["try/linux-rel-inverse-fyi"],
@@ -140,7 +140,7 @@
     ]
 
     if len(orchestrator_nodes) != 1:
-        fail("compilator should have exactly 1 referring orchestrator, got: {}".format(
+        fail("compilator should have exactly 1 referring orchestrator, got: {}, {}".format(
             _builder_name(node),
             [_builder_name(n) for n in orchestrator_nodes],
         ))
diff --git a/infra/config/subprojects/chrome/try.star b/infra/config/subprojects/chrome/try.star
index a5b6ce6..43fb1c0 100644
--- a/infra/config/subprojects/chrome/try.star
+++ b/infra/config/subprojects/chrome/try.star
@@ -35,6 +35,7 @@
             experiment_percentage = tryjob.experiment_percentage,
             location_filters = location_filters,
             cancel_stale = tryjob.cancel_stale,
+            result_visibility = cq.COMMENT_LEVEL_RESTRICTED,
         )
     else:
         branches.cq_tryjob_verifier(
@@ -45,6 +46,7 @@
                 "googlers",
                 "project-chromium-robot-committers",
             ],
+            result_visibility = cq.COMMENT_LEVEL_RESTRICTED,
             **kwargs
         )
 
@@ -92,6 +94,7 @@
         "googlers",
         "project-chromium-robot-committers",
     ],
+    result_visibility = cq.COMMENT_LEVEL_RESTRICTED,
 )
 
 chrome_internal_verifier(
@@ -164,7 +167,7 @@
 chrome_internal_verifier(
     builder = "linux-chromeos-compile-chrome",
     tryjob = try_.job(
-        experiment_percentage = 50,
+        experiment_percentage = 100,
     ),
 )
 
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.android.star b/infra/config/subprojects/chromium/try/tryserver.chromium.android.star
index 90e7b301..ae3885e 100644
--- a/infra/config/subprojects/chromium/try/tryserver.chromium.android.star
+++ b/infra/config/subprojects/chromium/try/tryserver.chromium.android.star
@@ -111,6 +111,26 @@
     # use_orchestrator_pool = True,
 )
 
+try_.orchestrator_builder(
+    name = "android-arm64-rel-inverse-fyi",
+    mirrors = [
+        "ci/Android Release (Nexus 5X)",  # Nexus 5X on Nougat
+        "ci/android-pie-arm64-rel",  # Pixel 1, 2 on Pie
+    ],
+    try_settings = builder_config.try_settings(
+        rts_config = builder_config.rts_config(
+            condition = builder_config.rts_condition.QUICK_RUN_ONLY,
+        ),
+    ),
+    experiments = {
+        "chromium_rts.inverted_rts": 100,
+        "chromium_rts.inverted_rts_bail_early": 100,
+    },
+    compilator = "android-arm64-rel-compilator",
+    check_for_flakiness = True,
+    use_orchestrator_pool = True,
+)
+
 try_.compilator_builder(
     name = "android-arm64-rel-compilator",
     branch_selector = branches.STANDARD_MILESTONE,
@@ -413,56 +433,6 @@
     ),
 )
 
-# TODO(crbug.com/1367393): Remove after android-arm64-rel is fully enabled.
-try_.orchestrator_builder(
-    name = "android-pie-arm64-rel",
-    mirrors = [
-        "ci/android-pie-arm64-rel",
-    ],
-    try_settings = builder_config.try_settings(
-        rts_config = builder_config.rts_config(
-            condition = builder_config.rts_condition.QUICK_RUN_ONLY,
-        ),
-    ),
-    compilator = "android-pie-arm64-rel-compilator",
-    check_for_flakiness = True,
-    branch_selector = branches.STANDARD_MILESTONE,
-    main_list_view = "try",
-    #tryjob = try_.job(),
-    # TODO(crbug.com/1372179): Use orchestrator pool once overloaded test pools
-    # are addressed
-    # use_orchestrator_pool = True,
-)
-
-try_.orchestrator_builder(
-    name = "android-pie-arm64-rel-inverse-fyi",
-    mirrors = [
-        "ci/android-pie-arm64-rel",
-    ],
-    try_settings = builder_config.try_settings(
-        rts_config = builder_config.rts_config(
-            condition = builder_config.rts_condition.QUICK_RUN_ONLY,
-        ),
-    ),
-    experiments = {
-        "chromium_rts.inverted_rts": 100,
-        "chromium_rts.inverted_rts_bail_early": 100,
-    },
-    compilator = "android-pie-arm64-rel-compilator",
-    check_for_flakiness = True,
-    use_orchestrator_pool = True,
-)
-
-try_.compilator_builder(
-    name = "android-pie-arm64-rel-compilator",
-    branch_selector = branches.STANDARD_MILESTONE,
-    check_for_flakiness = True,
-    goma_backend = None,
-    main_list_view = "try",
-    # TODO (gatong): Remove once we've migrated to n2s
-    cores = "16|32",
-)
-
 try_.builder(
     name = "android-pie-x86-rel",
     mirrors = [
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
index c15e622..495c8363 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -795,7 +795,7 @@
     "Use Google Lens to Search for images";
 const char kUseLensToSearchForImageDescription[] =
     "When enabled, use Lens to search for images from the long press context "
-    "menu when Google is the selected search engine.";
+    "menu when Google is the selected search engine. iPhone only.";
 
 const char kEnableLensInHomeScreenWidgetName[] =
     "Enable Google Lens in the Home Screen Widget";
diff --git a/ios/chrome/browser/history/BUILD.gn b/ios/chrome/browser/history/BUILD.gn
index ffbd8e3a..7564f55 100644
--- a/ios/chrome/browser/history/BUILD.gn
+++ b/ios/chrome/browser/history/BUILD.gn
@@ -33,9 +33,11 @@
     "//components/pref_registry",
     "//components/prefs",
     "//components/sync",
+    "//components/version_info",
     "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/signin",
     "//ios/chrome/browser/url:constants",
+    "//ios/chrome/common",
     "//ios/components/webui:url_constants",
     "//ios/web",
     "//net",
diff --git a/ios/chrome/browser/history/history_service_factory.cc b/ios/chrome/browser/history/history_service_factory.cc
index 5581d05..0fc1b70 100644
--- a/ios/chrome/browser/history/history_service_factory.cc
+++ b/ios/chrome/browser/history/history_service_factory.cc
@@ -19,6 +19,7 @@
 #include "ios/chrome/browser/browser_state/browser_state_otr_helper.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/history/history_client_impl.h"
+#include "ios/chrome/common/channel_info.h"
 
 namespace ios {
 
@@ -33,7 +34,7 @@
               ios::BookmarkModelFactory::GetForBrowserState(browser_state)),
           nullptr));
   if (!history_service->Init(history::HistoryDatabaseParamsForPath(
-          browser_state->GetStatePath()))) {
+          browser_state->GetStatePath(), GetChannel()))) {
     return nullptr;
   }
   return history_service;
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/BUILD.gn b/ios/chrome/browser/infobars/overlays/browser_agent/BUILD.gn
index c613080..c1f7d36c 100644
--- a/ios/chrome/browser/infobars/overlays/browser_agent/BUILD.gn
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/BUILD.gn
@@ -40,6 +40,7 @@
     "//ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/tailored_security",
     "//ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/translate",
     "//ios/chrome/browser/main:public",
+    "//ios/chrome/browser/overlays/public/infobar_banner",
   ]
 }
 
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/infobar_overlay_browser_agent_util.mm b/ios/chrome/browser/infobars/overlays/browser_agent/infobar_overlay_browser_agent_util.mm
index 1c121037..e92442e 100644
--- a/ios/chrome/browser/infobars/overlays/browser_agent/infobar_overlay_browser_agent_util.mm
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/infobar_overlay_browser_agent_util.mm
@@ -7,15 +7,20 @@
 #import "base/feature_list.h"
 #import "components/safe_browsing/core/common/features.h"
 #import "ios/chrome/browser/infobars/overlays/browser_agent/infobar_overlay_browser_agent.h"
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/autofill_address_profile/save_address_profile_infobar_interaction_handler.h"
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/confirm/confirm_infobar_interaction_handler.h"
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/save_password_infobar_interaction_handler.h"
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/update_password_infobar_interaction_handler.h"
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/permissions/permissions_infobar_interaction_handler.h"
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/save_card/save_card_infobar_interaction_handler.h"
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/sync_error/sync_error_infobar_interaction_handler.h"
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/tailored_security/tailored_security_infobar_interaction_handler.h"
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/translate/translate_infobar_interaction_handler.h"
+#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/autofill_address_profile/save_address_profile_infobar_banner_interaction_handler.h"
+#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/autofill_address_profile/save_address_profile_infobar_modal_interaction_handler.h"
+#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/confirm/confirm_infobar_banner_interaction_handler.h"
+#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_banner_interaction_handler.h"
+#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_modal_interaction_handler.h"
+#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/permissions/permissions_infobar_banner_interaction_handler.h"
+#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/save_card/save_card_infobar_banner_interaction_handler.h"
+#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/save_card/save_card_infobar_modal_interaction_handler.h"
+#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/sync_error/sync_error_infobar_banner_interaction_handler.h"
+#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/tailored_security/tailored_security_infobar_banner_interaction_handler.h"
+#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/translate/translate_infobar_banner_interaction_handler.h"
+#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/translate/translate_infobar_modal_interaction_handler.h"
+#import "ios/chrome/browser/overlays/public/infobar_banner/password_infobar_banner_overlay.h"
+#import "ios/chrome/browser/overlays/public/infobar_banner/tailored_security_service_infobar_banner_overlay_request_config.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -25,26 +30,71 @@
   InfobarOverlayBrowserAgent::CreateForBrowser(browser);
   InfobarOverlayBrowserAgent* browser_agent =
       InfobarOverlayBrowserAgent::FromBrowser(browser);
+  {
+    auto banner_handler =
+        std::make_unique<PasswordInfobarBannerInteractionHandler>(
+            PasswordInfobarBannerOverlayRequestConfig::RequestSupport());
+    auto modal_handler =
+        std::make_unique<PasswordInfobarModalInteractionHandler>(
+            browser, password_modal::PasswordAction::kSave);
+    browser_agent->AddInfobarInteractionHandler(
+        std::make_unique<InfobarInteractionHandler>(
+            InfobarType::kInfobarTypePasswordSave, std::move(banner_handler),
+            std::move(modal_handler)));
+  }
+  {
+    auto banner_handler =
+        std::make_unique<PasswordInfobarBannerInteractionHandler>(
+            PasswordInfobarBannerOverlayRequestConfig::RequestSupport());
+    auto modal_handler =
+        std::make_unique<PasswordInfobarModalInteractionHandler>(
+            browser, password_modal::PasswordAction::kUpdate);
+    browser_agent->AddInfobarInteractionHandler(
+        std::make_unique<InfobarInteractionHandler>(
+            InfobarType::kInfobarTypePasswordUpdate, std::move(banner_handler),
+            std::move(modal_handler)));
+  }
   browser_agent->AddInfobarInteractionHandler(
-      std::make_unique<SavePasswordInfobarInteractionHandler>(browser));
+      std::make_unique<InfobarInteractionHandler>(
+          InfobarType::kInfobarTypeConfirm,
+          std::make_unique<ConfirmInfobarBannerInteractionHandler>(),
+          /*modal_handler=*/nullptr));
   browser_agent->AddInfobarInteractionHandler(
-      std::make_unique<UpdatePasswordInfobarInteractionHandler>(browser));
+      std::make_unique<InfobarInteractionHandler>(
+          InfobarType::kInfobarTypeTranslate,
+          std::make_unique<TranslateInfobarBannerInteractionHandler>(),
+          std::make_unique<TranslateInfobarModalInteractionHandler>()));
   browser_agent->AddInfobarInteractionHandler(
-      std::make_unique<ConfirmInfobarInteractionHandler>());
+      std::make_unique<InfobarInteractionHandler>(
+          InfobarType::kInfobarTypeSaveCard,
+          std::make_unique<SaveCardInfobarBannerInteractionHandler>(),
+          std::make_unique<SaveCardInfobarModalInteractionHandler>()));
+  browser_agent->AddInfobarInteractionHandler(std::make_unique<
+                                              InfobarInteractionHandler>(
+      InfobarType::kInfobarTypeSaveAutofillAddressProfile,
+      std::make_unique<SaveAddressProfileInfobarBannerInteractionHandler>(),
+      std::make_unique<SaveAddressProfileInfobarModalInteractionHandler>()));
   browser_agent->AddInfobarInteractionHandler(
-      std::make_unique<TranslateInfobarInteractionHandler>());
+      std::make_unique<InfobarInteractionHandler>(
+          InfobarType::kInfobarTypePermissions,
+          std::make_unique<PermissionsInfobarBannerInteractionHandler>(),
+          /*modal_handler=*/nullptr));
   browser_agent->AddInfobarInteractionHandler(
-      std::make_unique<SaveCardInfobarInteractionHandler>());
-  browser_agent->AddInfobarInteractionHandler(
-      std::make_unique<SaveAddressProfileInfobarInteractionHandler>());
-  browser_agent->AddInfobarInteractionHandler(
-      std::make_unique<PermissionsInfobarInteractionHandler>());
-  browser_agent->AddInfobarInteractionHandler(
-      std::make_unique<SyncErrorInfobarInteractionHandler>());
+      std::make_unique<InfobarInteractionHandler>(
+          InfobarType::kInfobarTypeSyncError,
+          std::make_unique<SyncErrorInfobarBannerInteractionHandler>(),
+          /*modal_handler=*/nullptr));
 
   if (base::FeatureList::IsEnabled(
           safe_browsing::kTailoredSecurityIntegration)) {
+    const OverlayRequestSupport* support =
+        tailored_security_service_infobar_overlays::
+            TailoredSecurityServiceBannerRequestConfig::RequestSupport();
     browser_agent->AddInfobarInteractionHandler(
-        std::make_unique<TailoredSecurityInfobarInteractionHandler>());
+        std::make_unique<InfobarInteractionHandler>(
+            InfobarType::kInfobarTypeTailoredSecurityService,
+            std::make_unique<TailoredSecurityInfobarBannerInteractionHandler>(
+                support),
+            nil));
   }
 }
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/autofill_address_profile/BUILD.gn b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/autofill_address_profile/BUILD.gn
index 3097cdb..9f3ac79 100644
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/autofill_address_profile/BUILD.gn
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/autofill_address_profile/BUILD.gn
@@ -7,8 +7,6 @@
   sources = [
     "save_address_profile_infobar_banner_interaction_handler.h",
     "save_address_profile_infobar_banner_interaction_handler.mm",
-    "save_address_profile_infobar_interaction_handler.h",
-    "save_address_profile_infobar_interaction_handler.mm",
     "save_address_profile_infobar_modal_interaction_handler.h",
     "save_address_profile_infobar_modal_interaction_handler.mm",
     "save_address_profile_infobar_modal_overlay_request_callback_installer.h",
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/autofill_address_profile/save_address_profile_infobar_interaction_handler.h b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/autofill_address_profile/save_address_profile_infobar_interaction_handler.h
deleted file mode 100644
index be72e0f..0000000
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/autofill_address_profile/save_address_profile_infobar_interaction_handler.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2021 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_AUTOFILL_ADDRESS_PROFILE_SAVE_ADDRESS_PROFILE_INFOBAR_INTERACTION_HANDLER_H_
-#define IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_AUTOFILL_ADDRESS_PROFILE_SAVE_ADDRESS_PROFILE_INFOBAR_INTERACTION_HANDLER_H_
-
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/infobar_interaction_handler.h"
-
-// An InfobarInteractionHandler that updates the model layer for interaction
-// events with the UI for save address profile infobars.
-class SaveAddressProfileInfobarInteractionHandler
-    : public InfobarInteractionHandler {
- public:
-  SaveAddressProfileInfobarInteractionHandler();
-  ~SaveAddressProfileInfobarInteractionHandler() override;
-};
-
-#endif  // IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_AUTOFILL_ADDRESS_PROFILE_SAVE_ADDRESS_PROFILE_INFOBAR_INTERACTION_HANDLER_H_
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/autofill_address_profile/save_address_profile_infobar_interaction_handler.mm b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/autofill_address_profile/save_address_profile_infobar_interaction_handler.mm
deleted file mode 100644
index 988c4bae..0000000
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/autofill_address_profile/save_address_profile_infobar_interaction_handler.mm
+++ /dev/null
@@ -1,24 +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 "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/autofill_address_profile/save_address_profile_infobar_interaction_handler.h"
-
-#import "ios/chrome/browser/infobars/infobar_type.h"
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/autofill_address_profile/save_address_profile_infobar_banner_interaction_handler.h"
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/autofill_address_profile/save_address_profile_infobar_modal_interaction_handler.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-SaveAddressProfileInfobarInteractionHandler::
-    SaveAddressProfileInfobarInteractionHandler()
-    : InfobarInteractionHandler(
-          InfobarType::kInfobarTypeSaveAutofillAddressProfile,
-          std::make_unique<SaveAddressProfileInfobarBannerInteractionHandler>(),
-          std::make_unique<
-              SaveAddressProfileInfobarModalInteractionHandler>()) {}
-
-SaveAddressProfileInfobarInteractionHandler::
-    ~SaveAddressProfileInfobarInteractionHandler() = default;
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/confirm/BUILD.gn b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/confirm/BUILD.gn
index cb0707f..f197ca4 100644
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/confirm/BUILD.gn
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/confirm/BUILD.gn
@@ -7,8 +7,6 @@
   sources = [
     "confirm_infobar_banner_interaction_handler.h",
     "confirm_infobar_banner_interaction_handler.mm",
-    "confirm_infobar_interaction_handler.h",
-    "confirm_infobar_interaction_handler.mm",
   ]
   deps = [
     "//base",
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/confirm/confirm_infobar_interaction_handler.h b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/confirm/confirm_infobar_interaction_handler.h
deleted file mode 100644
index 238d9a2..0000000
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/confirm/confirm_infobar_interaction_handler.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_CONFIRM_CONFIRM_INFOBAR_INTERACTION_HANDLER_H_
-#define IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_CONFIRM_CONFIRM_INFOBAR_INTERACTION_HANDLER_H_
-
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/infobar_interaction_handler.h"
-
-// An InfobarInteractionHandler that updates the model layer for interaction
-// events with the UI for confirm infobars.
-class ConfirmInfobarInteractionHandler : public InfobarInteractionHandler {
- public:
-  ConfirmInfobarInteractionHandler();
-  ~ConfirmInfobarInteractionHandler() override;
-};
-
-#endif  // IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_CONFIRM_CONFIRM_INFOBAR_INTERACTION_HANDLER_H_
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/confirm/confirm_infobar_interaction_handler.mm b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/confirm/confirm_infobar_interaction_handler.mm
deleted file mode 100644
index e9a93d28..0000000
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/confirm/confirm_infobar_interaction_handler.mm
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/confirm/confirm_infobar_interaction_handler.h"
-
-#import "ios/chrome/browser/infobars/infobar_type.h"
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/confirm/confirm_infobar_banner_interaction_handler.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-ConfirmInfobarInteractionHandler::ConfirmInfobarInteractionHandler()
-    : InfobarInteractionHandler(
-          InfobarType::kInfobarTypeConfirm,
-          std::make_unique<ConfirmInfobarBannerInteractionHandler>(),
-          /*modal_handler=*/nullptr) {}
-
-ConfirmInfobarInteractionHandler::~ConfirmInfobarInteractionHandler() = default;
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/BUILD.gn b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/BUILD.gn
index aae0f86..b87465c 100644
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/BUILD.gn
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/BUILD.gn
@@ -11,10 +11,6 @@
     "password_infobar_modal_interaction_handler.mm",
     "password_infobar_modal_overlay_request_callback_installer.h",
     "password_infobar_modal_overlay_request_callback_installer.mm",
-    "save_password_infobar_interaction_handler.h",
-    "save_password_infobar_interaction_handler.mm",
-    "update_password_infobar_interaction_handler.h",
-    "update_password_infobar_interaction_handler.mm",
   ]
   deps = [
     "//base",
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/save_password_infobar_interaction_handler.h b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/save_password_infobar_interaction_handler.h
deleted file mode 100644
index 1aa06c8..0000000
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/save_password_infobar_interaction_handler.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_PASSWORDS_SAVE_PASSWORD_INFOBAR_INTERACTION_HANDLER_H_
-#define IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_PASSWORDS_SAVE_PASSWORD_INFOBAR_INTERACTION_HANDLER_H_
-
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/infobar_interaction_handler.h"
-
-class Browser;
-
-// An InfobarInteractionHandler that updates the model layer for interaction
-// events with the UI for password infobars.
-class SavePasswordInfobarInteractionHandler : public InfobarInteractionHandler {
- public:
-  SavePasswordInfobarInteractionHandler(Browser* browser);
-  ~SavePasswordInfobarInteractionHandler() override;
-};
-
-#endif  // IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_PASSWORDS_SAVE_PASSWORD_INFOBAR_INTERACTION_HANDLER_H_
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/save_password_infobar_interaction_handler.mm b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/save_password_infobar_interaction_handler.mm
deleted file mode 100644
index 2c88653..0000000
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/save_password_infobar_interaction_handler.mm
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/save_password_infobar_interaction_handler.h"
-
-#import "ios/chrome/browser/infobars/infobar_type.h"
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_banner_interaction_handler.h"
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_modal_interaction_handler.h"
-#import "ios/chrome/browser/overlays/public/infobar_banner/password_infobar_banner_overlay.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-SavePasswordInfobarInteractionHandler::SavePasswordInfobarInteractionHandler(
-    Browser* browser)
-    : InfobarInteractionHandler(
-          InfobarType::kInfobarTypePasswordSave,
-          std::make_unique<PasswordInfobarBannerInteractionHandler>(
-              PasswordInfobarBannerOverlayRequestConfig::RequestSupport()),
-          std::make_unique<PasswordInfobarModalInteractionHandler>(
-              browser,
-              password_modal::PasswordAction::kSave)) {}
-
-SavePasswordInfobarInteractionHandler::
-    ~SavePasswordInfobarInteractionHandler() = default;
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/update_password_infobar_interaction_handler.h b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/update_password_infobar_interaction_handler.h
deleted file mode 100644
index 665b88e..0000000
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/update_password_infobar_interaction_handler.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_PASSWORDS_UPDATE_PASSWORD_INFOBAR_INTERACTION_HANDLER_H_
-#define IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_PASSWORDS_UPDATE_PASSWORD_INFOBAR_INTERACTION_HANDLER_H_
-
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/infobar_interaction_handler.h"
-
-class Browser;
-
-// An InfobarInteractionHandler that updates the model layer for interaction
-// events with the UI for update password infobars.
-class UpdatePasswordInfobarInteractionHandler
-    : public InfobarInteractionHandler {
- public:
-  UpdatePasswordInfobarInteractionHandler(Browser* browser);
-  ~UpdatePasswordInfobarInteractionHandler() override;
-};
-
-#endif  // IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_PASSWORDS_UPDATE_PASSWORD_INFOBAR_INTERACTION_HANDLER_H_
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/update_password_infobar_interaction_handler.mm b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/update_password_infobar_interaction_handler.mm
deleted file mode 100644
index e2a6e22f..0000000
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/update_password_infobar_interaction_handler.mm
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/update_password_infobar_interaction_handler.h"
-
-#import "ios/chrome/browser/infobars/infobar_type.h"
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_banner_interaction_handler.h"
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/password_infobar_modal_interaction_handler.h"
-#import "ios/chrome/browser/overlays/public/infobar_banner/password_infobar_banner_overlay.h"
-#import "ios/chrome/browser/overlays/public/infobar_modal/password_infobar_modal_overlay_request_config.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-UpdatePasswordInfobarInteractionHandler::
-    UpdatePasswordInfobarInteractionHandler(Browser* browser)
-    : InfobarInteractionHandler(
-          InfobarType::kInfobarTypePasswordUpdate,
-          std::make_unique<PasswordInfobarBannerInteractionHandler>(
-              PasswordInfobarBannerOverlayRequestConfig::RequestSupport()),
-          std::make_unique<PasswordInfobarModalInteractionHandler>(
-              browser,
-              password_modal::PasswordAction::kUpdate)) {}
-
-UpdatePasswordInfobarInteractionHandler::
-    ~UpdatePasswordInfobarInteractionHandler() = default;
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/permissions/BUILD.gn b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/permissions/BUILD.gn
index 5f7de28..9349f6ab 100644
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/permissions/BUILD.gn
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/permissions/BUILD.gn
@@ -7,8 +7,6 @@
   sources = [
     "permissions_infobar_banner_interaction_handler.h",
     "permissions_infobar_banner_interaction_handler.mm",
-    "permissions_infobar_interaction_handler.h",
-    "permissions_infobar_interaction_handler.mm",
   ]
   deps = [
     "//base",
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/permissions/permissions_infobar_interaction_handler.h b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/permissions/permissions_infobar_interaction_handler.h
deleted file mode 100644
index bdf5d9d7..0000000
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/permissions/permissions_infobar_interaction_handler.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2022 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_PERMISSIONS_PERMISSIONS_INFOBAR_INTERACTION_HANDLER_H_
-#define IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_PERMISSIONS_PERMISSIONS_INFOBAR_INTERACTION_HANDLER_H_
-
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/infobar_interaction_handler.h"
-
-// An InfobarInteractionHandler that updates the model layer for interaction
-// events with the UI for the permissions infobar.
-class PermissionsInfobarInteractionHandler : public InfobarInteractionHandler {
- public:
-  PermissionsInfobarInteractionHandler();
-  ~PermissionsInfobarInteractionHandler() override;
-};
-
-#endif  // IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_PERMISSIONS_PERMISSIONS_INFOBAR_INTERACTION_HANDLER_H_
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/permissions/permissions_infobar_interaction_handler.mm b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/permissions/permissions_infobar_interaction_handler.mm
deleted file mode 100644
index 2fa5385..0000000
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/permissions/permissions_infobar_interaction_handler.mm
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2022 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/permissions/permissions_infobar_interaction_handler.h"
-
-#import "ios/chrome/browser/infobars/infobar_type.h"
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/permissions/permissions_infobar_banner_interaction_handler.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-PermissionsInfobarInteractionHandler::PermissionsInfobarInteractionHandler()
-    : InfobarInteractionHandler(
-          InfobarType::kInfobarTypePermissions,
-          std::make_unique<PermissionsInfobarBannerInteractionHandler>(),
-          /*modal_handler=*/nullptr) {}
-
-PermissionsInfobarInteractionHandler::~PermissionsInfobarInteractionHandler() =
-    default;
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/save_card/BUILD.gn b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/save_card/BUILD.gn
index d428360..ad4c955 100644
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/save_card/BUILD.gn
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/save_card/BUILD.gn
@@ -9,8 +9,6 @@
     "save_card_infobar_banner_interaction_handler.mm",
     "save_card_infobar_banner_overlay_request_callback_installer.h",
     "save_card_infobar_banner_overlay_request_callback_installer.mm",
-    "save_card_infobar_interaction_handler.h",
-    "save_card_infobar_interaction_handler.mm",
     "save_card_infobar_modal_interaction_handler.h",
     "save_card_infobar_modal_interaction_handler.mm",
     "save_card_infobar_modal_overlay_request_callback_installer.h",
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/save_card/save_card_infobar_interaction_handler.h b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/save_card/save_card_infobar_interaction_handler.h
deleted file mode 100644
index 2526457..0000000
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/save_card/save_card_infobar_interaction_handler.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_SAVE_CARD_SAVE_CARD_INFOBAR_INTERACTION_HANDLER_H_
-#define IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_SAVE_CARD_SAVE_CARD_INFOBAR_INTERACTION_HANDLER_H_
-
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/infobar_interaction_handler.h"
-
-// An InfobarInteractionHandler that updates the model layer for interaction
-// events with the UI for save card infobars.
-class SaveCardInfobarInteractionHandler : public InfobarInteractionHandler {
- public:
-  SaveCardInfobarInteractionHandler();
-  ~SaveCardInfobarInteractionHandler() override;
-};
-
-#endif  // IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_SAVE_CARD_SAVE_CARD_INFOBAR_INTERACTION_HANDLER_H_
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/save_card/save_card_infobar_interaction_handler.mm b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/save_card/save_card_infobar_interaction_handler.mm
deleted file mode 100644
index 410f8bb..0000000
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/save_card/save_card_infobar_interaction_handler.mm
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/save_card/save_card_infobar_interaction_handler.h"
-
-#import "ios/chrome/browser/infobars/infobar_type.h"
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/save_card/save_card_infobar_banner_interaction_handler.h"
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/save_card/save_card_infobar_modal_interaction_handler.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-SaveCardInfobarInteractionHandler::SaveCardInfobarInteractionHandler()
-    : InfobarInteractionHandler(
-          InfobarType::kInfobarTypeSaveCard,
-          std::make_unique<SaveCardInfobarBannerInteractionHandler>(),
-          std::make_unique<SaveCardInfobarModalInteractionHandler>()) {}
-
-SaveCardInfobarInteractionHandler::~SaveCardInfobarInteractionHandler() =
-    default;
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/sync_error/BUILD.gn b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/sync_error/BUILD.gn
index afac765..cebcc71 100644
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/sync_error/BUILD.gn
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/sync_error/BUILD.gn
@@ -7,8 +7,6 @@
   sources = [
     "sync_error_infobar_banner_interaction_handler.h",
     "sync_error_infobar_banner_interaction_handler.mm",
-    "sync_error_infobar_interaction_handler.h",
-    "sync_error_infobar_interaction_handler.mm",
   ]
   deps = [
     "//base",
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/sync_error/sync_error_infobar_interaction_handler.h b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/sync_error/sync_error_infobar_interaction_handler.h
deleted file mode 100644
index f3425c0..0000000
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/sync_error/sync_error_infobar_interaction_handler.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2022 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_SYNC_ERROR_SYNC_ERROR_INFOBAR_INTERACTION_HANDLER_H_
-#define IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_SYNC_ERROR_SYNC_ERROR_INFOBAR_INTERACTION_HANDLER_H_
-
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/common/infobar_banner_interaction_handler.h"
-
-// Helper object that updates the model layer for interaction events with the
-// sync error infobar banner UI.
-class SyncErrorInfobarInteractionHandler : public InfobarInteractionHandler {
- public:
-  SyncErrorInfobarInteractionHandler();
-  ~SyncErrorInfobarInteractionHandler() override;
-};
-
-#endif  // IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_SYNC_ERROR_SYNC_ERROR_INFOBAR_INTERACTION_HANDLER_H_
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/sync_error/sync_error_infobar_interaction_handler.mm b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/sync_error/sync_error_infobar_interaction_handler.mm
deleted file mode 100644
index 62dd666a..0000000
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/sync_error/sync_error_infobar_interaction_handler.mm
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2022 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/sync_error/sync_error_infobar_interaction_handler.h"
-
-#import "ios/chrome/browser/infobars/infobar_type.h"
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/sync_error/sync_error_infobar_banner_interaction_handler.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-SyncErrorInfobarInteractionHandler::SyncErrorInfobarInteractionHandler()
-    : InfobarInteractionHandler(
-          InfobarType::kInfobarTypeSyncError,
-          std::make_unique<SyncErrorInfobarBannerInteractionHandler>(),
-          /*modal_handler=*/nullptr) {}
-
-SyncErrorInfobarInteractionHandler::~SyncErrorInfobarInteractionHandler() =
-    default;
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/tailored_security/BUILD.gn b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/tailored_security/BUILD.gn
index abb8e049..2aed93d5 100644
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/tailored_security/BUILD.gn
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/tailored_security/BUILD.gn
@@ -7,8 +7,6 @@
   sources = [
     "tailored_security_infobar_banner_interaction_handler.h",
     "tailored_security_infobar_banner_interaction_handler.mm",
-    "tailored_security_infobar_interaction_handler.h",
-    "tailored_security_infobar_interaction_handler.mm",
   ]
   deps = [
     "//base",
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/tailored_security/tailored_security_infobar_interaction_handler.h b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/tailored_security/tailored_security_infobar_interaction_handler.h
deleted file mode 100644
index 15a4b03..0000000
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/tailored_security/tailored_security_infobar_interaction_handler.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2022 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_TAILORED_SECURITY_TAILORED_SECURITY_INFOBAR_INTERACTION_HANDLER_H_
-#define IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_TAILORED_SECURITY_TAILORED_SECURITY_INFOBAR_INTERACTION_HANDLER_H_
-
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/infobar_interaction_handler.h"
-
-// An InfobarInteractionHandler that updates the model layer for interaction
-// events with the UI for tailored security infobars.
-class TailoredSecurityInfobarInteractionHandler
-    : public InfobarInteractionHandler {
- public:
-  TailoredSecurityInfobarInteractionHandler();
-  ~TailoredSecurityInfobarInteractionHandler() override;
-};
-
-#endif  // IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_TAILORED_SECURITY_TAILORED_SECURITY_INFOBAR_INTERACTION_HANDLER_H_
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/tailored_security/tailored_security_infobar_interaction_handler.mm b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/tailored_security/tailored_security_infobar_interaction_handler.mm
deleted file mode 100644
index e7ec31c..0000000
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/tailored_security/tailored_security_infobar_interaction_handler.mm
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2022 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/tailored_security/tailored_security_infobar_interaction_handler.h"
-
-#import "ios/chrome/browser/infobars/infobar_type.h"
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/tailored_security/tailored_security_infobar_banner_interaction_handler.h"
-#import "ios/chrome/browser/overlays/public/infobar_banner/tailored_security_service_infobar_banner_overlay_request_config.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-TailoredSecurityInfobarInteractionHandler::
-    TailoredSecurityInfobarInteractionHandler()
-    : InfobarInteractionHandler(
-          InfobarType::kInfobarTypeTailoredSecurityService,
-          std::make_unique<TailoredSecurityInfobarBannerInteractionHandler>(
-              tailored_security_service_infobar_overlays::
-                  TailoredSecurityServiceBannerRequestConfig::RequestSupport()),
-          nil) {}
-
-TailoredSecurityInfobarInteractionHandler::
-    ~TailoredSecurityInfobarInteractionHandler() = default;
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/translate/BUILD.gn b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/translate/BUILD.gn
index ecb9988..b4c26226 100644
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/translate/BUILD.gn
+++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/translate/BUILD.gn
@@ -7,8 +7,6 @@
   sources = [
     "translate_infobar_banner_interaction_handler.h",
     "translate_infobar_banner_interaction_handler.mm",
-    "translate_infobar_interaction_handler.h",
-    "translate_infobar_interaction_handler.mm",
     "translate_infobar_modal_interaction_handler.h",
     "translate_infobar_modal_interaction_handler.mm",
     "translate_infobar_modal_overlay_request_callback_installer.h",
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/translate/translate_infobar_interaction_handler.h b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/translate/translate_infobar_interaction_handler.h
deleted file mode 100644
index ddb20d8..0000000
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/translate/translate_infobar_interaction_handler.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_TRANSLATE_TRANSLATE_INFOBAR_INTERACTION_HANDLER_H_
-#define IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_TRANSLATE_TRANSLATE_INFOBAR_INTERACTION_HANDLER_H_
-
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/infobar_interaction_handler.h"
-
-// An InfobarInteractionHandler that updates the model layer for interaction
-// events with the UI for Translate infobars.
-class TranslateInfobarInteractionHandler : public InfobarInteractionHandler {
- public:
-  TranslateInfobarInteractionHandler();
-  ~TranslateInfobarInteractionHandler() override;
-};
-
-#endif  // IOS_CHROME_BROWSER_INFOBARS_OVERLAYS_BROWSER_AGENT_INTERACTION_HANDLERS_TRANSLATE_TRANSLATE_INFOBAR_INTERACTION_HANDLER_H_
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/translate/translate_infobar_interaction_handler.mm b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/translate/translate_infobar_interaction_handler.mm
deleted file mode 100644
index 527d32a0..0000000
--- a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/translate/translate_infobar_interaction_handler.mm
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/translate/translate_infobar_interaction_handler.h"
-
-#import "components/infobars/core/infobar.h"
-#import "ios/chrome/browser/infobars/infobar_ios.h"
-#import "ios/chrome/browser/infobars/infobar_manager_impl.h"
-#import "ios/chrome/browser/infobars/infobar_type.h"
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/translate/translate_infobar_banner_interaction_handler.h"
-#import "ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/translate/translate_infobar_modal_interaction_handler.h"
-#import "ios/chrome/browser/infobars/overlays/infobar_overlay_request_inserter.h"
-#import "ios/chrome/browser/main/browser.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-TranslateInfobarInteractionHandler::TranslateInfobarInteractionHandler()
-    : InfobarInteractionHandler(
-          InfobarType::kInfobarTypeTranslate,
-          std::make_unique<TranslateInfobarBannerInteractionHandler>(),
-          std::make_unique<TranslateInfobarModalInteractionHandler>()) {}
-
-TranslateInfobarInteractionHandler::~TranslateInfobarInteractionHandler() =
-    default;
diff --git a/ios/chrome/browser/policy/policy_egtest.mm b/ios/chrome/browser/policy/policy_egtest.mm
index 5c6f4f4..9228fafc 100644
--- a/ios/chrome/browser/policy/policy_egtest.mm
+++ b/ios/chrome/browser/policy/policy_egtest.mm
@@ -331,8 +331,7 @@
 
 // Tests that language detection is not performed and the tool manual trigger
 // button is disabled when the pref kOfferTranslateEnabled is set to false.
-// TODO(crbug.com/1341363): Disabled due to flakiness. Re-enabled when fixed.
-- (void)DISABLED_testTranslateEnabled {
+- (void)testTranslateEnabled {
   GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
   const GURL testURL = self.testServer->GetURL("/pony.html");
   const std::string pageText = "pony";
@@ -359,10 +358,14 @@
 
   // Make sure the Translate manual trigger button disabled.
   [ChromeEarlGreyUI openToolsMenu];
+  id<GREYMatcher> toolsMenuMatcher =
+      [ChromeEarlGrey isNewOverflowMenuEnabled]
+          ? grey_accessibilityID(kPopupMenuToolsMenuActionListId)
+          : grey_accessibilityID(kPopupMenuToolsMenuTableViewId);
   [[[EarlGrey selectElementWithMatcher:ToolsMenuTranslateButton()]
          usingSearchAction:grey_scrollInDirection(kGREYDirectionDown,
                                                   /*amount=*/200)
-      onElementWithMatcher:chrome_test_util::ToolsMenuView()]
+      onElementWithMatcher:toolsMenuMatcher]
       assertWithMatcher:grey_accessibilityTrait(
                             UIAccessibilityTraitNotEnabled)];
 
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_home_consumer.h b/ios/chrome/browser/ui/bookmarks/bookmark_home_consumer.h
index b6b6aff..981dcc4d 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmark_home_consumer.h
+++ b/ios/chrome/browser/ui/bookmarks/bookmark_home_consumer.h
@@ -37,6 +37,10 @@
 // Displays the table view background for the given `style`.
 - (void)updateTableViewBackgroundStyle:(BookmarkHomeBackgroundStyle)style;
 
+// Sets the editing mode for tableView, update context bar and search state
+// accordingly.
+- (void)setTableViewEditing:(BOOL)editing;
+
 // Displays the signin UI configured by `command`.
 - (void)showSignin:(ShowSigninCommand*)command;
 
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_home_mediator.mm b/ios/chrome/browser/ui/bookmarks/bookmark_home_mediator.mm
index eb99ff1..8b34393f 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmark_home_mediator.mm
+++ b/ios/chrome/browser/ui/bookmarks/bookmark_home_mediator.mm
@@ -396,6 +396,9 @@
   // reload here.)
   if (bookmarkNode == self.sharedState.tableViewDisplayedRootNode &&
       !self.sharedState.addingNewFolder) {
+    if (self.sharedState.currentlyInEditMode && ![self hasBookmarksOrFolders]) {
+      [self.consumer setTableViewEditing:NO];
+    }
     [self.consumer refreshContents];
     return;
   }
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
index b847dfa..8e6021d6 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
+++ b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
@@ -517,6 +517,17 @@
 
 #pragma mark - BookmarkHomeConsumer
 
+- (void)setTableViewEditing:(BOOL)editing {
+  self.sharedState.currentlyInEditMode = editing;
+  [self setContextBarState:editing ? BookmarksContextBarBeginSelection
+                                   : BookmarksContextBarDefault];
+  self.searchController.searchBar.userInteractionEnabled = !editing;
+  self.searchController.searchBar.alpha =
+      editing ? kTableViewNavigationAlphaForDisabledSearchBar : 1.0;
+
+  self.tableView.dragInteractionEnabled = !editing;
+}
+
 - (void)refreshContents {
   if (self.sharedState.currentlyShowingSearchResults) {
     NSString* noResults = GetNSString(IDS_HISTORY_NO_SEARCH_RESULTS);
@@ -1166,19 +1177,6 @@
   return controller;
 }
 
-// Sets the editing mode for tableView, update context bar and search state
-// accordingly.
-- (void)setTableViewEditing:(BOOL)editing {
-  self.sharedState.currentlyInEditMode = editing;
-  [self setContextBarState:editing ? BookmarksContextBarBeginSelection
-                                   : BookmarksContextBarDefault];
-  self.searchController.searchBar.userInteractionEnabled = !editing;
-  self.searchController.searchBar.alpha =
-      editing ? kTableViewNavigationAlphaForDisabledSearchBar : 1.0;
-
-  self.tableView.dragInteractionEnabled = !editing;
-}
-
 // Row selection of the tableView will be cleared after reloadData.  This
 // function is used to restore the row selection.  It also updates editNodes in
 // case some selected nodes are removed.
diff --git a/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm b/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm
index 78e2183..f359c9c 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm
+++ b/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm
@@ -826,6 +826,34 @@
       verifyAbsenceOfBookmarkWithURL:base::SysUTF8ToNSString(firstURL.spec())];
 }
 
+// Test that when bookmark is on edit mode and all entries are deleted outside
+// of that window it automatically quits edit mode.
+- (void)testBookmarksSyncWhenAllEntriesAreCancelled {
+  [BookmarkEarlGrey setupStandardBookmarks];
+  [BookmarkEarlGreyUI openBookmarks];
+  [BookmarkEarlGreyUI openMobileBookmarks];
+
+  // Go in edit mode.
+  [[EarlGrey
+      selectElementWithMatcher:grey_accessibilityID(
+                                   kBookmarkHomeTrailingButtonIdentifier)]
+      performAction:grey_tap()];
+
+  // Delete all bookmarks and folders under Mobile Bookmarks.
+  [BookmarkEarlGrey removeBookmarkWithTitle:@"Folder 1.1"];
+  [BookmarkEarlGrey removeBookmarkWithTitle:@"Folder 1"];
+  [BookmarkEarlGrey removeBookmarkWithTitle:@"French URL"];
+  [BookmarkEarlGrey removeBookmarkWithTitle:@"Second URL"];
+
+  // Check window is still in edit mode (still one bookmark/folder left).
+  [BookmarkEarlGreyUI verifyContextBarInEditMode];
+  [BookmarkEarlGrey removeBookmarkWithTitle:@"First URL"];
+
+  // Check window is no more in edit mode (no bookmark/folder left).
+  [BookmarkEarlGreyUI verifyContextBarInDefaultStateWithSelectEnabled:NO
+                                                     newFolderEnabled:YES];
+}
+
 // TODO(crbug.com/695749): Add egtests for:
 // 1. Spinner background.
 // 2. Reorder bookmarks. (make sure it won't clear the row selection on table)
diff --git a/ios/chrome/browser/ui/context_menu/context_menu_configuration_provider.mm b/ios/chrome/browser/ui/context_menu/context_menu_configuration_provider.mm
index 59eea66..d4ee9fed 100644
--- a/ios/chrome/browser/ui/context_menu/context_menu_configuration_provider.mm
+++ b/ios/chrome/browser/ui/context_menu/context_menu_configuration_provider.mm
@@ -52,6 +52,7 @@
 #import "ios/web/common/url_scheme_util.h"
 #import "ios/web/public/ui/context_menu_params.h"
 #import "ios/web/public/web_state.h"
+#import "ui/base/device_form_factor.h"
 #import "ui/base/l10n/l10n_util.h"
 #import "url/gurl.h"
 
@@ -261,7 +262,9 @@
         ios::provider::IsLensSupported() &&
         base::FeatureList::IsEnabled(kUseLensToSearchForImage);
     const BOOL useLens =
-        lensEnabled && search_engines::SupportsSearchImageWithLens(service);
+        lensEnabled && search_engines::SupportsSearchImageWithLens(service) &&
+        ui::GetDeviceFormFactor() != ui::DEVICE_FORM_FACTOR_TABLET;
+
     if (useLens) {
       UIAction* searchImageWithLensAction =
           [actionFactory actionToSearchImageUsingLensWithBlock:^{
@@ -272,7 +275,10 @@
       [menuElements addObject:searchImageWithLensAction];
       UMA_HISTOGRAM_ENUMERATION(kIOSLensSupportStatusHistogram,
                                 LensSupportStatus::LensSearchSupported);
-    } else if (lensEnabled) {
+    } else if (ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_TABLET) {
+      UMA_HISTOGRAM_ENUMERATION(kIOSLensSupportStatusHistogram,
+                                LensSupportStatus::DeviceFormFactorTablet);
+    } else {
       UMA_HISTOGRAM_ENUMERATION(kIOSLensSupportStatusHistogram,
                                 LensSupportStatus::NonGoogleSearchEngine);
     }
diff --git a/ios/chrome/browser/ui/lens/lens_availability.h b/ios/chrome/browser/ui/lens/lens_availability.h
index eacca396..56fb7eb 100644
--- a/ios/chrome/browser/ui/lens/lens_availability.h
+++ b/ios/chrome/browser/ui/lens/lens_availability.h
@@ -11,7 +11,8 @@
 enum class LensSupportStatus {
   LensSearchSupported = 0,
   NonGoogleSearchEngine = 1,
-  kMaxValue = NonGoogleSearchEngine,
+  DeviceFormFactorTablet = 2,
+  kMaxValue = DeviceFormFactorTablet,
 };
 
 extern const char kIOSLensSupportStatusHistogram[];
diff --git a/ios/chrome/browser/ui/ntp/metrics/BUILD.gn b/ios/chrome/browser/ui/ntp/metrics/BUILD.gn
index a76746d..a189b6fb 100644
--- a/ios/chrome/browser/ui/ntp/metrics/BUILD.gn
+++ b/ios/chrome/browser/ui/ntp/metrics/BUILD.gn
@@ -7,6 +7,7 @@
   sources = [
     "feed_metrics_constants.h",
     "feed_metrics_constants.mm",
+    "feed_metrics_recorder+testing.h",
     "feed_metrics_recorder.h",
     "feed_metrics_recorder.mm",
     "feed_session_recorder+testing.h",
@@ -34,11 +35,15 @@
 source_set("unit_tests") {
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
-  sources = [ "feed_session_recorder_unittest.mm" ]
+  sources = [
+    "feed_metrics_recorder_unittest.mm",
+    "feed_session_recorder_unittest.mm",
+  ]
   deps = [
     ":metrics",
     "//base",
     "//base/test:test_support",
+    "//components/feed/core/v2/public:common",
     "//ios/chrome/test:test_support",
     "//ios/web/public/test",
     "//testing/gtest",
diff --git a/ios/chrome/browser/ui/ntp/metrics/feed_metrics_recorder+testing.h b/ios/chrome/browser/ui/ntp/metrics/feed_metrics_recorder+testing.h
new file mode 100644
index 0000000..00e1a44
--- /dev/null
+++ b/ios/chrome/browser/ui/ntp/metrics/feed_metrics_recorder+testing.h
@@ -0,0 +1,18 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_NTP_METRICS_FEED_METRICS_RECORDER_TESTING_H_
+#define IOS_CHROME_BROWSER_UI_NTP_METRICS_FEED_METRICS_RECORDER_TESTING_H_
+
+#import "ios/chrome/browser/ui/ntp/metrics/feed_metrics_recorder.h"
+
+// Category for exposing properties and methods for testing.
+@interface FeedMetricsRecorder (Testing)
+
+// Exposing resetGoodVisitSession to mimic session expiration.
+- (void)resetGoodVisitSession;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_NTP_METRICS_FEED_METRICS_RECORDER_TESTING_H_
diff --git a/ios/chrome/browser/ui/ntp/metrics/feed_metrics_recorder_unittest.mm b/ios/chrome/browser/ui/ntp/metrics/feed_metrics_recorder_unittest.mm
new file mode 100644
index 0000000..b451b11
--- /dev/null
+++ b/ios/chrome/browser/ui/ntp/metrics/feed_metrics_recorder_unittest.mm
@@ -0,0 +1,103 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/ntp/metrics/feed_metrics_recorder.h"
+
+#import <Foundation/Foundation.h>
+
+#import "base/test/metrics/histogram_tester.h"
+#import "components/feed/core/v2/public/common_enums.h"
+#import "ios/chrome/browser/ui/ntp/metrics/feed_metrics_recorder+testing.h"
+#import "testing/gtest/include/gtest/gtest.h"
+#import "testing/gtest_mac.h"
+#import "testing/platform_test.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+using feed::FeedEngagementType;
+
+class FeedMetricsRecorderTest : public PlatformTest {
+ public:
+  FeedMetricsRecorderTest() {
+    recorder = [[FeedMetricsRecorder alloc] init];
+    histogram_tester_.reset(new base::HistogramTester());
+  }
+
+ protected:
+  void TearDown() override {
+    [recorder resetGoodVisitSession];
+    PlatformTest::TearDown();
+  }
+  FeedMetricsRecorder* recorder;
+  std::unique_ptr<base::HistogramTester> histogram_tester_;
+};
+
+// Tests that a Good Visit is recorded when a url is added to Read Later.
+TEST_F(FeedMetricsRecorderTest, GoodExplicitInteraction) {
+  // There should not be a Good Visit recorded.
+  histogram_tester_->ExpectBucketCount(kAllFeedsEngagementTypeHistogram,
+                                       FeedEngagementType::kGoodVisit, 0);
+  // Add URL to Read Later constitutes a Good Visit by itself.
+  [recorder recordAddURLToReadLater];
+  // There should be a Good Visit recorded.
+  histogram_tester_->ExpectBucketCount(kAllFeedsEngagementTypeHistogram,
+                                       FeedEngagementType::kGoodVisit, 1);
+}
+
+// Tests that a Good Visit is recorded when we open a url in a new incognito
+// tab.
+TEST_F(FeedMetricsRecorderTest, GoodVisit_OpenInNewIncognitoTab) {
+  // There should not be a Good Visit recorded.
+  histogram_tester_->ExpectBucketCount(kAllFeedsEngagementTypeHistogram,
+                                       FeedEngagementType::kGoodVisit, 0);
+  // After Action, Good Visit should be recorded.
+  [recorder recordOpenURLInIncognitoTab];
+  histogram_tester_->ExpectBucketCount(kAllFeedsEngagementTypeHistogram,
+                                       FeedEngagementType::kGoodVisit, 1);
+}
+
+// Tests that a Good Visit is recorded when we do a long press on a card.
+TEST_F(FeedMetricsRecorderTest, GoodVisit_LongPress) {
+  // There should not be a Good Visit recorded.
+  histogram_tester_->ExpectBucketCount(kAllFeedsEngagementTypeHistogram,
+                                       FeedEngagementType::kGoodVisit, 0);
+  // After Action, Good Visit should be recorded.
+  [recorder recordNativeContextMenuVisibilityChanged:YES];
+  histogram_tester_->ExpectBucketCount(kAllFeedsEngagementTypeHistogram,
+                                       FeedEngagementType::kGoodVisit, 1);
+}
+
+// Tests that a Good Visit is only logged once for each Good Visit session.
+TEST_F(FeedMetricsRecorderTest, GoodVisit_OnlyLoggedOncePerVisit) {
+  // There should not be a Good Visit recorded.
+  histogram_tester_->ExpectBucketCount(kAllFeedsEngagementTypeHistogram,
+                                       FeedEngagementType::kGoodVisit, 0);
+  // Start with a Good Visit.
+  [recorder recordAddURLToReadLater];
+  histogram_tester_->ExpectBucketCount(kAllFeedsEngagementTypeHistogram,
+                                       FeedEngagementType::kGoodVisit, 1);
+  // Adding to Read Later should count as a Good Visit, but we only log one Good
+  // Visit per session, so the histogram count should remain at 1.
+  [recorder recordAddURLToReadLater];
+  histogram_tester_->ExpectBucketCount(kAllFeedsEngagementTypeHistogram,
+                                       FeedEngagementType::kGoodVisit, 1);
+}
+
+// Tests that a Good Visit is not logged when a non-Good Visit action is
+// triggered.
+TEST_F(FeedMetricsRecorderTest, GoodVisit_NonGoodVisitActionTriggered) {
+  // There should not be a Good Visit recorded.
+  histogram_tester_->ExpectBucketCount(kAllFeedsEngagementTypeHistogram,
+                                       FeedEngagementType::kGoodVisit, 0);
+  // Trigger a non-Good Visit action.
+  [recorder recordHeaderMenuManageTapped];
+  // There should not be a Good Visit recorded as the action was not a trigger
+  // for a Good Visit.
+  histogram_tester_->ExpectBucketCount(kAllFeedsEngagementTypeHistogram,
+                                       FeedEngagementType::kGoodVisit, 0);
+}
+
+// TODO(crbug.com/1399110): Add Time-Based tests in follow up CL.
diff --git a/ios/chrome/browser/ui/ntp/metrics/feed_session_recorder+testing.h b/ios/chrome/browser/ui/ntp/metrics/feed_session_recorder+testing.h
index 6f86a9ec..bcdcc44 100644
--- a/ios/chrome/browser/ui/ntp/metrics/feed_session_recorder+testing.h
+++ b/ios/chrome/browser/ui/ntp/metrics/feed_session_recorder+testing.h
@@ -5,8 +5,8 @@
 #ifndef IOS_CHROME_BROWSER_UI_NTP_METRICS_FEED_SESSION_RECORDER_TESTING_H_
 #define IOS_CHROME_BROWSER_UI_NTP_METRICS_FEED_SESSION_RECORDER_TESTING_H_
 
-#include "base/time/time.h"
-#include "ios/chrome/browser/ui/ntp/metrics/feed_session_recorder.h"
+#import "base/time/time.h"
+#import "ios/chrome/browser/ui/ntp/metrics/feed_session_recorder.h"
 
 // Category for exposing properties and methods for testing.
 @interface FeedSessionRecorder (Testing)
@@ -16,6 +16,9 @@
 @property(nonatomic, assign) base::TimeDelta timeBetweenSessions;
 // Exposing the recorded time between interactions.
 @property(nonatomic, assign) base::TimeDelta timeBetweenInteractions;
+// Exposing previousTimeInFeedForGoodVisitSession
+@property(nonatomic, assign)
+    NSTimeInterval previousTimeInFeedForGoodVisitSession;
 // Exposing a private version of the method `recordUserInteractionOrScrolling`
 // that takes an argument. `interactionDate` is the date (and time) of the user
 // interaction or scrolling event.
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm b/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm
index a7370049..6108620 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm
+++ b/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm
@@ -770,28 +770,6 @@
 
 @end
 
-// Test case for the NTP home UI, except the new omnibox popup flag is enabled
-// with variant 2.
-@interface NewOmniboxPopupLocationBarSteadyStateVariant2TestCase
-    : NewOmniboxPopupLocationBarSteadyStateTestCase
-@end
-
-@implementation NewOmniboxPopupLocationBarSteadyStateVariant2TestCase
-
-- (void)setUp {
-  _variant = std::string(kIOSOmniboxUpdatedPopupUIVariation2UIKit);
-
-  // `appConfigurationForTestCase` is called during [super setUp], and
-  // depends on _variant.
-  [super setUp];
-}
-
-// This is currently needed to prevent this test case from being ignored.
-- (void)testEmpty {
-}
-
-@end
-
 #pragma mark - Edit state tests
 
 @interface LocationBarEditStateTestCase : ChromeTestCase
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_ui_features.cc b/ios/chrome/browser/ui/omnibox/omnibox_ui_features.cc
index ff7f3933..3f020be4 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_ui_features.cc
+++ b/ios/chrome/browser/ui/omnibox/omnibox_ui_features.cc
@@ -37,20 +37,11 @@
 }
 
 bool IsOmniboxActionsVisualTreatment1() {
-  if (!IsOmniboxActionsEnabled()) {
-    return false;
-  }
-  auto param = base::GetFieldTrialParamValueByFeature(
-      kIOSOmniboxUpdatedPopupUI, kIOSOmniboxUpdatedPopupUIVariationName);
-  return param == kIOSOmniboxUpdatedPopupUIVariation1 ||
-         param == kIOSOmniboxUpdatedPopupUIVariation1UIKit;
+  return base::FeatureList::IsEnabled(kIOSOmniboxUpdatedPopupUI);
 }
 
 bool IsOmniboxActionsVisualTreatment2() {
-  if (!IsOmniboxActionsEnabled()) {
-    return false;
-  }
-  return !IsOmniboxActionsVisualTreatment1();
+  return false;
 }
 
 bool IsSwiftUIPopupEnabled() {
diff --git a/ios/chrome/browser/ui/ui_feature_flags.cc b/ios/chrome/browser/ui/ui_feature_flags.cc
index 63c6d8d..b4cc0633 100644
--- a/ios/chrome/browser/ui/ui_feature_flags.cc
+++ b/ios/chrome/browser/ui/ui_feature_flags.cc
@@ -61,7 +61,7 @@
 
 BASE_FEATURE(kIOSOmniboxUpdatedPopupUI,
              "IOSOmniboxUpdatedPopupUI",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+             base::FEATURE_ENABLED_BY_DEFAULT);
 
 BASE_FEATURE(kRemoveCrashInfobar,
              "RemoveCrashInfobar",
@@ -86,7 +86,7 @@
 
 BASE_FEATURE(kUseLensToSearchForImage,
              "UseLensToSearchForImage",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+             base::FEATURE_ENABLED_BY_DEFAULT);
 
 BASE_FEATURE(kEnableLensInHomeScreenWidget,
              "EnableLensInHomeScreenWidget",
diff --git a/media/base/audio_latency.cc b/media/base/audio_latency.cc
index ced5873..abf1d90 100644
--- a/media/base/audio_latency.cc
+++ b/media/base/audio_latency.cc
@@ -207,14 +207,14 @@
   DCHECK_GE(max_hardware_buffer_size, min_hardware_buffer_size);
   DCHECK(max_hardware_buffer_size == 0 ||
          hardware_buffer_size <= max_hardware_buffer_size);
-  DCHECK(max_hardware_buffer_size == 0 ||
-         max_hardware_buffer_size <= max_allowed_buffer_size);
+  DCHECK_LE(hardware_buffer_size, max_allowed_buffer_size);
 
   int requested_buffer_size = std::round(duration.InSecondsF() * sample_rate);
 
   if (min_hardware_buffer_size &&
-      requested_buffer_size <= min_hardware_buffer_size)
+      requested_buffer_size <= min_hardware_buffer_size) {
     return min_hardware_buffer_size;
+  }
 
   if (requested_buffer_size <= hardware_buffer_size)
     return hardware_buffer_size;
@@ -244,7 +244,8 @@
   }
 
   const int platform_max_buffer_size =
-      max_hardware_buffer_size
+      (max_hardware_buffer_size &&
+       max_hardware_buffer_size <= max_allowed_buffer_size)
           ? (max_allowed_buffer_size / max_hardware_buffer_size) *
                 max_hardware_buffer_size
           : (max_allowed_buffer_size / multiplier) * multiplier;
diff --git a/media/base/audio_latency.h b/media/base/audio_latency.h
index 2b000bc..ff59112 100644
--- a/media/base/audio_latency.h
+++ b/media/base/audio_latency.h
@@ -44,24 +44,27 @@
   static int GetInteractiveBufferSize(int hardware_buffer_size);
 
   // Return the closest buffer size for this platform that will result in a
-  // latency not less than |duration| for the given |sample_rate|.
+  // latency not less than `duration` for the given `sample_rate`.
   //
   // Requirements:
-  // - |hardware_buffer_size| > 0 and |max_allowed_buffer_size| > 0.
-  // - If |min_hardware_buffer_size| and |max_hardware_buffer_size| are > 0 then
-  //   the following must be true: |min_hardware_buffer_size| <=
-  //   |hardware_buffer_size| <= |max_hardware_buffer_size| <=
-  //   |max_allowed_buffer_size|.
+  // - `hardware_buffer_size > 0` and `max_allowed_buffer_size > 0`.
+  // - If `min_hardware_buffer_size` and `max_hardware_buffer_size` are > 0 then
+  //   the following must be true: `min_hardware_buffer_size <=
+  //   hardware_buffer_size <= max_hardware_buffer_size`
+  // - `hardware_buffer_size <= max_allowed_buffer_size`
   //
   // The returned buffer size is guaranteed to be between
-  // |min_hardware_buffer_size| and |max_allowed_buffer_size|.
-  // |max_hardware_buffer_size| is used to help determine a buffer size that
+  // `min_hardware_buffer_size` and `max_allowed_buffer_size`.
+  // `max_hardware_buffer_size` is used to help determine a buffer size that
   // won't cause the caller and the hardware to run at unsynchronized buffer
   // sizes (e.g. hardware running at 4096 and caller running at 4224).
-  // |hardware_buffer_size| is the platform's preferred buffer size.
+  // `hardware_buffer_size` is the platform's preferred buffer size.
+  //
+  // TODO(crbug.com/1395234) Ensure that all callers validate conditions listed
+  // above.
   //
   // It is valid for both the min and max to be zero in which case only
-  // |hardware_buffer_size| and multiples of it will be used.
+  // `hardware_buffer_size` and multiples of it will be used.
   static int GetExactBufferSize(base::TimeDelta duration,
                                 int sample_rate,
                                 int hardware_buffer_size,
diff --git a/media/base/audio_latency_unittest.cc b/media/base/audio_latency_unittest.cc
index 6b5145c..d1f0d27a 100644
--- a/media/base/audio_latency_unittest.cc
+++ b/media/base/audio_latency_unittest.cc
@@ -41,7 +41,7 @@
 #endif
 
     const int platform_max_buffer_size =
-        max_buffer_size
+        (max_buffer_size && max_buffer_size < limits::kMaxWebAudioBufferSize)
             ? (limits::kMaxWebAudioBufferSize / max_buffer_size) *
                   max_buffer_size
             : (limits::kMaxWebAudioBufferSize / multiplier) * multiplier;
@@ -74,7 +74,7 @@
         media::AudioLatency::GetExactBufferSize(
             base::Seconds(10.0), hardware_sample_rate, hardware_buffer_size,
             min_buffer_size, max_buffer_size, limits::kMaxWebAudioBufferSize));
-    if (max_buffer_size) {
+    if (max_buffer_size && max_buffer_size < limits::kMaxWebAudioBufferSize) {
       EXPECT_EQ(max_buffer_size,
                 media::AudioLatency::GetExactBufferSize(
                     base::Seconds(max_buffer_size /
@@ -203,7 +203,8 @@
                                     limits::kMaxAudioBufferSize))
 #else
     testing::Values(std::make_tuple(44100, 256, 0, 0),
-                    std::make_tuple(44100, 440, 0, 0))
+                    std::make_tuple(44100, 440, 0, 0),
+                    std::make_tuple(48000, 480, 480, 48000))
 #endif
 );
 }  // namespace media
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc
index f079269..9e9fdd2a 100644
--- a/media/base/media_switches.cc
+++ b/media/base/media_switches.cc
@@ -452,11 +452,21 @@
              "MemoryPressureBasedSourceBufferGC",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+// Enables binding software video NV12/P010 GMBs as separate shared images.
+BASE_FEATURE(kMultiPlaneSoftwareVideoSharedImages,
+             "MultiPlaneSoftwareVideoSharedImages",
+#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
+             base::FEATURE_ENABLED_BY_DEFAULT
+#else
+             base::FEATURE_DISABLED_BY_DEFAULT
+#endif
+);
+
 // Enable binding multiple shared images to a single GpuMemoryBuffer for video
 // frames created by video capture.
 BASE_FEATURE(kMultiPlaneVideoCaptureSharedImages,
              "MultiPlaneVideoCaptureSharedImages",
-#if BUILDFLAG(IS_MAC)
+#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
              base::FEATURE_ENABLED_BY_DEFAULT
 #else
              base::FEATURE_DISABLED_BY_DEFAULT
diff --git a/media/base/media_switches.h b/media/base/media_switches.h
index 483ee22..5243e1f1 100644
--- a/media/base/media_switches.h
+++ b/media/base/media_switches.h
@@ -216,6 +216,7 @@
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kMediaOptimizer);
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kMediaPowerExperiment);
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kMemoryPressureBasedSourceBufferGC);
+MEDIA_EXPORT BASE_DECLARE_FEATURE(kMultiPlaneSoftwareVideoSharedImages);
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kMultiPlaneVideoCaptureSharedImages);
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kOpenscreenCastStreamingSession);
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kOverlayFullscreenVideo);
diff --git a/media/gpu/v4l2/test/v4l2_stateless_decoder.cc b/media/gpu/v4l2/test/v4l2_stateless_decoder.cc
index 30368be..45565ac 100644
--- a/media/gpu/v4l2/test/v4l2_stateless_decoder.cc
+++ b/media/gpu/v4l2/test/v4l2_stateless_decoder.cc
@@ -204,9 +204,7 @@
         base::StringPrintf("%s%.6d.yuv", output_file_prefix.c_str(), i));
     base::File output_file(
         filename, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
-    output_file.WriteAtCurrentPos(y_plane.data(), size.GetArea());
-    output_file.WriteAtCurrentPos(u_plane.data(), size.GetArea() / 4);
-    output_file.WriteAtCurrentPos(v_plane.data(), size.GetArea() / 4);
+    output_file.Write(0, yuv_plane.data(), yuv_plane.size());
   }
 
   return EXIT_SUCCESS;
diff --git a/media/video/gpu_memory_buffer_video_frame_pool.cc b/media/video/gpu_memory_buffer_video_frame_pool.cc
index a67c6bd..3035d18 100644
--- a/media/video/gpu_memory_buffer_video_frame_pool.cc
+++ b/media/video/gpu_memory_buffer_video_frame_pool.cc
@@ -55,15 +55,6 @@
 
 namespace media {
 
-BASE_FEATURE(kMultiPlaneSoftwareVideoSharedImages,
-             "MultiPlaneSoftwareVideoSharedImages",
-#if BUILDFLAG(IS_MAC)
-             base::FEATURE_ENABLED_BY_DEFAULT
-#else
-             base::FEATURE_DISABLED_BY_DEFAULT
-#endif
-);
-
 bool GpuMemoryBufferVideoFramePool::MultiPlaneVideoSharedImagesEnabled() {
   return base::FeatureList::IsEnabled(kMultiPlaneSoftwareVideoSharedImages);
 }
@@ -1230,9 +1221,12 @@
 
   bool allow_overlay = false;
 #if BUILDFLAG(IS_WIN)
-  // Windows direct composition path only supports dual GMB NV12 video overlays.
+  // Windows direct composition path only supports NV12 video overlays. We use
+  // separate shared images for the planes for both single and dual NV12 GMBs.
   allow_overlay = (output_format_ ==
-                   GpuVideoAcceleratorFactories::OutputFormat::NV12_DUAL_GMB);
+                   GpuVideoAcceleratorFactories::OutputFormat::NV12_DUAL_GMB) ||
+                  (output_format_ ==
+                   GpuVideoAcceleratorFactories::OutputFormat::NV12_SINGLE_GMB);
 #else
   switch (output_format_) {
     case GpuVideoAcceleratorFactories::OutputFormat::I420:
@@ -1243,7 +1237,7 @@
       allow_overlay = true;
       break;
     case GpuVideoAcceleratorFactories::OutputFormat::NV12_DUAL_GMB:
-      // Only used on Windows where we can't use single NV12 textures.
+      // Only used on configurations where we can't support overlays.
       break;
     case GpuVideoAcceleratorFactories::OutputFormat::XR30:
     case GpuVideoAcceleratorFactories::OutputFormat::XB30:
diff --git a/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc b/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc
index eb32f8e..396c1f1 100644
--- a/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc
+++ b/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc
@@ -774,13 +774,13 @@
 
   EXPECT_NE(software_frame.get(), frame.get());
   EXPECT_EQ(PIXEL_FORMAT_P016LE, frame->format());
-#if BUILDFLAG(IS_MAC)
-  EXPECT_EQ(2u, frame->NumTextures());
-  EXPECT_EQ(2u, sii_->shared_image_count());
-#else
-  EXPECT_EQ(1u, frame->NumTextures());
-  EXPECT_EQ(1u, sii_->shared_image_count());
-#endif
+  if (GpuMemoryBufferVideoFramePool::MultiPlaneVideoSharedImagesEnabled()) {
+    EXPECT_EQ(2u, frame->NumTextures());
+    EXPECT_EQ(2u, sii_->shared_image_count());
+  } else {
+    EXPECT_EQ(1u, frame->NumTextures());
+    EXPECT_EQ(1u, sii_->shared_image_count());
+  }
   EXPECT_TRUE(frame->metadata().read_lock_fences_enabled);
 
   EXPECT_EQ(1u, mock_gpu_factories_->created_memory_buffers().size());
@@ -814,13 +814,13 @@
       gfx::IsOddHeightMultiPlanarBuffersAllowed()) {
     EXPECT_NE(software_frame.get(), frame.get());
     EXPECT_EQ(PIXEL_FORMAT_P016LE, frame->format());
-#if BUILDFLAG(IS_MAC)
-    EXPECT_EQ(2u, frame->NumTextures());
-    EXPECT_EQ(2u, sii_->shared_image_count());
-#else
-    EXPECT_EQ(1u, frame->NumTextures());
-    EXPECT_EQ(1u, sii_->shared_image_count());
-#endif
+    if (GpuMemoryBufferVideoFramePool::MultiPlaneVideoSharedImagesEnabled()) {
+      EXPECT_EQ(2u, frame->NumTextures());
+      EXPECT_EQ(2u, sii_->shared_image_count());
+    } else {
+      EXPECT_EQ(1u, frame->NumTextures());
+      EXPECT_EQ(1u, sii_->shared_image_count());
+    }
     EXPECT_TRUE(frame->metadata().read_lock_fences_enabled);
 
     EXPECT_EQ(1u, mock_gpu_factories_->created_memory_buffers().size());
diff --git a/mojo/public/java/system/src/org/chromium/mojo/system/impl/CoreImpl.java b/mojo/public/java/system/src/org/chromium/mojo/system/impl/CoreImpl.java
index 74c6716..00927b1 100644
--- a/mojo/public/java/system/src/org/chromium/mojo/system/impl/CoreImpl.java
+++ b/mojo/public/java/system/src/org/chromium/mojo/system/impl/CoreImpl.java
@@ -239,7 +239,9 @@
         if (handles != null && !handles.isEmpty()) {
             handlesBuffer = allocateDirectBuffer(handles.size() * HANDLE_SIZE);
             for (Handle handle : handles) {
-                handlesBuffer.putLong(getMojoHandle(handle));
+                // NOTE: Handles are closed by native code regardless of whether writeMessage()
+                // succeeds below, so we unconditionally release them here.
+                handlesBuffer.putLong(handle.releaseNativeHandle());
             }
             handlesBuffer.position(0);
         }
@@ -248,14 +250,6 @@
         if (mojoResult != MojoResult.OK) {
             throw new MojoException(mojoResult);
         }
-        // Success means the handles have been invalidated.
-        if (handles != null) {
-            for (Handle handle : handles) {
-                if (handle.isValid()) {
-                    ((HandleBase) handle).invalidateHandle();
-                }
-            }
-        }
     }
 
     /**
diff --git a/net/quic/web_transport_client.h b/net/quic/web_transport_client.h
index af1941a77..fd4b312 100644
--- a/net/quic/web_transport_client.h
+++ b/net/quic/web_transport_client.h
@@ -103,7 +103,6 @@
 
   bool allow_pooling = false;
 
-  bool enable_quic_transport = false;
   bool enable_web_transport_http3 = false;
 
   // A vector of fingerprints for expected server certificates, as described in
diff --git a/printing/print_settings.h b/printing/print_settings.h
index f2907c1e..3596f3c6 100644
--- a/printing/print_settings.h
+++ b/printing/print_settings.h
@@ -146,12 +146,22 @@
 
   int device_units_per_inch() const {
 #if BUILDFLAG(IS_MAC)
-    return 72;
+    return kMacDeviceUnitsPerInch;
 #else   // BUILDFLAG(IS_MAC)
     return dpi();
 #endif  // BUILDFLAG(IS_MAC)
   }
 
+  const gfx::Size& device_units_per_inch_size() const {
+#if BUILDFLAG(IS_MAC)
+    static constexpr gfx::Size kSize{kMacDeviceUnitsPerInch,
+                                     kMacDeviceUnitsPerInch};
+    return kSize;
+#else   // BUILDFLAG(IS_MAC)
+    return dpi_size();
+#endif  // BUILDFLAG(IS_MAC)
+  }
+
   void set_ranges(const PageRanges& ranges) { ranges_ = ranges; }
   const PageRanges& ranges() const { return ranges_; }
 
@@ -252,6 +262,10 @@
   static int NewCookie();
 
  private:
+#if BUILDFLAG(IS_MAC)
+  static constexpr int kMacDeviceUnitsPerInch = 72;
+#endif
+
   // Multi-page printing. Each `PageRange` describes a from-to page combination.
   // This permits printing selected pages only.
   PageRanges ranges_;
diff --git a/printing/print_settings_conversion.cc b/printing/print_settings_conversion.cc
index 1c7afa9a..2efe97f 100644
--- a/printing/print_settings_conversion.cc
+++ b/printing/print_settings_conversion.cc
@@ -95,8 +95,11 @@
 
   // Scale the page size and printable area to device units.
   float x_scale =
-      static_cast<float>(settings.dpi_horizontal()) / kMicronsPerInch;
-  float y_scale = static_cast<float>(settings.dpi_vertical()) / kMicronsPerInch;
+      static_cast<float>(settings.device_units_per_inch_size().width()) /
+      kMicronsPerInch;
+  float y_scale =
+      static_cast<float>(settings.device_units_per_inch_size().height()) /
+      kMicronsPerInch;
   gfx::Size page_size = gfx::ScaleToRoundedSize(size_microns, x_scale, y_scale);
   // Flip the y-axis since the imageable area origin is at the bottom-left,
   // while the gfx::Rect origin is at the top-left.
diff --git a/printing/print_settings_conversion_unittest.cc b/printing/print_settings_conversion_unittest.cc
index f9f496a..213bed16 100644
--- a/printing/print_settings_conversion_unittest.cc
+++ b/printing/print_settings_conversion_unittest.cc
@@ -111,7 +111,15 @@
   EXPECT_FALSE(settings);
 }
 
-TEST(PrintSettingsConversionTest, ConversionTestWithValidImageableArea) {
+TEST(PrintSettingsConversionTest, WithValidImageableArea) {
+#if BUILDFLAG(IS_MAC)
+  static constexpr gfx::Size kExpectedSize{595, 842};
+  static constexpr gfx::Rect kExpectedPrintableArea{0, 0, 510, 839};
+#else
+  static constexpr gfx::Size kExpectedSize{2480, 3508};
+  static constexpr gfx::Rect kExpectedPrintableArea{0, 0, 2126, 3496};
+#endif
+
   base::Value value = base::test::ParseJson(kPrinterSettingsWithImageableArea);
   ASSERT_TRUE(value.is_dict());
   auto& dict = value.GetDict();
@@ -119,26 +127,32 @@
   ASSERT_TRUE(settings);
   EXPECT_EQ(settings->dpi_horizontal(), 300);
   EXPECT_EQ(settings->dpi_vertical(), 300);
-  EXPECT_EQ(settings->page_setup_device_units().physical_size(),
-            gfx::Size(2480, 3508));
+  EXPECT_EQ(settings->page_setup_device_units().physical_size(), kExpectedSize);
   EXPECT_EQ(settings->page_setup_device_units().printable_area(),
-            gfx::Rect(0, 0, 2126, 3496));
+            kExpectedPrintableArea);
 }
 
-TEST(PrintSettingsConversionTest, ConversionTestWithValidFlippedImageableArea) {
+TEST(PrintSettingsConversionTest, WithValidFlippedImageableArea) {
+#if BUILDFLAG(IS_MAC)
+  static constexpr gfx::Size kExpectedSize{842, 595};
+  static constexpr gfx::Rect kExpectedPrintableArea{0, 85, 839, 510};
+#else
+  static constexpr gfx::Size kExpectedSize{3508, 2480};
+  static constexpr gfx::Rect kExpectedPrintableArea{0, 354, 3496, 2126};
+#endif
+
   base::Value value = base::test::ParseJson(kPrinterSettingsWithImageableArea);
   ASSERT_TRUE(value.is_dict());
   auto& dict = value.GetDict();
   dict.Set("landscape", true);
   std::unique_ptr<PrintSettings> settings = PrintSettingsFromJobSettings(dict);
   ASSERT_TRUE(settings);
-  EXPECT_EQ(settings->page_setup_device_units().physical_size(),
-            gfx::Size(3508, 2480));
+  EXPECT_EQ(settings->page_setup_device_units().physical_size(), kExpectedSize);
   EXPECT_EQ(settings->page_setup_device_units().printable_area(),
-            gfx::Rect(0, 354, 3496, 2126));
+            kExpectedPrintableArea);
 }
 
-TEST(PrintSettingsConversionTest, ConversionTestWithOutOfBoundsImageableArea) {
+TEST(PrintSettingsConversionTest, WithOutOfBoundsImageableArea) {
   base::Value value = base::test::ParseJson(kPrinterSettingsWithImageableArea);
   ASSERT_TRUE(value.is_dict());
   auto& dict = value.GetDict();
@@ -151,7 +165,7 @@
   EXPECT_TRUE(settings->page_setup_device_units().printable_area().IsEmpty());
 }
 
-TEST(PrintSettingsConversionTest, ConversionTestWithMissingImageableAreaValue) {
+TEST(PrintSettingsConversionTest, WithMissingImageableAreaValue) {
   base::Value value = base::test::ParseJson(kPrinterSettingsWithImageableArea);
   ASSERT_TRUE(value.is_dict());
   auto& dict = value.GetDict();
diff --git a/services/device/geolocation/BUILD.gn b/services/device/geolocation/BUILD.gn
index 98af4ed..60903b00 100644
--- a/services/device/geolocation/BUILD.gn
+++ b/services/device/geolocation/BUILD.gn
@@ -52,6 +52,7 @@
 
   deps = [
     "//base",
+    "//components/device_event_log",
     "//mojo/public/cpp/bindings",
     "//mojo/public/cpp/system",
     "//net",
diff --git a/services/device/geolocation/DEPS b/services/device/geolocation/DEPS
index 878c3d9..aae53f9 100644
--- a/services/device/geolocation/DEPS
+++ b/services/device/geolocation/DEPS
@@ -2,6 +2,7 @@
   "+chromeos",
   "+chromeos/crosapi",
   "+chromeos/lacros",
+  "+components/device_event_log",
   "+components/location",
   "+dbus",
   "+net/base",
diff --git a/services/device/geolocation/network_location_provider.cc b/services/device/geolocation/network_location_provider.cc
index ecc368f7..5f6f0f61 100644
--- a/services/device/geolocation/network_location_provider.cc
+++ b/services/device/geolocation/network_location_provider.cc
@@ -15,6 +15,7 @@
 #include "base/task/task_runner.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "components/device_event_log/device_event_log.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/device/geolocation/position_cache.h"
 #include "services/device/public/cpp/geolocation/geoposition.h"
@@ -34,6 +35,7 @@
 // be returned as a fresh estimate. This should be at least as long as the
 // longest polling interval used by the WifiDataProvider.
 const int kLastPositionMaxAgeSeconds = 10 * 60;  // 10 minutes
+
 }  // namespace
 
 // NetworkLocationProvider
@@ -150,6 +152,9 @@
   // In this case it is better to call RequestPosition and return a cached
   // position estimate if it is available.
   bool delayed = wifi_data_provider_handle_->DelayedByPolicy();
+  GEOLOCATION_LOG(DEBUG)
+      << "New Wi-Fi data is available: is_wifi_data_complete_="
+      << is_wifi_data_complete_ << " delayed=" << delayed;
   if (is_wifi_data_complete_ || delayed)
     RequestPosition();
 }
@@ -159,6 +164,7 @@
     bool server_error,
     const WifiData& wifi_data) {
   DCHECK(thread_checker_.CalledOnValidThread());
+  GEOLOCATION_LOG(DEBUG) << "Got new position";
   // Record the position and update our cache.
   position_cache_->SetLastUsedNetworkPosition(position);
   if (ValidateGeoposition(position))
@@ -171,6 +177,7 @@
 }
 
 void NetworkLocationProvider::StartProvider(bool high_accuracy) {
+  GEOLOCATION_LOG(DEBUG) << "Start provider: high_accuracy=" << high_accuracy;
   DCHECK(thread_checker_.CalledOnValidThread());
 
   if (IsStarted())
@@ -191,6 +198,7 @@
 }
 
 void NetworkLocationProvider::StopProvider() {
+  GEOLOCATION_LOG(DEBUG) << "Stop provider";
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(IsStarted());
   wifi_data_provider_handle_ = nullptr;
@@ -203,6 +211,9 @@
 
 void NetworkLocationProvider::RequestPosition() {
   DCHECK(thread_checker_.CalledOnValidThread());
+  GEOLOCATION_LOG(DEBUG) << "Request position: is_new_data_available_="
+                         << is_new_data_available_ << " is_wifi_data_complete_="
+                         << is_wifi_data_complete_;
 
 #if BUILDFLAG(IS_MAC)
   if (!is_system_permission_granted_) {
@@ -227,6 +238,8 @@
     base::TimeDelta last_position_age = now - last_position.timestamp;
     if (last_position_age.InSeconds() < kLastPositionMaxAgeSeconds &&
         !location_provider_update_callback_.is_null()) {
+      GEOLOCATION_LOG(DEBUG)
+          << "Updating the last network position timestamp to the current time";
       // Update the timestamp to the current time.
       mojom::Geoposition position = last_position;
       position.timestamp = now;
@@ -256,6 +269,7 @@
     position.timestamp = wifi_timestamp_;
     is_new_data_available_ = false;
 
+    GEOLOCATION_LOG(DEBUG) << "Updating the cached WiFi position: ";
     // Record the position.
     position_cache_->SetLastUsedNetworkPosition(position);
 
diff --git a/services/device/geolocation/network_location_request.cc b/services/device/geolocation/network_location_request.cc
index 54d62420..ae26ef6 100644
--- a/services/device/geolocation/network_location_request.cc
+++ b/services/device/geolocation/network_location_request.cc
@@ -22,6 +22,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
+#include "components/device_event_log/device_event_log.h"
 #include "net/base/load_flags.h"
 #include "net/base/net_errors.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
@@ -128,9 +129,13 @@
     const WifiData& wifi_data,
     const base::Time& wifi_timestamp,
     const net::PartialNetworkTrafficAnnotationTag& partial_traffic_annotation) {
+  GEOLOCATION_LOG(DEBUG)
+      << "Sending a network location request: Number of Wi-Fi APs="
+      << wifi_data.access_point_data.size();
   RecordUmaEvent(NETWORK_LOCATION_REQUEST_EVENT_REQUEST_START);
   RecordUmaAccessPoints(wifi_data.access_point_data.size());
   if (url_loader_) {
+    GEOLOCATION_LOG(DEBUG) << "Cancelling pending network location request";
     DVLOG(1) << "NetworkLocationRequest : Cancelling pending request";
     RecordUmaEvent(NETWORK_LOCATION_REQUEST_EVENT_REQUEST_CANCEL);
     url_loader_.reset();
@@ -189,6 +194,8 @@
   if (url_loader_->ResponseInfo())
     response_code = url_loader_->ResponseInfo()->headers->response_code();
   RecordUmaResponseCode(response_code);
+  GEOLOCATION_LOG(DEBUG) << "Got network location response: response_code="
+                         << response_code;
 
   mojom::Geoposition position;
   GetLocationFromResponse(net_error, response_code, std::move(data),
diff --git a/services/device/geolocation/position_cache_impl.cc b/services/device/geolocation/position_cache_impl.cc
index 000e17a..ce444e37 100644
--- a/services/device/geolocation/position_cache_impl.cc
+++ b/services/device/geolocation/position_cache_impl.cc
@@ -6,6 +6,7 @@
 
 #include "base/ranges/algorithm.h"
 #include "base/strings/utf_string_conversions.h"
+#include "components/device_event_log/device_event_log.h"
 #include "services/device/geolocation/wifi_data.h"
 #include "services/device/public/mojom/geoposition.mojom.h"
 
@@ -85,6 +86,7 @@
 
 const mojom::Geoposition& PositionCacheImpl::GetLastUsedNetworkPosition()
     const {
+  GEOLOCATION_LOG(DEBUG) << "Get last used network position";
   return last_used_position_;
 }
 
@@ -95,6 +97,7 @@
 
 void PositionCacheImpl::OnNetworkChanged(
     net::NetworkChangeNotifier::ConnectionType) {
+  GEOLOCATION_LOG(DEBUG) << "Network changed";
   // OnNetworkChanged is called " when a change occurs to the host
   // computer's hardware or software that affects the route network packets
   // take to any network server.". This means that whatever position we had
diff --git a/services/device/geolocation/wifi_data_provider_common.cc b/services/device/geolocation/wifi_data_provider_common.cc
index 0ba01643..b519b3b 100644
--- a/services/device/geolocation/wifi_data_provider_common.cc
+++ b/services/device/geolocation/wifi_data_provider_common.cc
@@ -10,6 +10,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/single_thread_task_runner.h"
+#include "components/device_event_log/device_event_log.h"
 
 namespace device {
 
@@ -81,6 +82,9 @@
     WifiPollingPolicy::Get()->UpdatePollingInterval(update_available);
     ScheduleNextScan(WifiPollingPolicy::Get()->PollingInterval());
   }
+  GEOLOCATION_LOG(DEBUG) << "Scanned: update_available=" << update_available
+                         << " is_first_scan_complete_="
+                         << is_first_scan_complete_;
   if (update_available || !is_first_scan_complete_) {
     is_first_scan_complete_ = true;
     RunCallbacks();
@@ -88,6 +92,7 @@
 }
 
 void WifiDataProviderCommon::ScheduleNextScan(int interval) {
+  GEOLOCATION_LOG(DEBUG) << "Schedule next scan: interval=" << interval << "ms";
   client_task_runner()->PostDelayedTask(
       FROM_HERE,
       base::BindOnce(&WifiDataProviderCommon::DoWifiScanTask,
diff --git a/services/network/web_transport.cc b/services/network/web_transport.cc
index 2c5f739..a0e1ac53 100644
--- a/services/network/web_transport.cc
+++ b/services/network/web_transport.cc
@@ -27,7 +27,6 @@
     const std::vector<mojom::WebTransportCertificateFingerprintPtr>&
         fingerprints) {
   net::WebTransportParameters params;
-  params.enable_quic_transport = false;
   params.enable_web_transport_http3 = true;
 
   for (const auto& fingerprint : fingerprints) {
diff --git a/services/viz/public/cpp/compositing/shared_quad_state_mojom_traits.h b/services/viz/public/cpp/compositing/shared_quad_state_mojom_traits.h
index eec64be..6cff66383 100644
--- a/services/viz/public/cpp/compositing/shared_quad_state_mojom_traits.h
+++ b/services/viz/public/cpp/compositing/shared_quad_state_mojom_traits.h
@@ -67,10 +67,6 @@
   static bool is_fast_rounded_corner(const OptSharedQuadState& input) {
     return input.sqs->is_fast_rounded_corner;
   }
-
-  static float de_jelly_delta_y(const OptSharedQuadState& input) {
-    return input.sqs->de_jelly_delta_y;
-  }
 };
 
 template <>
@@ -117,10 +113,6 @@
     return sqs.is_fast_rounded_corner;
   }
 
-  static float de_jelly_delta_y(const viz::SharedQuadState& sqs) {
-    return sqs.de_jelly_delta_y;
-  }
-
   static bool Read(viz::mojom::SharedQuadStateDataView data,
                    viz::SharedQuadState* out) {
     if (!data.ReadQuadToTargetTransform(&out->quad_to_target_transform) ||
@@ -138,7 +130,6 @@
     out->blend_mode = static_cast<SkBlendMode>(data.blend_mode());
     out->sorting_context_id = data.sorting_context_id();
     out->is_fast_rounded_corner = data.is_fast_rounded_corner();
-    out->de_jelly_delta_y = data.de_jelly_delta_y();
 
     return true;
   }
diff --git a/services/viz/public/mojom/compositing/shared_quad_state.mojom b/services/viz/public/mojom/compositing/shared_quad_state.mojom
index f8b3706..a4b29b4e 100644
--- a/services/viz/public/mojom/compositing/shared_quad_state.mojom
+++ b/services/viz/public/mojom/compositing/shared_quad_state.mojom
@@ -40,8 +40,4 @@
 
   bool is_fast_rounded_corner;
 
-  // The y offset by which to skew quads in this layer. For experimental
-  // de-jelly effect.
-  float de_jelly_delta_y;
-
 };
diff --git a/styleguide/c++/c++-features.md b/styleguide/c++/c++-features.md
index 51b646ab..95b403ff 100644
--- a/styleguide/c++/c++-features.md
+++ b/styleguide/c++/c++-features.md
@@ -38,6 +38,7 @@
     features below_
     *   absl::AnyInvocable: Initially supported June 20, 2022
     *   Log library: Initially supported Aug 31, 2022
+    *   CRC32C library: Initially supported Dec 5, 2022
 
 [TOC]
 
@@ -1937,6 +1938,19 @@
 Supplements `base/containers/`.
 ***
 
+### CRC32C library <sup>[tbd]</sup>
+
+**Description:** API for computing CRC32C values as checksums for arbitrary
+sequences of bytes provided as a string buffer.
+
+**Documentation:**
+[crc32.h](https://source.chromium.org/chromium/chromium/src/+/main:third_party/abseil-cpp/crc/crc32c.h)
+
+**Notes:**
+*** promo
+Overlaps with //third_party/crc32c.
+***
+
 ### Log macros and related classes <sup>[tbd]</sup>
 
 ```c++
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json
index 1aa96a2..cdc717d 100644
--- a/testing/buildbot/chrome.json
+++ b/testing/buildbot/chrome.json
@@ -1571,7 +1571,6 @@
               "pool": "chrome.tests"
             }
           ],
-          "hard_timeout": 7200,
           "idempotent": false,
           "io_timeout": 3600,
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -1915,7 +1914,7 @@
       {
         "args": [],
         "cros_board": "dedede",
-        "cros_img": "dedede-release/R109-15236.21.0",
+        "cros_img": "dedede-release/R109-15236.27.0",
         "name": "lacros_all_tast_tests DEDEDE_RELEASE_BETA",
         "resultdb": {
           "enable": true,
@@ -1979,7 +1978,7 @@
       {
         "args": [],
         "cros_board": "eve",
-        "cros_img": "eve-release/R109-15236.21.0",
+        "cros_img": "eve-release/R109-15236.27.0",
         "name": "lacros_all_tast_tests EVE_RELEASE_BETA",
         "resultdb": {
           "enable": true,
@@ -2122,7 +2121,7 @@
       {
         "args": [],
         "cros_board": "jacuzzi",
-        "cros_img": "jacuzzi-release/R109-15236.21.0",
+        "cros_img": "jacuzzi-release/R109-15236.27.0",
         "name": "lacros_all_tast_tests JACUZZI_RELEASE_BETA",
         "resultdb": {
           "enable": true,
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index 943ac95..95c4046 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -5750,9 +5750,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_v110.0.5464.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5465.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 110.0.5464.0",
+        "description": "Run with ash-chrome version 110.0.5465.0",
         "isolate_profile_data": true,
         "merge": {
           "args": [],
@@ -5764,8 +5764,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v110.0.5464.0",
-              "revision": "version:110.0.5464.0"
+              "location": "lacros_version_skew_tests_v110.0.5465.0",
+              "revision": "version:110.0.5465.0"
             }
           ],
           "dimension_sets": [
@@ -5921,9 +5921,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5464.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5465.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 110.0.5464.0",
+        "description": "Run with ash-chrome version 110.0.5465.0",
         "isolate_profile_data": true,
         "merge": {
           "args": [],
@@ -5935,8 +5935,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v110.0.5464.0",
-              "revision": "version:110.0.5464.0"
+              "location": "lacros_version_skew_tests_v110.0.5465.0",
+              "revision": "version:110.0.5465.0"
             }
           ],
           "dimension_sets": [
@@ -6073,9 +6073,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5464.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5465.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 110.0.5464.0",
+        "description": "Run with ash-chrome version 110.0.5465.0",
         "isolate_profile_data": true,
         "merge": {
           "args": [],
@@ -6087,8 +6087,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v110.0.5464.0",
-              "revision": "version:110.0.5464.0"
+              "location": "lacros_version_skew_tests_v110.0.5465.0",
+              "revision": "version:110.0.5465.0"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 8e5dbf2e..c07bd93ea 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -85321,9 +85321,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_v110.0.5464.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5465.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 110.0.5464.0",
+        "description": "Run with ash-chrome version 110.0.5465.0",
         "isolate_profile_data": true,
         "merge": {
           "args": [],
@@ -85335,8 +85335,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v110.0.5464.0",
-              "revision": "version:110.0.5464.0"
+              "location": "lacros_version_skew_tests_v110.0.5465.0",
+              "revision": "version:110.0.5465.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -85462,9 +85462,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5464.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5465.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 110.0.5464.0",
+        "description": "Run with ash-chrome version 110.0.5465.0",
         "isolate_profile_data": true,
         "merge": {
           "args": [],
@@ -85476,8 +85476,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v110.0.5464.0",
-              "revision": "version:110.0.5464.0"
+              "location": "lacros_version_skew_tests_v110.0.5465.0",
+              "revision": "version:110.0.5465.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -85589,9 +85589,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5464.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5465.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 110.0.5464.0",
+        "description": "Run with ash-chrome version 110.0.5465.0",
         "isolate_profile_data": true,
         "merge": {
           "args": [],
@@ -85603,8 +85603,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v110.0.5464.0",
-              "revision": "version:110.0.5464.0"
+              "location": "lacros_version_skew_tests_v110.0.5465.0",
+              "revision": "version:110.0.5465.0"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -86937,9 +86937,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_v110.0.5464.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5465.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 110.0.5464.0",
+        "description": "Run with ash-chrome version 110.0.5465.0",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -86950,8 +86950,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v110.0.5464.0",
-              "revision": "version:110.0.5464.0"
+              "location": "lacros_version_skew_tests_v110.0.5465.0",
+              "revision": "version:110.0.5465.0"
             }
           ],
           "dimension_sets": [
@@ -87108,9 +87108,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5464.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5465.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 110.0.5464.0",
+        "description": "Run with ash-chrome version 110.0.5465.0",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -87121,8 +87121,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v110.0.5464.0",
-              "revision": "version:110.0.5464.0"
+              "location": "lacros_version_skew_tests_v110.0.5465.0",
+              "revision": "version:110.0.5465.0"
             }
           ],
           "dimension_sets": [
@@ -87260,9 +87260,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5464.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5465.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 110.0.5464.0",
+        "description": "Run with ash-chrome version 110.0.5465.0",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -87273,8 +87273,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v110.0.5464.0",
-              "revision": "version:110.0.5464.0"
+              "location": "lacros_version_skew_tests_v110.0.5465.0",
+              "revision": "version:110.0.5465.0"
             }
           ],
           "dimension_sets": [
@@ -88798,9 +88798,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_v110.0.5464.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5465.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 110.0.5464.0",
+        "description": "Run with ash-chrome version 110.0.5465.0",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -88811,8 +88811,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v110.0.5464.0",
-              "revision": "version:110.0.5464.0"
+              "location": "lacros_version_skew_tests_v110.0.5465.0",
+              "revision": "version:110.0.5465.0"
             }
           ],
           "dimension_sets": [
@@ -88969,9 +88969,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5464.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5465.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 110.0.5464.0",
+        "description": "Run with ash-chrome version 110.0.5465.0",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -88982,8 +88982,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v110.0.5464.0",
-              "revision": "version:110.0.5464.0"
+              "location": "lacros_version_skew_tests_v110.0.5465.0",
+              "revision": "version:110.0.5465.0"
             }
           ],
           "dimension_sets": [
@@ -89121,9 +89121,9 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5464.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5465.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 110.0.5464.0",
+        "description": "Run with ash-chrome version 110.0.5465.0",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -89134,8 +89134,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v110.0.5464.0",
-              "revision": "version:110.0.5464.0"
+              "location": "lacros_version_skew_tests_v110.0.5465.0",
+              "revision": "version:110.0.5465.0"
             }
           ],
           "dimension_sets": [
@@ -89907,9 +89907,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_v110.0.5464.0/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5465.0/test_ash_chrome"
         ],
-        "description": "Run with ash-chrome version 110.0.5464.0",
+        "description": "Run with ash-chrome version 110.0.5465.0",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
@@ -89920,8 +89920,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v110.0.5464.0",
-              "revision": "version:110.0.5464.0"
+              "location": "lacros_version_skew_tests_v110.0.5465.0",
+              "revision": "version:110.0.5465.0"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index 69b482a..2762e1fe 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -18656,12 +18656,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_v110.0.5464.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5465.0/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 110.0.5464.0",
+        "description": "Run with ash-chrome version 110.0.5465.0",
         "isolate_profile_data": true,
         "merge": {
           "args": [],
@@ -18673,8 +18673,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v110.0.5464.0",
-              "revision": "version:110.0.5464.0"
+              "location": "lacros_version_skew_tests_v110.0.5465.0",
+              "revision": "version:110.0.5465.0"
             }
           ],
           "dimension_sets": [
@@ -18847,12 +18847,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5464.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5465.0/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 110.0.5464.0",
+        "description": "Run with ash-chrome version 110.0.5465.0",
         "isolate_profile_data": true,
         "merge": {
           "args": [],
@@ -18864,8 +18864,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v110.0.5464.0",
-              "revision": "version:110.0.5464.0"
+              "location": "lacros_version_skew_tests_v110.0.5465.0",
+              "revision": "version:110.0.5465.0"
             }
           ],
           "dimension_sets": [
@@ -19014,12 +19014,12 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5464.0/test_ash_chrome",
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5465.0/test_ash_chrome",
           "--test-launcher-print-test-stdio=always",
           "--combine-ash-logs-on-bots",
           "--asan-symbolize-output"
         ],
-        "description": "Run with ash-chrome version 110.0.5464.0",
+        "description": "Run with ash-chrome version 110.0.5465.0",
         "isolate_profile_data": true,
         "merge": {
           "args": [],
@@ -19031,8 +19031,8 @@
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v110.0.5464.0",
-              "revision": "version:110.0.5464.0"
+              "location": "lacros_version_skew_tests_v110.0.5465.0",
+              "revision": "version:110.0.5465.0"
             }
           ],
           "dimension_sets": [
diff --git a/testing/buildbot/internal.chromeos.fyi.json b/testing/buildbot/internal.chromeos.fyi.json
index 2149e48..6d8e5c6 100644
--- a/testing/buildbot/internal.chromeos.fyi.json
+++ b/testing/buildbot/internal.chromeos.fyi.json
@@ -1120,7 +1120,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R109-15236.21.0",
+        "cros_img": "octopus-release/R109-15236.27.0",
         "name": "lacros_fyi_tast_tests OCTOPUS_RELEASE_BETA",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1166,7 +1166,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R109-15236.21.0",
+        "cros_img": "octopus-release/R109-15236.27.0",
         "name": "ozone_unittests OCTOPUS_RELEASE_BETA",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1219,7 +1219,7 @@
       {
         "args": [],
         "cros_board": "hana",
-        "cros_img": "hana-release/R109-15236.21.0",
+        "cros_img": "hana-release/R109-15236.27.0",
         "name": "lacros_all_tast_tests HANA_RELEASE_BETA",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1267,7 +1267,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R109-15236.21.0",
+        "cros_img": "strongbad-release/R109-15236.27.0",
         "name": "lacros_all_tast_tests STRONGBAD_RELEASE_BETA",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1313,7 +1313,7 @@
       {
         "args": [],
         "cros_board": "hana",
-        "cros_img": "hana-release/R109-15236.21.0",
+        "cros_img": "hana-release/R109-15236.27.0",
         "name": "ozone_unittests HANA_RELEASE_BETA",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1357,7 +1357,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R109-15236.21.0",
+        "cros_img": "strongbad-release/R109-15236.27.0",
         "name": "ozone_unittests STRONGBAD_RELEASE_BETA",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1401,7 +1401,7 @@
       {
         "args": [],
         "cros_board": "hana",
-        "cros_img": "hana-release/R109-15236.21.0",
+        "cros_img": "hana-release/R109-15236.27.0",
         "name": "viz_unittests HANA_RELEASE_BETA",
         "swarming": {},
         "test": "viz_unittests",
@@ -1445,7 +1445,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R109-15236.21.0",
+        "cros_img": "strongbad-release/R109-15236.27.0",
         "name": "viz_unittests STRONGBAD_RELEASE_BETA",
         "swarming": {},
         "test": "viz_unittests",
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index bba0dfd..be8b1da 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -1219,8 +1219,6 @@
         'swarming': {
           # Reducing parallelism due to DUT shortage (b/238271231)
           'shards': 5,
-          # Increased timeout to 2 hours due to shard timeout (b/261363192)
-          'hard_timeout': 7200,
         }
       },
     },
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index dff06e6..78387735 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_v110.0.5464.0/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v110.0.5465.0/test_ash_chrome',
     ],
-    'description': 'Run with ash-chrome version 110.0.5464.0',
+    'description': 'Run with ash-chrome version 110.0.5465.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_v110.0.5464.0',
-          'revision': 'version:110.0.5464.0',
+          'location': 'lacros_version_skew_tests_v110.0.5465.0',
+          'revision': 'version:110.0.5465.0',
         },
       ],
     },
@@ -488,8 +488,8 @@
   'CROS_DEDEDE_RELEASE_BETA': {
     'skylab': {
       'cros_board': 'dedede',
-      'cros_chrome_version': '109.0.5414.21',
-      'cros_img': 'dedede-release/R109-15236.21.0',
+      'cros_chrome_version': '109.0.5414.29',
+      'cros_img': 'dedede-release/R109-15236.27.0',
     },
     'enabled': True,
     'identifier': 'DEDEDE_RELEASE_BETA',
@@ -524,8 +524,8 @@
   'CROS_EVE_RELEASE_BETA': {
     'skylab': {
       'cros_board': 'eve',
-      'cros_chrome_version': '109.0.5414.21',
-      'cros_img': 'eve-release/R109-15236.21.0',
+      'cros_chrome_version': '109.0.5414.29',
+      'cros_img': 'eve-release/R109-15236.27.0',
     },
     'enabled': True,
     'identifier': 'EVE_RELEASE_BETA',
@@ -570,8 +570,8 @@
   'CROS_HANA_RELEASE_BETA': {
     'skylab': {
       'cros_board': 'hana',
-      'cros_chrome_version': '109.0.5414.21',
-      'cros_img': 'hana-release/R109-15236.21.0',
+      'cros_chrome_version': '109.0.5414.29',
+      'cros_img': 'hana-release/R109-15236.27.0',
     },
     'enabled': True,
     'identifier': 'HANA_RELEASE_BETA',
@@ -615,8 +615,8 @@
   'CROS_JACUZZI_RELEASE_BETA': {
     'skylab': {
       'cros_board': 'jacuzzi',
-      'cros_chrome_version': '109.0.5414.21',
-      'cros_img': 'jacuzzi-release/R109-15236.21.0',
+      'cros_chrome_version': '109.0.5414.29',
+      'cros_img': 'jacuzzi-release/R109-15236.27.0',
     },
     'enabled': True,
     'identifier': 'JACUZZI_RELEASE_BETA',
@@ -681,8 +681,8 @@
   'CROS_OCTOPUS_RELEASE_BETA': {
     'skylab': {
       'cros_board': 'octopus',
-      'cros_chrome_version': '109.0.5414.21',
-      'cros_img': 'octopus-release/R109-15236.21.0',
+      'cros_chrome_version': '109.0.5414.29',
+      'cros_img': 'octopus-release/R109-15236.27.0',
     },
     'enabled': True,
     'identifier': 'OCTOPUS_RELEASE_BETA',
@@ -717,8 +717,8 @@
   'CROS_STRONGBAD_RELEASE_BETA': {
     'skylab': {
       'cros_board': 'strongbad',
-      'cros_chrome_version': '109.0.5414.21',
-      'cros_img': 'strongbad-release/R109-15236.21.0',
+      'cros_chrome_version': '109.0.5414.29',
+      'cros_img': 'strongbad-release/R109-15236.27.0',
     },
     'enabled': True,
     'identifier': 'STRONGBAD_RELEASE_BETA',
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index d657146..09899bf 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -4875,21 +4875,6 @@
             ]
         }
     ],
-    "GoogleLensIOS": [
-        {
-            "platforms": [
-                "ios"
-            ],
-            "experiments": [
-                {
-                    "name": "LensContextMenuModal_20220201",
-                    "enable_features": [
-                        "UseLensToSearchForImage"
-                    ]
-                }
-            ]
-        }
-    ],
     "GoogleLensTabletIntegration": [
         {
             "platforms": [
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index 85df873b..da1edcb7 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -297,17 +297,15 @@
 const base::FeatureParam<base::TimeDelta> kSharedStorageBudgetInterval = {
     &kSharedStorageAPI, "SharedStorageBudgetInterval", base::Hours(24)};
 const base::FeatureParam<base::TimeDelta>
-    kSharedStorageStaleOriginPurgeInitialInterval = {
-        &kSharedStorageAPI, "SharedStorageStaleOriginPurgeInitialInterval",
-        base::Minutes(15)};
+    kSharedStorageStalePurgeInitialInterval = {
+        &kSharedStorageAPI, "SharedStorageStalePurgeInitialInterval",
+        base::Minutes(2)};
 const base::FeatureParam<base::TimeDelta>
-    kSharedStorageStaleOriginPurgeRecurringInterval = {
-        &kSharedStorageAPI, "SharedStorageStaleOriginPurgeRecurringInterval",
+    kSharedStorageStalePurgeRecurringInterval = {
+        &kSharedStorageAPI, "SharedStorageStalePurgeRecurringInterval",
         base::Hours(2)};
-const base::FeatureParam<base::TimeDelta>
-    kSharedStorageOriginStalenessThreshold = {
-        &kSharedStorageAPI, "SharedStorageOriginStalenessThreshold",
-        base::Days(30)};
+const base::FeatureParam<base::TimeDelta> kSharedStorageStalenessThreshold = {
+    &kSharedStorageAPI, "SharedStorageStalenessThreshold", base::Days(30)};
 const base::FeatureParam<int>
     kSharedStorageMaxAllowedFencedFrameDepthForSelectURL = {
         &kSharedStorageAPI,
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h
index 2427bbc..2762fb9 100644
--- a/third_party/blink/public/common/features.h
+++ b/third_party/blink/public/common/features.h
@@ -111,19 +111,19 @@
 BLINK_COMMON_EXPORT extern const base::FeatureParam<base::TimeDelta>
     kSharedStorageBudgetInterval;
 // Initial interval from service startup after which
-// SharedStorageManager first checks for any stale origins, purging any that it
+// SharedStorageManager first checks for any stale entries, purging any that it
 // finds.
 BLINK_COMMON_EXPORT extern const base::FeatureParam<base::TimeDelta>
-    kSharedStorageStaleOriginPurgeInitialInterval;
+    kSharedStorageStalePurgeInitialInterval;
 // Second and subsequent intervals from service startup after
-// which SharedStorageManager checks for any stale origins, purging any that it
+// which SharedStorageManager checks for any stale entries, purging any that it
 // finds.
 BLINK_COMMON_EXPORT extern const base::FeatureParam<base::TimeDelta>
-    kSharedStorageStaleOriginPurgeRecurringInterval;
-// Length of time between origin creation and origin expiration. When an
-// origin's data is older than this threshold, it will be auto-purged.
+    kSharedStorageStalePurgeRecurringInterval;
+// Length of time between last key write access and key expiration. When an
+// entry's data is older than this threshold, it will be auto-purged.
 BLINK_COMMON_EXPORT extern const base::FeatureParam<base::TimeDelta>
-    kSharedStorageOriginStalenessThreshold;
+    kSharedStorageStalenessThreshold;
 // Maximum depth of fenced frame where sharedStorage.selectURL() is allowed to
 // be invoked. The depth of a fenced frame is the number of the fenced frame
 // boundaries above that frame (i.e. the outermost main frame's frame tree has
diff --git a/third_party/blink/public/mojom/navigation/navigation_params.mojom b/third_party/blink/public/mojom/navigation/navigation_params.mojom
index 8980fb9..ff1d968 100644
--- a/third_party/blink/public/mojom/navigation/navigation_params.mojom
+++ b/third_party/blink/public/mojom/navigation/navigation_params.mojom
@@ -16,6 +16,7 @@
 import "services/network/public/mojom/url_response_head.mojom";
 import "services/network/public/mojom/web_client_hints_types.mojom";
 import "services/network/public/mojom/web_sandbox_flags.mojom";
+import "third_party/blink/public/mojom/back_forward_cache_not_restored_reasons.mojom";
 import "third_party/blink/public/mojom/fetch/fetch_api_request.mojom";
 import "third_party/blink/public/mojom/frame/view_transition_state.mojom";
 import "third_party/blink/public/mojom/fenced_frame/fenced_frame_config.mojom";
@@ -524,4 +525,9 @@
   // Only non-null for embedder-initiated navigations of a fenced frame root,
   // and urn navigations in iframes while they're supported.
   FencedFrameProperties? fenced_frame_properties;
+
+  // `not_restored_reasons` contains the reasons why this navigation is not
+  // served from back/forward cache if applicable. This is only sent for
+  // cross-document main frame history navigations.
+  blink.mojom.BackForwardCacheNotRestoredReasons? not_restored_reasons;
 };
diff --git a/third_party/blink/public/mojom/use_counter/metrics/css_property_id.mojom b/third_party/blink/public/mojom/use_counter/metrics/css_property_id.mojom
index 6ba1375..dcb194b 100644
--- a/third_party/blink/public/mojom/use_counter/metrics/css_property_id.mojom
+++ b/third_party/blink/public/mojom/use_counter/metrics/css_property_id.mojom
@@ -568,7 +568,7 @@
     kFontDisplay = 516,
     kContain = 517,
     kD = 518,
-    kLineHeightStep = 519,
+    // kLineHeightStep = 519,
     kBreakAfter = 520,
     kBreakBefore = 521,
     kBreakInside = 522,
diff --git a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
index fc9d911f..efa5a96 100644
--- a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
+++ b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
@@ -2078,9 +2078,9 @@
   kV8HTMLMediaElement_CaptureStream_Method = 2729,
   kQuirkyLineBoxBackgroundSize = 2730,
   kDirectlyCompositedImage = 2731,
-  kV8HTMLVideoElement_AutoPictureInPicture_AttributeGetter = 2733,
-  kV8HTMLVideoElement_AutoPictureInPicture_AttributeSetter = 2734,
-  kAutoPictureInPictureAttribute = 2735,
+  kOBSOLETE_V8HTMLVideoElement_AutoPictureInPicture_AttributeGetter = 2733,
+  kOBSOLETE_V8HTMLVideoElement_AutoPictureInPicture_AttributeSetter = 2734,
+  kOBSOLETE_AutoPictureInPictureAttribute = 2735,
   kOBSOLETE_RTCAudioJitterBufferRtxHandling = 2736,
   kWebShareCanShare = 2737,
   kPriorityHints = 2738,
diff --git a/third_party/blink/renderer/bindings/generated_in_core.gni b/third_party/blink/renderer/bindings/generated_in_core.gni
index 8422d27..be5bdfc 100644
--- a/third_party/blink/renderer/bindings/generated_in_core.gni
+++ b/third_party/blink/renderer/bindings/generated_in_core.gni
@@ -97,6 +97,8 @@
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_base_property_indexed_keyframe.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_baselines.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_baselines.h",
+  "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_before_toggle_event_init.cc",
+  "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_before_toggle_event_init.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_blob_property_bag.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_blob_property_bag.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_canvas_high_dynamic_range_options.cc",
@@ -613,6 +615,8 @@
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_bar_prop.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_before_create_policy_event.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_before_create_policy_event.h",
+  "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_before_toggle_event.cc",
+  "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_before_toggle_event.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_before_unload_event.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_before_unload_event.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_blob.cc",
@@ -1743,8 +1747,8 @@
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_float32array_uint16array_uint8clampedarray.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_float_stringelementrecord.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_float_stringelementrecord.h",
-  "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_htmlcanvaselement_imagebitmap_offscreencanvas.cc",
-  "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_htmlcanvaselement_imagebitmap_offscreencanvas.h",
+  "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_htmlcanvaselement_htmlvideoelement_imagebitmap_offscreencanvas.cc",
+  "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_htmlcanvaselement_htmlvideoelement_imagebitmap_offscreencanvas.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_htmlcanvaselement_offscreencanvas.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_htmlcanvaselement_offscreencanvas.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_union_htmlelement_long.cc",
diff --git a/third_party/blink/renderer/bindings/idl_in_core.gni b/third_party/blink/renderer/bindings/idl_in_core.gni
index d56e51e..33d19ba 100644
--- a/third_party/blink/renderer/bindings/idl_in_core.gni
+++ b/third_party/blink/renderer/bindings/idl_in_core.gni
@@ -204,6 +204,8 @@
           "//third_party/blink/renderer/core/events/animation_playback_event.idl",
           "//third_party/blink/renderer/core/events/animation_playback_event_init.idl",
           "//third_party/blink/renderer/core/events/before_create_policy_event.idl",
+          "//third_party/blink/renderer/core/events/before_toggle_event.idl",
+          "//third_party/blink/renderer/core/events/before_toggle_event_init.idl",
           "//third_party/blink/renderer/core/events/before_unload_event.idl",
           "//third_party/blink/renderer/core/events/clipboard_event.idl",
           "//third_party/blink/renderer/core/events/clipboard_event_init.idl",
diff --git a/third_party/blink/renderer/build/scripts/templates/runtime_feature_state_read_context.h.tmpl b/third_party/blink/renderer/build/scripts/templates/runtime_feature_state_read_context.h.tmpl
index 06b2f49..e1218d1 100644
--- a/third_party/blink/renderer/build/scripts/templates/runtime_feature_state_read_context.h.tmpl
+++ b/third_party/blink/renderer/build/scripts/templates/runtime_feature_state_read_context.h.tmpl
@@ -48,6 +48,27 @@
 
   // Values for all read/write features on context creation.
   base::flat_map<blink::mojom::RuntimeFeatureState, bool> initial_values_;
+
+ private:
+  // Only RuntimeFeatureChangeImpl should be able to make changes
+  // to the read-only context, when a feature diff is sent from
+  // the renderer to the browser via IPC. Thus, ApplyFeatureChange()
+  // is private but will be called in RuntimeFeatureChangeImpl instances.
+  // This function allows RuntimeFeatureChangeImpl to update the
+  // browser process's copy of the feature state
+  // (RuntimeFeatureStateReadContext) to match the state found in
+  // the renderer process.
+  // TODO(https://crbug.com/1377000): friend the
+  // RuntimeFeatureChangeImpl class once implemented.
+  void ApplyFeatureChange(
+    const base::flat_map<blink::mojom::RuntimeFeatureState,
+                                       bool>& modified_features) {
+    // Feature values sent from the renderer take precedence over state
+    // held currently in the browser, so insert_or_assign is used.
+    for(auto const& feature : modified_features) {
+      feature_overrides_.insert_or_assign(feature.first, feature.second);
+    }
+  }
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
index 6530a17..e6cfaa6 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
@@ -530,6 +530,7 @@
     "events/animation_event.idl",
     "events/animation_playback_event.idl",
     "events/before_create_policy_event.idl",
+    "events/before_toggle_event.idl",
     "events/before_unload_event.idl",
     "events/clipboard_event.idl",
     "events/composition_event.idl",
diff --git a/third_party/blink/renderer/core/css/css.dict b/third_party/blink/renderer/core/css/css.dict
index b2223c9b7..db200ac 100644
--- a/third_party/blink/renderer/core/css/css.dict
+++ b/third_party/blink/renderer/core/css/css.dict
@@ -1173,7 +1173,6 @@
 "light-level"
 "line-grid"
 "line-height"
-"line-height-step"
 "line-snap"
 "list-style"
 "list-style-image"
diff --git a/third_party/blink/renderer/core/css/css_properties.json5 b/third_party/blink/renderer/core/css/css_properties.json5
index 7a1adb21..8b4ef94 100644
--- a/third_party/blink/renderer/core/css/css_properties.json5
+++ b/third_party/blink/renderer/core/css/css_properties.json5
@@ -3121,18 +3121,6 @@
       valid_for_marker: true,
     },
     {
-      name: "line-height-step",
-      property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
-      inherited: true,
-      runtime_flag: "CSSSnapSize",
-      field_group: "*",
-      field_template: "primitive",
-      default_value: "0",
-      type_name: "uint8_t",
-      converter: "ConvertComputedLength<uint8_t>",
-      typedom_types: ["Length"],
-    },
-    {
       name: "list-style-image",
       property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
       interpolable: true,
diff --git a/third_party/blink/renderer/core/css/cssom/css_unit_value.cc b/third_party/blink/renderer/core/css/cssom/css_unit_value.cc
index f3ed253..3e21cb3 100644
--- a/third_party/blink/renderer/core/css/cssom/css_unit_value.cc
+++ b/third_party/blink/renderer/core/css/cssom/css_unit_value.cc
@@ -69,7 +69,6 @@
     case CSSPropertyID::kFontSizeAdjust:
     case CSSPropertyID::kFontStretch:
     case CSSPropertyID::kInlineSize:
-    case CSSPropertyID::kLineHeightStep:
     case CSSPropertyID::kMaxBlockSize:
     case CSSPropertyID::kMaxInlineSize:
     case CSSPropertyID::kMinBlockSize:
diff --git a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
index 93f36972..ea631eee 100644
--- a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
+++ b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
@@ -4570,21 +4570,6 @@
   return ComputedStyleUtils::ValueForLineHeight(style);
 }
 
-const CSSValue* LineHeightStep::ParseSingleValue(
-    CSSParserTokenRange& range,
-    const CSSParserContext& context,
-    const CSSParserLocalContext&) const {
-  return css_parsing_utils::ConsumeLength(
-      range, context, CSSPrimitiveValue::ValueRange::kNonNegative);
-}
-
-const CSSValue* LineHeightStep::CSSValueFromComputedStyleInternal(
-    const ComputedStyle& style,
-    const LayoutObject*,
-    bool allow_visited_style) const {
-  return ZoomAdjustedPixelValue(style.LineHeightStep(), style);
-}
-
 const CSSValue* ListStyleImage::ParseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
diff --git a/third_party/blink/renderer/core/dom/global_event_handlers.h b/third_party/blink/renderer/core/dom/global_event_handlers.h
index 4252aaf..16dcb8fc 100644
--- a/third_party/blink/renderer/core/dom/global_event_handlers.h
+++ b/third_party/blink/renderer/core/dom/global_event_handlers.h
@@ -47,6 +47,7 @@
   DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(auxclick, kAuxclick)
   DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(beforeinput, kBeforeinput)
   DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(beforematch, kBeforematch)
+  DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(beforetoggle, kBeforetoggle)
   DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(blur, kBlur)
   DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(cancel, kCancel)
   DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(canplay, kCanplay)
diff --git a/third_party/blink/renderer/core/dom/global_event_handlers.idl b/third_party/blink/renderer/core/dom/global_event_handlers.idl
index efd6a84a..284ce0c 100644
--- a/third_party/blink/renderer/core/dom/global_event_handlers.idl
+++ b/third_party/blink/renderer/core/dom/global_event_handlers.idl
@@ -35,6 +35,7 @@
     attribute EventHandler onabort;
     attribute EventHandler onbeforeinput;
     [RuntimeEnabled=BeforeMatchEvent] attribute EventHandler onbeforematch;
+    [RuntimeEnabled=HTMLPopoverAttribute] attribute EventHandler onbeforetoggle;
     attribute EventHandler onblur;
     attribute EventHandler oncancel;
     attribute EventHandler oncanplay;
diff --git a/third_party/blink/renderer/core/events/before_toggle_event.cc b/third_party/blink/renderer/core/events/before_toggle_event.cc
new file mode 100644
index 0000000..2076d5a
--- /dev/null
+++ b/third_party/blink/renderer/core/events/before_toggle_event.cc
@@ -0,0 +1,52 @@
+// 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 "third_party/blink/renderer/core/events/before_toggle_event.h"
+
+#include "third_party/blink/renderer/bindings/core/v8/v8_before_toggle_event_init.h"
+#include "third_party/blink/renderer/core/dom/events/event.h"
+#include "third_party/blink/renderer/core/event_interface_names.h"
+
+namespace blink {
+
+BeforeToggleEvent::BeforeToggleEvent() = default;
+
+BeforeToggleEvent::BeforeToggleEvent(const AtomicString& type,
+                                     Event::Cancelable cancelable,
+                                     const String& current_state,
+                                     const String& new_state)
+    : Event(type, Bubbles::kNo, cancelable),
+      current_state_(current_state),
+      new_state_(new_state) {}
+
+BeforeToggleEvent::BeforeToggleEvent(const AtomicString& type,
+                                     const BeforeToggleEventInit* initializer)
+    : Event(type, initializer) {
+  if (initializer->hasCurrentState()) {
+    current_state_ = initializer->currentState();
+  }
+  if (initializer->hasNewState()) {
+    new_state_ = initializer->newState();
+  }
+}
+
+BeforeToggleEvent::~BeforeToggleEvent() = default;
+
+const String& BeforeToggleEvent::currentState() const {
+  return current_state_;
+}
+
+const String& BeforeToggleEvent::newState() const {
+  return new_state_;
+}
+
+const AtomicString& BeforeToggleEvent::InterfaceName() const {
+  return event_interface_names::kBeforeToggleEvent;
+}
+
+void BeforeToggleEvent::Trace(Visitor* visitor) const {
+  Event::Trace(visitor);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/events/before_toggle_event.h b/third_party/blink/renderer/core/events/before_toggle_event.h
new file mode 100644
index 0000000..379b836
--- /dev/null
+++ b/third_party/blink/renderer/core/events/before_toggle_event.h
@@ -0,0 +1,58 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_BEFORE_TOGGLE_EVENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_BEFORE_TOGGLE_EVENT_H_
+
+#include "third_party/blink/renderer/core/dom/events/event.h"
+
+namespace blink {
+
+class BeforeToggleEventInit;
+
+class BeforeToggleEvent final : public Event {
+  DEFINE_WRAPPERTYPEINFO();
+
+ public:
+  static BeforeToggleEvent* Create() {
+    return MakeGarbageCollected<BeforeToggleEvent>();
+  }
+  static BeforeToggleEvent* Create(const AtomicString& type,
+                                   const BeforeToggleEventInit* initializer) {
+    return MakeGarbageCollected<BeforeToggleEvent>(type, initializer);
+  }
+  static BeforeToggleEvent* CreateBubble(const AtomicString& type,
+                                         Event::Cancelable cancelable,
+                                         const String& current_state,
+                                         const String& new_state) {
+    auto* event = MakeGarbageCollected<BeforeToggleEvent>(
+        type, cancelable, current_state, new_state);
+    event->SetBubbles(true);
+    return event;
+  }
+
+  BeforeToggleEvent();
+  BeforeToggleEvent(const AtomicString& type,
+                    Event::Cancelable cancelable,
+                    const String& current_state,
+                    const String& new_state);
+  BeforeToggleEvent(const AtomicString& type,
+                    const BeforeToggleEventInit* initializer);
+  ~BeforeToggleEvent() override;
+
+  const String& currentState() const;
+  const String& newState() const;
+
+  const AtomicString& InterfaceName() const override;
+
+  void Trace(Visitor*) const override;
+
+ private:
+  String current_state_;
+  String new_state_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_BEFORE_TOGGLE_EVENT_H_
diff --git a/third_party/blink/renderer/core/events/before_toggle_event.idl b/third_party/blink/renderer/core/events/before_toggle_event.idl
new file mode 100644
index 0000000..1b9329d
--- /dev/null
+++ b/third_party/blink/renderer/core/events/before_toggle_event.idl
@@ -0,0 +1,12 @@
+// 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.
+
+[
+    Exposed=Window,
+    RuntimeEnabled=HTMLPopoverAttribute
+] interface BeforeToggleEvent : Event {
+    constructor(DOMString type, optional BeforeToggleEventInit eventInitDict = {});
+    readonly attribute DOMString currentState;
+    readonly attribute DOMString newState;
+};
diff --git a/third_party/blink/renderer/core/events/before_toggle_event_init.idl b/third_party/blink/renderer/core/events/before_toggle_event_init.idl
new file mode 100644
index 0000000..a4db6a2
--- /dev/null
+++ b/third_party/blink/renderer/core/events/before_toggle_event_init.idl
@@ -0,0 +1,8 @@
+// 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.
+
+dictionary BeforeToggleEventInit : EventInit {
+    DOMString currentState = "";
+    DOMString newState = "";
+};
diff --git a/third_party/blink/renderer/core/events/build.gni b/third_party/blink/renderer/core/events/build.gni
index 1840a23..7aac8201 100644
--- a/third_party/blink/renderer/core/events/build.gni
+++ b/third_party/blink/renderer/core/events/build.gni
@@ -13,6 +13,8 @@
   "before_print_event.h",
   "before_text_inserted_event.cc",
   "before_text_inserted_event.h",
+  "before_toggle_event.cc",
+  "before_toggle_event.h",
   "before_unload_event.cc",
   "before_unload_event.h",
   "clipboard_event.cc",
diff --git a/third_party/blink/renderer/core/events/event_type_names.json5 b/third_party/blink/renderer/core/events/event_type_names.json5
index 744b02e..a5f2bb40 100644
--- a/third_party/blink/renderer/core/events/event_type_names.json5
+++ b/third_party/blink/renderer/core/events/event_type_names.json5
@@ -52,6 +52,7 @@
     "beforematch",
     "beforepaste",
     "beforeprint",
+    "beforetoggle",
     "beforeunload",
     "beforexrselect",
     "beginEvent",
diff --git a/third_party/blink/renderer/core/frame/picture_in_picture_controller.h b/third_party/blink/renderer/core/frame/picture_in_picture_controller.h
index 69fdda4..1c6283376 100644
--- a/third_party/blink/renderer/core/frame/picture_in_picture_controller.h
+++ b/third_party/blink/renderer/core/frame/picture_in_picture_controller.h
@@ -67,15 +67,6 @@
   // Should be called when an element has exited Picture-in-Picture.
   virtual void OnExitedPictureInPicture(ScriptPromiseResolver*) = 0;
 
-  // Add video element to the list of video elements for the associated document
-  // that are eligible to Auto Picture-in-Picture.
-  virtual void AddToAutoPictureInPictureElementsList(HTMLVideoElement*) = 0;
-
-  // Remove video element from the list of video elements for the associated
-  // document that are eligible to Auto Picture-in-Picture.
-  virtual void RemoveFromAutoPictureInPictureElementsList(
-      HTMLVideoElement*) = 0;
-
   // Notifies that one of the states used by Picture-in-Picture has changed.
   virtual void OnPictureInPictureStateChange() = 0;
 
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
index 13ac041..ac6ab24 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
@@ -34,9 +34,9 @@
 #include <utility>
 
 #include "base/auto_reset.h"
-#include "base/callback_helpers.h"
 #include "base/debug/crash_logging.h"
 #include "base/debug/dump_without_crashing.h"
+#include "base/functional/function_ref.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/task/single_thread_task_runner.h"
@@ -170,13 +170,12 @@
 
 void ForEachLocalFrameControlledByWidget(
     LocalFrame* frame,
-    const base::RepeatingCallback<void(WebLocalFrameImpl*)>& callback) {
-  callback.Run(WebLocalFrameImpl::FromFrame(frame));
+    base::FunctionRef<void(WebLocalFrameImpl*)> callback) {
+  callback(WebLocalFrameImpl::FromFrame(frame));
   for (Frame* child = frame->FirstChild(); child;
        child = child->NextSibling()) {
-    if (child->IsLocalFrame()) {
-      ForEachLocalFrameControlledByWidget(DynamicTo<LocalFrame>(child),
-                                          callback);
+    if (auto* local_child = DynamicTo<LocalFrame>(child)) {
+      ForEachLocalFrameControlledByWidget(local_child, callback);
     }
   }
 }
@@ -185,11 +184,11 @@
 // any RemoteFrames have have another LocalFrame root as their parent.
 void ForEachRemoteFrameChildrenControlledByWidget(
     Frame* frame,
-    const base::RepeatingCallback<void(RemoteFrame*)>& callback) {
+    base::FunctionRef<void(RemoteFrame*)> callback) {
   for (Frame* child = frame->Tree().FirstChild(); child;
        child = child->Tree().NextSibling()) {
     if (auto* remote_frame = DynamicTo<RemoteFrame>(child)) {
-      callback.Run(remote_frame);
+      callback(remote_frame);
       ForEachRemoteFrameChildrenControlledByWidget(remote_frame, callback);
     } else if (auto* local_frame = DynamicTo<LocalFrame>(child)) {
       // If iteration arrives at a local root then don't descend as it will be
@@ -206,14 +205,14 @@
       if (auto* portals = DocumentPortals::Get(*document)) {
         for (PortalContents* portal : portals->GetPortals()) {
           if (RemoteFrame* remote_frame = portal->GetFrame())
-            callback.Run(remote_frame);
+            callback(remote_frame);
         }
       }
       // Iterate on any fenced frames owned by a local frame.
       if (auto* fenced_frames = DocumentFencedFrames::Get(*document)) {
         for (HTMLFencedFrameElement* fenced_frame :
              fenced_frames->GetFencedFrames()) {
-          callback.Run(To<RemoteFrame>(fenced_frame->ContentFrame()));
+          callback(To<RemoteFrame>(fenced_frame->ContentFrame()));
         }
       }
     }
@@ -1333,10 +1332,9 @@
 
 void WebFrameWidgetImpl::DidCommitAndDrawCompositorFrame() {
   ForEachLocalFrameControlledByWidget(
-      local_root_->GetFrame(),
-      WTF::BindRepeating([](WebLocalFrameImpl* local_frame) {
+      local_root_->GetFrame(), [](WebLocalFrameImpl* local_frame) {
         local_frame->Client()->DidCommitAndDrawCompositorFrame();
-      }));
+      });
 }
 
 void WebFrameWidgetImpl::DidObserveFirstScrollDelay(
@@ -1359,17 +1357,17 @@
     return;
 
   ForEachLocalFrameControlledByWidget(
-      local_root_->GetFrame(),
-      WTF::BindRepeating([](WebLocalFrameImpl* local_frame) {
+      local_root_->GetFrame(), [](WebLocalFrameImpl* local_frame) {
+        // A frame in the frame tree is fully attached and must always have a
+        // document.
         auto* document = local_frame->GetFrame()->GetDocument();
-        if (!document)
-          return;
+        DCHECK(document);
 
         if (auto* transition =
                 ViewTransitionUtils::GetActiveTransition(*document)) {
           transition->WillBeginMainFrame();
         }
-      }));
+      });
 }
 
 std::unique_ptr<cc::LayerTreeFrameSink>
@@ -1510,11 +1508,11 @@
 
     // Send the capture sequence number to RemoteFrames that are below the
     // local root for this widget.
-    ForEachRemoteFrameControlledByWidget(WTF::BindRepeating(
-        [](uint32_t capture_sequence_number, RemoteFrame* remote_frame) {
+    ForEachRemoteFrameControlledByWidget(
+        [capture_sequence_number = visual_properties.capture_sequence_number](
+            RemoteFrame* remote_frame) {
           remote_frame->UpdateCaptureSequenceNumber(capture_sequence_number);
-        },
-        visual_properties.capture_sequence_number));
+        });
   }
 
   if (!View()->AutoResizeMode()) {
@@ -1537,17 +1535,15 @@
       widget_base_->VisibleViewportSizeInDIPs()) {
     ForEachLocalFrameControlledByWidget(
         local_root_->GetFrame(),
-        WTF::BindRepeating([](WebLocalFrameImpl* local_frame) {
-          local_frame->ResetHasScrolledFocusedEditableIntoView();
-        }));
+        &WebLocalFrameImpl::ResetHasScrolledFocusedEditableIntoView);
 
     // Propagate changes down to child local root RenderWidgets and
     // BrowserPlugins in other frame trees/processes.
-    ForEachRemoteFrameControlledByWidget(WTF::BindRepeating(
-        [](const gfx::Size& visible_viewport_size, RemoteFrame* remote_frame) {
+    ForEachRemoteFrameControlledByWidget(
+        [visible_viewport_size = widget_base_->VisibleViewportSizeInDIPs()](
+            RemoteFrame* remote_frame) {
           remote_frame->DidChangeVisibleViewportSize(visible_viewport_size);
-        },
-        widget_base_->VisibleViewportSizeInDIPs()));
+        });
   }
 
   // All non-top-level Widgets (child local-root frames, Portals, GuestViews,
@@ -1946,11 +1942,9 @@
 
   // Part of the UpdateVisualProperties dance we send the zoom level to
   // RemoteFrames that are below the local root for this widget.
-  ForEachRemoteFrameControlledByWidget(WTF::BindRepeating(
-      [](double zoom_level, RemoteFrame* remote_frame) {
-        remote_frame->ZoomLevelChanged(zoom_level);
-      },
-      zoom_level));
+  ForEachRemoteFrameControlledByWidget([zoom_level](RemoteFrame* remote_frame) {
+    remote_frame->ZoomLevelChanged(zoom_level);
+  });
 }
 
 void WebFrameWidgetImpl::SetAutoResizeMode(bool auto_resize,
@@ -2155,13 +2149,14 @@
       .RecomputeMouseHoverStateIfNeeded();
 
   ForEachLocalFrameControlledByWidget(
-      LocalRootImpl()->GetFrame(),
-      WTF::BindRepeating([](WebLocalFrameImpl* local_frame) {
-        if (LocalFrameView* view = local_frame->GetFrameView()) {
-          if (FragmentAnchor* anchor = view->GetFragmentAnchor())
-            anchor->PerformScriptableActions();
-        }
-      }));
+      LocalRootImpl()->GetFrame(), [](WebLocalFrameImpl* local_frame) {
+        // A frame in the frame tree is fully attached and must always have a
+        // view.
+        LocalFrameView* view = local_frame->GetFrameView();
+        DCHECK(view);
+        if (FragmentAnchor* anchor = view->GetFragmentAnchor())
+          anchor->PerformScriptableActions();
+      });
 
   absl::optional<LocalFrameUkmAggregator::ScopedUkmHierarchicalTimer> ukm_timer;
   if (WidgetBase::ShouldRecordBeginMainFrameMetrics()) {
@@ -2494,12 +2489,10 @@
     LocalFrame* frame = LocalRootImpl()->GetFrame();
     frame->WindowSegmentsChanged(window_segments_);
 
-    ForEachRemoteFrameControlledByWidget(WTF::BindRepeating(
-        [](const std::vector<gfx::Rect>& window_segments,
-           RemoteFrame* remote_frame) {
+    ForEachRemoteFrameControlledByWidget(
+        [&window_segments = window_segments_param](RemoteFrame* remote_frame) {
           remote_frame->DidChangeRootWindowSegments(window_segments);
-        },
-        window_segments_param));
+        });
   }
 }
 
@@ -2869,12 +2862,9 @@
   }
 
   ForEachLocalFrameControlledByWidget(
-      local_root_->GetFrame(),
-      WTF::BindRepeating(
-          [](WebMeaningfulLayout layout_type, WebLocalFrameImpl* local_frame) {
-            local_frame->Client()->DidMeaningfulLayout(layout_type);
-          },
-          layout_type));
+      local_root_->GetFrame(), [layout_type](WebLocalFrameImpl* local_frame) {
+        local_frame->Client()->DidMeaningfulLayout(layout_type);
+      });
 }
 
 void WebFrameWidgetImpl::PresentationCallbackForMeaningfulLayout(
@@ -3953,7 +3943,7 @@
 #endif
 
 void WebFrameWidgetImpl::ForEachRemoteFrameControlledByWidget(
-    const base::RepeatingCallback<void(RemoteFrame*)>& callback) {
+    base::FunctionRef<void(RemoteFrame*)> callback) {
   ForEachRemoteFrameChildrenControlledByWidget(local_root_->GetFrame(),
                                                callback);
 }
@@ -4051,11 +4041,12 @@
 
   // Update the scale factor for remote frames which in turn depends on the
   // compositing scale factor set in the widget.
-  ForEachRemoteFrameControlledByWidget(
-      WTF::BindRepeating([](RemoteFrame* remote_frame) {
-        if (remote_frame->View())
-          remote_frame->View()->UpdateCompositingScaleFactor();
-      }));
+  ForEachRemoteFrameControlledByWidget([](RemoteFrame* remote_frame) {
+    // Only RemoteFrames with a local parent frame participate in compositing
+    // (and thus have a view).
+    if (remote_frame->View())
+      remote_frame->View()->UpdateCompositingScaleFactor();
+  });
 }
 
 void WebFrameWidgetImpl::NotifyPageScaleFactorChanged(
@@ -4072,13 +4063,11 @@
   // global value per-page, we could instead store it once in the browser
   // (such as in RenderViewHost) and distribute it to each WebFrameWidgetImpl
   // from there.
-  ForEachRemoteFrameControlledByWidget(WTF::BindRepeating(
-      [](float page_scale_factor, bool is_pinch_gesture_active,
-         RemoteFrame* remote_frame) {
+  ForEachRemoteFrameControlledByWidget(
+      [page_scale_factor, is_pinch_gesture_active](RemoteFrame* remote_frame) {
         remote_frame->PageScaleFactorChanged(page_scale_factor,
                                              is_pinch_gesture_active);
-      },
-      page_scale_factor, is_pinch_gesture_active));
+      });
 }
 
 void WebFrameWidgetImpl::SetPageScaleStateAndLimits(
@@ -4163,27 +4152,23 @@
   // window.screen events are fired as well.
   ForEachLocalFrameControlledByWidget(
       LocalRootImpl()->GetFrame(),
-      WTF::BindRepeating(
-          [](const display::ScreenInfos& original_screen_infos,
-             bool window_screen_has_changed, WebLocalFrameImpl* local_frame) {
-            auto* screen = local_frame->GetFrame()->DomWindow()->screen();
-            screen->UpdateDisplayId(original_screen_infos.current().display_id);
-            CoreInitializer::GetInstance().DidUpdateScreens(
-                *local_frame->GetFrame(), original_screen_infos);
-            if (window_screen_has_changed)
-              screen->DispatchEvent(*Event::Create(event_type_names::kChange));
-          },
-          original_screen_infos, window_screen_has_changed));
+      [&original_screen_infos,
+       window_screen_has_changed](WebLocalFrameImpl* local_frame) {
+        auto* screen = local_frame->GetFrame()->DomWindow()->screen();
+        screen->UpdateDisplayId(original_screen_infos.current().display_id);
+        CoreInitializer::GetInstance().DidUpdateScreens(
+            *local_frame->GetFrame(), original_screen_infos);
+        if (window_screen_has_changed)
+          screen->DispatchEvent(*Event::Create(event_type_names::kChange));
+      });
 
   if (previous_original_screen_infos != original_screen_infos) {
     // Propagate changes down to child local root RenderWidgets and
     // BrowserPlugins in other frame trees/processes.
-    ForEachRemoteFrameControlledByWidget(WTF::BindRepeating(
-        [](const display::ScreenInfos& original_screen_infos,
-           RemoteFrame* remote_frame) {
+    ForEachRemoteFrameControlledByWidget(
+        [&original_screen_infos](RemoteFrame* remote_frame) {
           remote_frame->DidChangeScreenInfos(original_screen_infos);
-        },
-        original_screen_infos));
+        });
   }
 }
 
@@ -4201,26 +4186,22 @@
 }
 
 void WebFrameWidgetImpl::WasHidden() {
-  ForEachLocalFrameControlledByWidget(
-      local_root_->GetFrame(),
-      WTF::BindRepeating([](WebLocalFrameImpl* local_frame) {
-        local_frame->Client()->WasHidden();
-      }));
+  ForEachLocalFrameControlledByWidget(local_root_->GetFrame(),
+                                      [](WebLocalFrameImpl* local_frame) {
+                                        local_frame->Client()->WasHidden();
+                                      });
 }
 
 void WebFrameWidgetImpl::WasShown(bool was_evicted) {
-  ForEachLocalFrameControlledByWidget(
-      local_root_->GetFrame(),
-      WTF::BindRepeating([](WebLocalFrameImpl* local_frame) {
-        local_frame->Client()->WasShown();
-      }));
+  ForEachLocalFrameControlledByWidget(local_root_->GetFrame(),
+                                      [](WebLocalFrameImpl* local_frame) {
+                                        local_frame->Client()->WasShown();
+                                      });
   if (was_evicted) {
     ForEachRemoteFrameControlledByWidget(
-        WTF::BindRepeating([](RemoteFrame* remote_frame) {
-          // On eviction, the last SurfaceId is invalidated. We need to
-          // allocate a new id.
-          remote_frame->ResendVisualProperties();
-        }));
+        // On eviction, the last SurfaceId is invalidated. We need to
+        // allocate a new id.
+        &RemoteFrame::ResendVisualProperties);
   }
 }
 
@@ -4355,17 +4336,17 @@
 
 void WebFrameWidgetImpl::PrepareForFinalLifecyclUpdateForTesting() {
   ForEachLocalFrameControlledByWidget(
-      LocalRootImpl()->GetFrame(),
-      WTF::BindRepeating([](WebLocalFrameImpl* local_frame) {
+      LocalRootImpl()->GetFrame(), [](WebLocalFrameImpl* local_frame) {
         LocalFrame* core_frame = local_frame->GetFrame();
-        if (!core_frame)
-          return;
+        // A frame in the frame tree is fully attached and must always have a
+        // core frame.
+        DCHECK(core_frame);
         Document* document = core_frame->GetDocument();
-        if (!document)
-          return;
+        // Similarly, a fully attached frame must always have a document.
+        DCHECK(document);
         if (auto* ds_controller = DeferredShapingController::From(*document))
           ds_controller->ReshapeAllDeferred(ReshapeReason::kTesting);
-      }));
+      });
 }
 
 void WebFrameWidgetImpl::SetMayThrottleIfUndrawnFrames(
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
index 47d3d9d4..38ad774 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
@@ -31,6 +31,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_WEB_FRAME_WIDGET_IMPL_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_WEB_FRAME_WIDGET_IMPL_H_
 
+#include "base/functional/function_ref.h"
 #include "base/memory/weak_ptr.h"
 #include "base/task/single_thread_task_runner.h"
 #include "base/time/time.h"
@@ -823,7 +824,7 @@
   void PresentationCallbackForMeaningfulLayout(base::TimeTicks);
 
   void ForEachRemoteFrameControlledByWidget(
-      const base::RepeatingCallback<void(RemoteFrame*)>& callback);
+      base::FunctionRef<void(RemoteFrame*)> callback);
 
   void SetWindowRectSynchronously(const gfx::Rect& new_window_rect);
 
diff --git a/third_party/blink/renderer/core/html/html_attribute_names.json5 b/third_party/blink/renderer/core/html/html_attribute_names.json5
index a546cbc..5539ed7 100644
--- a/third_party/blink/renderer/core/html/html_attribute_names.json5
+++ b/third_party/blink/renderer/core/html/html_attribute_names.json5
@@ -29,7 +29,6 @@
     "autocorrect",
     "autofocus",
     "autoplay",
-    "autopictureinpicture",
     "axis",
     "background",
     "behavior",
@@ -164,6 +163,7 @@
     "onbeforeinput",
     "onbeforepaste",
     "onbeforeprint",
+    "onbeforetoggle",
     "onbeforeunload",
     "onblur",
     "oncancel",
diff --git a/third_party/blink/renderer/core/html/html_element.cc b/third_party/blink/renderer/core/html/html_element.cc
index 7d5c47f..1bd55b3 100644
--- a/third_party/blink/renderer/core/html/html_element.cc
+++ b/third_party/blink/renderer/core/html/html_element.cc
@@ -58,6 +58,7 @@
 #include "third_party/blink/renderer/core/editing/serializers/serialization.h"
 #include "third_party/blink/renderer/core/editing/spellcheck/spell_checker.h"
 #include "third_party/blink/renderer/core/event_type_names.h"
+#include "third_party/blink/renderer/core/events/before_toggle_event.h"
 #include "third_party/blink/renderer/core/events/keyboard_event.h"
 #include "third_party/blink/renderer/core/events/pointer_event.h"
 #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
@@ -440,6 +441,8 @@
        event_type_names::kBeforeinput, nullptr},
       {html_names::kOnbeforepasteAttr, kNoWebFeature,
        event_type_names::kBeforepaste, nullptr},
+      {html_names::kOnbeforetoggleAttr, kNoWebFeature,
+       event_type_names::kBeforetoggle, nullptr},
       {html_names::kOnblurAttr, kNoWebFeature, event_type_names::kBlur,
        nullptr},
       {html_names::kOncancelAttr, kNoWebFeature, event_type_names::kCancel,
@@ -565,10 +568,6 @@
        event_type_names::kPointerup, nullptr},
       {html_names::kOnprogressAttr, kNoWebFeature, event_type_names::kProgress,
        nullptr},
-      {html_names::kOnpopoverhideAttr, kNoWebFeature,
-       event_type_names::kPopoverhide, nullptr},
-      {html_names::kOnpopovershowAttr, kNoWebFeature,
-       event_type_names::kPopovershow, nullptr},
       {html_names::kOnratechangeAttr, kNoWebFeature,
        event_type_names::kRatechange, nullptr},
       {html_names::kOnresetAttr, kNoWebFeature, event_type_names::kReset,
@@ -1319,13 +1318,19 @@
     return exception_state.ThrowDOMException(exception_code, error);
   }
 
-  // Fire the popovershow event (bubbles, cancelable).
-  Event* event = Event::CreateCancelableBubble(event_type_names::kPopovershow);
+  // Fire the "opening" beforetoggle event.
+  auto* event = BeforeToggleEvent::CreateBubble(
+      event_type_names::kBeforetoggle, Event::Cancelable::kYes,
+      /*current_state*/ "closed", /*new_state*/ "open");
+  DCHECK(event->bubbles());
+  DCHECK(event->cancelable());
+  DCHECK_EQ(event->currentState(), "closed");
+  DCHECK_EQ(event->newState(), "open");
   event->SetTarget(this);
   if (DispatchEvent(*event) != DispatchEventResult::kNotCanceled)
     return;
 
-  // The 'popovershow' event handler could have changed this popover, e.g. by
+  // The 'beforetoggle' event handler could have changed this popover, e.g. by
   // changing its type, removing it from the document, or calling showPopover().
   if (!HasPopoverAttribute() || !isConnected() || popoverOpen())
     return;
@@ -1343,8 +1348,8 @@
                          HidePopoverFocusBehavior::kNone,
                          HidePopoverForcingLevel::kHideAfterAnimations);
 
-    // The 'popoverhide' event handlers could have changed this popover, e.g. by
-    // changing its type, removing it from the document, or calling
+    // The 'beforetoggle' event handlers could have changed this popover, e.g.
+    // by changing its type, removing it from the document, or calling
     // showPopover().
     if (!HasPopoverAttribute() || !isConnected() || popoverOpen() ||
         PopoverType() != original_type)
@@ -1455,7 +1460,7 @@
 // 1. Capture any already-running animations via getAnimations(), including
 //    animations on descendant elements.
 // 2. Remove the `:open` pseudo class.
-// 3. Fire the 'popoverhide' event.
+// 3. Fire the 'beforetoggle' event.
 // 4. If the hidePopover() call is *not* the result of the popover being "forced
 //    out" of the top layer, e.g. by a modal dialog or fullscreen element:
 //   a. Restore focus to the previously-focused element.
@@ -1475,8 +1480,8 @@
     // Hide any popovers above us in the stack.
     HideAllPopoversUntil(this, document, focus_behavior, forcing_level);
 
-    // The 'popoverhide' event handlers could have changed this popover, e.g. by
-    // changing its type, removing it from the document, or calling
+    // The 'beforetoggle' event handlers could have changed this popover, e.g.
+    // by changing its type, removing it from the document, or calling
     // hidePopover().
     if (!HasPopoverAttribute() || !isConnected() ||
         GetPopoverData()->visibilityState() !=
@@ -1505,8 +1510,14 @@
   GetPopoverData()->setInvoker(nullptr);
   GetPopoverData()->setNeedsRepositioningForSelectMenu(false);
 
-  // Fire the popoverhide event (bubbles, not cancelable).
-  Event* event = Event::CreateBubble(event_type_names::kPopoverhide);
+  // Fire the "closing" beforetoggle event.
+  auto* event = BeforeToggleEvent::CreateBubble(
+      event_type_names::kBeforetoggle, Event::Cancelable::kNo,
+      /*current_state*/ "open", /*new_state*/ "closed");
+  DCHECK(event->bubbles());
+  DCHECK(!event->cancelable());
+  DCHECK_EQ(event->currentState(), "open");
+  DCHECK_EQ(event->newState(), "closed");
   event->SetTarget(this);
   if (force_hide) {
     // Stop matching `:open` now:
@@ -1527,7 +1538,7 @@
   GetPopoverData()->setVisibilityState(PopoverVisibilityState::kTransitioning);
   PseudoStateChanged(CSSSelector::kPseudoOpen);
 
-  // The 'popoverhide' event handler could have changed this popover, e.g. by
+  // The 'beforetoggle' event handler could have changed this popover, e.g. by
   // changing its type, removing it from the document, or calling showPopover().
   if (!isConnected() || !HasPopoverAttribute() ||
       GetPopoverData()->visibilityState() !=
diff --git a/third_party/blink/renderer/core/html/media/html_video_element.cc b/third_party/blink/renderer/core/html/media/html_video_element.cc
index b2233e5..4fb2aef 100644
--- a/third_party/blink/renderer/core/html/media/html_video_element.cc
+++ b/third_party/blink/renderer/core/html/media/html_video_element.cc
@@ -218,16 +218,6 @@
       remoting_interstitial_->OnPosterImageChanged();
     if (picture_in_picture_interstitial_)
       picture_in_picture_interstitial_->OnPosterImageChanged();
-  } else if (params.name == html_names::kAutopictureinpictureAttr &&
-             RuntimeEnabledFeatures::AutoPictureInPictureEnabled(
-                 GetExecutionContext())) {
-    if (!params.new_value.IsNull()) {
-      PictureInPictureController::From(GetDocument())
-          .AddToAutoPictureInPictureElementsList(this);
-    } else {
-      PictureInPictureController::From(GetDocument())
-          .RemoveFromAutoPictureInPictureElementsList(this);
-    }
   } else {
     HTMLMediaElement::ParseAttribute(params);
   }
diff --git a/third_party/blink/renderer/core/layout/line/root_inline_box.cc b/third_party/blink/renderer/core/layout/line/root_inline_box.cc
index e8067f5..efad325 100644
--- a/third_party/blink/renderer/core/layout/line/root_inline_box.cc
+++ b/third_party/blink/renderer/core/layout/line/root_inline_box.cc
@@ -229,20 +229,6 @@
   }
 }
 
-static inline void ApplyLineHeightStep(uint8_t line_height_step,
-                                       LayoutUnit& max_ascent,
-                                       LayoutUnit& max_descent) {
-  // Round up to the multiple of units, by adding spaces to over/under equally.
-  // https://drafts.csswg.org/css-rhythm/#line-height-step
-  int remainder = (max_ascent + max_descent).ToInt() % line_height_step;
-  if (!remainder)
-    return;
-  DCHECK_GT(remainder, 0);
-  int space = line_height_step - remainder;
-  max_descent += space / 2;
-  max_ascent += space - space / 2;
-}
-
 LayoutUnit RootInlineBox::AlignBoxesInBlockDirection(
     LayoutUnit height_of_block,
     GlyphOverflowAndFallbackFontsMap& text_box_data_map,
@@ -273,10 +259,6 @@
     AdjustMaxAscentAndDescent(max_ascent, max_descent, max_position_top.ToInt(),
                               max_position_bottom.ToInt());
 
-  if (uint8_t line_height_step =
-          GetLineLayoutItem().StyleRef().LineHeightStep())
-    ApplyLineHeightStep(line_height_step, max_ascent, max_descent);
-
   LayoutUnit max_height = LayoutUnit(max_ascent + max_descent);
   LayoutUnit line_top = height_of_block;
   LayoutUnit line_bottom = height_of_block;
diff --git a/third_party/blink/renderer/core/layout/ng/grid/layout_ng_grid.cc b/third_party/blink/renderer/core/layout/ng/grid/layout_ng_grid.cc
index c67acb4..6d2fe79 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/layout_ng_grid.cc
+++ b/third_party/blink/renderer/core/layout/ng/grid/layout_ng_grid.cc
@@ -143,15 +143,7 @@
   if (!HasCachedPlacementData())
     return 0;
 
-  const bool is_for_columns = track_direction == kForColumns;
-  const wtf_size_t auto_repeat_size =
-      is_for_columns
-          ? StyleRef().GridTemplateColumns().TrackList().AutoRepeatTrackCount()
-          : StyleRef().GridTemplateRows().TrackList().AutoRepeatTrackCount();
-
-  return auto_repeat_size *
-         (is_for_columns ? cached_placement_data_->column_auto_repetitions
-                         : cached_placement_data_->row_auto_repetitions);
+  return cached_placement_data_->AutoRepeatTrackCount(track_direction);
 }
 
 wtf_size_t LayoutNGGrid::ExplicitGridStartForDirection(
@@ -170,14 +162,9 @@
   if (!HasCachedPlacementData())
     return 0;
 
-  const wtf_size_t explicit_grid_track_count =
-      (track_direction == kForColumns)
-          ? cached_placement_data_->explicit_grid_column_count
-          : cached_placement_data_->explicit_grid_row_count;
-
   return base::checked_cast<wtf_size_t>(
       ExplicitGridStartForDirection(track_direction) +
-      explicit_grid_track_count);
+      cached_placement_data_->ExplicitGridTrackCount(track_direction));
 }
 
 LayoutUnit LayoutNGGrid::GridGap(
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_data.h b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_data.h
index 554e2d28..f8ca7c90 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_data.h
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_data.h
@@ -16,57 +16,71 @@
   NGGridPlacementData(NGGridPlacementData&&) = default;
   NGGridPlacementData& operator=(NGGridPlacementData&&) = default;
 
-  explicit NGGridPlacementData(const ComputedStyle& grid_style)
-      : line_resolver(grid_style) {}
+  explicit NGGridPlacementData(const ComputedStyle& grid_style,
+                               wtf_size_t column_auto_repetitions,
+                               wtf_size_t row_auto_repetitions)
+      : line_resolver(grid_style,
+                      column_auto_repetitions,
+                      row_auto_repetitions) {}
 
   // Subgrids need to map named lines from every parent grid. This constructor
   // should be used exclusively by subgrids to differentiate such scenario.
   NGGridPlacementData(const ComputedStyle& grid_style,
                       const NGGridLineResolver& parent_line_resolver,
                       GridArea subgrid_area)
-      : line_resolver(grid_style, parent_line_resolver, subgrid_area) {
-    if (subgrid_area.columns.IsTranslatedDefinite())
-      subgridded_column_span_size = subgrid_area.SpanSize(kForColumns);
-    if (subgrid_area.rows.IsTranslatedDefinite())
-      subgridded_row_span_size = subgrid_area.SpanSize(kForRows);
-  }
+      : line_resolver(grid_style, parent_line_resolver, subgrid_area) {}
 
   // This constructor only copies inputs to the auto-placement algorithm.
   NGGridPlacementData(const NGGridPlacementData& other)
-      : line_resolver(other.line_resolver),
-        subgridded_column_span_size(other.subgridded_column_span_size),
-        subgridded_row_span_size(other.subgridded_row_span_size),
-        column_auto_repetitions(other.column_auto_repetitions),
-        row_auto_repetitions(other.row_auto_repetitions) {}
+      : line_resolver(other.line_resolver) {}
 
   // This method compares the fields computed by the auto-placement algorithm in
   // |NGGridPlacement| and it's only intended to validate the cached data.
   bool operator==(const NGGridPlacementData& other) const {
     return grid_item_positions == other.grid_item_positions &&
-           explicit_grid_column_count == other.explicit_grid_column_count &&
-           explicit_grid_row_count == other.explicit_grid_row_count &&
            column_start_offset == other.column_start_offset &&
-           row_start_offset == other.row_start_offset;
+           row_start_offset == other.row_start_offset &&
+           line_resolver == other.line_resolver;
   }
 
+  bool operator!=(const NGGridPlacementData& other) const {
+    return !(*this == other);
+  }
+
+  // TODO(kschmi): Remove placement data from `NGGridPlacement` as well as
+  // these helpers.
   bool HasStandaloneAxis(GridTrackSizingDirection track_direction) const {
-    const wtf_size_t subgrid_span_size = (track_direction == kForColumns)
-                                             ? subgridded_column_span_size
-                                             : subgridded_row_span_size;
-    return subgrid_span_size == kNotFound;
+    return line_resolver.HasStandaloneAxis(track_direction);
+  }
+
+  wtf_size_t AutoRepetitions(GridTrackSizingDirection track_direction) const {
+    return line_resolver.AutoRepetitions(track_direction);
+  }
+
+  wtf_size_t AutoRepeatTrackCount(
+      GridTrackSizingDirection track_direction) const {
+    return line_resolver.AutoRepeatTrackCount(track_direction);
+  }
+
+  wtf_size_t SubgridSpanSize(GridTrackSizingDirection track_direction) const {
+    return line_resolver.SubgridSpanSize(track_direction);
+  }
+
+  wtf_size_t ExplicitGridTrackCount(
+      GridTrackSizingDirection track_direction) const {
+    return line_resolver.ExplicitGridTrackCount(track_direction);
+  }
+
+  wtf_size_t StartOffset(GridTrackSizingDirection track_direction) const {
+    return (track_direction == kForColumns) ? column_start_offset
+                                            : row_start_offset;
   }
 
   NGGridLineResolver line_resolver;
-  wtf_size_t subgridded_column_span_size{kNotFound};
-  wtf_size_t subgridded_row_span_size{kNotFound};
-  wtf_size_t column_auto_repetitions{1};
-  wtf_size_t row_auto_repetitions{1};
 
   // These fields are computed in |NGGridPlacement::RunAutoPlacementAlgorithm|,
   // so they're not considered inputs to the grid placement step.
   Vector<GridArea> grid_item_positions;
-  wtf_size_t explicit_grid_column_count{0};
-  wtf_size_t explicit_grid_row_count{0};
   wtf_size_t column_start_offset{0};
   wtf_size_t row_start_offset{0};
 };
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
index d0c89f0..a0f3e2fc 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
@@ -477,22 +477,24 @@
 
   const auto& node = Node();
   const auto& style = node.Style();
-
-  // Initialize this grid's placement data.
-  auto placement_data =
-      parent_line_resolver
-          ? NGGridPlacementData(style, *parent_line_resolver,
-                                SubgriddedAreaInParent(subgrid_data))
-          : NGGridPlacementData(style);
+  wtf_size_t column_auto_repetitions = kNotFound;
+  wtf_size_t row_auto_repetitions = kNotFound;
 
   // TODO(ethavar): Compute automatic repetitions for subgridded axes as
   // described in https://drafts.csswg.org/css-grid-2/#auto-repeat.
   if (!parent_sizing_data) {
-    placement_data.column_auto_repetitions =
-        ComputeAutomaticRepetitions(kForColumns);
-    placement_data.row_auto_repetitions = ComputeAutomaticRepetitions(kForRows);
+    column_auto_repetitions = ComputeAutomaticRepetitions(kForColumns);
+    row_auto_repetitions = ComputeAutomaticRepetitions(kForRows);
   }
 
+  // Initialize this grid's placement data.
+  // TODO(kschmi): Remove placement data from `NGGridPlacement`.
+  auto placement_data =
+      parent_line_resolver
+          ? NGGridPlacementData(style, *parent_line_resolver,
+                                SubgriddedAreaInParent(subgrid_data))
+          : NGGridPlacementData(style, column_auto_repetitions,
+                                row_auto_repetitions);
   bool has_nested_subgrid = false;
   auto& sizing_data = sizing_tree->CreateSizingData();
 
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_line_resolver.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_line_resolver.cc
index 6f05764..9570bdb 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_line_resolver.cc
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_line_resolver.cc
@@ -39,6 +39,11 @@
           grid_style.ImplicitNamedGridColumnLines()),
       subgridded_rows_merged_implicit_grid_line_names_(
           grid_style.ImplicitNamedGridRowLines()) {
+  if (subgrid_area.columns.IsTranslatedDefinite())
+    subgridded_column_span_size_ = subgrid_area.SpanSize(kForColumns);
+  if (subgrid_area.rows.IsTranslatedDefinite())
+    subgridded_row_span_size_ = subgrid_area.SpanSize(kForRows);
+
   auto MergeNamedGridLinesWithParent = [](NamedGridLinesMap& subgrid_map,
                                           const NamedGridLinesMap& parent_map,
                                           GridSpan subgrid_span) -> void {
@@ -208,6 +213,16 @@
   }
 }
 
+bool NGGridLineResolver::operator==(const NGGridLineResolver& other) const {
+  // This should only compare input data for placement. |style_| isn't
+  // applicable since we shouldn't compare line resolvers of different nodes,
+  // and the named line maps are a product of the computed style and the inputs.
+  return column_auto_repetitions_ == other.column_auto_repetitions_ &&
+         row_auto_repetitions_ == other.row_auto_repetitions_ &&
+         subgridded_column_span_size_ == other.subgridded_column_span_size_ &&
+         subgridded_row_span_size_ == other.subgridded_row_span_size_;
+}
+
 void NGGridLineResolver::InitialAndFinalPositionsFromStyle(
     const ComputedStyle& grid_item_style,
     GridTrackSizingDirection track_direction,
@@ -319,54 +334,75 @@
   return merged_explicit_grid_line_names.has_value();
 }
 
-wtf_size_t NGGridLineResolver::ExplicitGridColumnCount(
-    wtf_size_t auto_repeat_tracks_count,
-    wtf_size_t subgrid_span_size) const {
-  if (subgrid_span_size != kNotFound)
-    return subgrid_span_size;
+wtf_size_t NGGridLineResolver::ExplicitGridColumnCount() const {
+  if (subgridded_column_span_size_ != kNotFound)
+    return subgridded_column_span_size_;
 
-  // TODO(kschmi): Refactor so that `subgrid_span_size` isn't necessary.
   return std::min<wtf_size_t>(std::max(style_->GridTemplateColumns()
                                                .track_sizes.NGTrackList()
                                                .TrackCountWithoutAutoRepeat() +
-                                           auto_repeat_tracks_count,
+                                           AutoRepeatTrackCount(kForColumns),
                                        style_->NamedGridAreaColumnCount()),
                               kGridMaxTracks);
 }
 
-wtf_size_t NGGridLineResolver::ExplicitGridRowCount(
-    wtf_size_t auto_repeat_rows_count,
-    wtf_size_t subgrid_span_size) const {
-  if (subgrid_span_size != kNotFound)
-    return subgrid_span_size;
+wtf_size_t NGGridLineResolver::ExplicitGridRowCount() const {
+  if (subgridded_row_span_size_ != kNotFound)
+    return subgridded_row_span_size_;
 
-  // TODO(kschmi): Refactor so that `subgrid_span_size` isn't necessary.
   return std::min<wtf_size_t>(std::max(style_->GridTemplateRows()
                                                .track_sizes.NGTrackList()
                                                .TrackCountWithoutAutoRepeat() +
-                                           auto_repeat_rows_count,
+                                           AutoRepeatTrackCount(kForRows),
                                        style_->NamedGridAreaRowCount()),
                               kGridMaxTracks);
 }
 
+wtf_size_t NGGridLineResolver::ExplicitGridTrackCount(
+    GridTrackSizingDirection track_direction) const {
+  return (track_direction == kForColumns) ? ExplicitGridColumnCount()
+                                          : ExplicitGridRowCount();
+}
+
+wtf_size_t NGGridLineResolver::AutoRepetitions(
+    GridTrackSizingDirection track_direction) const {
+  return (track_direction == kForColumns) ? column_auto_repetitions_
+                                          : row_auto_repetitions_;
+}
+
+wtf_size_t NGGridLineResolver::AutoRepeatTrackCount(
+    GridTrackSizingDirection track_direction) const {
+  return AutoRepetitions(track_direction) *
+         ComputedGridTrackList(track_direction)
+             .TrackList()
+             .AutoRepeatTrackCount();
+}
+
+wtf_size_t NGGridLineResolver::SubgridSpanSize(
+    GridTrackSizingDirection track_direction) const {
+  return (track_direction == kForColumns) ? subgridded_column_span_size_
+                                          : subgridded_row_span_size_;
+}
+
+bool NGGridLineResolver::HasStandaloneAxis(
+    GridTrackSizingDirection track_direction) const {
+  return (track_direction == kForColumns)
+             ? subgridded_column_span_size_ == kNotFound
+             : subgridded_row_span_size_ == kNotFound;
+}
+
 wtf_size_t NGGridLineResolver::ExplicitGridSizeForSide(
-    GridPositionSide side,
-    wtf_size_t auto_repeat_tracks_count,
-    wtf_size_t subgrid_span_size) const {
+    GridPositionSide side) const {
   return (side == kColumnStartSide || side == kColumnEndSide)
-             ? ExplicitGridColumnCount(auto_repeat_tracks_count,
-                                       subgrid_span_size)
-             : ExplicitGridRowCount(auto_repeat_tracks_count,
-                                    subgrid_span_size);
+             ? ExplicitGridColumnCount()
+             : ExplicitGridRowCount();
 }
 
 GridSpan
 NGGridLineResolver::ResolveNamedGridLinePositionAgainstOppositePosition(
     int opposite_line,
     const GridPosition& position,
-    wtf_size_t auto_repeat_tracks_count,
-    GridPositionSide side,
-    wtf_size_t subgrid_span_size) const {
+    GridPositionSide side) const {
   DCHECK(position.IsSpan());
   DCHECK(!position.NamedGridLine().IsNull());
   // Negative positions are not allowed per the specification and should have
@@ -377,9 +413,9 @@
   const auto& implicit_grid_line_names = ImplicitNamedLinesMap(track_direction);
   const auto& explicit_grid_line_names = ExplicitNamedLinesMap(track_direction);
   const auto& computed_grid_track_list = ComputedGridTrackList(track_direction);
+  const auto& auto_repeat_tracks_count = AutoRepeatTrackCount(track_direction);
 
-  wtf_size_t last_line = ExplicitGridSizeForSide(side, auto_repeat_tracks_count,
-                                                 subgrid_span_size);
+  wtf_size_t last_line = ExplicitGridSizeForSide(side);
 
   NGGridNamedLineCollection lines_collection(
       position.NamedGridLine(), track_direction, implicit_grid_line_names,
@@ -442,9 +478,7 @@
 GridSpan NGGridLineResolver::ResolveGridPositionAgainstOppositePosition(
     int opposite_line,
     const GridPosition& position,
-    GridPositionSide side,
-    wtf_size_t auto_repeat_tracks_count,
-    wtf_size_t subgrid_span_size) const {
+    GridPositionSide side) const {
   if (position.IsAuto()) {
     if (side == kColumnStartSide || side == kRowStartSide) {
       return GridSpan::UntranslatedDefiniteGridSpan(opposite_line - 1,
@@ -460,9 +494,8 @@
   if (!position.NamedGridLine().IsNull()) {
     // span 2 'c' -> we need to find the appropriate grid line before / after
     // our opposite position.
-    return ResolveNamedGridLinePositionAgainstOppositePosition(
-        opposite_line, position, auto_repeat_tracks_count, side,
-        subgrid_span_size);
+    return ResolveNamedGridLinePositionAgainstOppositePosition(opposite_line,
+                                                               position, side);
   }
 
   return DefiniteGridSpanWithSpanAgainstOpposite(opposite_line, position, side);
@@ -496,17 +529,16 @@
 
 int NGGridLineResolver::ResolveNamedGridLinePosition(
     const GridPosition& position,
-    GridPositionSide side,
-    wtf_size_t auto_repeat_tracks_count,
-    wtf_size_t subgrid_span_size) const {
+    GridPositionSide side) const {
   DCHECK(!position.NamedGridLine().IsNull());
 
-  wtf_size_t last_line = ExplicitGridSizeForSide(side, auto_repeat_tracks_count,
-                                                 subgrid_span_size);
+  wtf_size_t last_line = ExplicitGridSizeForSide(side);
   GridTrackSizingDirection track_direction = DirectionFromSide(side);
   const auto& implicit_grid_line_names = ImplicitNamedLinesMap(track_direction);
   const auto& explicit_grid_line_names = ExplicitNamedLinesMap(track_direction);
   const auto& track_list = ComputedGridTrackList(track_direction);
+  const auto& auto_repeat_tracks_count = AutoRepeatTrackCount(track_direction);
+
   NGGridNamedLineCollection lines_collection(
       position.NamedGridLine(), track_direction, implicit_grid_line_names,
       explicit_grid_line_names, track_list, last_line, auto_repeat_tracks_count,
@@ -521,20 +553,17 @@
                                   last_line, lines_collection);
 }
 
-int NGGridLineResolver::ResolveGridPosition(
-    const GridPosition& position,
-    GridPositionSide side,
-    wtf_size_t auto_repeat_tracks_count,
-    wtf_size_t subgrid_span_size) const {
+int NGGridLineResolver::ResolveGridPosition(const GridPosition& position,
+                                            GridPositionSide side) const {
   auto track_direction = DirectionFromSide(side);
+  const auto& auto_repeat_tracks_count = AutoRepeatTrackCount(track_direction);
 
   switch (position.GetType()) {
     case kExplicitPosition: {
       DCHECK(position.IntegerPosition());
 
       if (!position.NamedGridLine().IsNull()) {
-        return ResolveNamedGridLinePosition(
-            position, side, auto_repeat_tracks_count, subgrid_span_size);
+        return ResolveNamedGridLinePosition(position, side);
       }
 
       // Handle <integer> explicit position.
@@ -542,8 +571,7 @@
         return position.IntegerPosition() - 1;
 
       wtf_size_t resolved_position = abs(position.IntegerPosition()) - 1;
-      wtf_size_t end_of_track = ExplicitGridSizeForSide(
-          side, auto_repeat_tracks_count, subgrid_span_size);
+      wtf_size_t end_of_track = ExplicitGridSizeForSide(side);
 
       return end_of_track - resolved_position;
     }
@@ -555,8 +583,7 @@
       String named_grid_line = position.NamedGridLine();
       DCHECK(!position.NamedGridLine().IsNull());
 
-      wtf_size_t last_line = ExplicitGridSizeForSide(
-          side, auto_repeat_tracks_count, subgrid_span_size);
+      wtf_size_t last_line = ExplicitGridSizeForSide(side);
 
       const auto& implicit_grid_line_names =
           ImplicitNamedLinesMap(track_direction);
@@ -597,9 +624,7 @@
 
 GridSpan NGGridLineResolver::ResolveGridPositionsFromStyle(
     const ComputedStyle& grid_item_style,
-    GridTrackSizingDirection track_direction,
-    wtf_size_t auto_repeat_tracks_count,
-    wtf_size_t subgrid_span_size) const {
+    GridTrackSizingDirection track_direction) const {
   GridPosition initial_position, final_position;
   InitialAndFinalPositionsFromStyle(grid_item_style, track_direction,
                                     initial_position, final_position);
@@ -625,30 +650,21 @@
   if (initial_should_be_resolved_against_opposite_position) {
     // Infer the position from the final_position position ('auto / 1' or 'span
     // 2 / 3' case).
-    int end_line =
-        ResolveGridPosition(final_position, final_side,
-                            auto_repeat_tracks_count, subgrid_span_size);
+    int end_line = ResolveGridPosition(final_position, final_side);
     return ResolveGridPositionAgainstOppositePosition(
-        end_line, initial_position, initial_side, auto_repeat_tracks_count,
-        subgrid_span_size);
+        end_line, initial_position, initial_side);
   }
 
   if (final_should_be_resolved_against_opposite_position) {
     // Infer our position from the initial_position position ('1 / auto' or '3 /
     // span 2' case).
-    int start_line =
-        ResolveGridPosition(initial_position, initial_side,
-                            auto_repeat_tracks_count, subgrid_span_size);
+    int start_line = ResolveGridPosition(initial_position, initial_side);
     return ResolveGridPositionAgainstOppositePosition(
-        start_line, final_position, final_side, auto_repeat_tracks_count,
-        subgrid_span_size);
+        start_line, final_position, final_side);
   }
 
-  int start_line =
-      ResolveGridPosition(initial_position, initial_side,
-                          auto_repeat_tracks_count, subgrid_span_size);
-  int end_line = ResolveGridPosition(
-      final_position, final_side, auto_repeat_tracks_count, subgrid_span_size);
+  int start_line = ResolveGridPosition(initial_position, initial_side);
+  int end_line = ResolveGridPosition(final_position, final_side);
 
   if (end_line < start_line)
     std::swap(end_line, start_line);
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_line_resolver.h b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_line_resolver.h
index 546471fc..3aff4ce 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_line_resolver.h
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_line_resolver.h
@@ -28,8 +28,12 @@
  public:
   NGGridLineResolver() = default;
 
-  explicit NGGridLineResolver(const ComputedStyle& grid_style)
-      : style_(&grid_style) {}
+  explicit NGGridLineResolver(const ComputedStyle& grid_style,
+                              wtf_size_t column_auto_repetitions,
+                              wtf_size_t row_auto_repetitions)
+      : style_(&grid_style),
+        column_auto_repetitions_(column_auto_repetitions),
+        row_auto_repetitions_(row_auto_repetitions) {}
 
   // Subgrids need to map named lines from every parent grid. This constructor
   // should be used exclusively by subgrids to differentiate such scenario.
@@ -37,22 +41,31 @@
                               const NGGridLineResolver& parent_line_resolver,
                               GridArea subgrid_area);
 
-  wtf_size_t ExplicitGridColumnCount(
-      wtf_size_t auto_repeat_columns_count,
-      wtf_size_t subgrid_span_size = kNotFound) const;
+  bool operator==(const NGGridLineResolver& other) const;
 
-  wtf_size_t ExplicitGridRowCount(
-      wtf_size_t auto_repeat_rows_count,
-      wtf_size_t subgrid_span_size = kNotFound) const;
+  wtf_size_t ExplicitGridColumnCount() const;
 
-  wtf_size_t SpanSizeForAutoPlacedItem(const ComputedStyle&,
-                                       GridTrackSizingDirection) const;
+  wtf_size_t ExplicitGridRowCount() const;
+
+  wtf_size_t ExplicitGridTrackCount(
+      GridTrackSizingDirection track_direction) const;
+
+  wtf_size_t AutoRepetitions(GridTrackSizingDirection track_direction) const;
+
+  wtf_size_t AutoRepeatTrackCount(
+      GridTrackSizingDirection track_direction) const;
+
+  wtf_size_t SubgridSpanSize(GridTrackSizingDirection track_direction) const;
+
+  bool HasStandaloneAxis(GridTrackSizingDirection track_direction) const;
+
+  wtf_size_t SpanSizeForAutoPlacedItem(
+      const ComputedStyle& grid_item_style,
+      GridTrackSizingDirection track_direction) const;
 
   GridSpan ResolveGridPositionsFromStyle(
-      const ComputedStyle&,
-      GridTrackSizingDirection,
-      wtf_size_t auto_repeat_tracks_count,
-      wtf_size_t subgrid_span_size = kNotFound) const;
+      const ComputedStyle& grid_item_style,
+      GridTrackSizingDirection track_direction) const;
 
  private:
   const NamedGridLinesMap& ImplicitNamedLinesMap(
@@ -67,25 +80,17 @@
   GridSpan ResolveGridPositionAgainstOppositePosition(
       int opposite_line,
       const GridPosition& position,
-      GridPositionSide side,
-      wtf_size_t auto_repeat_tracks_count,
-      wtf_size_t subgrid_span_size) const;
+      GridPositionSide side) const;
 
   GridSpan ResolveNamedGridLinePositionAgainstOppositePosition(
       int opposite_line,
       const GridPosition& position,
-      wtf_size_t auto_repeat_tracks_count,
-      GridPositionSide side,
-      wtf_size_t subgrid_span_size) const;
+      GridPositionSide side) const;
 
   int ResolveGridPosition(const GridPosition& position,
-                          GridPositionSide side,
-                          wtf_size_t auto_repeat_tracks_count,
-                          wtf_size_t subgrid_span_size) const;
+                          GridPositionSide side) const;
 
-  wtf_size_t ExplicitGridSizeForSide(GridPositionSide side,
-                                     wtf_size_t auto_repeat_tracks_count,
-                                     wtf_size_t subgrid_span_size) const;
+  wtf_size_t ExplicitGridSizeForSide(GridPositionSide side) const;
 
   wtf_size_t LookAheadForNamedGridLine(
       int start,
@@ -103,9 +108,7 @@
                                    const GridPosition& final_position) const;
 
   int ResolveNamedGridLinePosition(const GridPosition& position,
-                                   GridPositionSide side,
-                                   wtf_size_t auto_repeat_tracks_count,
-                                   wtf_size_t subgrid_span_size) const;
+                                   GridPositionSide side) const;
 
   void InitialAndFinalPositionsFromStyle(
       const ComputedStyle& grid_item_style,
@@ -124,6 +127,11 @@
 
   scoped_refptr<const ComputedStyle> style_;
 
+  wtf_size_t column_auto_repetitions_{1};
+  wtf_size_t row_auto_repetitions_{1};
+  wtf_size_t subgridded_column_span_size_{kNotFound};
+  wtf_size_t subgridded_row_span_size_{kNotFound};
+
   absl::optional<NamedGridLinesMap>
       subgridded_columns_merged_explicit_grid_line_names_;
   absl::optional<NamedGridLinesMap>
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_node.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_node.cc
index bd05bab..d854bdb 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_node.cc
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_node.cc
@@ -47,10 +47,7 @@
     grid_items.ReserveInitialCapacity(
         cached_placement_data->grid_item_positions.size());
 
-    if (placement_data.column_auto_repetitions !=
-            cached_placement_data->column_auto_repetitions ||
-        placement_data.row_auto_repetitions !=
-            cached_placement_data->row_auto_repetitions) {
+    if (placement_data != *cached_placement_data) {
       // We need to recompute grid item placement if the automatic column/row
       // repetitions changed due to updates in the container's style.
       cached_placement_data = nullptr;
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_placement.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_placement.cc
index d61b8af..0d97113 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_placement.cc
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_placement.cc
@@ -37,25 +37,19 @@
 
 NGGridPlacement::NGGridPlacement(const ComputedStyle& grid_style,
                                  const NGGridPlacementData& placement_data)
-    : packing_behavior_(grid_style.IsGridAutoFlowAlgorithmSparse()
+    : placement_data_(placement_data),
+      packing_behavior_(grid_style.IsGridAutoFlowAlgorithmSparse()
                             ? PackingBehavior::kSparse
                             : PackingBehavior::kDense),
-      placement_data_(placement_data),
       // The major direction is the one specified in the 'grid-auto-flow'
       // property (row or column), the minor direction is its opposite.
       major_direction_(grid_style.IsGridAutoFlowDirectionRow() ? kForRows
                                                                : kForColumns),
       minor_direction_(grid_style.IsGridAutoFlowDirectionRow() ? kForColumns
-                                                               : kForRows),
+                                                               : kForRows) {
 #if DCHECK_IS_ON()
-      auto_placement_algorithm_called_(false),
+  auto_placement_algorithm_called_ = false;
 #endif
-      column_auto_repeat_track_count_(
-          grid_style.GridTemplateColumns().TrackList().AutoRepeatTrackCount() *
-          placement_data.column_auto_repetitions),
-      row_auto_repeat_track_count_(
-          grid_style.GridTemplateRows().TrackList().AutoRepeatTrackCount() *
-          placement_data.row_auto_repetitions) {
 }
 
 // https://drafts.csswg.org/css-grid/#auto-placement-algo
@@ -137,13 +131,11 @@
     GridArea position;
     position.columns =
         placement_data_.line_resolver.ResolveGridPositionsFromStyle(
-            item_style, kForColumns, column_auto_repeat_track_count_,
-            placement_data_.subgridded_column_span_size);
+            item_style, kForColumns);
     DCHECK(!position.columns.IsTranslatedDefinite());
 
     position.rows = placement_data_.line_resolver.ResolveGridPositionsFromStyle(
-        item_style, kForRows, row_auto_repeat_track_count_,
-        placement_data_.subgridded_row_span_size);
+        item_style, kForRows);
     DCHECK(!position.rows.IsTranslatedDefinite());
 
     // When we have negative indices that go beyond the start of the explicit
@@ -165,21 +157,12 @@
     placement_data_.grid_item_positions.emplace_back(position);
   }
 
-  placement_data_.explicit_grid_column_count =
-      placement_data_.line_resolver.ExplicitGridColumnCount(
-          column_auto_repeat_track_count_,
-          placement_data_.subgridded_column_span_size);
-
-  placement_data_.explicit_grid_row_count =
-      placement_data_.line_resolver.ExplicitGridRowCount(
-          row_auto_repeat_track_count_,
-          placement_data_.subgridded_row_span_size);
-
-  minor_max_end_line_ = (minor_direction_ == kForColumns)
-                            ? placement_data_.column_start_offset +
-                                  placement_data_.explicit_grid_column_count
-                            : placement_data_.row_start_offset +
-                                  placement_data_.explicit_grid_row_count;
+  minor_max_end_line_ =
+      (minor_direction_ == kForColumns)
+          ? placement_data_.column_start_offset +
+                placement_data_.ExplicitGridTrackCount(kForColumns)
+          : placement_data_.row_start_offset +
+                placement_data_.ExplicitGridTrackCount(kForRows);
 
   placed_items->needs_to_sort_item_vector = false;
   auto& non_auto_placed_items = placed_items->item_vector;
@@ -349,7 +332,8 @@
 
 void NGGridPlacement::ClampGridItemsToFitSubgridArea(
     GridTrackSizingDirection track_direction) {
-  const wtf_size_t subgrid_span_size = SubgridSpanSize(track_direction);
+  const wtf_size_t subgrid_span_size =
+      placement_data_.SubgridSpanSize(track_direction);
 
   // If no subgrid span size was specified, then we should create implicit grid
   // lines for placement, so we don't need to clamp the resolved positions.
@@ -357,7 +341,7 @@
     return;
 
   DCHECK_GT(subgrid_span_size, 0u);
-  const int start_offset = StartOffset(track_direction);
+  const int start_offset = placement_data_.StartOffset(track_direction);
 
   for (auto& resolved_position : placement_data_.grid_item_positions) {
     int start_line =
@@ -380,32 +364,6 @@
     placement_data_.row_start_offset = 0;
 }
 
-wtf_size_t NGGridPlacement::AutoRepeatTrackCount(
-    GridTrackSizingDirection track_direction) const {
-  return (track_direction == kForColumns) ? column_auto_repeat_track_count_
-                                          : row_auto_repeat_track_count_;
-}
-
-wtf_size_t NGGridPlacement::AutoRepetitions(
-    GridTrackSizingDirection track_direction) const {
-  return (track_direction == kForColumns)
-             ? placement_data_.column_auto_repetitions
-             : placement_data_.row_auto_repetitions;
-}
-
-wtf_size_t NGGridPlacement::StartOffset(
-    GridTrackSizingDirection track_direction) const {
-  return (track_direction == kForColumns) ? placement_data_.column_start_offset
-                                          : placement_data_.row_start_offset;
-}
-
-wtf_size_t NGGridPlacement::SubgridSpanSize(
-    GridTrackSizingDirection track_direction) const {
-  return (track_direction == kForColumns)
-             ? placement_data_.subgridded_column_span_size
-             : placement_data_.subgridded_row_span_size;
-}
-
 bool NGGridPlacement::HasSparsePacking() const {
   return packing_behavior_ == PackingBehavior::kSparse;
 }
@@ -667,19 +625,8 @@
   const auto track_direction = track_collection.Direction();
   const bool is_for_columns = track_direction == kForColumns;
 
-  const wtf_size_t auto_repeat_track_count =
-      is_for_columns
-          ? grid_style.GridTemplateColumns()
-                    .TrackList()
-                    .AutoRepeatTrackCount() *
-                placement_data.column_auto_repetitions
-          : grid_style.GridTemplateRows().TrackList().AutoRepeatTrackCount() *
-                placement_data.row_auto_repetitions;
-
   const auto span = placement_data.line_resolver.ResolveGridPositionsFromStyle(
-      item_style, track_direction, auto_repeat_track_count,
-      is_for_columns ? placement_data.subgridded_column_span_size
-                     : placement_data.subgridded_row_span_size);
+      item_style, track_direction);
 
   if (span.IsIndefinite())
     return;
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_placement.h b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_placement.h
index be12a86..cf8999b 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_placement.h
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_placement.h
@@ -36,9 +36,6 @@
       wtf_size_t* start_line,
       wtf_size_t* end_line);
 
-  wtf_size_t AutoRepetitions(GridTrackSizingDirection track_direction) const;
-  wtf_size_t StartOffset(GridTrackSizingDirection track_direction) const;
-
  private:
   enum class CursorMovementBehavior { kAuto, kForceMajorLine, kForceMinorLine };
 
@@ -159,24 +156,17 @@
   // subgrid, clamp their resolved positions to the subgrid's explicit grid.
   void ClampGridItemsToFitSubgridArea(GridTrackSizingDirection track_direction);
 
-  wtf_size_t AutoRepeatTrackCount(
-      GridTrackSizingDirection track_direction) const;
-  wtf_size_t SubgridSpanSize(GridTrackSizingDirection track_direction) const;
-
   bool HasSparsePacking() const;
 
-  PackingBehavior packing_behavior_;
-  NGGridPlacementData placement_data_;
-
-  GridTrackSizingDirection major_direction_;
-  GridTrackSizingDirection minor_direction_;
-
 #if DCHECK_IS_ON()
   bool auto_placement_algorithm_called_ : 1;
 #endif
 
-  wtf_size_t column_auto_repeat_track_count_;
-  wtf_size_t row_auto_repeat_track_count_;
+  // TODO(kschmi): Replace `NGGridPlacementData` with line resolver.
+  NGGridPlacementData placement_data_;
+  PackingBehavior packing_behavior_;
+  GridTrackSizingDirection major_direction_;
+  GridTrackSizingDirection minor_direction_;
   wtf_size_t minor_max_end_line_;
 };
 
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.cc
index fa9c2ed..02ebeaa 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.cc
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.cc
@@ -67,9 +67,7 @@
     const ComputedStyle& grid_style,
     const NGGridPlacementData& placement_data,
     GridTrackSizingDirection track_direction)
-    : auto_repetitions_((track_direction == kForColumns)
-                            ? placement_data.column_auto_repetitions
-                            : placement_data.row_auto_repetitions),
+    : auto_repetitions_(placement_data.AutoRepetitions(track_direction)),
       start_offset_((track_direction == kForColumns)
                         ? placement_data.column_start_offset
                         : placement_data.row_start_offset),
diff --git a/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_algorithm.cc
index 10aa30b..36f25d2 100644
--- a/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/svg/ng_svg_text_layout_algorithm.cc
@@ -320,7 +320,9 @@
                                 }) -
          1;
     // 2.4.4. Find the per-character adjustment small-delta = delta/n.
-    float character_delta = n != 0 ? delta / n : delta;
+    // character_delta should be 0 if n==0 because it means we have no
+    // adjustable characters for this textLength.
+    float character_delta = n != 0 ? delta / n : 0;
     // 2.4.5. Let shift = 0.
     shift = 0.0f;
     // 2.4.6. For each index k in the range [i,j]:
diff --git a/third_party/blink/renderer/core/style/computed_style_diff_functions.json5 b/third_party/blink/renderer/core/style/computed_style_diff_functions.json5
index 2448648..2c85bc9 100644
--- a/third_party/blink/renderer/core/style/computed_style_diff_functions.json5
+++ b/third_party/blink/renderer/core/style/computed_style_diff_functions.json5
@@ -82,7 +82,7 @@
                 "TextEmphasisMark", "text-emphasis-position",
                 "TextEmphasisCustomMark", "text-orientation",
                 "text-combine-upright", "tab-size", "text-size-adjust",
-                "list-style-image", "line-height-step",
+                "list-style-image",
                 "-webkit-text-stroke-width", "line-height",
                 "-webkit-border-horizontal-spacing",
                 "-webkit-border-vertical-spacing", "TextAutosizingMultiplier",
diff --git a/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_impl.cc b/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_impl.cc
index e10af94..5e86349 100644
--- a/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_impl.cc
+++ b/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_impl.cc
@@ -8,13 +8,10 @@
 #include <utility>
 
 #include "base/callback_helpers.h"
-#include "base/ranges/algorithm.h"
 #include "media/mojo/mojom/media_player.mojom-blink.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
 #include "third_party/blink/public/common/media/display_type.h"
-#include "third_party/blink/public/common/scheme_registry.h"
-#include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h"
 #include "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
@@ -340,82 +337,6 @@
   return element == picture_in_picture_element_;
 }
 
-void PictureInPictureControllerImpl::AddToAutoPictureInPictureElementsList(
-    HTMLVideoElement* element) {
-  RemoveFromAutoPictureInPictureElementsList(element);
-  auto_picture_in_picture_elements_.push_back(element);
-}
-
-void PictureInPictureControllerImpl::RemoveFromAutoPictureInPictureElementsList(
-    HTMLVideoElement* element) {
-  DCHECK(element);
-  auto it = base::ranges::find(auto_picture_in_picture_elements_, element);
-  if (it != auto_picture_in_picture_elements_.end())
-    auto_picture_in_picture_elements_.erase(it);
-}
-
-HTMLVideoElement* PictureInPictureControllerImpl::AutoPictureInPictureElement()
-    const {
-  return auto_picture_in_picture_elements_.empty()
-             ? nullptr
-             : auto_picture_in_picture_elements_.back();
-}
-
-bool PictureInPictureControllerImpl::IsEnterAutoPictureInPictureAllowed()
-    const {
-  // Entering Auto Picture-in-Picture is allowed if one of these conditions is
-  // true:
-  // - Document runs in a Chrome Extension.
-  // - Document is in fullscreen.
-  // - Document is in a PWA window that runs in the scope of the PWA.
-  bool is_in_pwa_window = false;
-  if (GetSupplementable()->GetFrame()) {
-    mojom::blink::DisplayMode display_mode =
-        GetSupplementable()->GetFrame()->GetWidgetForLocalRoot()->DisplayMode();
-    is_in_pwa_window = display_mode != mojom::blink::DisplayMode::kBrowser;
-  }
-  if (!(CommonSchemeRegistry::IsExtensionScheme(
-            GetSupplementable()->Url().Protocol().Ascii()) ||
-        Fullscreen::FullscreenElementFrom(*GetSupplementable()) ||
-        (is_in_pwa_window && GetSupplementable()->IsInWebAppScope()))) {
-    return false;
-  }
-
-  // Don't allow if there's already an element in Auto Picture-in-Picture.
-  if (picture_in_picture_element_)
-    return false;
-
-#if !BUILDFLAG(IS_ANDROID)
-  // Don't allow if there's already a Document Picture-in-Picture window.
-  if (document_picture_in_picture_window_)
-    return false;
-#endif  // !BUILDFLAG(IS_ANDROID)
-
-  // Don't allow if there's no element eligible to enter Auto Picture-in-Picture
-  if (!AutoPictureInPictureElement())
-    return false;
-
-  // Don't allow if video won't resume playing automatically when it becomes
-  // visible again.
-  if (AutoPictureInPictureElement()->PausedWhenVisible())
-    return false;
-
-  // Allow if video is allowed to enter Picture-in-Picture.
-  return (IsElementAllowed(*AutoPictureInPictureElement(),
-                           /*report_failure=*/true) == Status::kEnabled);
-}
-
-bool PictureInPictureControllerImpl::IsExitAutoPictureInPictureAllowed() const {
-  // Don't allow exiting Auto Picture-in-Picture if there's no eligible element
-  // to exit Auto Picture-in-Picture.
-  if (!AutoPictureInPictureElement())
-    return false;
-
-  // Allow if the element already in Picture-in-Picture is the same as the one
-  // eligible to exit Auto Picture-in-Picture.
-  return (picture_in_picture_element_ == AutoPictureInPictureElement());
-}
-
 #if !BUILDFLAG(IS_ANDROID)
 LocalDOMWindow* PictureInPictureControllerImpl::documentPictureInPictureWindow()
     const {
@@ -567,24 +488,6 @@
 }
 #endif  // !BUILDFLAG(IS_ANDROID)
 
-void PictureInPictureControllerImpl::PageVisibilityChanged() {
-  DCHECK(GetSupplementable());
-
-  // If page becomes visible and exiting Auto Picture-in-Picture is allowed,
-  // exit Picture-in-Picture.
-  if (GetSupplementable()->IsPageVisible() &&
-      IsExitAutoPictureInPictureAllowed()) {
-    ExitPictureInPicture(picture_in_picture_element_, nullptr);
-    return;
-  }
-
-  // If page becomes hidden and entering Auto Picture-in-Picture is allowed,
-  // enter Picture-in-Picture.
-  if (GetSupplementable()->hidden() && IsEnterAutoPictureInPictureAllowed()) {
-    EnterPictureInPicture(AutoPictureInPictureElement(), /*promise=*/nullptr);
-  }
-}
-
 void PictureInPictureControllerImpl::OnPictureInPictureStateChange() {
   DCHECK(picture_in_picture_element_);
   DCHECK(picture_in_picture_element_->GetWebMediaPlayer());
@@ -638,20 +541,17 @@
   visitor->Trace(open_document_pip_resolver_);
 #endif  // !BUILDFLAG(IS_ANDROID)
   visitor->Trace(picture_in_picture_element_);
-  visitor->Trace(auto_picture_in_picture_elements_);
   visitor->Trace(picture_in_picture_window_);
   visitor->Trace(session_observer_receiver_);
   visitor->Trace(picture_in_picture_service_);
   visitor->Trace(picture_in_picture_session_);
   PictureInPictureController::Trace(visitor);
-  PageVisibilityObserver::Trace(visitor);
   ExecutionContextClient::Trace(visitor);
 }
 
 PictureInPictureControllerImpl::PictureInPictureControllerImpl(
     Document& document)
     : PictureInPictureController(document),
-      PageVisibilityObserver(document.GetPage()),
       ExecutionContextClient(document.GetExecutionContext()),
       session_observer_receiver_(this, document.GetExecutionContext()),
       picture_in_picture_service_(document.GetExecutionContext()),
diff --git a/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_impl.h b/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_impl.h
index c190a6b1..00caecc 100644
--- a/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_impl.h
+++ b/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_impl.h
@@ -11,10 +11,8 @@
 #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
 #include "third_party/blink/renderer/core/frame/picture_in_picture_controller.h"
-#include "third_party/blink/renderer/core/page/page_visibility_observer.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_window.h"
-#include "third_party/blink/renderer/platform/heap/collection_support/heap_deque.h"
 #include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h"
 #include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
 
@@ -39,7 +37,6 @@
 // whether they want to instantiate an object when they make a call.
 class MODULES_EXPORT PictureInPictureControllerImpl
     : public PictureInPictureController,
-      public PageVisibilityObserver,
       public ExecutionContextClient,
       public blink::mojom::blink::PictureInPictureSessionObserver {
  public:
@@ -64,16 +61,6 @@
   // video-only PiP.
   PictureInPictureWindow* pictureInPictureWindow() const;
 
-  // Returns video element whose autoPictureInPicture attribute was set most
-  // recently.
-  HTMLVideoElement* AutoPictureInPictureElement() const;
-
-  // Returns whether entering Auto Picture-in-Picture is allowed.
-  bool IsEnterAutoPictureInPictureAllowed() const;
-
-  // Returns whether exiting Auto Picture-in-Picture is allowed.
-  bool IsExitAutoPictureInPictureAllowed() const;
-
 #if !BUILDFLAG(IS_ANDROID)
   // Returns the Document Picture-in-Picture window if there is any.
   LocalDOMWindow* documentPictureInPictureWindow() const;
@@ -90,8 +77,6 @@
   void EnterPictureInPicture(HTMLVideoElement*,
                              ScriptPromiseResolver*) override;
   void ExitPictureInPicture(HTMLVideoElement*, ScriptPromiseResolver*) override;
-  void AddToAutoPictureInPictureElementsList(HTMLVideoElement*) override;
-  void RemoveFromAutoPictureInPictureElementsList(HTMLVideoElement*) override;
   bool IsPictureInPictureElement(const Element*) const override;
   void OnPictureInPictureStateChange() override;
   Element* PictureInPictureElement() const override;
@@ -104,9 +89,6 @@
   void OnWindowSizeChanged(const gfx::Size&) override;
   void OnStopped() override;
 
-  // Implementation of PageVisibilityObserver.
-  void PageVisibilityChanged() override;
-
   void Trace(Visitor*) const override;
 
   bool IsSessionObserverReceiverBoundForTesting() {
@@ -194,10 +176,6 @@
   // The Picture-in-Picture element for the associated document.
   Member<HTMLVideoElement> picture_in_picture_element_;
 
-  // The list of video elements for the associated document that are eligible
-  // to Auto Picture-in-Picture.
-  HeapDeque<Member<HTMLVideoElement>> auto_picture_in_picture_elements_;
-
   // The Picture-in-Picture window for the associated document. This is for
   // video-only PiP.
   Member<PictureInPictureWindow> picture_in_picture_window_;
diff --git a/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_test.cc b/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_test.cc
index 4c00bd0..754270d 100644
--- a/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_test.cc
+++ b/third_party/blink/renderer/modules/document_picture_in_picture/picture_in_picture_controller_test.cc
@@ -24,7 +24,6 @@
 #include "third_party/blink/renderer/core/dom/events/event.h"
 #include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
-#include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
 #include "third_party/blink/renderer/core/html/media/html_media_test_helper.h"
 #include "third_party/blink/renderer/core/html/media/html_video_element.h"
 #include "third_party/blink/renderer/core/layout/layout_image.h"
@@ -642,89 +641,8 @@
                 .IsElementAllowed(*Video(), /*report_failure=*/false));
 }
 
-TEST_F(PictureInPictureControllerTestWithWidget,
-       AutoEnterAndExitPictureInPicture) {
-  WebMediaPlayer* player = Video()->GetWebMediaPlayer();
-  EXPECT_CALL(Service(),
-              StartSession(player->GetDelegateId(), _, TestSurfaceId(),
-                           player->NaturalSize(), true, _, _, _));
-
-  auto& controller = PictureInPictureControllerImpl::From(GetDocument());
-
-  // Video element must be on the auto-enter list, and playing in full screen.
-  controller.AddToAutoPictureInPictureElementsList(Video());
-  Video()->Play();
-  LocalFrame::NotifyUserActivation(
-      &GetFrame(), mojom::UserActivationNotificationType::kTest);
-  Fullscreen::RequestFullscreen(*Video());
-  GetWebView()->DidEnterFullscreen();
-  ASSERT_EQ(*Video(), Fullscreen::FullscreenElementFrom(GetDocument()));
-
-  // Hiding the page should trigger auto PiP.
-  GetDocument().GetPage()->SetVisibilityState(
-      mojom::blink::PageVisibilityState::kHidden, /*is_initial_state=*/false);
-  MakeGarbageCollected<WaitForEvent>(Video(),
-                                     event_type_names::kEnterpictureinpicture);
-  EXPECT_TRUE(PictureInPictureControllerImpl::From(GetDocument())
-                  .IsPictureInPictureElement(Video()));
-
-  EXPECT_CALL(Service().Session(), Stop(_));
-
-  GetDocument().GetPage()->SetVisibilityState(
-      mojom::blink::PageVisibilityState::kVisible, /*is_initial_state=*/false);
-  MakeGarbageCollected<WaitForEvent>(Video(),
-                                     event_type_names::kLeavepictureinpicture);
-  EXPECT_FALSE(PictureInPictureControllerImpl::From(GetDocument())
-                   .IsPictureInPictureElement(Video()));
-
-  PictureInPictureControllerImpl::From(GetDocument())
-      .RemoveFromAutoPictureInPictureElementsList(Video());
-
-  EXPECT_EQ(nullptr, PictureInPictureControllerImpl::From(GetDocument())
-                         .PictureInPictureElement());
-}
-
 #if !BUILDFLAG(IS_ANDROID)
 TEST_F(PictureInPictureControllerTestWithWidget,
-       AutoEnterPictureInPictureDuringDocumentPiP) {
-  WebMediaPlayer* player = Video()->GetWebMediaPlayer();
-  EXPECT_CALL(Service(),
-              StartSession(player->GetDelegateId(), _, TestSurfaceId(),
-                           player->NaturalSize(), true, _, _, _))
-      .Times(0);
-
-  auto& controller = PictureInPictureControllerImpl::From(GetDocument());
-
-  // Video element must be on the auto-enter list, and playing in full screen.
-  controller.AddToAutoPictureInPictureElementsList(Video());
-  Video()->Play();
-  LocalFrame::NotifyUserActivation(
-      &GetFrame(), mojom::UserActivationNotificationType::kTest);
-  Fullscreen::RequestFullscreen(*Video());
-  GetWebView()->DidEnterFullscreen();
-  ASSERT_EQ(*Video(), Fullscreen::FullscreenElementFrom(GetDocument()));
-
-  // Hiding the page should not trigger auto PiP if there is a document PiP
-  // window open.
-  V8TestingScope v8_scope;
-  ScriptState* script_state =
-      ToScriptStateForMainWorld(GetDocument().GetFrame());
-  ScriptState::Scope entered_context_scope(script_state);
-  LocalFrame::NotifyUserActivation(
-      &GetFrame(), mojom::UserActivationNotificationType::kTest);
-  auto* window = OpenDocumentPictureInPictureWindow(v8_scope, GetDocument(),
-                                                    CopyStyleSheetOptions::kNo);
-  ASSERT_TRUE(window);
-  GetDocument().GetPage()->SetVisibilityState(
-      mojom::blink::PageVisibilityState::kHidden, /*is_initial_state=*/false);
-
-  EXPECT_TRUE(Fullscreen::IsFullscreenElement(*Video()));
-  EXPECT_EQ(nullptr, PictureInPictureControllerImpl::From(GetDocument())
-                         .PictureInPictureElement());
-  base::RunLoop().RunUntilIdle();
-}
-
-TEST_F(PictureInPictureControllerTestWithWidget,
        DocumentPiPDoesNotAllowVizThrottling) {
   EXPECT_TRUE(GetWidget()->GetMayThrottleIfUndrawnFramesForTesting());
 
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_graph.cc b/third_party/blink/renderer/modules/ml/webnn/ml_graph.cc
index ec67718..f63348fb 100644
--- a/third_party/blink/renderer/modules/ml/webnn/ml_graph.cc
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_graph.cc
@@ -31,21 +31,13 @@
     return false;
   }
   for (const auto& named_array_buffer_view : named_array_buffer_views) {
-    const auto& [name, array_buffer_or_view] = named_array_buffer_view;
+    const auto& [name, array_buffer_view] = named_array_buffer_view;
     if (!resources_info.Contains(name)) {
       error_message = String::Format("The name \"%s\" isn't part of the graph.",
                                      name.Utf8().c_str());
       return false;
     }
     const auto& info = resources_info.at(name);
-    if (!array_buffer_or_view->IsArrayBufferView()) {
-      error_message = String::Format(
-          "The object with name \"%s\" is not an ArrayBufferView.",
-          name.Utf8().c_str());
-      return false;
-    }
-    auto* array_buffer_view =
-        array_buffer_or_view->GetAsArrayBufferView().Get();
     if (array_buffer_view->GetType() != GetArrayBufferViewType(info.type)) {
       error_message = String::Format(
           "The type (%s) of the array buffer view with name \"%s\" doesn't "
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_graph.h b/third_party/blink/renderer/modules/ml/webnn/ml_graph.h
index 08489d8..58d1ce1 100644
--- a/third_party/blink/renderer/modules/ml/webnn/ml_graph.h
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_graph.h
@@ -5,7 +5,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_ML_WEBNN_ML_GRAPH_H_
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_ML_WEBNN_ML_GRAPH_H_
 
-#include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_ml_operand_descriptor.h"
 #include "third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
@@ -22,13 +21,7 @@
 
 // Implement the MLNamedArrayBufferViews type definition of WebNN spec:
 // https://www.w3.org/TR/webnn/#typedefdef-mlnamedarraybufferviews
-
-// TODO(crbug.com/1382288): There is a build error for the C++ type
-// HeapVector<std::pair<String, NotShared<DOMArrayBufferView>>> generated for
-// IDL type record<DOMString, ArrayBufferView>. Use
-// V8UnionArrayBufferOrArrayBufferView as a workaround.
-typedef HeapVector<
-    std::pair<String, Member<V8UnionArrayBufferOrArrayBufferView>>>
+typedef HeapVector<std::pair<String, NotShared<DOMArrayBufferView>>>
     MLNamedArrayBufferViews;
 
 class MODULES_EXPORT MLGraph : public ScriptWrappable {
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder_test.cc b/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder_test.cc
index 6443e80c..323a146 100644
--- a/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder_test.cc
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder_test.cc
@@ -2537,18 +2537,15 @@
   size_t number_of_elements;
   V8MLOperandType::Enum type;
 
-  // TODO(crbug.com/1382288): Return a DOMArrayBufferView.
-  V8UnionArrayBufferOrArrayBufferView* ToArrayBufferView() {
-    return MakeGarbageCollected<V8UnionArrayBufferOrArrayBufferView>(
-        CreateDOMArrayBufferView(number_of_elements, type));
+  NotShared<DOMArrayBufferView> ToArrayBufferView() {
+    return CreateDOMArrayBufferView(number_of_elements, type);
   }
 };
 
 // Helper function to create an ArrayBufferView given an operand.
-V8UnionArrayBufferOrArrayBufferView* CreateArrayBufferViewForOperand(
+NotShared<DOMArrayBufferView> CreateArrayBufferViewForOperand(
     const MLOperand* operand) {
-  return MakeGarbageCollected<V8UnionArrayBufferOrArrayBufferView>(
-      CreateDOMArrayBufferView(operand->NumberOfElements(), operand->Type()));
+  return CreateDOMArrayBufferView(operand->NumberOfElements(), operand->Type());
 }
 
 TEST_P(FakeMLGraphTest, ComputeTest) {
@@ -2724,42 +2721,6 @@
               "Invalid outputs: The byte length (32) of the array buffer view "
               "with name \"c\" doesn't match the expected byte length (36).");
   }
-  {
-    // Test throwing exception if the input is not an array buffer view object.
-    MLNamedArrayBufferViews inputs;
-    inputs.emplace_back("a", CreateArrayBufferViewForOperand(a));
-    inputs.emplace_back(
-        "b", MakeGarbageCollected<V8UnionArrayBufferOrArrayBufferView>(
-                 CreateDOMArrayBufferView(12, V8MLOperandType::Enum::kFloat32)
-                     ->buffer()));
-    MLNamedArrayBufferViews outputs;
-    outputs.emplace_back("c", CreateArrayBufferViewForOperand(c));
-    auto* exception = ComputeGraph(scope, graph, inputs, outputs);
-    EXPECT_NE(exception, nullptr);
-    EXPECT_EQ(exception->name(),
-              DOMException::GetErrorName(DOMExceptionCode::kDataError));
-    EXPECT_EQ(exception->message(),
-              "Invalid inputs: The object with name \"b\" is not an "
-              "ArrayBufferView.");
-  }
-  {
-    // Test throwing exception if the output is not an array buffer view object.
-    MLNamedArrayBufferViews inputs;
-    inputs.emplace_back("a", CreateArrayBufferViewForOperand(a));
-    inputs.emplace_back("b", CreateArrayBufferViewForOperand(b));
-    MLNamedArrayBufferViews outputs;
-    outputs.emplace_back(
-        "c", MakeGarbageCollected<V8UnionArrayBufferOrArrayBufferView>(
-                 CreateDOMArrayBufferView(9, V8MLOperandType::Enum::kFloat32)
-                     ->buffer()));
-    auto* exception = ComputeGraph(scope, graph, inputs, outputs);
-    EXPECT_NE(exception, nullptr);
-    EXPECT_EQ(exception->name(),
-              DOMException::GetErrorName(DOMExceptionCode::kDataError));
-    EXPECT_EQ(exception->message(),
-              "Invalid outputs: The object with name \"c\" is not an "
-              "ArrayBufferView.");
-  }
 }
 
 INSTANTIATE_TEST_SUITE_P(All,
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_stats_report.cc b/third_party/blink/renderer/modules/peerconnection/rtc_stats_report.cc
index 72c778f0f..20f4d40 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_stats_report.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_stats_report.cc
@@ -33,11 +33,6 @@
   return v8_object;
 }
 
-bool IsFullScreenEnabled(LocalDOMWindow* window) {
-  Document* document = window->document();
-  return document && DocumentFullscreen::fullscreenElement(*document);
-}
-
 bool IsCapturing(LocalDOMWindow* window) {
   UserMediaClient* user_media_client = UserMediaClient::From(window);
   return user_media_client && user_media_client->IsCapturing();
@@ -46,12 +41,11 @@
 bool ExposeHardwareCapabilityStats(ScriptState* script_state) {
   // According the the spec description at
   // https://w3c.github.io/webrtc-stats/#dfn-exposing-hardware-is-allowed,
-  // hardware capabilities may be exposed if,
-  // 1. there is a full-screen element, or
-  // 2. the context capturing state is true.
+  // hardware capabilities may be exposed if the context capturing state is
+  // true.
   ExecutionContext* ctx = ExecutionContext::From(script_state);
   LocalDOMWindow* window = DynamicTo<LocalDOMWindow>(ctx);
-  return window && (IsCapturing(window) || IsFullScreenEnabled(window));
+  return window && IsCapturing(window);
 }
 
 v8::Local<v8::Object> RTCStatsToV8Object(ScriptState* script_state,
diff --git a/third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.cc b/third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.cc
index c37e4ae..77758d9 100644
--- a/third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.cc
+++ b/third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.cc
@@ -61,8 +61,7 @@
 bool HTMLVideoElementPictureInPicture::FastHasAttribute(
     const HTMLVideoElement& element,
     const QualifiedName& name) {
-  DCHECK(name == html_names::kDisablepictureinpictureAttr ||
-         name == html_names::kAutopictureinpictureAttr);
+  DCHECK(name == html_names::kDisablepictureinpictureAttr);
   return element.FastHasAttribute(name);
 }
 
@@ -71,8 +70,7 @@
     HTMLVideoElement& element,
     const QualifiedName& name,
     bool value) {
-  DCHECK(name == html_names::kDisablepictureinpictureAttr ||
-         name == html_names::kAutopictureinpictureAttr);
+  DCHECK(name == html_names::kDisablepictureinpictureAttr);
   element.SetBooleanAttribute(name, value);
 
   Document& document = element.GetDocument();
diff --git a/third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.idl b/third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.idl
index 8c2d12d..17fda7a 100644
--- a/third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.idl
+++ b/third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.idl
@@ -12,6 +12,5 @@
     [RuntimeEnabled=PictureInPictureAPI] attribute EventHandler onenterpictureinpicture;
     [RuntimeEnabled=PictureInPictureAPI] attribute EventHandler onleavepictureinpicture;
 
-    [RuntimeEnabled=AutoPictureInPicture, CEReactions, Measure, Reflect] attribute boolean autoPictureInPicture;
     [RuntimeEnabled=PictureInPictureAPI, CEReactions, Measure, Reflect] attribute boolean disablePictureInPicture;
 };
diff --git a/third_party/blink/renderer/modules/webgpu/external_texture_helper.cc b/third_party/blink/renderer/modules/webgpu/external_texture_helper.cc
index d369d6c3..aee2af9 100644
--- a/third_party/blink/renderer/modules/webgpu/external_texture_helper.cc
+++ b/third_party/blink/renderer/modules/webgpu/external_texture_helper.cc
@@ -56,7 +56,7 @@
                          &dst_primary_matrix_from_XYZD50);
 
   skcms_Matrix3x3 transform_matrix = skcms_Matrix3x3_concat(
-      &src_primary_matrix_to_XYZD50, &dst_primary_matrix_from_XYZD50);
+      &dst_primary_matrix_from_XYZD50, &src_primary_matrix_to_XYZD50);
   // From row major matrix to col major matrix
   color_space_conversion_constants.gamut_conversion_matrix =
       std::array<float, 9>{
@@ -68,7 +68,7 @@
 
   // Set constants for source transfer function.
   skcms_TransferFunction src_transfer_fn;
-  src_color_space.GetInverseTransferFunction(&src_transfer_fn);
+  src_color_space.GetTransferFunction(&src_transfer_fn);
   color_space_conversion_constants.src_transfer_constants =
       std::array<float, 7>{src_transfer_fn.g, src_transfer_fn.a,
                            src_transfer_fn.b, src_transfer_fn.c,
@@ -77,7 +77,7 @@
 
   // Set constants for destination transfer function.
   skcms_TransferFunction dst_transfer_fn;
-  dst_color_space.GetTransferFunction(&dst_transfer_fn);
+  dst_color_space.GetInverseTransferFunction(&dst_transfer_fn);
   color_space_conversion_constants.dst_transfer_constants =
       std::array<float, 7>{dst_transfer_fn.g, dst_transfer_fn.a,
                            dst_transfer_fn.b, dst_transfer_fn.c,
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_image_copy_external_image.idl b/third_party/blink/renderer/modules/webgpu/gpu_image_copy_external_image.idl
index 9a17814..98ed5dd 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_image_copy_external_image.idl
+++ b/third_party/blink/renderer/modules/webgpu/gpu_image_copy_external_image.idl
@@ -6,7 +6,7 @@
 // https://gpuweb.github.io/gpuweb/
 
 dictionary GPUImageCopyExternalImage {
-    required (ImageBitmap or HTMLCanvasElement or OffscreenCanvas) source;
+    required (ImageBitmap or HTMLCanvasElement or HTMLVideoElement or OffscreenCanvas) source;
     GPUOrigin2D origin = {};
     boolean flipY = false;
 };
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_queue.cc b/third_party/blink/renderer/modules/webgpu/gpu_queue.cc
index b6d7e40..1c2f3c1 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_queue.cc
+++ b/third_party/blink/renderer/modules/webgpu/gpu_queue.cc
@@ -9,7 +9,7 @@
 #include "gpu/command_buffer/client/webgpu_interface.h"
 #include "gpu/command_buffer/common/shared_image_usage.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_union_htmlcanvaselement_imagebitmap_offscreencanvas.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_union_htmlcanvaselement_htmlvideoelement_imagebitmap_offscreencanvas.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_command_buffer_descriptor.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_image_copy_external_image.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_image_copy_image_bitmap.h"
@@ -25,6 +25,7 @@
 #include "third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h"
 #include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
 #include "third_party/blink/renderer/modules/webgpu/dawn_conversions.h"
+#include "third_party/blink/renderer/modules/webgpu/external_texture_helper.h"
 #include "third_party/blink/renderer/modules/webgpu/gpu_buffer.h"
 #include "third_party/blink/renderer/modules/webgpu/gpu_command_buffer.h"
 #include "third_party/blink/renderer/modules/webgpu/gpu_device.h"
@@ -121,49 +122,76 @@
          << kDawnBytesPerRowAlignmentBits;
 }
 
-scoped_refptr<Image> GetImageFromExternalImage(
-    const V8UnionHTMLCanvasElementOrImageBitmapOrOffscreenCanvas*
+struct ExternalSource {
+  ExternalTextureSource external_texture_source;
+  scoped_refptr<Image> image = nullptr;
+  uint32_t width = 0;
+  uint32_t height = 0;
+  bool valid = false;
+};
+
+ExternalSource GetExternalSourceFromExternalImage(
+    const V8UnionHTMLCanvasElementOrHTMLVideoElementOrImageBitmapOrOffscreenCanvas*
         external_image,
     ExceptionState& exception_state) {
-  CanvasImageSource* source = nullptr;
+  ExternalSource external_source;
+  ExternalTextureSource external_texture_source;
+  CanvasImageSource* canvas_image_source = nullptr;
   CanvasRenderingContextHost* canvas = nullptr;
   switch (external_image->GetContentType()) {
-    case V8UnionHTMLCanvasElementOrImageBitmapOrOffscreenCanvas::ContentType::
-        kHTMLCanvasElement:
-      source = external_image->GetAsHTMLCanvasElement();
+    case V8UnionHTMLCanvasElementOrHTMLVideoElementOrImageBitmapOrOffscreenCanvas::
+        ContentType::kHTMLVideoElement:
+      external_texture_source = GetExternalTextureSourceFromVideoElement(
+          external_image->GetAsHTMLVideoElement(), exception_state);
+      if (external_texture_source.valid) {
+        external_source.external_texture_source = external_texture_source;
+        DCHECK(external_texture_source.media_video_frame);
+        external_source.width = static_cast<uint32_t>(
+            external_texture_source.media_video_frame->visible_rect().width());
+        external_source.height = static_cast<uint32_t>(
+            external_texture_source.media_video_frame->visible_rect().height());
+        external_source.valid = true;
+      }
+      return external_source;
+    case V8UnionHTMLCanvasElementOrHTMLVideoElementOrImageBitmapOrOffscreenCanvas::
+        ContentType::kHTMLCanvasElement:
+      canvas_image_source = external_image->GetAsHTMLCanvasElement();
       canvas = external_image->GetAsHTMLCanvasElement();
       break;
-    case V8UnionHTMLCanvasElementOrImageBitmapOrOffscreenCanvas::ContentType::
-        kImageBitmap:
-      source = external_image->GetAsImageBitmap();
+    case V8UnionHTMLCanvasElementOrHTMLVideoElementOrImageBitmapOrOffscreenCanvas::
+        ContentType::kImageBitmap:
+      canvas_image_source = external_image->GetAsImageBitmap();
       break;
-    case V8UnionHTMLCanvasElementOrImageBitmapOrOffscreenCanvas::ContentType::
-        kOffscreenCanvas:
-      source = external_image->GetAsOffscreenCanvas();
+    case V8UnionHTMLCanvasElementOrHTMLVideoElementOrImageBitmapOrOffscreenCanvas::
+        ContentType::kOffscreenCanvas:
+      canvas_image_source = external_image->GetAsOffscreenCanvas();
       canvas = external_image->GetAsOffscreenCanvas();
       break;
+    default:
+      NOTREACHED();
+      break;
   }
 
   // Neutered external image.
-  if (source->IsNeutered()) {
+  if (canvas_image_source->IsNeutered()) {
     exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
                                       "External Image has been detached.");
-    return nullptr;
+    return external_source;
   }
 
   // Placeholder source is not allowed.
-  if (source->IsPlaceholder()) {
+  if (canvas_image_source->IsPlaceholder()) {
     exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
                                       "Cannot copy from a canvas that has had "
                                       "transferControlToOffscreen() called.");
-    return nullptr;
+    return external_source;
   }
 
   // Canvas element contains cross-origin data and may not be loaded
-  if (source->WouldTaintOrigin()) {
+  if (canvas_image_source->WouldTaintOrigin()) {
     exception_state.ThrowSecurityError(
         "The external image is tainted by cross-origin data.");
-    return nullptr;
+    return external_source;
   }
 
   if (canvas && !(canvas->IsWebGL() || canvas->IsRenderingContext2D() ||
@@ -172,13 +200,13 @@
         DOMExceptionCode::kOperationError,
         "CopyExternalImageToTexture doesn't support canvas without 2d, webgl,"
         " webgl2 or webgpu context");
-    return nullptr;
+    return external_source;
   }
 
   // HTMLCanvasElement and OffscreenCanvas won't care image orientation. But for
   // ImageBitmap, use kRespectImageOrientation will make ElementSize() behave
   // as Size().
-  gfx::SizeF image_size = source->ElementSize(
+  gfx::SizeF image_size = canvas_image_source->ElementSize(
       gfx::SizeF(),  // It will be ignored and won't affect size.
       kRespectImageOrientation);
 
@@ -189,15 +217,20 @@
   // This will help combine more transforms (e.g. flipY, color-space)
   // into a single blit.
   SourceImageStatus source_image_status = kInvalidSourceImageStatus;
-  auto image = source->GetSourceImageForCanvas(&source_image_status, image_size,
-                                               kDontChangeAlpha);
+  auto image = canvas_image_source->GetSourceImageForCanvas(
+      &source_image_status, image_size, kDontChangeAlpha);
   if (source_image_status != kNormalSourceImageStatus) {
     // Canvas back resource is broken, zero size, incomplete or invalid.
     // but developer can do nothing. Return nullptr and issue an noop.
-    return nullptr;
+    return external_source;
   }
 
-  return image;
+  external_source.image = image;
+  external_source.width = static_cast<uint32_t>(image->width());
+  external_source.height = static_cast<uint32_t>(image->height());
+  external_source.valid = true;
+
+  return external_source;
 }
 
 // CopyExternalImageToTexture() will always copy from the top-left corner of the
@@ -439,13 +472,9 @@
     ExceptionState& exception_state) {
   // "srgb" is the only valid color space for now.
   DCHECK_EQ(destination->colorSpace(), "srgb");
-
-  scoped_refptr<Image> image =
-      GetImageFromExternalImage(copyImage->source(), exception_state);
-
-  scoped_refptr<StaticBitmapImage> static_bitmap_image =
-      DynamicTo<StaticBitmapImage>(image.get());
-  if (!static_bitmap_image) {
+  ExternalSource source =
+      GetExternalSourceFromExternalImage(copyImage->source(), exception_state);
+  if (!source.valid) {
     device_->AddConsoleWarning(
         "CopyExternalImageToTexture(): Browser fails extracting valid resource"
         "from external image. This API call will return early.");
@@ -454,22 +483,15 @@
 
   WGPUExtent3D dawn_copy_size = AsDawnType(copy_size);
 
-  // Extract source origin
+  // Extract and validate source origin value.
   WGPUOrigin3D origin_in_external_image =
       GPUOrigin2DToWGPUOrigin3D(copyImage->origin());
 
-  // Validate origin value
   const bool copyRectOutOfBounds =
-      static_cast<uint32_t>(static_bitmap_image->width()) <
-          origin_in_external_image.x ||
-      static_cast<uint32_t>(static_bitmap_image->height()) <
-          origin_in_external_image.y ||
-      static_cast<uint32_t>(static_bitmap_image->width()) -
-              origin_in_external_image.x <
-          dawn_copy_size.width ||
-      static_cast<uint32_t>(static_bitmap_image->height()) -
-              origin_in_external_image.y <
-          dawn_copy_size.height;
+      source.width < origin_in_external_image.x ||
+      source.height < origin_in_external_image.y ||
+      source.width - origin_in_external_image.x < dawn_copy_size.width ||
+      source.height - origin_in_external_image.y < dawn_copy_size.height;
 
   if (copyRectOutOfBounds) {
     exception_state.ThrowDOMException(
@@ -531,7 +553,18 @@
         "({width|height|depthOrArrayLayers} equals to 0).");
   }
 
-  if (!UploadContentToTexture(
+  if (source.external_texture_source.valid) {
+    CopyFromVideoElement(source.external_texture_source,
+                         origin_in_external_image, dawn_copy_size,
+                         dawn_destination, destination->premultipliedAlpha(),
+                         color_space, copyImage->flipY());
+    return;
+  }
+
+  scoped_refptr<StaticBitmapImage> static_bitmap_image =
+      DynamicTo<StaticBitmapImage>(source.image.get());
+  DCHECK(static_bitmap_image);
+  if (!CopyFromCanvasSourceImage(
           static_bitmap_image.get(), origin_in_external_image, dawn_copy_size,
           dawn_destination, destination->premultipliedAlpha(), color_space,
           copyImage->flipY())) {
@@ -541,13 +574,72 @@
   }
 }
 
-bool GPUQueue::UploadContentToTexture(StaticBitmapImage* image,
-                                      const WGPUOrigin3D& origin,
-                                      const WGPUExtent3D& copy_size,
-                                      const WGPUImageCopyTexture& destination,
-                                      bool dst_premultiplied_alpha,
-                                      PredefinedColorSpace dst_color_space,
-                                      bool flipY) {
+void GPUQueue::CopyFromVideoElement(const ExternalTextureSource source,
+                                    const WGPUOrigin3D& origin,
+                                    const WGPUExtent3D& copy_size,
+                                    const WGPUImageCopyTexture& destination,
+                                    bool dst_premultiplied_alpha,
+                                    PredefinedColorSpace dst_color_space,
+                                    bool flipY) {
+  DCHECK(source.valid);
+
+  // Import GPUExternalTexture to sRGB color space always.
+  // Delegate future color space conversion for
+  // Dawn::CopyExternalTextureForBrowser.
+  gfx::ColorSpace external_texture_dst_color_space =
+      PredefinedColorSpaceToGfxColorSpace(dst_color_space);
+  ExternalTexture external_texture =
+      CreateExternalTexture(device_, source.media_video_frame->ColorSpace(),
+                            external_texture_dst_color_space,
+                            source.media_video_frame, source.video_renderer);
+
+  WGPUCopyTextureForBrowserOptions options = {};
+
+  // Extracting contents from HTMLVideoElement (e.g. CreateStaticBitmapImage(),
+  // GetSourceImageForCanvas) always assume alpha mode as premultiplied. Keep
+  // this assumption here.
+  options.srcAlphaMode = WGPUAlphaMode_Premultiplied;
+  options.dstAlphaMode = dst_premultiplied_alpha
+                             ? WGPUAlphaMode_Premultiplied
+                             : WGPUAlphaMode_Unpremultiplied;
+
+  // Set color space conversion params
+  gfx::ColorSpace gfx_dst_color_space =
+      PredefinedColorSpaceToGfxColorSpace(dst_color_space);
+
+  ColorSpaceConversionConstants color_space_conversion_constants;
+
+  if (external_texture_dst_color_space != gfx_dst_color_space) {
+    color_space_conversion_constants = GetColorSpaceConversionConstants(
+        external_texture_dst_color_space, gfx_dst_color_space);
+
+    options.needsColorSpaceConversion = true;
+    options.srcTransferFunctionParameters =
+        color_space_conversion_constants.src_transfer_constants.data();
+    options.dstTransferFunctionParameters =
+        color_space_conversion_constants.dst_transfer_constants.data();
+    options.conversionMatrix =
+        color_space_conversion_constants.gamut_conversion_matrix.data();
+  }
+
+  options.flipY = flipY;
+
+  WGPUImageCopyExternalTexture src = {};
+  src.externalTexture = external_texture.wgpu_external_texture;
+  src.origin = origin;
+
+  GetProcs().queueCopyExternalTextureForBrowser(GetHandle(), &src, &destination,
+                                                &copy_size, &options);
+}
+
+bool GPUQueue::CopyFromCanvasSourceImage(
+    StaticBitmapImage* image,
+    const WGPUOrigin3D& origin,
+    const WGPUExtent3D& copy_size,
+    const WGPUImageCopyTexture& destination,
+    bool dst_premultiplied_alpha,
+    PredefinedColorSpace dst_color_space,
+    bool flipY) {
   PaintImage paint_image = image->PaintImageForCurrentFrame();
   SkColorType source_color_type = paint_image.GetSkImageInfo().colorType();
 
@@ -580,43 +672,24 @@
   if (sk_src_color_space == nullptr) {
     sk_src_color_space = SkColorSpace::MakeSRGB();
   }
-  sk_sp<SkColorSpace> sk_dst_color_space =
-      PredefinedColorSpaceToSkColorSpace(dst_color_space);
-  std::array<float, 7> gamma_decode_params;
-  std::array<float, 7> gamma_encode_params;
-  std::array<float, 9> conversion_matrix;
-  if (!SkColorSpace::Equals(sk_src_color_space.get(),
-                            sk_dst_color_space.get())) {
-    skcms_TransferFunction src_transfer_fn = {};
-    skcms_TransferFunction dst_transfer_fn = {};
 
-    // Row major matrix
-    skcms_Matrix3x3 transfer_matrix = {};
+  gfx::ColorSpace gfx_src_color_space = gfx::ColorSpace(*sk_src_color_space);
+  gfx::ColorSpace gfx_dst_color_space =
+      PredefinedColorSpaceToGfxColorSpace(dst_color_space);
 
-    sk_src_color_space->transferFn(&src_transfer_fn);
-    sk_dst_color_space->invTransferFn(&dst_transfer_fn);
-    sk_src_color_space->gamutTransformTo(sk_dst_color_space.get(),
-                                         &transfer_matrix);
-    gamma_decode_params = {src_transfer_fn.g, src_transfer_fn.a,
-                           src_transfer_fn.b, src_transfer_fn.c,
-                           src_transfer_fn.d, src_transfer_fn.e,
-                           src_transfer_fn.f};
-    gamma_encode_params = {dst_transfer_fn.g, dst_transfer_fn.a,
-                           dst_transfer_fn.b, dst_transfer_fn.c,
-                           dst_transfer_fn.d, dst_transfer_fn.e,
-                           dst_transfer_fn.f};
+  ColorSpaceConversionConstants color_space_conversion_constants;
 
-    // From row major matrix to col major matrix
-    conversion_matrix = {transfer_matrix.vals[0][0], transfer_matrix.vals[1][0],
-                         transfer_matrix.vals[2][0], transfer_matrix.vals[0][1],
-                         transfer_matrix.vals[1][1], transfer_matrix.vals[2][1],
-                         transfer_matrix.vals[0][2], transfer_matrix.vals[1][2],
-                         transfer_matrix.vals[2][2]};
+  if (gfx_src_color_space != gfx_dst_color_space) {
+    color_space_conversion_constants = GetColorSpaceConversionConstants(
+        gfx_src_color_space, gfx_dst_color_space);
 
     options.needsColorSpaceConversion = true;
-    options.srcTransferFunctionParameters = gamma_decode_params.data();
-    options.dstTransferFunctionParameters = gamma_encode_params.data();
-    options.conversionMatrix = conversion_matrix.data();
+    options.srcTransferFunctionParameters =
+        color_space_conversion_constants.src_transfer_constants.data();
+    options.dstTransferFunctionParameters =
+        color_space_conversion_constants.dst_transfer_constants.data();
+    options.conversionMatrix =
+        color_space_conversion_constants.gamut_conversion_matrix.data();
   }
 
   bool use_gpu_uploading = image->IsTextureBacked();
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_queue.h b/third_party/blink/renderer/modules/webgpu/gpu_queue.h
index 1c6852ed..e925946 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_queue.h
+++ b/third_party/blink/renderer/modules/webgpu/gpu_queue.h
@@ -25,6 +25,7 @@
 class ScriptPromiseResolver;
 class ScriptState;
 class StaticBitmapImage;
+struct ExternalTextureSource;
 
 class GPUQueue : public DawnObject<WGPUQueue> {
   DEFINE_WRAPPERTYPEINFO();
@@ -84,14 +85,20 @@
  private:
   void OnWorkDoneCallback(ScriptPromiseResolver* resolver,
                           WGPUQueueWorkDoneStatus status);
-
-  bool UploadContentToTexture(StaticBitmapImage* image,
-                              const WGPUOrigin3D& origin,
-                              const WGPUExtent3D& copy_size,
-                              const WGPUImageCopyTexture& destination,
-                              bool dst_premultiplied_alpha,
-                              PredefinedColorSpace dst_color_space,
-                              bool flipY);
+  void CopyFromVideoElement(const ExternalTextureSource source,
+                            const WGPUOrigin3D& origin,
+                            const WGPUExtent3D& copy_size,
+                            const WGPUImageCopyTexture& destination,
+                            bool dst_premultiplied_alpha,
+                            PredefinedColorSpace dst_color_space,
+                            bool flipY);
+  bool CopyFromCanvasSourceImage(StaticBitmapImage* image,
+                                 const WGPUOrigin3D& origin,
+                                 const WGPUExtent3D& copy_size,
+                                 const WGPUImageCopyTexture& destination,
+                                 bool dst_premultiplied_alpha,
+                                 PredefinedColorSpace dst_color_space,
+                                 bool flipY);
   void WriteBufferImpl(ScriptState* script_state,
                        GPUBuffer* buffer,
                        uint64_t buffer_offset,
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
index 4e75d37..1760c66 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
@@ -110,7 +110,7 @@
 static constexpr base::TimeDelta kUnusedPreloadTimeout = base::Seconds(3);
 
 static constexpr char kCrossDocumentCachedResource[] =
-    "Blink.MemoryCache.CrossDocumentCachedResource";
+    "Blink.MemoryCache.CrossDocumentCachedResource2";
 
 #define RESOURCE_HISTOGRAM_PREFIX "Blink.MemoryCache.RevalidationPolicy."
 
@@ -1161,7 +1161,8 @@
 
   // in_cached_resources_map is checked to detect Resources shared across
   // Documents, in the same way as features::kScopeMemoryCachePerContext.
-  if (policy == RevalidationPolicy::kUse && !in_cached_resources_map) {
+  if (!is_static_data && policy == RevalidationPolicy::kUse &&
+      !in_cached_resources_map) {
     base::UmaHistogramEnumeration(kCrossDocumentCachedResource,
                                   resource->GetType());
   }
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 31c07f9..38026b3 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -336,11 +336,6 @@
       settable_from_internals: true,
     },
     {
-      name: "AutoPictureInPicture",
-      depends_on: ["PictureInPictureAPI"],
-      status: "experimental",
-    },
-    {
       // Flag set by the media::kAutoplayIgnoreWebAudio feature flag.
       name: "AutoplayIgnoresWebAudio",
       public: true,
@@ -541,6 +536,7 @@
     },
     {
       name: "CompositeClipPathAnimation",
+      public: true,
     },
     {
       name: "CompositedSelectionUpdate",
@@ -868,10 +864,6 @@
       base_feature: "CssSelectorFragmentAnchor",
     },
     {
-      name: "CSSSnapSize",
-      status: "experimental",
-    },
-    {
       // Support for CSS ::spelling-error, ::grammar-error, and the
       // spelling-error and grammar-error values in text-decoration-line.
       //
diff --git a/third_party/blink/renderer/platform/video_capture/video_capture_impl.cc b/third_party/blink/renderer/platform/video_capture/video_capture_impl.cc
index 7c3abc23..4b4dc626 100644
--- a/third_party/blink/renderer/platform/video_capture/video_capture_impl.cc
+++ b/third_party/blink/renderer/platform/video_capture/video_capture_impl.cc
@@ -527,21 +527,8 @@
   usage |= gpu::SHARED_IMAGE_USAGE_MACOS_VIDEO_TOOLBOX;
 #endif
 
-  unsigned texture_target =
-      buffer_context_->gpu_factories()->ImageTextureTarget(
-          gpu_memory_buffer_->GetFormat());
-
-  // TODO(sunnyps): Get rid of NV12_DUAL_GMB format and instead rely on enabled
-  // by default multi plane shared images on Windows.
-
-  const bool use_multiplane =
-#if BUILDFLAG(IS_WIN)
-      output_format ==
-          media::GpuVideoAcceleratorFactories::OutputFormat::NV12_DUAL_GMB ||
-#endif
-      base::FeatureList::IsEnabled(media::kMultiPlaneVideoCaptureSharedImages);
-
-  if (use_multiplane) {
+  if (base::FeatureList::IsEnabled(
+          media::kMultiPlaneVideoCaptureSharedImages)) {
     planes.push_back(gfx::BufferPlane::Y);
     planes.push_back(gfx::BufferPlane::UV);
   } else {
@@ -563,6 +550,10 @@
     }
   }
 
+  const unsigned texture_target =
+      buffer_context_->gpu_factories()->ImageTextureTarget(
+          gpu_memory_buffer_->GetFormat());
+
   const gpu::SyncToken sync_token = sii->GenVerifiedSyncToken();
 
   gpu::MailboxHolder mailbox_holder_array[media::VideoFrame::kMaxPlanes];
diff --git a/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc b/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc
index 047a135..76b9bf7 100644
--- a/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc
+++ b/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc
@@ -14,7 +14,6 @@
 #include "cc/base/features.h"
 #include "cc/base/switches.h"
 #include "cc/tiles/image_decode_cache_utils.h"
-#include "components/viz/common/display/de_jelly.h"
 #include "components/viz/common/features.h"
 #include "components/viz/common/switches.h"
 #include "gpu/command_buffer/service/gpu_switches.h"
@@ -556,15 +555,6 @@
 
   settings.send_compositor_frame_ack = false;
 
-  // Renderer can de-jelly, browser UI can not. We do not know whether we are
-  // going to apply de-jelly until we draw a frame in the Viz process. Because
-  // of this, all changes in the renderer are based on whether de-jelly may be
-  // active (viz::DeJellyEnabled) vs whether it is currently active
-  // (viz::DeJellyActive).
-  settings.allow_de_jelly_effect = viz::DeJellyEnabled();
-  // Disable occlusion if de-jelly effect is enabled.
-  settings.enable_occlusion &= !settings.allow_de_jelly_effect;
-
   settings.enable_backface_visibility_interop =
       RuntimeEnabledFeatures::BackfaceVisibilityInteropEnabled();
 
diff --git a/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_sink.py b/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_sink.py
index d77a022..f4f8efd 100644
--- a/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_sink.py
+++ b/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_sink.py
@@ -133,6 +133,16 @@
             tags.append(
                 pair('web_tests_image_diff_stats',
                      str(result.image_diff_stats)))
+        test_type = []
+        for name in result.artifacts.artifacts.keys():
+            if name == 'actual_text':
+                test_type.extend(['text'])
+            elif name == 'actual_image':
+                test_type.extend(['image'])
+            elif name == 'actual_audio':
+                test_type.extend(['audio'])
+        if len(test_type) > 0:
+            tags.append(pair('web_tests_test_type', str(test_type)))
 
         for used_file in self._port.used_expectations_files():
             tags.append(
diff --git a/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_sink_unittest.py b/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_sink_unittest.py
index 2faa40b5..16eae9e 100644
--- a/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_sink_unittest.py
+++ b/third_party/blink/tools/blinkpy/web_tests/controllers/test_result_sink_unittest.py
@@ -272,6 +272,59 @@
         sent_data = self.sink(True, tr)
         self.assertEqual(sent_data['tags'], expected_tags)
 
+    def test_sink_with_test_type(self):
+        tr = test_results.TestResult(test_name='test-name')
+        tr.artifacts.AddArtifact('actual_image', '/tmp/test-image.png', True)
+        tr.type = ResultType.Crash
+        expected_tags = [
+            {
+                'key': 'test_name',
+                'value': 'test-name'
+            },
+            {
+                'key': 'web_tests_device_failed',
+                'value': 'False'
+            },
+            {
+                'key': 'web_tests_result_type',
+                'value': 'CRASH'
+            },
+            {
+                'key': 'web_tests_flag_specific_config_name',
+                'value': '',
+            },
+            {
+                'key': 'web_tests_base_timeout',
+                'value': '6'
+            },
+            {
+                'key': 'web_tests_test_type',
+                'value': "['image']"
+            },
+            {
+                'key': 'web_tests_used_expectations_file',
+                'value': 'TestExpectations',
+            },
+            {
+                'key': 'web_tests_used_expectations_file',
+                'value': 'WebDriverExpectations',
+            },
+            {
+                'key': 'web_tests_used_expectations_file',
+                'value': 'NeverFixTests',
+            },
+            {
+                'key': 'web_tests_used_expectations_file',
+                'value': 'StaleTestExpectations',
+            },
+            {
+                'key': 'web_tests_used_expectations_file',
+                'value': 'SlowTests',
+            },
+        ]
+        sent_data = self.sink(True, tr)
+        self.assertEqual(sent_data['tags'], expected_tags)
+
     def test_test_metadata(self):
         tr = test_results.TestResult('')
         base_path = '//' + RELATIVE_WEB_TESTS
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 3587086..40863f09 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -1586,10 +1586,6 @@
 crbug.com/958381 [ Win ] virtual/text-antialias/hyphen-min-preferred-width.html [ Failure ]
 crbug.com/958381 [ Mac ] fragmentation/single-line-cells-paginated-with-text.html [ Failure ]
 
-# Popover test needing a fix
-
-crbug.com/1396139 virtual/popover-disabled/popover-disabled.html [ Failure Pass ]
-
 # TablesNG ends
 
 # ====== LayoutNG-only failures until here ======
@@ -3018,6 +3014,8 @@
 crbug.com/626703 [ Win ] virtual/partitioned-cookies/http/tests/inspector-protocol/network/disabled-cache-navigation.js [ Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 [ Mac12 ] external/wpt/content-security-policy/embedded-enforcement/subsumption_algorithm-general.html [ Timeout ]
+crbug.com/626703 [ Mac12 ] external/wpt/content-security-policy/embedded-enforcement/subsumption_algorithm-nonces.html [ Timeout ]
 crbug.com/626703 [ Mac10.15 ] virtual/prefetch/external/wpt/speculation-rules/prefetch/prefetch-traverse-reload.sub.html [ Timeout ]
 crbug.com/626703 [ Mac11 ] virtual/prefetch/external/wpt/speculation-rules/prefetch/prefetch-traverse-reload.sub.html [ Timeout ]
 crbug.com/626703 [ Mac11-arm64 ] virtual/prefetch/external/wpt/speculation-rules/prefetch/prefetch-traverse-reload.sub.html [ Timeout ]
@@ -4368,22 +4366,15 @@
 crbug.com/626703 external/wpt/infrastructure/channels/test_serialize.html [ Timeout ]
 crbug.com/626703 [ Win10.20h2 ] external/wpt/mediacapture-streams/MediaDevices-enumerateDevices-per-origin-ids.sub.https.html [ Failure Timeout ]
 crbug.com/626703 [ Win10.20h2 ] virtual/feature-policy-permissions/external/wpt/mediacapture-streams/MediaDevices-enumerateDevices-per-origin-ids.sub.https.html [ Failure Timeout ]
-crbug.com/626703 [ Mac11-arm64 ] external/wpt/webrtc/RTCDataChannel-close.html [ Skip Timeout ]
-crbug.com/626703 [ Mac11-arm64 ] external/wpt/webrtc/RTCPeerConnection-capture-video.https.html [ Skip Timeout ]
-crbug.com/626703 [ Mac11-arm64 ] external/wpt/webrtc/RTCPeerConnection-iceConnectionState.https.html [ Skip Timeout ]
 crbug.com/626703 [ Mac11-arm64 ] external/wpt/navigation-timing/nav2_test_response_end_and_duration_before_during_and_after_load_event.html [ Skip Timeout ]
 crbug.com/626703 [ Mac12-arm64 ] external/wpt/navigation-timing/nav2_test_response_end_and_duration_before_during_and_after_load_event.html [ Skip Timeout ]
 crbug.com/1270841 [ Mac ] external/wpt/media-capabilities/encodingInfo.any.worker.html [ Crash ]
 crbug.com/626703 [ Win10.20h2 ] external/wpt/web-locks/bfcache/abort.tentative.https.html [ Failure Timeout ]
-crbug.com/626703 [ Mac11-arm64 ] external/wpt/webrtc/RTCPeerConnection-getStats.https.html [ Skip Timeout ]
 crbug.com/626703 [ Mac10.14 ] external/wpt/workers/modules/shared-worker-import-csp.html [ Skip Timeout ]
 crbug.com/626703 [ Mac10.15 ] external/wpt/WebCryptoAPI/generateKey/successes_AES-CTR.https.any.html [ Skip Timeout ]
 crbug.com/626703 [ Mac10.15 ] external/wpt/WebCryptoAPI/generateKey/successes_RSA-OAEP.https.any.html?1-10 [ Skip Timeout ]
 crbug.com/626703 [ Mac10.15 ] external/wpt/WebCryptoAPI/generateKey/successes_RSA-OAEP.https.any.worker.html?141-150 [ Skip Timeout ]
 crbug.com/626703 [ Mac10.15 ] external/wpt/WebCryptoAPI/import_export/ec_importKey.https.any.html [ Skip Timeout ]
-crbug.com/626703 [ Mac11-arm64 ] external/wpt/webrtc/RTCIceConnectionState-candidate-pair.https.html [ Skip Timeout ]
-crbug.com/626703 [ Mac11-arm64 ] external/wpt/webrtc/RTCPeerConnection-ondatachannel.html [ Skip Timeout ]
-crbug.com/626703 [ Mac11-arm64 ] external/wpt/webrtc/protocol/ice-state.https.html [ Skip Timeout ]
 crbug.com/626703 [ Linux ] external/wpt/media-capabilities/encodingInfo.any.worker.html [ Crash ]
 crbug.com/626703 [ Win10.20h2 ] external/wpt/media-capabilities/encodingInfo.any.worker.html [ Crash ]
 crbug.com/626703 external/wpt/workers/interfaces/WorkerUtils/importScripts/blob-url.worker.html [ Failure ]
@@ -4409,39 +4400,6 @@
 crbug.com/626703 external/wpt/webrtc-extensions/transfer-datachannel.html [ Timeout ]
 crbug.com/626703 [ Win ] external/wpt/websockets/Create-blocked-port.any.worker.html?wpt_flags=h2 [ Failure Timeout ]
 crbug.com/626703 [ Win ] external/wpt/websockets/stream/tentative/constructor.any.serviceworker.html?wss [ Failure Timeout ]
-crbug.com/626703 [ Mac10.14 ] external/wpt/webrtc/RTCPeerConnection-ondatachannel.html [ Skip Timeout ]
-crbug.com/626703 [ Mac11 ] external/wpt/webrtc/RTCPeerConnection-ondatachannel.html [ Skip Timeout ]
-crbug.com/626703 [ Mac10.14 ] external/wpt/webrtc/protocol/rtp-clockrate.html [ Skip Timeout ]
-crbug.com/626703 [ Mac11 ] external/wpt/webrtc/protocol/rtp-clockrate.html [ Skip Timeout ]
-crbug.com/626703 [ Mac11-arm64 ] external/wpt/webrtc/protocol/rtp-clockrate.html [ Skip Timeout ]
-crbug.com/626703 [ Mac10.14 ] external/wpt/webrtc-extensions/RTCRtpSynchronizationSource-captureTimestamp.html [ Skip Timeout ]
-crbug.com/626703 [ Mac11 ] external/wpt/webrtc-extensions/RTCRtpSynchronizationSource-captureTimestamp.html [ Skip Timeout ]
-crbug.com/626703 [ Mac11-arm64 ] external/wpt/webrtc-extensions/RTCRtpSynchronizationSource-captureTimestamp.html [ Skip Timeout ]
-crbug.com/626703 [ Mac10.14 ] external/wpt/webrtc-extensions/RTCRtpSynchronizationSource-senderCaptureTimeOffset.html [ Skip Timeout ]
-crbug.com/626703 [ Mac11 ] external/wpt/webrtc-extensions/RTCRtpSynchronizationSource-senderCaptureTimeOffset.html [ Skip Timeout ]
-crbug.com/626703 [ Mac10.14 ] external/wpt/webrtc/RTCDataChannel-send.html [ Skip Timeout ]
-crbug.com/626703 [ Mac11 ] external/wpt/webrtc/RTCDataChannel-send.html [ Skip Timeout ]
-crbug.com/626703 [ Mac10.14 ] external/wpt/webrtc/RTCDataChannel-iceRestart.html [ Skip Timeout ]
-crbug.com/626703 [ Mac11 ] external/wpt/webrtc/RTCDataChannel-iceRestart.html [ Skip Timeout ]
-crbug.com/626703 [ Mac11-arm64 ] external/wpt/webrtc/RTCDataChannel-iceRestart.html [ Skip Timeout ]
-crbug.com/626703 [ Mac10.14 ] external/wpt/webrtc/RTCPeerConnection-createDataChannel.html [ Skip Timeout ]
-crbug.com/626703 [ Mac11 ] external/wpt/webrtc/RTCPeerConnection-createDataChannel.html [ Skip Timeout ]
-crbug.com/626703 [ Mac10.14 ] external/wpt/webrtc/RTCPeerConnection-videoDetectorTest.html [ Skip Timeout ]
-crbug.com/626703 [ Mac11 ] external/wpt/webrtc/RTCPeerConnection-videoDetectorTest.html [ Skip Timeout ]
-crbug.com/626703 [ Mac10.14 ] external/wpt/webrtc/RTCPeerConnection-iceConnectionState-disconnected.https.html [ Skip Timeout ]
-crbug.com/626703 [ Mac11 ] external/wpt/webrtc/RTCPeerConnection-iceConnectionState-disconnected.https.html [ Skip Timeout ]
-crbug.com/626703 [ Mac10.14 ] external/wpt/webrtc/protocol/ice-state.https.html [ Skip Timeout ]
-crbug.com/626703 [ Mac11 ] external/wpt/webrtc/protocol/ice-state.https.html [ Skip Timeout ]
-crbug.com/626703 [ Mac10.14 ] external/wpt/webrtc/RTCDataChannel-bufferedAmount.html [ Skip Timeout ]
-crbug.com/626703 [ Mac11 ] external/wpt/webrtc/RTCDataChannel-bufferedAmount.html [ Skip Timeout ]
-crbug.com/626703 [ Mac11-arm64 ] external/wpt/webrtc/RTCDataChannel-bufferedAmount.html [ Skip Timeout ]
-crbug.com/626703 [ Mac11 ] external/wpt/webrtc/RTCDataChannel-close.html [ Skip Timeout ]
-crbug.com/626703 [ Mac11 ] external/wpt/webrtc/protocol/candidate-exchange.https.html [ Skip Timeout ]
-crbug.com/626703 [ Mac11 ] external/wpt/webrtc/RTCPeerConnection-getStats.https.html [ Skip Timeout ]
-crbug.com/626703 [ Mac11 ] external/wpt/webrtc/RTCPeerConnection-addIceCandidate-connectionSetup.html [ Skip Timeout ]
-crbug.com/626703 [ Mac11-arm64 ] external/wpt/webrtc/RTCPeerConnection-addIceCandidate-connectionSetup.html [ Skip Timeout ]
-crbug.com/626703 [ Mac11 ] external/wpt/webrtc/protocol/rtp-demuxing.html [ Skip Timeout ]
-crbug.com/626703 [ Mac11 ] external/wpt/webrtc/RTCIceConnectionState-candidate-pair.https.html [ Skip Timeout ]
 crbug.com/1209223 external/wpt/html/syntax/xmldecl/xmldecl-2.html [ Failure ]
 crbug.com/626703 [ Mac ] editing/pasteboard/drag-selected-image-to-contenteditable.html [ Failure ]
 crbug.com/626703 [ Mac ] external/wpt/webxr/xrSession_requestReferenceSpace_features.https.html [ Pass Timeout ]
@@ -8010,7 +7968,7 @@
 crbug.com/1376679 virtual/threaded/external/wpt/scroll-animations/css/scroll-timeline-dynamic.tentative.html [ Crash Failure Pass Timeout ]
 
 # Investigate the flake.
-crbug.com/1371395 external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-same-origin-bfcache.window.html [ Failure Pass ]
+crbug.com/1371395 external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-same-origin-bfcache.tentative.window.html [ Failure Pass ]
 
 # Test is flaky because of test_driver.bless, see crbug.com/1066891
 crbug.com/1382865 external/wpt/storage-access-api/requestStorageAccess-cross-origin-iframe.sub.https.window.html [ Failure Pass ]
@@ -8106,3 +8064,6 @@
 
 # Sheriff 2022-12-07
 crbug.com/1396185 accessibility/reach-and-scroll-overflow-div-without-mouse.html [ Pass Timeout ]
+
+# Sheriff 2022-12-08
+crbug.com/1383847 [ Linux ] virtual/exotic-color-space/images/color-profile-image-canvas.html [ Crash Failure Pass ]
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 c1f1ffe..f5a0829 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
@@ -6192,6 +6192,13 @@
        null,
        {}
       ]
+     ],
+     "worker-termination.https.html": [
+      "b9b988b36c27e68bd0b1bb18763fb591f07d6845",
+      [
+       null,
+       {}
+      ]
      ]
     }
    },
@@ -13645,13 +13652,6 @@
        {}
       ]
      ],
-     "element-request-fullscreen-same-manual.html": [
-      "defe9ce54d07eb6b9323d5a7571879452b539a2e",
-      [
-       null,
-       {}
-      ]
-     ],
      "element-request-fullscreen-svg-rect-manual.html": [
       "56ae56eec1794da991d8989cfec681ddc23a64a9",
       [
@@ -13680,48 +13680,6 @@
        {}
       ]
      ],
-     "element-request-fullscreen-twice-manual.html": [
-      "06641deb48b119f8236f391adae6ef252dcdcb1b",
-      [
-       null,
-       {}
-      ]
-     ],
-     "element-request-fullscreen-twice-manual.tentative.html": [
-      "a8b5531fa1835af333c7faab4ce041ce429cc4ca",
-      [
-       null,
-       {}
-      ]
-     ],
-     "element-request-fullscreen-two-elements-manual.html": [
-      "11baad7da7885b2709d842d4fa6274995c9a7ba8",
-      [
-       null,
-       {}
-      ]
-     ],
-     "element-request-fullscreen-two-elements-manual.tentative.html": [
-      "5ebc628b3b3b56d5e41a87ec96bb6da4862af463",
-      [
-       null,
-       {}
-      ]
-     ],
-     "element-request-fullscreen-two-iframes-manual.html": [
-      "916ae7969502cee6a825303b6c5c695c514e597d",
-      [
-       null,
-       {}
-      ]
-     ],
-     "element-request-fullscreen-two-iframes-manual.tentative.html": [
-      "691c221904e90ccc79d2deff6139b8346f235a9f",
-      [
-       null,
-       {}
-      ]
-     ],
      "promises-resolve-manual.html": [
       "e58b8d90fed4b613c972e004db54e9a828816fcd",
       [
@@ -259345,11 +259303,11 @@
   "support": {
    ".cache": {
     "gitignore2.json": [
-     "3e17f3bb68725a2da4ad181b09b09df55d8021d8",
+     "ca89190b30c4d87d561fcb69ae3f3e3878d03c7b",
      []
     ],
     "mtime.json": [
-     "8072d84a1f54619d4614b11e4d73c5c2d788f244",
+     "80d23bbdab42e43082de259b9ca32a63bfe47ba9",
      []
     ]
    },
@@ -259619,7 +259577,7 @@
      []
     ],
     "bindings-inject-values-bypass-chain.html.ini": [
-     "ab75b1b8be2142a31c2653c6cbef5204d9df5c75",
+     "321c5fd871101c24af92dc6ca1007ec604c8e8f2",
      []
     ],
     "database-names-by-origin.html.ini": [
@@ -259635,7 +259593,7 @@
      []
     ],
     "idbobjectstore_batchGetAll_largeValue.tentative.any.js.ini": [
-     "6f6a8d0040345934ff8927b5eacf7a56e1a76532",
+     "93a6866c016e708634692cbd0bf74f7ebe9ddd88",
      []
     ],
     "resources": {
@@ -264659,6 +264617,14 @@
      ]
     },
     "inheritance": {
+     "history-iframe.sub.html.ini": [
+      "3d47c07320d23e9f61a5faf20eee5119d20d0b8a",
+      []
+     ],
+     "history.sub.html.ini": [
+      "9728b70673c3922eafeeb1decc0608dd5a1ab388",
+      []
+     ],
      "sandboxed-blob-scheme.html.sub.headers": [
       "adc398d890fda1c5e11143f9e5aad5e9f6ac0932",
       []
@@ -265883,11 +265849,11 @@
      []
     ],
     "cookieListItem_attributes.https.any.js.ini": [
-     "7b5686f32369d75b4de6ebd528453d2060657d1d",
+     "035485e0a713bb745dac8ae3ce4d7e30211bf6f9",
      []
     ],
     "cookieStore_set_arguments.https.any.js.ini": [
-     "7495e61b42f64520c068474c22915d28c48b1579",
+     "71af6b80aeee987e924680fecc89a0b538378540",
      []
     ],
     "cookieStore_subscribe_arguments.https.any.js.ini": [
@@ -266180,7 +266146,7 @@
     },
     "samesite": {
      "form-post-blank-reload.https.html.ini": [
-      "474bdcb939113d28f9ec5d5eeedd78f0f3c471d7",
+      "25c3e4acef5bf932cb514f79d326a9118b69c153",
       []
      ],
      "form-post-blank.https.html.ini": [
@@ -266363,7 +266329,7 @@
      ]
     },
     "fedcm-network-requests.https.html.ini": [
-     "d8949723adfd7ec89e7deaec5f52c4cf16ed6567",
+     "313555ba6d147688ab9bf79280fdec0e39b40329",
      []
     ],
     "federatedcredential-framed-get.sub.https-expected.txt": [
@@ -275210,7 +275176,7 @@
       []
      ],
      "Element-getAnimations-dynamic-changes.tentative.html.ini": [
-      "cd79bce0007ca0a053223c57c0ae0e86b094c20e",
+      "90372850a2b15bec987edeacd277c571fa2bae64",
       []
      ],
      "KeyframeEffect-getKeyframes.tentative-expected.txt": [
@@ -285868,7 +285834,7 @@
       []
      ],
      "image-as-flexitem-size-001v.html.ini": [
-      "fc1afa3f544957ecafe9b6c362d9388aa84ea0f3",
+      "0c7857241b0cb204a1289b009a9a5405172d0809",
       []
      ],
      "image-as-flexitem-size-002.html.ini": [
@@ -285916,7 +285882,7 @@
       []
      ],
      "image-as-flexitem-size-007v.html.ini": [
-      "29ec443eb46590639eacd77cf6f942b54e16ac37",
+      "5d58a48ac7dbfdf24f0534672e6412b05bb963b5",
       []
      ],
      "interactive": {
@@ -286862,7 +286828,7 @@
       []
      ],
      "crash-large-grapheme-cluster.html.ini": [
-      "83547c688a0acf58f149fd7af6882d6b76524e6d",
+      "be7498aefa7b7a79c9e35b3adcd39511020adb24",
       []
      ],
      "downloadable-font-in-iframe-print-ref.html": [
@@ -299099,7 +299065,7 @@
        []
       ],
       "Initial-letter-breaking-vlr.html.ini": [
-       "0b139d8c707a3a0282d818bd3cead54c3fbf6f53",
+       "a76ddebb09122ea844c4ced99309e7c4105566b3",
        []
       ],
       "Initial-letter-breaking-vrl-ref.html": [
@@ -299107,7 +299073,7 @@
        []
       ],
       "Initial-letter-breaking-vrl.html.ini": [
-       "a3abcef3f2de6b9a92a2186e9a3fbcc24cbc8aea",
+       "95bff1082a42475a6be9667358d42516b14d2824",
        []
       ],
       "Initial-letter-breaking.html.ini": [
@@ -299123,7 +299089,7 @@
        []
       ],
       "initial-letter-block-position-drop-over-ruby-tall.html.ini": [
-       "6c2775276ea718ec41d046d428e706a9d6b35dfa",
+       "7ba52f02d6af7e6b823d92b68bb40d05b8f623d9",
        []
       ],
       "initial-letter-block-position-drop-over-ruby.html.ini": [
@@ -299171,7 +299137,7 @@
        []
       ],
       "initial-letter-block-position-margins-vrl.html.ini": [
-       "b5f8d7be7b0e9ef6a3f09f4b41301caf7ae03897",
+       "24a438372dc05867981d6f64b85d9fb1716f4b52",
        []
       ],
       "initial-letter-block-position-margins.html.ini": [
@@ -299187,7 +299153,7 @@
        []
       ],
       "initial-letter-block-position-raise-over-ruby-tall.html.ini": [
-       "50a3c7cc6b0b2246a3ca302ebfc002b293f5513b",
+       "4b8cec5ca34e64330806ec03efb83328c4d011e8",
        []
       ],
       "initial-letter-block-position-raise-over-ruby.html.ini": [
@@ -299223,7 +299189,7 @@
        []
       ],
       "initial-letter-drop-initial-rtl.html.ini": [
-       "04516eb078242106741db3c5add65563d0241752",
+       "d6e86990f0cd7dde7154de02ce20b0bf63e97fc6",
        []
       ],
       "initial-letter-drop-initial-vlr-ref.html": [
@@ -299239,7 +299205,7 @@
        []
       ],
       "initial-letter-drop-initial-vrl.html.ini": [
-       "6c731bbadcc79d12fa6c90635cdb3b3d148458bd",
+       "9324bd347f71f55e49cd491d089e1145363f6d95",
        []
       ],
       "initial-letter-drop-initial.html.ini": [
@@ -299263,7 +299229,7 @@
        []
       ],
       "initial-letter-float-001-vlr.html.ini": [
-       "72b9d1f623146292108a7bcad02e61f0d85da5b0",
+       "c90a4c2d81fa1d6dea8c956c8a593c503338dec0",
        []
       ],
       "initial-letter-float-001-vrl-ref.html": [
@@ -299271,7 +299237,7 @@
        []
       ],
       "initial-letter-float-001-vrl.html.ini": [
-       "d320f2a681808bf655ccb910ca62ffb6d6937e0d",
+       "7d4942a71138fdfef8ac6e42418fa50568808c7b",
        []
       ],
       "initial-letter-float-001.html.ini": [
@@ -299283,7 +299249,7 @@
        []
       ],
       "initial-letter-float-002.html.ini": [
-       "3555bde855c42401f1e3687bdcaa36e8d20e5174",
+       "eeb0e18a7eace82f31abbdd12e385c425c5845fa",
        []
       ],
       "initial-letter-float-003-ref.html": [
@@ -299307,7 +299273,7 @@
        []
       ],
       "initial-letter-float-005.html.ini": [
-       "e71bd47b8463f6d2fc0774151440f4a915526894",
+       "702ca03f01d97eab08744f8c6b2a6cb92d8d08a5",
        []
       ],
       "initial-letter-indentation-ref.html": [
@@ -299323,7 +299289,7 @@
        []
       ],
       "initial-letter-indentation.html.ini": [
-       "2f25a7a3aa6494563e10625c54ef4659a702ece5",
+       "fbc24c225c34e2f35829cc904f469bff56350f9a",
        []
       ],
       "initial-letter-layout-text-decoration-underline-ref.html": [
@@ -299331,7 +299297,7 @@
        []
       ],
       "initial-letter-layout-text-decoration-underline.html.ini": [
-       "24aef2dd8d35fcd9b76ae0379ceac337c315b3c9",
+       "87a653d81d272f04db703b27e8ef6e2aae8cf63a",
        []
       ],
       "initial-letter-raise-initial-ref.html": [
@@ -299351,7 +299317,7 @@
        []
       ],
       "initial-letter-raise-initial-vlr.html.ini": [
-       "71ec40fd94c668c0f8ecf18dd446b9a4d3a05928",
+       "3487598fa44ea871ef93d7d84c4ce98ae48092e7",
        []
       ],
       "initial-letter-raise-initial-vrl-ref.html": [
@@ -299371,7 +299337,7 @@
        []
       ],
       "initial-letter-raised-sunken-caps-raise.html.ini": [
-       "883813906f243b01413462b615001388cca72cba",
+       "0d15c001d4a89a6c0144c3a697ce2c6c4cc6ec00",
        []
       ],
       "initial-letter-raised-sunken-caps-sunken-ref.html": [
@@ -299379,7 +299345,7 @@
        []
       ],
       "initial-letter-raised-sunken-caps-sunken.html.ini": [
-       "858a0ee023dd09641c6760806feec30819a37bee",
+       "9280e8ef0b41c09e7a95315599c1a38607ad4721",
        []
       ],
       "initial-letter-short-para-initial-letter-clears-ref.html": [
@@ -299415,7 +299381,7 @@
        []
       ],
       "initial-letter-sunk-initial-vlr.html.ini": [
-       "017a0f1d77a316ce8461c29d0d49331ba6aff606",
+       "84fa955e9b48a110d3b028481fc640d8ced287f8",
        []
       ],
       "initial-letter-sunk-initial-vrl-ref.html": [
@@ -299423,7 +299389,7 @@
        []
       ],
       "initial-letter-sunk-initial-vrl.html.ini": [
-       "48e8fe1209b990c6f7d4ac77306eefa8a2794818",
+       "68a12ebb278d5d266ea2239bdedd75253a674497",
        []
       ],
       "initial-letter-sunk-initial.html.ini": [
@@ -299439,7 +299405,7 @@
        []
       ],
       "initial-letter-with-first-line.html.ini": [
-       "5170dd0df78a659e4e6d9690135c444e2600bec9",
+       "dd1718d432a47cc881b6d3bcb4fa76aa0f613910",
        []
       ],
       "initial-letter-with-tab-ref.html": [
@@ -299451,11 +299417,11 @@
        []
       ],
       "initial-letter-with-tab-rtl.html.ini": [
-       "2085f9a8fa9ca13085723ac00db1bf0ead986d18",
+       "c20c7725426ebf7b96138d313f0bc27165b7664a",
        []
       ],
       "initial-letter-with-tab.html.ini": [
-       "dbd3639de25ea5c06a3ce8ef00a69f8ba899e811",
+       "8bc01f529ccc1760da157c292c1d437648a2377c",
        []
       ]
      },
@@ -299636,6 +299602,10 @@
       }
      },
      "fallback-intrinsic-sizes": {
+      "constructor-error.https.html.ini": [
+       "1244ec0ebc2cc18d26f4101095e6d3eb2cd70586",
+       []
+      ],
       "fallback-ref.html": [
        "6808e14eb683fde8c30a2c89318c6cccba12ca1a",
        []
@@ -299688,6 +299658,10 @@
        "41593560470dd8c81b81febcebc591480db7f168",
        []
       ],
+      "negative-min.https.html.ini": [
+       "a42ed9d446a6618087743f68d225ca240b66a7f1",
+       []
+      ],
       "negative-ref.html": [
        "6808e14eb683fde8c30a2c89318c6cccba12ca1a",
        []
@@ -300795,7 +300769,7 @@
        []
       ],
       "clip-path-inline-001.html.ini": [
-       "c87eb82357b0de46119bbf273892ce08cf2eac89",
+       "3917a432eee9ec2d3266c4db5941181ee2d5015a",
        []
       ],
       "clip-path-inline-002.html.ini": [
@@ -302002,11 +301976,11 @@
       []
      ],
      "getclientrects-000.html.ini": [
-      "7dcf0d3a46bae8805415235e70dd9f01a80e94c5",
+      "bd86605e287c9b4a3dfe74fac4e272ad55466e21",
       []
      ],
      "getclientrects-001.html.ini": [
-      "1d32d9521dcde0c9ac9163f7b37cbfd9a5985063",
+      "38d7beae04ef678926c3455f4d2ad5ec1c58177c",
       []
      ],
      "hit-test-transformed-child.html.ini": [
@@ -303904,7 +303878,7 @@
       []
      ],
      "scrollable-overflow-input-001.html.ini": [
-      "53c5a71e2f1773ce8c40e0f759b4c5fb91952439",
+      "af5b11c450c65eaf1e3432fb428f5b5e8bd9f109",
       []
      ],
      "scrollable-overflow-input-002-ref.html": [
@@ -303912,7 +303886,7 @@
       []
      ],
      "scrollable-overflow-input-002.html.ini": [
-      "6e03ac5f353bb60fc0f81f763375e7aac0cbbbd1",
+      "eba9b192af82bb1e776a747aec56d515e6bd072c",
       []
      ],
      "scrollable-overflow-padding.html.ini": [
@@ -304444,7 +304418,7 @@
       []
      ],
      "parse-input-arguments-018.https.html.ini": [
-      "9905f9f8ad5e64a36db44308b83d79cce7f0dad7",
+      "30ab18db601cdf95e080cbcd05dd6aa4bda8a692",
       []
      ],
      "parse-input-arguments-ref.html": [
@@ -307691,6 +307665,10 @@
         "8f529e412cff1dcf89660eb975392e4890f45a4a",
         []
        ],
+       "shape-image-026.html.ini": [
+        "d20ff4ec7d32be1e51f5f9c30440dd5af664023f",
+        []
+       ],
        "support": {
         "animated.gif": [
          "9e424df7cdfb6b228b18297334fba7cabdb270cd",
@@ -313977,7 +313955,7 @@
        []
       ],
       "text-transform-capitalize-003.html.ini": [
-       "6fa8326af0841c0227ed7f5d159f56e69d5fbc1b",
+       "38e66a2dc4a6c69a3dd79df3f84abe55bd072294",
        []
       ],
       "text-transform-capitalize-005.html.ini": [
@@ -314000,6 +313978,10 @@
        "869d3178e27f1539e32ecd49339a5d6b2db5956f",
        []
       ],
+      "text-transform-capitalize-018.html.ini": [
+       "87e51404e16bbebfa59694f95dfaa34426e0f4b4",
+       []
+      ],
       "text-transform-capitalize-026.html.ini": [
        "ff630745fc27ca4844b809a72548171a8c32ad20",
        []
@@ -329230,7 +329212,7 @@
       []
      ],
      "input-file-print.html.ini": [
-      "1ec656fb80df94164ab32ab2de9b14c353823195",
+      "be2fa5760cb9b3f63e182fd310ce757ab33ed53f",
       []
      ],
      "page-overflow-crash-print.html.ini": [
@@ -329770,20 +329752,12 @@
       }
      },
      "parsing": {
-      "parse-has-disallow-nesting-has-inside-has-expected.txt": [
-       "daddf3a13f8d97cb0dbf691dbe7969541c2c6b4b",
-       []
-      ],
-      "parse-has-disallow-nesting-has-inside-has.html.ini": [
-       "8c2bec6b329571ef650f906a29f12b8a7d20dfe0",
-       []
-      ],
       "parse-has-expected.txt": [
-       "f10c3bec6369c45698b8ca3ba34efb32ce1eab28",
+       "d486ca05e4f8d7447626907c833d02a1b56627c3",
        []
       ],
       "parse-has.html.ini": [
-       "d35c1f9a3cee1ee58a8ccdede4d72f64040f6a98",
+       "4f611c93b759297c2e7184620dce49a61f8db9dc",
        []
       ]
      },
@@ -331826,11 +331800,11 @@
     },
     "ranges": {
      "Range-mutations-dataChange.html.ini": [
-      "7158a50a34d3428f41cd3a6672018936c2c3c088",
+      "c1f1d46ce54df403fe78ec637233281dbb7e2fef",
       []
      ],
      "Range-mutations-replaceData.html.ini": [
-      "51870a60a546d1da49f45ec8b1651271708a7d27",
+      "8b10363f77b3f47c8589ad7e1ef5a45b0fcff496",
       []
      ],
      "Range-mutations.js": [
@@ -332078,6 +332052,10 @@
       []
      ]
     },
+    "xml_xpath_runner.html.ini": [
+     "b9af709d743120691862162d43e765066c8ab218",
+     []
+    ],
     "xml_xpath_tests.xml": [
      "91d6428f48a15056fb6d7f4a3d567dcfe580511d",
      []
@@ -333002,7 +332980,7 @@
       []
      ],
      "join-pre-and-other-block.html.ini": [
-      "793ad47e33536def309422b5dac7da43e8f8c7ab",
+      "5baa1903863e11c77e55f9c98ef949fae79f9ef2",
       []
      ],
      "join-pre-and-other-block_method=backspace_block=blockquote-expected.txt": [
@@ -333836,10 +333814,6 @@
        "9a64388b411ed15ffe4db2502d486609c0fbb055",
        []
       ],
-      "eucjp-encode-href-errors-han.html.ini": [
-       "d439e022d809d21bf9c0bb09d70eff22d9f77ae4",
-       []
-      ],
       "eucjp-encode-href-errors-hangul.html.headers": [
        "9a64388b411ed15ffe4db2502d486609c0fbb055",
        []
@@ -333996,6 +333970,10 @@
        "e8a046f875179688890a13bacbeef9388ae59bd4",
        []
       ],
+      "sjis-decode-ms_kanji.html.ini": [
+       "521412ae4d0588e0b198c8730c3e5f9dd775e987",
+       []
+      ],
       "sjis-decoder.js": [
        "48e08b3fbf7c304570551dbf20c255b60d88aec9",
        []
@@ -334141,7 +334119,7 @@
     "legacy-mb-korean": {
      "euc-kr": {
       "euckr-decode-ksc5601.html.ini": [
-       "0bcc6595f6d98dd9ff9eed9fb106ffa94710207d",
+       "9df145d78aaba544e082b9eea10855b1fc2f50c5",
        []
       ],
       "euckr-decoder.js": [
@@ -334330,6 +334308,10 @@
     },
     "legacy-mb-tchinese": {
      "big5": {
+      "big5-decode-csbig5.html.ini": [
+       "0dbbd0671cc0d21ece43355257e07e18a78e3b59",
+       []
+      ],
       "big5-decode-expected.txt": [
        "d3328d8e88bc16cf15cb9cfc5bd2bb41f34797bb",
        []
@@ -334643,7 +334625,7 @@
      []
     ],
     "unsupported-labels.window.js.ini": [
-     "a9762cc45391392c23133d69051fab76c8f154bc",
+     "ff6ba32c8edce3a6ed6b4c9b29a1b6a48bf8d529",
      []
     ]
    },
@@ -337867,7 +337849,7 @@
        []
       ],
       "element-iframe.sub.html.ini": [
-       "96b1dbd1f4dd749b14c3bf115ba193d92c7fa8bd",
+       "11568fc41667ea078f67436da26aef727a8095b3",
        []
       ],
       "element-img-environment-change.https.sub.html.ini": [
@@ -337887,7 +337869,7 @@
        []
       ],
       "element-input-image.https.sub.html.ini": [
-       "7570dde7296e048ae8c559f4647f79932f0d675d",
+       "09e396bf461eb56d1db76965d01f98bf09a9dd1a",
        []
       ],
       "element-link-icon.https.sub.html.ini": [
@@ -338406,7 +338388,7 @@
       []
      ],
      "iframe.tentative.https.window.js.ini": [
-      "feb271922656ded4d6f595bf5ea223ece84cec25",
+      "b72e9d870cb3e16ffdde924238ba2ddfcd216ce9",
       []
      ],
      "iframe.tentative.window-expected.txt": [
@@ -338516,11 +338498,11 @@
       ]
      },
      "service-worker-background-fetch.https.window.js.ini": [
-      "352bde56b0dfc1d294f9189193963935350f7e32",
+      "8f76e152b2ff5aaf1cdac34efa3d0bc8bb82073d",
       []
      ],
      "service-worker-fetch.https.window.js.ini": [
-      "ed7c7004a9508c29e98b03c0ee1d9929c039d325",
+      "21e60215aad4134e72cc6815e3babaca2ff85de5",
       []
      ],
      "shared-worker.window.js.ini": [
@@ -338832,6 +338814,10 @@
      "7abdb092cc80f8a0516f1c53a4a98c985088d37c",
      []
     ],
+    "activeelement-after-immediately-focusing-same-site-iframe.html.ini": [
+     "75cf448d8907e94eadb47bc5eb9cf953767853dc",
+     []
+    ],
     "focus-already-focused-iframe-deep-different-site.html.ini": [
      "dd9caa934c6696ba8d0ef70402c01b45b7a3f052",
      []
@@ -338913,7 +338899,7 @@
      []
     ],
     "iframe-contentwindow-focus-with-different-site-intermediate-frame.html.ini": [
-     "0a09915f1e98f4c646189830392f864ae8ea4eb9",
+     "c06c0e7b0764126a030d499192ff674c867e5a25",
      []
     ],
     "iframe-contentwindow-focus-with-same-as-top-intermediate-frame-expected.txt": [
@@ -338929,7 +338915,7 @@
      []
     ],
     "iframe-focus-with-different-site-intermediate-frame.html.ini": [
-     "a4e9ffefd3d4c43282dea6fd72191db23d6006cb",
+     "501950368012f28203aead245411c7e608f36c68",
      []
     ],
     "iframe-focus-with-same-as-top-intermediate-frame-expected.txt": [
@@ -340360,10 +340346,6 @@
      "12cf0e36d35303a5936a5a1f0fba87083b219262",
      []
     ],
-    "FileSystemFileHandle-create-sync-access-handle.https.tentative.window.js.ini": [
-     "76445ac370b2bbc23df7e0a62b910dfa095440b3",
-     []
-    ],
     "META.yml": [
      "23d7765cdfa39689ef72ae6a0beb15b8b4292ecd",
      []
@@ -340559,10 +340541,18 @@
       "8647747c883a1d003752da271535cb1d308c6905",
       []
      ],
+     "element-request-fullscreen-consume-user-activation.html.ini": [
+      "83b659bf33452ba7f7e4c7be9cc09480dff08806",
+      []
+     ],
      "element-request-fullscreen-options.tentative.html.ini": [
       "1b21f6facdd4c84cd09bd374680abd6906d00c9e",
       []
      ],
+     "element-request-fullscreen-same-element.html.ini": [
+      "21020b07d9818cfd736ed4d12f1f4846d180a93a",
+      []
+     ],
      "element-request-fullscreen.html.ini": [
       "4558e71c6854b6c520397fb8483bf492a2986940",
       []
@@ -340973,7 +340963,7 @@
      []
     ],
     "clamped-time-origin.html.ini": [
-     "aefff521ac62ba51d6348330bee5a5b834e872a0",
+     "9082a0b2944b33844a9d5a28ccfbb3a43f1f8f1e",
      []
     ],
     "cross-origin-isolated-timing-attack.https.html.headers": [
@@ -341038,11 +341028,11 @@
     ],
     "anonymous-iframe": {
      "anonymous-iframe-popup.tentative.https.window.js.ini": [
-      "e222dfd551725762c48d5b69537476e130995685",
+      "76ec1609759908f0a56d16cb35d591fcff066ea6",
       []
      ],
      "embedding.tentative.https.window.js.ini": [
-      "316e6541bbd65b57e9dccf6a61e0361289207afa",
+      "e332734a5300078157db6b1ef4dd863400b3e4e7",
       []
      ],
      "fenced-frame-bypass.tentative.https.window-expected.txt": [
@@ -341150,7 +341140,7 @@
         []
        ],
        "focus.html.ini": [
-        "622a0b95aa0d7d5636257d0b95bd4b2e40739730",
+        "8bb63c5be2f3a7d721e8560df0dd503d49bd3931",
         []
        ],
        "pushstate.https.html.ini": [
@@ -341307,7 +341297,11 @@
        ],
        "event-order": {
         "before-load-hash-twice.html.ini": [
-         "8c2aa5c1779cf355498b08a58ca73c8742c3743b",
+         "2f3190eb5f573658eadf15ac371a26bf8ef5fcc7",
+         []
+        ],
+        "before-load-hash.html.ini": [
+         "460c4ca140f54314734f042f83e5223e418bc441",
          []
         ]
        },
@@ -341862,7 +341856,7 @@
         []
        ],
        "cross-document-traversal-cross-document-traversal.html.ini": [
-        "ba0661429f27099523035104ee640d34679fa8d5",
+        "8452eaf736003e12ee2fa8edbdc844ffbdb6fc95",
         []
        ],
        "cross-document-traversal-same-document-traversal.html.ini": [
@@ -341908,7 +341902,7 @@
         []
        ],
        "same-document-traversal-cross-document-traversal.html.ini": [
-        "62a41e27381079a370805c9fe9e90527dc746eb1",
+        "cef5e4f842132ace9f6f873b6e449d53cdad1b0f",
         []
        ],
        "same-document-traversal-same-document-traversal-hashchange.html.ini": [
@@ -342317,10 +342311,6 @@
         "d150449eb2df241e4ae286cf8ba13fc37f0874c3",
         []
        ],
-       "011.html.ini": [
-        "96c1a36296e8468ae837a2e58dade114273f0089",
-        []
-       ],
        "blank-new.html": [
         "2a545af0ed30d69b1e4bb7d1e608273b89dd3d1e",
         []
@@ -342582,7 +342572,7 @@
         []
        ],
        "location-protocol-setter-non-broken.html.ini": [
-        "504d86aee122cf41ba76c332ac4ad6bbe8654b5a",
+        "1af48f800039c5bed03a9686df62078f17d6c2d0",
         []
        ],
        "location-prototype-setting-cross-origin-domain.sub-expected.txt": [
@@ -342804,7 +342794,7 @@
         []
        ],
        "cross-origin-objects-function-name.html.ini": [
-        "ab20f7d67ec27b63a5eeba7fc9bd2357fab36d05",
+        "df54342880d0038f649b9a569f018e176e1b65db",
         []
        ],
        "cross-origin-objects-on-new-window.html.ini": [
@@ -342862,16 +342852,12 @@
          "470b5e72ad2865cbd3ec3af9a1a84a685d964be4",
          []
         ],
-        "parent-no-child-yes-subdomain.sub.https.html.ini": [
-         "25b59d55b3ff51436b120a4cfef4fdcd600385c8",
-         []
-        ],
         "parent-yes-child-no-port.sub.https.html.headers": [
          "79a20f30fc0f486014c8b93edef7483605101504",
          []
         ],
         "parent-yes-child-no-port.sub.https.html.ini": [
-         "de4b97c19953bc66c1ffb116d34602d66aa5724d",
+         "5383b4d6c44128b9efe8d2a58b3d4660d59f1198",
          []
         ],
         "parent-yes-child-no-same.sub.https.html.headers": [
@@ -342879,7 +342865,7 @@
          []
         ],
         "parent-yes-child-no-same.sub.https.html.ini": [
-         "7683c127a6934937d22bf2eaaaba2f8789fd25fa",
+         "2066f0aa9ca91dd53bc2d525ebcf3a6e723370e7",
          []
         ],
         "parent-yes-child-no-subdomain.sub.https.html.headers": [
@@ -342887,7 +342873,7 @@
          []
         ],
         "parent-yes-child-no-subdomain.sub.https.html.ini": [
-         "4df55d70d7e6176e97c1361ebd0e1542b2b3d290",
+         "ebb9852bb2f5514efbf01b8c07e0f6f16bc51776",
          []
         ],
         "parent-yes-child-yes-port.sub.https.html.headers": [
@@ -342895,7 +342881,7 @@
          []
         ],
         "parent-yes-child-yes-port.sub.https.html.ini": [
-         "5f428d85c58be189cc011c3e8b44b6892f5b6083",
+         "1fe764980cdb004b33f17ae5ae9329436157fe58",
          []
         ],
         "parent-yes-child-yes-same.sub.https.html.headers": [
@@ -342903,7 +342889,7 @@
          []
         ],
         "parent-yes-child-yes-same.sub.https.html.ini": [
-         "e3a89c0f7ce9961f842110f8818e4e27fd505f8b",
+         "2b7fa4f27546ce75c088fb484df17a380bfb685f",
          []
         ],
         "parent-yes-child-yes-subdomain.sub.https.html.headers": [
@@ -342911,13 +342897,13 @@
          []
         ],
         "parent-yes-child-yes-subdomain.sub.https.html.ini": [
-         "bb7bb06aa9e0dea3b2ed99d2355d71f6275efe55",
+         "fff3f00c74140bedbb6d4448b89f100999df598e",
          []
         ]
        },
        "2-iframes": {
         "parent-no-child1-no-subdomain-child2-yes-subdomain.sub.https.html.ini": [
-         "9be6e053e2e35fc8317599a32e5bc7ec77d05524",
+         "bd99113e184f4b958eb2c35963486e4ad1ae05d4",
          []
         ],
         "parent-no-child1-no-subdomain-child2-yes-subdomainport.sub.https.html.ini": [
@@ -342925,15 +342911,15 @@
          []
         ],
         "parent-no-child1-no-subdomain1-child2-yes-subdomain2.sub.https.html.ini": [
-         "d350ba94fa60e0a348a9414131a2078d8079bc99",
+         "ff06302c1d7e9e24e4913d2105fff02c1c570c2b",
          []
         ],
         "parent-no-child1-yes-subdomain-child2-no-port.sub.https.html.ini": [
-         "25a890756c222591fc6d2b2e08a360f6d69a9347",
+         "d91cf4a25896887e4178ddc3fc0e70a77fb525dd",
          []
         ],
         "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": [
@@ -342941,7 +342927,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": [
@@ -342949,7 +342935,7 @@
          []
         ],
         "parent-yes-child1-no-subdomain-child2-no-subdomain2.sub.https.html.ini": [
-         "404db309da3ac1a095aacac8eb9e0ece8fea79f1",
+         "aa399ed59ccdefdbb932b99134446613c9aacf5c",
          []
         ],
         "parent-yes-child1-no-subdomain-child2-yes-subdomain.sub.https.html.headers": [
@@ -342957,7 +342943,7 @@
          []
         ],
         "parent-yes-child1-no-subdomain-child2-yes-subdomain.sub.https.html.ini": [
-         "870d618369d11b43e52dc7c558668b4de5cd8807",
+         "55c9507947dd54f89a1ba668d8a092793a789cc8",
          []
         ],
         "parent-yes-child1-no-subdomain-child2-yes-subdomain2.sub.https.html.headers": [
@@ -342965,7 +342951,7 @@
          []
         ],
         "parent-yes-child1-no-subdomain-child2-yes-subdomain2.sub.https.html.ini": [
-         "21a86a7c819b5d0c466d5315b28abab528e425ca",
+         "7b86435b4bd91133fe7f0a6b8081b3dff5c8d544",
          []
         ],
         "parent-yes-child1-no-subdomain-child2-yes-subdomainport.sub.https.html.headers": [
@@ -342973,7 +342959,7 @@
          []
         ],
         "parent-yes-child1-no-subdomain-child2-yes-subdomainport.sub.https.html.ini": [
-         "55806ef001609af9235592387679abd651d7046f",
+         "7ba4e734b61e2c82f12f4dbf60462f5c2ae1ad9d",
          []
         ],
         "parent-yes-child1-yes-subdomain-child2-no-port.sub.https.html.headers": [
@@ -342981,7 +342967,7 @@
          []
         ],
         "parent-yes-child1-yes-subdomain-child2-no-port.sub.https.html.ini": [
-         "0a4b7f80ff58fd6a22811c9c950ffcdc17f28ba3",
+         "54fc998ef0bc7951df4757f05c19f4bc08f3907a",
          []
         ],
         "parent-yes-child1-yes-subdomain-child2-no-subdomain.sub.https.html.headers": [
@@ -342989,7 +342975,7 @@
          []
         ],
         "parent-yes-child1-yes-subdomain-child2-no-subdomain.sub.https.html.ini": [
-         "2c6c938020ce3530ea71e41f8a95c24a49cc5d86",
+         "6e0693527992a576cfad006f536fec04161c98ee",
          []
         ],
         "parent-yes-child1-yes-subdomain-child2-yes-subdomain.sub.https.html.headers": [
@@ -342997,7 +342983,7 @@
          []
         ],
         "parent-yes-child1-yes-subdomain-child2-yes-subdomain.sub.https.html.ini": [
-         "7542bf66fbff1266ab6c5dcffd60abd0180418b2",
+         "3be8b66c60fbd9a158e332ffde611ae30634ba03",
          []
         ],
         "parent-yes-child1-yes-subdomain-child2-yes-subdomain2.sub.https.html.headers": [
@@ -343005,7 +342991,7 @@
          []
         ],
         "parent-yes-child1-yes-subdomain-child2-yes-subdomain2.sub.https.html.ini": [
-         "aa87e78f8149db9dc3a0e2bf36e2d1ec2bed7a49",
+         "985a6571bcf04911bee8fc8e47cfc696ae25698c",
          []
         ],
         "parent-yes-child1-yes-subdomain-child2-yes-subdomainport.sub.https.html.headers": [
@@ -343013,7 +342999,7 @@
          []
         ],
         "parent-yes-child1-yes-subdomain-child2-yes-subdomainport.sub.https.html.ini": [
-         "e3b0508f4657609580638d04ce6d4902d3c18ee9",
+         "cb8c40e9e256893e2f926e7ed55b7338a72568f9",
          []
         ]
        },
@@ -343042,7 +343028,7 @@
         []
        ],
        "document-domain.sub.https.html.ini": [
-        "0303cd30e3960680057883be31140eaa7388c8c6",
+        "b9c6e71fc002345edad1abc024d7a6ecf32a75f3",
         []
        ],
        "getter-special-cases": {
@@ -343070,12 +343056,16 @@
          "79a20f30fc0f486014c8b93edef7483605101504",
          []
         ],
+        "javascript-url-yes.https.html.ini": [
+         "300ae43ef4c3e8800127b329607ad79591d30700",
+         []
+        ],
         "removed-iframe.sub.https.html.headers": [
          "79a20f30fc0f486014c8b93edef7483605101504",
          []
         ],
         "removed-iframe.sub.https.html.ini": [
-         "dda6109a3a066d66d299ff3b5fb4469896a098cc",
+         "80f7bcf227596aa09729be979f5e2927648e5b5a",
          []
         ],
         "resources": {
@@ -343109,7 +343099,7 @@
          []
         ],
         "sandboxed-same-origin-iframe-no.https.html.ini": [
-         "27d7b90a39f0b3627a686e2a6c41bd450bbc5872",
+         "6739f44f945f58f283bd3cc722bbf29c0bec78c7",
          []
         ],
         "sandboxed-same-origin-iframe-yes.https.html.headers": [
@@ -343131,23 +343121,23 @@
        ],
        "iframe-navigation": {
         "parent-no-1-no-same-2-yes-port.sub.https.html.ini": [
-         "ec2a502d92a980ccdf4976cc1155f85ad599095b",
+         "43e1bec1c03d27c5865143a3f0a76fccf9ff6020",
          []
         ],
         "parent-no-1-no-same-2-yes-subdomain.sub.https.html.ini": [
-         "0a52bd7a03736073351b0d9d541e679a71140fd1",
+         "e824e3432f938be819a1725cca68086e678d68ec",
          []
         ],
         "parent-no-1-no-subdomain-2-yes-subdomain.sub.https.html.ini": [
-         "6470857baec00b2b95575b09146fedd9c6c97b1a",
+         "bc4291179155d809b1e290566a6bca9fa1a1338a",
          []
         ],
         "parent-no-1-no-subdomain-2-yes-subdomain2.sub.https.html.ini": [
-         "5f9d08c01e11e0a681e9ebea2cb018754f38c160",
+         "ea522458742cd738c23f9c72817d8bab6c65d062",
          []
         ],
         "parent-no-1-subdomain-yes-2-subdomain2-no.sub.https.html.ini": [
-         "1473b343f0b75a6bf2284c54f59b0d0a5a569993",
+         "d6d82bef75e9dc641d39d8b49db1e901e6ac5024",
          []
         ],
         "parent-yes-1-no-same-2-no-port.sub.https.html.headers": [
@@ -343155,7 +343145,7 @@
          []
         ],
         "parent-yes-1-no-same-2-no-port.sub.https.html.ini": [
-         "8215e4ce046000d54a9b788291bfafdfa4509367",
+         "b88a9015459c1e08089c2a8be42ede0d3e6785be",
          []
         ],
         "parent-yes-1-no-same-2-no-subdomain.sub.https.html.headers": [
@@ -343163,7 +343153,7 @@
          []
         ],
         "parent-yes-1-no-same-2-no-subdomain.sub.https.html.ini": [
-         "8de18d45c5775dc84ae71e8755415835f35a3c06",
+         "1f51943954728a7d5e67c30710de91a35f5178e2",
          []
         ]
        },
@@ -343177,7 +343167,15 @@
        ],
        "popups": {
         "opener-no-openee-yes-port.sub.https.html.ini": [
-         "2d3830c48a40b503ba9dca88df1f48163973ccd6",
+         "31826e4cff13a577307c3e57ac3107f1b8deb590",
+         []
+        ],
+        "opener-no-openee-yes-same.sub.https.html.ini": [
+         "3383d84434c1aeab74ee35e2a3d2ad8d6886d385",
+         []
+        ],
+        "opener-no-openee-yes-subdomain.sub.https.html.ini": [
+         "cd6ff86474171e22c5d8b72318e9204acdf002f9",
          []
         ],
         "opener-yes-openee-no-port.sub.https.html.headers": [
@@ -343185,7 +343183,7 @@
          []
         ],
         "opener-yes-openee-no-port.sub.https.html.ini": [
-         "6cfbabff6796ee5a36819a9e2bbbd64e655f33e4",
+         "8af48a347d2cec4f9a92c050c5b344494f1e6967",
          []
         ],
         "opener-yes-openee-no-same.sub.https.html.headers": [
@@ -343193,7 +343191,7 @@
          []
         ],
         "opener-yes-openee-no-same.sub.https.html.ini": [
-         "6919e10c6ae8df3a65ce7c09296382794df7cb9f",
+         "053a0b74c9f0692fea76477f8f8ad74481baa651",
          []
         ],
         "opener-yes-openee-no-subdomain.sub.https.html.headers": [
@@ -343201,7 +343199,7 @@
          []
         ],
         "opener-yes-openee-no-subdomain.sub.https.html.ini": [
-         "9c5a85f028021da104891c7fbffea885952a13d9",
+         "83fcc1fe1ce693d1b36c9ca3daef9ab38cb52aa6",
          []
         ],
         "opener-yes-openee-yes-port.sub.https.html.headers": [
@@ -343209,7 +343207,7 @@
          []
         ],
         "opener-yes-openee-yes-port.sub.https.html.ini": [
-         "91c6bca92c3a2f66e39f091128a5d51c0a54c58b",
+         "e1431348cca8f106345fbafd820354e60e87f00c",
          []
         ],
         "opener-yes-openee-yes-same.sub.https.html.headers": [
@@ -343217,7 +343215,7 @@
          []
         ],
         "opener-yes-openee-yes-same.sub.https.html.ini": [
-         "ae30272e16741a04ec38ea7fca8b9b00b17fcf81",
+         "776bd28755764c4232add0141ec9cdbf173c2620",
          []
         ],
         "opener-yes-openee-yes-subdomain.sub.https.html.headers": [
@@ -343225,7 +343223,7 @@
          []
         ],
         "opener-yes-openee-yes-subdomain.sub.https.html.ini": [
-         "b6c7af36b692956d4f7d28443cd2f1ee871cc947",
+         "5ec40809a53c4531066a5390fc579f9179351a42",
          []
         ]
        },
@@ -343234,7 +343232,7 @@
         []
        ],
        "removing-iframes.sub.https.html.ini": [
-        "5557c8037c1bce363242d51ab413f6660d1eb2b8",
+        "be224fc4ad929f09cc49d701818ed8ebe84ff400",
         []
        ],
        "resources": {
@@ -343580,7 +343578,7 @@
         ]
        },
        "open-features-is-popup-condition.html.ini": [
-        "af7186ed756cf5a08b77aeba2d0703bf7caeeebe",
+        "bd8e1e949fb4adcb4d9e53f2bf170e9231f1fdfc",
         []
        ],
        "open-features-negative-innerwidth-innerheight.html.ini": [
@@ -343632,7 +343630,7 @@
         []
        ],
        "open-features-non-integer-screeny.html.ini": [
-        "980af6d6ee0ccccf181fba485215d64563ec2b4f",
+        "2fbad0dd12c4027691d6194f54a3c83c1bc4651a",
         []
        ],
        "open-features-non-integer-top-expected.txt": [
@@ -343644,11 +343642,7 @@
         []
        ],
        "open-features-non-integer-width.html.ini": [
-        "497b762e34d0b5838aa953a72c8a47f3a366e50f",
-        []
-       ],
-       "open-features-tokenization-innerheight-innerwidth.html.ini": [
-        "646e2a2a5f3a2712dae2be6b6a4b27cd508ea2b8",
+        "bb49dcd395b91a38064c5df2f64e9142acfeec05",
         []
        ],
        "open-features-tokenization-screenx-screeny-expected.txt": [
@@ -343664,7 +343658,7 @@
         []
        ],
        "open-features-tokenization-top-left.html.ini": [
-        "d713e6c8ab3b052836f33ea32c3f72a2fe0aa935",
+        "a5ba4c24deabf5feac62e046e01bf9f663a60048",
         []
        ],
        "open-features-tokenization-width-height.html.ini": [
@@ -343744,10 +343738,6 @@
        "8279047ce6df44c2ad11907145d79379a810bb5d",
        []
       ],
-      "window-open-popup-behavior.html.ini": [
-       "892817e38fb1b2bf0f9d9f100519ab5e8d59ee9a",
-       []
-      ],
       "window-open-windowfeatures-values.html.ini": [
        "d9e0e4f30172d211e80db333678752d7aedbe94b",
        []
@@ -345018,7 +345008,7 @@
           []
          ],
          "canvas-filter-object-turbulence.html.ini": [
-          "af2297cd032e5fc33c8ed4c21468764279bc7a04",
+          "64be7110e67eac2c7834a43514d9090fecd9343a",
           []
          ],
          "idl-conversions": {
@@ -345271,7 +345261,7 @@
          []
         ],
         "canvas-display-p3-drawImage-video.html.ini": [
-         "76b154ac1ad111a1db36648b7fda9ba36b0b87d8",
+         "311dd8ddbbb5a22b425414cc223647d45ba7e4e9",
          []
         ],
         "canvas-display-p3-drawImage.https-expected.txt": [
@@ -345832,7 +345822,7 @@
       },
       "fill-and-stroke-styles": {
        "2d.pattern.paint.repeat.basic.html.ini": [
-        "59c6d7d3f9c14d3dd9470bb82563a12804617949",
+        "1f019e8689b6eb34c6a4fe377c9721098a5835bb",
         []
        ],
        "2d.pattern.paint.repeat.outside.html.ini": [
@@ -345857,7 +345847,7 @@
          []
         ],
         "offscreencanvas.resize.html.ini": [
-         "763b2bf7bc28e6c00a644809f64394df19b53119",
+         "06d83dce689b6519ba5740ea3bebd100c7fe93da",
          []
         ],
         "offscreencanvas.transferrable-expected.txt": [
@@ -346386,10 +346376,6 @@
        "4698ae9917a3b8e7ae291824405fdc4125b958fc",
        []
       ],
-      "fetch.https.window.js.ini": [
-       "3b8a30b9f6d968dc579fc5b2bd03d47ceae6e628",
-       []
-      ],
       "iframe-coep-credentialless.https.window.js.ini": [
        "717be1887333e1b6d198cad9571380ceb28eb30d",
        []
@@ -346564,7 +346550,7 @@
       []
      ],
      "reporting-navigation.https.html.ini": [
-      "360865ceec1c5218f7bd40e25db3317e21c229e0",
+      "a972216ca77f1070a43ad3e90c6894a33f172eed",
       []
      ],
      "reporting-subresource-corp.https-expected.txt": [
@@ -346859,10 +346845,6 @@
       "63b60e490f47f4db77d33d7a4ca2f5b9a4181de8",
       []
      ],
-     "coep-with-same-site.https.html.ini": [
-      "7938d8f2b665e7fc8bbf947af158948991ed4210",
-      []
-     ],
      "coop-coep-sandbox.https.html.headers": [
       "4fff9d9fba4c81f953826ffea010a75be626b95d",
       []
@@ -346879,10 +346861,6 @@
       "23d80f798b7a26ee2c86d2ec028204d1db95e3dc",
       []
      ],
-     "coop-navigate-same-origin-csp-sandbox.html.ini": [
-      "a7102153e9b504a74092eb3b3075f8a48e116557",
-      []
-     ],
      "coop-navigated-history-popup.https.html.ini": [
       "839081c700e738be0b295a919da598796d93157b",
       []
@@ -346904,25 +346882,17 @@
       []
      ],
      "header-parsing-failures.https.html.ini": [
-      "21617c90867560582db3bb00b67c7ff85aed515a",
+      "52441529c66f8c38c4f869dede363a1dd69ca43d",
       []
      ],
      "header-parsing-non-ascii.https.html.headers": [
       "54e44a7113def0babd42f726c878fc90db2e99f9",
       []
      ],
-     "header-parsing-non-ascii.https.html.ini": [
-      "fdad5f372d471cabc1c7323fb898008931d09d70",
-      []
-     ],
      "header-parsing-repeated.https.html.headers": [
       "85c58be8a1c60ed64b2efaed8a155fc5e087537e",
       []
      ],
-     "header-parsing-repeated.https.html.ini": [
-      "0ff031216698bcc77afe7110f069d5f7d0fd27e9",
-      []
-     ],
      "historical": {
       "popup-same-origin-unsafe-allow-outgoing-with-cross-origin.https.html.headers": [
        "a19f4400cea33a60c99807330704a23ee363b146",
@@ -346937,7 +346907,7 @@
        []
       ],
       "popup-same-origin-unsafe-allow-outgoing-with-same-origin.https.html.ini": [
-       "6095039701b3ae4114a122f88d33f0a291771c10",
+       "0dbd28d2424042e2d2ababfedc49e07f00f97e32",
        []
       ],
       "popup-same-origin-unsafe-allow-outgoing-with-same-site.https.html.headers": [
@@ -346945,7 +346915,7 @@
        []
       ],
       "popup-same-origin-unsafe-allow-outgoing-with-same-site.https.html.ini": [
-       "d9c553b3661a59a30f77a03f180e580f1bb5b69e",
+       "a39425e4f08a1b98febdbd6ad084b80945d2b93c",
        []
       ],
       "popup-same-site-unsafe-allow-outgoing-with-cross-origin.https.html.headers": [
@@ -346990,7 +346960,7 @@
       []
      ],
      "iframe-popup-same-origin-allow-popups-to-same-origin-allow-popups.https.html.ini": [
-      "4963b2f3da43a5479e578684597043ae550ea2d3",
+      "c563da96ae7db292b99ebc70c87b9edccad35854",
       []
      ],
      "iframe-popup-same-origin-allow-popups-to-same-origin.https.html.headers": [
@@ -346998,7 +346968,7 @@
       []
      ],
      "iframe-popup-same-origin-allow-popups-to-same-origin.https.html.ini": [
-      "249776d5e935bdd0408bc4a4efb23ee712d28c60",
+      "9efa1fc26fa5a594910ac58e0ea82acd38f951dd",
       []
      ],
      "iframe-popup-same-origin-allow-popups-to-unsafe-none.https.html.headers": [
@@ -347006,7 +346976,7 @@
       []
      ],
      "iframe-popup-same-origin-allow-popups-to-unsafe-none.https.html.ini": [
-      "a82ac75288fa958187916d7adbd091663311be06",
+      "4af327b4dcff11a7d9c3a5cd3cc1d470c0fcf53a",
       []
      ],
      "iframe-popup-same-origin-to-same-origin.https.html.headers": [
@@ -347030,7 +347000,7 @@
       []
      ],
      "iframe-popup-unsafe-none-to-same-origin.https.html.ini": [
-      "69ae4a6f25dcd6dfe7ac2e70c96154a4c58f551d",
+      "0412b32433d27e3540de089c24cbd97d70c41a17",
       []
      ],
      "iframe-popup-unsafe-none-to-unsafe-none.https.html.headers": [
@@ -347038,11 +347008,11 @@
       []
      ],
      "iframe-popup-unsafe-none-to-unsafe-none.https.html.ini": [
-      "3deb888f6a7785ad9af9dac239d60e1473bb47d5",
+      "c1f50620461237a83c2f199dfa2b83c85c300407",
       []
      ],
      "javascript-url.https.html.ini": [
-      "bad4145fd793af38d26fc628ec75c8730ecc51b0",
+      "232f5c10881fb2ba8330affea639ffcafc9a9caa",
       []
      ],
      "navigate-to-aboutblank.https.html.ini": [
@@ -347050,27 +347020,19 @@
       []
      ],
      "navigate-top-to-aboutblank.https.html.ini": [
-      "d5c6b7629520bbf8969208c96e72707a0ef0454e",
+      "1aeca853cfa3c55b386ca9cb36493b699d321c2b",
       []
      ],
      "no-https.html.headers": [
       "46ad58d83bf6e98913ca4c564b7acb8f19fa0093",
       []
      ],
-     "popup-meta-http-equiv.https.html.ini": [
-      "4dcab80a4e0a7c541f3fb0430d498b5017866b16",
-      []
-     ],
      "popup-redirect-cache.https.html.headers": [
       "46ad58d83bf6e98913ca4c564b7acb8f19fa0093",
       []
      ],
      "popup-redirect-cache.https.html.ini": [
-      "46717b7eb11bbad1d49f06917b847bcab6a1fe03",
-      []
-     ],
-     "popup-redirect-same-origin-allow-popups.https.html.ini": [
-      "4cc8d43391fcd469555c9dcc045d76c782bf09eb",
+      "cc11c621ff2321b6cbf0e20325a2ff4666eb2436",
       []
      ],
      "popup-same-origin-allow-popups-with-cross-origin.https.html.headers": [
@@ -347081,6 +347043,10 @@
       "d83ed86fb9b5d159b9f380424887402edc96cb75",
       []
      ],
+     "popup-same-origin-allow-popups-with-same-origin.https.html.ini": [
+      "b3e0ea1fad38500a0a2b30a6481ee6e87daead9b",
+      []
+     ],
      "popup-same-origin-allow-popups-with-same-site.https.html.headers": [
       "d83ed86fb9b5d159b9f380424887402edc96cb75",
       []
@@ -347097,18 +347063,22 @@
       "46ad58d83bf6e98913ca4c564b7acb8f19fa0093",
       []
      ],
+     "popup-same-origin-with-same-origin.https.html.ini": [
+      "817cd70b3ddfb062864c8a571da9f0020743a05b",
+      []
+     ],
      "popup-same-origin-with-same-site.https.html.headers": [
       "46ad58d83bf6e98913ca4c564b7acb8f19fa0093",
       []
      ],
-     "popup-same-origin-with-same-site.https.html.ini": [
-      "efa88bcf39bc8e49c23bad6caadd6ff1d05d2297",
-      []
-     ],
      "popup-unsafe-none-with-cross-origin.https.html.headers": [
       "073ce7adfbd81cb7c0b2f91f96c8349b6677f26c",
       []
      ],
+     "popup-unsafe-none-with-cross-origin.https.html.ini": [
+      "1693ee1d806331a9a4ef3e315e8d0108b817346f",
+      []
+     ],
      "popup-unsafe-none-with-same-origin.https.html.headers": [
       "073ce7adfbd81cb7c0b2f91f96c8349b6677f26c",
       []
@@ -347118,15 +347088,15 @@
       []
      ],
      "popup-unsafe-none-with-same-site.https.html.ini": [
-      "604de218d0bb79bd663522c70ec31d106a271e02",
+      "c087e20995b049d95a5478c10ced52f7f2ee2b68",
       []
      ],
      "popup-unspecified-with-cross-origin.https.html.ini": [
-      "6f1e872520590723fb96d2c67837a02d78f18977",
+      "856b722020bffd785541783f9f67d5fbede0ece7",
       []
      ],
-     "popup-unspecified-with-same-origin.https.html.ini": [
-      "0d2dc3b16bd511d0412a206007cdf2a888350dab",
+     "popup-unspecified-with-same-site.https.html.ini": [
+      "1819e214ca5210f364421e5164802f7d6637b209",
       []
      ],
      "popup-with-structured-header.https.html.headers": [
@@ -347134,7 +347104,7 @@
       []
      ],
      "popup-with-structured-header.https.html.ini": [
-      "6da6ff1fb621440715858cf87aa8bc554cdd2c0f",
+      "b824bdd45c1be17dc4c7d5fa52416f0562d703a4",
       []
      ],
      "reporting": {
@@ -347144,11 +347114,11 @@
       ],
       "access-reporting": {
        "access-from-coop-page-to-openee_coop-ro.https.html.ini": [
-        "0ee8233d691420e013bdda7f4c3b46472979f854",
+        "4ca363c7fe04cdbcceba5b8f932f804456ded41c",
         []
        ],
        "access-from-coop-page-to-openee_coop-ro_cross-origin.https.html.ini": [
-        "e85ff7282f33acb9edc3d317368f7163743505b8",
+        "c525d52f14f5dc4556b20fd1965377e84ca1469b",
         []
        ],
        "access-from-coop-page-to-opener_coop-ro.https.html.ini": [
@@ -347168,15 +347138,15 @@
         []
        ],
        "access-to-coop-page-from-openee_coop-ro.https.html.ini": [
-        "9945127a1697b0e64a2a230f6b577bda3408e732",
+        "45761bcac8beb541cddf6110a9432b612089da0b",
         []
        ],
        "access-to-coop-page-from-openee_coop-ro_cross-origin.https.html.ini": [
-        "a609388561b9a0d87902cecb4a1bef2c20277b53",
+        "f90dfadf0031050388abab28128b4c575ee0b842",
         []
        ],
        "access-to-coop-page-from-opener_coop-ro.https.html.ini": [
-        "235fd40a5cfe8e609d8dfb144ed164bbe57ab3fb",
+        "cde27b4c14b78933da042eb61dbdf389002521c5",
         []
        ],
        "access-to-coop-page-from-opener_coop-ro_cross-origin.https.html.ini": [
@@ -347184,7 +347154,7 @@
         []
        ],
        "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": [
@@ -347192,7 +347162,7 @@
         []
        ],
        "property-blur.https.html.ini": [
-        "15edb0a3073414558d7dc85ef08a6084f746d4db",
+        "9bb724af3d93878ae49888c2ca5ccad79fcbaf48",
         []
        ],
        "property-close.https.html.ini": [
@@ -347204,11 +347174,11 @@
         []
        ],
        "property-focus.https.html.ini": [
-        "3c5b98eaf088f8b1eceebd6f111a3e5e496c560c",
+        "2db32f1edef3c5c1def240fb6fa5fbf980b5e42b",
         []
        ],
        "property-frames.https.html.ini": [
-        "01f4fcd2960d85861b72c469942031529268ec2f",
+        "bba3c339f8681499c4686acfdcf4cb1c2b2d33fc",
         []
        ],
        "property-indexed-getter.https.html.headers": [
@@ -347220,15 +347190,15 @@
         []
        ],
        "property-length.https.html.ini": [
-        "20d6b2365f8b4923966dc04baee0b70e9f004ed3",
+        "adac8732a3e22ead8ec3bcd459996e33d0182d61",
         []
        ],
        "property-location-get.https.html.ini": [
-        "205cfdd37a72f81f2e9bea29700a48f4e9c9e4b1",
+        "e48075ce4e2a4af8072fae88e9b06b515a8a9ea5",
         []
        ],
        "property-location-set.https.html.ini": [
-        "2f7117844e127f6a83ab378339e2027d18eea311",
+        "e016cf9c67e1853eefcc7da328877d3d0866029c",
         []
        ],
        "property-named-getter.https.html.headers": [
@@ -347252,19 +347222,19 @@
         []
        ],
        "property-postmessage-2.https.html.ini": [
-        "426cf305bd7453933de82985822e531bebd9958c",
+        "586bba13313b39313f8fbebcc6071a2c38596100",
         []
        ],
        "property-self.https.html.ini": [
-        "911a48fe0d6eaeb845e1ec91e968d70a1ba6b4f2",
+        "189215bc7f4f6a65585c207e1ea409f9b0320ac5",
         []
        ],
        "property-top.https.html.ini": [
-        "e3a7586a247307c588eb7e9c9a3cdb75dbe2b04c",
+        "86f71d5893d8e032d15760e6ac85681db9a1350a",
         []
        ],
        "property-window.https.html.ini": [
-        "799db67cf15e60af5be3156b0c11c7bb738c4426",
+        "78ab09d6a8d589bf1883847508b9769c9cd037dc",
         []
        ],
        "report-to-both_coop-ro.https.html.ini": [
@@ -347286,15 +347256,15 @@
         []
        ],
        "report-to-both_coop-ro.https.html.ini": [
-        "46d3e2453d8b141994297fa9ca23abea51bbb623",
+        "cfda1f96c55cd572eb1ee67fd74a62182fdeb79d",
         []
        ],
        "reporting-redirect-with-same-origin-allow-popups.https.html.ini": [
-        "18bb1f2390bffd060cf2e565cb466a01b64357b2",
+        "80bec0a81f7a9d7d09671ee611d5694ba88b57c3",
         []
        ],
        "reporting-redirect-with-unsafe-none.https.html.ini": [
-        "7b11492b982a5f967e17720d55c7e546173d1e25",
+        "f6002819e54c01078fa964d9f2565d8801071f6b",
         []
        ]
       },
@@ -347412,7 +347382,7 @@
       }
      },
      "resource-popup.https.html.ini": [
-      "6772889870836969ff235a33bc865209edc7fbb6",
+      "a51cce9644d598a63940893a19044588125aab23",
       []
      ],
      "resources": {
@@ -347496,7 +347466,7 @@
         []
        ],
        "iframe-popup-to-soap.https.html.ini": [
-        "9311679589c79eb9c3b7a6756121044bee700977",
+        "f8661d582e1632d4967a02fc2a63c594f5c87a44",
         []
        ],
        "iframe-popup-to-un.https.html.headers": [
@@ -347571,10 +347541,6 @@
         "46ad58d83bf6e98913ca4c564b7acb8f19fa0093",
         []
        ],
-       "popup-so.https.html.ini": [
-        "463b52a78e56cc78018b26cc440fe9457a27121d",
-        []
-       ],
        "popup-soap.https-expected.txt": [
         "8c40e7b3b1e288546cc4f2a9a739c4ada36e2df0",
         []
@@ -347604,7 +347570,7 @@
         []
        ],
        "popup-un.https.html.ini": [
-        "3a961ac1793866af69d3bc770cf36c507b7a11ea",
+        "3825ee4b58097e7262bc7d1e1cff1fcc0684f5fa",
         []
        ],
        "popup-with-cross-origin.https-expected.txt": [
@@ -347704,7 +347670,7 @@
         []
        ],
        "document-cookie.html.ini": [
-        "87ed3754a09930097225b085f7f8528dd5256968",
+        "4bbf824cad421323c92858302f0c08cc58fd0bb9",
         []
        ],
        "document-lastModified.html.headers": [
@@ -348197,7 +348163,7 @@
      ],
      "render-blocking": {
       "parser-inserted-async-script.tentative.html.ini": [
-       "fdd5875612bea98ead2805b8abb4e4b78c658752",
+       "430f7e9d060fbe52117e285478cf2630547f96f8",
        []
       ],
       "remove-attr-script-keeps-blocking.tentative.html.ini": [
@@ -348205,11 +348171,7 @@
        []
       ],
       "script-inserted-module-script.tentative.html.ini": [
-       "d44d37c17eece38b93cbbe0bcee1abd26cc50c4e",
-       []
-      ],
-      "script-inserted-script.html.ini": [
-       "ead65bc24dceaea549524c8c86703d2914535e42",
+       "f99eaff02bdab091261741486d47ef8ed1624fd0",
        []
       ],
       "support": {
@@ -352062,7 +352024,7 @@
         ]
        },
        "spin-by-blocking-style-sheet.html.ini": [
-        "00570c373aca5ce1f4427800af219acd089ffda4",
+        "a197e599d7ad4625823b89923332040c0c30d315",
         []
        ],
        "update-the-rendering.html.ini": [
@@ -353853,7 +353815,7 @@
          []
         ],
         "resource-selection-invoke-audio-constructor.html.ini": [
-         "c3afabdba66cec6bdd9775973e8424a22449f487",
+         "832554d322a83d49960e5586a1b22eb166cf8708",
          []
         ],
         "resource-selection-invoke-in-sync-event-expected.txt": [
@@ -353873,11 +353835,11 @@
          []
         ],
         "resource-selection-invoke-insert-source-not-in-document.html.ini": [
-         "39ff443e34ab057e6b8a2a7ca81fb5930fb2789d",
+         "3829b48f202acb68af288d247d939330120d0793",
          []
         ],
         "resource-selection-invoke-insert-source.html.ini": [
-         "e410f1248d74939a401973f7e2164d26fbdd07b4",
+         "b9e47853f8f672609ae70204e6051675a51d8f81",
          []
         ],
         "resource-selection-invoke-load.html.ini": [
@@ -353885,7 +353847,7 @@
          []
         ],
         "resource-selection-invoke-pause-networkState.html.ini": [
-         "25cb22e2354a4a62aa7664f5652ce4185a6af0b5",
+         "e889ab762e3f0df906ff3f35139c60e0c4a89904",
          []
         ],
         "resource-selection-invoke-pause.html.ini": [
@@ -353900,8 +353862,12 @@
          "33e2bbbf2db5f400c6b95c9f46e33d3e663a43c5",
          []
         ],
+        "resource-selection-invoke-remove-src.html.ini": [
+         "ed1c736bede1a0394bb074d8a569ebe242447e94",
+         []
+        ],
         "resource-selection-invoke-set-src-not-in-document.html.ini": [
-         "9ba4e89b183fd7b50490489051e7294eeff948f6",
+         "f899a9366be9f983fbc89724f1d069187f2a455e",
          []
         ],
         "resource-selection-invoke-set-src.html.ini": [
@@ -354384,7 +354350,7 @@
           []
          ],
          "track-cue-rendering-after-controls-removed.html.ini": [
-          "0b0196140f96a07b5365b3283622df28e160e592",
+          "dc0f14724d666376d7aad5815c85261e8e0ce6ac",
           []
          ],
          "track-cue-rendering-line-doesnt-fit-ref.html": [
@@ -354846,7 +354812,7 @@
         []
        ],
        "sandbox-top-navigation-child-special-cases.tentative.sub.window.js.ini": [
-        "f9911a23d4a342e19aaa2faf1ffeccc719fc3749",
+        "142c71cae926a9342206d8c6f1e0b1eb8868ad75",
         []
        ],
        "sandbox-top-navigation-child.tentative.sub.window.js.ini": [
@@ -354854,11 +354820,15 @@
         []
        ],
        "sandbox-top-navigation-escalate-privileges.tentative.sub.window.js.ini": [
-        "97ef093ef87c260edde06ebe1fb0aed548542ea3",
+        "51b5920089b5c879430e9c8c220ebfefcd733e34",
         []
        ],
        "sandbox-top-navigation-grandchild.tentative.sub.window.js.ini": [
-        "0f880d19a60c4a6828e6646a4ffe8c3be47f1fb8",
+        "f6d097fe095955bb078b69bde166b123ba27c40a",
+        []
+       ],
+       "sandbox_026.htm.ini": [
+        "882568f40068b809e3b97c1b8c00cd372d35e6cb",
         []
        ],
        "stash.py": [
@@ -355134,7 +355104,7 @@
         []
        ],
        "image-loading-lazy-base-url-2.html.ini": [
-        "2e3fbd978f5bd3b40547ee704387081df3fc15fa",
+        "b0363e4de7578bd60156bcdc1d7a525b8227181a",
         []
        ],
        "image-loading-lazy-base-url-expected.txt": [
@@ -355560,7 +355530,7 @@
         []
        ],
        "urlencoded2.window.js.ini": [
-        "7b41c1dce21ba402aa40631b1130bdcdb7fe9649",
+        "f3533e60e710331c864e6dfde3ce03aef932f62f",
         []
        ]
       },
@@ -355573,18 +355543,10 @@
         "bbc3b71e9423b6a17b07c065e20b8435e4c492f4",
         []
        ],
-       "rel-base-target.html.ini": [
-        "790eba9e3b58b3a4bd400cd41bb618f8975f6765",
-        []
-       ],
        "rel-form-target.html.ini": [
         "eae93147204be11623d1f15212d71d5b6430bd23",
         []
        ],
-       "rel-input-target.html.ini": [
-        "b9b05574948bf95f127acf31b949cef46a71e430",
-        []
-       ],
        "resources": {
         "endpoint.html": [
          "be9e7942927dabeea32bf9e17b88d6643bc4ea91",
@@ -355902,7 +355864,7 @@
         []
        ],
        "selectmenu-form-state-restore.tentative.html.ini": [
-        "6a35a5d5a063d07e24ff6725306f7a87724b7cb3",
+        "961645cc8e91587c5d74af8275f23c5e9f4f7e67",
         []
        ],
        "selectmenu-keyboard.tentative.html.ini": [
@@ -356310,7 +356272,7 @@
         []
        ],
        "activation-behavior.window.js.ini": [
-        "b60fec3891157546b9ea1c3b84bf3d3047af6a7f",
+        "4f7ebf54fcf9d301a315d60a253b53d373ee6f49",
         []
        ]
       },
@@ -360301,7 +360263,7 @@
          []
         ],
         "promise-job-entry.html.ini": [
-         "64a96d3e6e2abf366fcfd157a96821d28aa6fba3",
+         "c7de4281de4df6272942ff189c6e155bb45682f9",
          []
         ],
         "promise-job-incumbent-expected.txt": [
@@ -360501,6 +360463,12 @@
        ]
       }
      },
+     "timers": {
+      "negative-settimeout.any.js.ini": [
+       "4160c845ca7aee77220a770b8df3d5d577c1b51e",
+       []
+      ]
+     },
      "update-rendering": {
       "child-document-raf-order-expected.txt": [
        "f9ba495c5a66c946d32656087abe29b6b7e83097",
@@ -360607,7 +360575,7 @@
      []
     ],
     "idle-detection-allowed-by-permissions-policy.https.sub.html.ini": [
-     "f6cc69da3ffc659493cd3096afde6da2c36f5844",
+     "6f363c189c39ce8e2921eb7be18b2a9a306423f7",
      []
     ],
     "idle-detection-default-permissions-policy.https.sub.html.ini": [
@@ -361686,7 +361654,7 @@
       []
      ],
      "webtransport-h3.https.sub.any.js.ini": [
-      "b8a3be552b3cf971813a22fee5efa5d138def973",
+      "bd9c4f877884896eb35aa2401c2fdd05a8acebf3",
       []
      ]
     },
@@ -363073,7 +363041,7 @@
      []
     ],
     "cross-origin-iframe.sub.html.ini": [
-     "0558ad8a3a16b6d52d32ec138aed6da0d64dd11f",
+     "b1797526eb84e7c420eadc7c8f00e180d684f177",
      []
     ],
     "idlharness.window-expected.txt": [
@@ -363510,7 +363478,7 @@
    "loading": {
     "early-hints": {
      "404-with-early-hints.h2.window.js.ini": [
-      "d1b88bddce64f1519a39f4b4475dff8842a4f5cc",
+      "e96503568885d864816c244fa3417d7b8c65eb56",
       []
      ],
      "arbitrary-header-in-early-hints.h2.window.js.ini": [
@@ -363558,7 +363526,7 @@
       []
      ],
      "csp-early-hints-disallowed-final-disallowed.h2.window.js.ini": [
-      "2aa08d2c04abd9bcf012352980a3e80d97d9b583",
+      "3e116223aecd0b524ef6af7118a31a9c70420c49",
       []
      ],
      "iframe-coep-disallow.h2.html.headers": [
@@ -363586,7 +363554,7 @@
       []
      ],
      "preload-in-flight-when-consumed.h2.window.js.ini": [
-      "426ffabfb947d4c1f5760a11da7de52090eecc8d",
+      "1cff5a1fb1635a5b29795e16f4dd8832332eedaf",
       []
      ],
      "preload-initiator-type.h2.window.js.ini": [
@@ -363876,10 +363844,6 @@
      "b4ede0575b1284b5c4fb3145caf471b6f978e629",
      []
     ],
-    "longtask-in-sibling-iframe-crossorigin.html.ini": [
-     "05e26df33cc59c0c79a55f56eaf07aa24cac99d8",
-     []
-    ],
     "resources": {
      "makelongtask.js": [
       "75de5453b5856deee20188afabee6e69f8426cb7",
@@ -364361,7 +364325,7 @@
        []
       ],
       "operator-dictionary-arabic-002.html.ini": [
-       "f0fa72f41bfa4a4f79b8af912e2e1b3857c5b907",
+       "97bb31e44c4c92de9880a9cec391ea86b81ff466",
        []
       ],
       "operator-dictionary-empty-and-three-chars-ref.html": [
@@ -364587,7 +364551,7 @@
        ]
       },
       "ignored-properties-001.html.ini": [
-       "2dbc02cf57d717daed98efb983b6bbe52098596c",
+       "ebd26616781caf806af4f87917b6967488c82f58",
        []
       ],
       "legacy-scriptminsize-attribute-ref.html": [
@@ -364602,6 +364566,10 @@
        "9fca6f49632ca080ee1b2a32a9ce2d251241dfcc",
        []
       ],
+      "lengths-2.html.ini": [
+       "6da6b90c05c88283b4bab3908ad299a5814e3a01",
+       []
+      ],
       "mathbackground-001-notref.html": [
        "65e2781c5e13ac75127703b2b7a601882b7a9b02",
        []
@@ -365647,7 +365615,7 @@
      []
     ],
     "mediasource-avtracks.html.ini": [
-     "580d06995a4d161a4c069feb01061cc33728190f",
+     "fe1dd281e1026dee5a4aaad715aedb72aad38e44",
      []
     ],
     "mediasource-buffered-expected.txt": [
@@ -365719,7 +365687,7 @@
      []
     ],
     "mediasource-duration.html.ini": [
-     "6c3d571c6457e9d1acaa45d91ac506cab4780209",
+     "362786749a60ce8a682ac18c2bf511d3ee0044d3",
      []
     ],
     "mediasource-endofstream-expected.txt": [
@@ -365727,7 +365695,7 @@
      []
     ],
     "mediasource-endofstream.html.ini": [
-     "eb2f72db20e269e593f8790db2f3821f655ac224",
+     "da1986cfb03d9426b771aa161d6229506ce30f5b",
      []
     ],
     "mediasource-invalid-codec.html.ini": [
@@ -367011,7 +366979,7 @@
      ]
     },
     "detach_iframe_during_open.https.window.js.ini": [
-     "9621dd612e5bf10a16c68fbb88bcdd1ebe58438e",
+     "81430e82c04b2a3202215ec257e91ee933a73259",
      []
     ],
     "resources": {
@@ -367069,6 +367037,10 @@
      ]
     },
     "focus-reset": {
+     "change-focus-then-remove-during-intercept.html.ini": [
+      "a22054980eaa5c4b7ee1d36cb25f5a4c42dad740",
+      []
+     ],
      "resources": {
       "helpers.mjs": [
        "0a8a0439e1c885fdf263da1ecc74bcbc304b35a0",
@@ -367345,7 +367317,7 @@
        []
       ],
       "navigate-initial-about-blank.html.ini": [
-       "53ea8ed367d9a62ef6a52253ccc1ee8d532b3328",
+       "0adc9d25d34e98f89c4e1f5c0d4fc93353f67e81",
        []
       ],
       "navigate-intercept-interrupted.html.ini": [
@@ -367476,7 +367448,7 @@
     },
     "scroll-behavior": {
      "after-transition-intercept-handler-modifies.html.ini": [
-      "61cb1657f2ae6ad5810ee5721301e6c25fbb872a",
+      "411718d4f69c535ee3832109bafba1326a81bd41",
       []
      ]
     },
@@ -367623,7 +367595,7 @@
      ]
     },
     "test-performance-attributes.sub.html.ini": [
-     "6b901ee96143c8de34d5692e780cc060c5e2e450",
+     "45c94f0b636fb67be47bc2ed2e58f04d5d854ce1",
      []
     ]
    },
@@ -368399,7 +368371,7 @@
      []
     ],
     "pending_beacon-sendondiscard.tentative.https.window.js.ini": [
-     "e569d9aa092ed81de41bae1ac726d9f08cc97061",
+     "cd98792b5921f05fc98469853e4b72c970dd08b4",
      []
     ],
     "pending_beacon-sendonhidden.tentative.https.window.js.ini": [
@@ -368492,7 +368464,7 @@
       []
      ],
      "performance-navigation-timing-same-origin-bfcache.window.js.ini": [
-      "ce013cd60e461f81fb566a4dca12b129fb259288",
+      "891fe82e7b26ca18470ceab69b4407aed9b13d0a",
       []
      ],
      "test-helper.js": [
@@ -368588,6 +368560,10 @@
      "909bd793378b957d40a78e86d8b568f8b3a45457",
      []
     ],
+    "permissions-garbage-collect.https.html.ini": [
+     "93acc408add19b573667f62de7a067a7c46da024",
+     []
+    ],
     "permissions-query-feature-policy-attribute.https.sub-expected.txt": [
      "b3a521320e8acb70c2f2199d608d4bd3379934e0",
      []
@@ -368715,6 +368691,10 @@
       "a54ad04c8585af431bd123c07479959332908ee2",
       []
      ],
+     "unload-allowed-by-default.tentative.window.js.ini": [
+      "041aee22275f57b2ff32f9481e29fe1d43f9fa63",
+      []
+     ],
      "vertical-scroll-main-frame-manual.tentative.html.headers": [
       "8d9c01e14835acbc0af74b5b9157a4a8b95243f8",
       []
@@ -372082,6 +372062,10 @@
      "2c234a543927877ad35b1dc5d40c115f745149a3",
      []
     ],
+    "callback-invoked.html.ini": [
+     "da0f2fae4a7cb272d752c4da123c9865cb86c0bf",
+     []
+    ],
     "callback-suspended.html.ini": [
      "7b01deb5f1599b627c7d84ce9da5d68d88181899",
      []
@@ -372110,12 +372094,16 @@
      "fc00d2e27e8fe14c0bf9988886f23467019a7da7",
      []
     ],
+    "deadline-max-rAF-dynamic.html.ini": [
+     "a3741db8a2ddde7857506d5dd8e735ac09686821",
+     []
+    ],
     "deadline-max-rAF.html.ini": [
-     "d24dbbff5b5c93a1cd4e4e58bf590c11511b032d",
+     "c2a9bbc2d2bfc59f1c6b4b8823275c23b7419994",
      []
     ],
     "deadline-max-timeout-dynamic.html.ini": [
-     "ccb80838bac1714b9f0f3d8f885f7041b48a4d80",
+     "960c1ca90fcd104ba5ca057ea87e3748c9cf863c",
      []
     ],
     "deadline-max.html.ini": [
@@ -372258,6 +372246,10 @@
      "33006cf002b9b9c3f4fb4c4757916052ae12fe92",
      []
     ],
+    "nested-context-navigations-iframe.html.ini": [
+     "3ca68dd96ae35f66e41bdc956f33999979d38ea0",
+     []
+    ],
     "no-entries-for-cross-origin-css-fetched-memory-cache.sub-expected.txt": [
      "9c172388cd5a0351593fc8dedb00168579aca645",
      []
@@ -372266,6 +372258,10 @@
      "e70c84d000d39ef8875f4d33ae97d692b2c2c615",
      []
     ],
+    "object-not-found-after-cross-origin-redirect.html.ini": [
+     "e13c217beef679f734ed68c67f70e471be95a3e4",
+     []
+    ],
     "ping-rt-entries-expected.txt": [
      "9655aed4059d9f60b88d16dac3b03c05a39f15af",
      []
@@ -372282,6 +372278,10 @@
      "3eaed3a93af01991d48976f0b3c916e504813866",
      []
     ],
+    "resource_timing.worker.js.ini": [
+     "6a6e5c2d46aa831248a07e3aa326707c4da9ffaf",
+     []
+    ],
     "resources": {
      "200.https.asis": [
       "5b7c25f4ca03a20660506fa4a1f965e7cf633618",
@@ -372657,7 +372657,7 @@
      ]
     },
     "response-status-code.html.ini": [
-     "6babe41904c54587181da9ac25009bcd30124ee8",
+     "8d5241ad8c20da100fb567898a5742fe199ee283",
      []
     ],
     "sleep.py": [
@@ -374581,12 +374581,16 @@
       "82c8165c34f3df1366bf49099aa5d75b79c59e7e",
       []
      ],
+     "cache-abort.https.any.js.ini": [
+      "d6cfd5df8bd5d92b6be1cb1742e56ac720b0bd27",
+      []
+     ],
      "cache-add.https.any-expected.txt": [
       "3d82496870edb6921cc927be315fb6db78bc5ad4",
       []
      ],
      "cache-add.https.any.js.ini": [
-      "3bc5319ed5616bb60fd7a70c37e17fa1b5e6a0ae",
+      "6be50b1655b56387d847d1410fd0376fe2582e54",
       []
      ],
      "cache-add.https.any.serviceworker-expected.txt": [
@@ -374852,11 +374856,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": [
@@ -374980,7 +374984,7 @@
       []
      ],
      "getregistrations.https.html.ini": [
-      "a7e154610d88f81a8fda2719d367f4e518aa77b7",
+      "4769a3b3065cbfd007b4a45f0d348bfb7a614823",
       []
      ],
      "idlharness-sw.https-expected.txt": [
@@ -376760,7 +376764,7 @@
       []
      ],
      "same-site-cookies.https.html.ini": [
-      "3413342b2670720ebce4e9e53008c6cd93f69d83",
+      "a1f53e127612151651cc58386fcb45ebd9637be2",
       []
      ],
      "unregister-immediately-before-installed.https.html.ini": [
@@ -376768,7 +376772,7 @@
       []
      ],
      "unregister-immediately-during-extendable-events.https.html.ini": [
-      "b72385b92b166e7a4cf038410e6bcabbdd7e3fa0",
+      "66a27a1d9dd07a841efb1e07bf8478cba3487af6",
       []
      ],
      "unregister-then-register-new-script.https-expected.txt": [
@@ -376857,9 +376861,17 @@
      ]
     },
     "declarative": {
+     "getinnerhtml.tentative-expected.txt": [
+      "a0035455c0de182e4b8f1a849c3fe65198c04f88",
+      []
+     ],
+     "getinnerhtml.tentative.html.ini": [
+      "7ab112592e92df3084de6aea893bd7d7a5b4a6d3",
+      []
+     ],
      "support": {
       "declarative-child-frame.html": [
-       "10608b4875e0bd7d0169cf109b62b2b3612a8288",
+       "603c47743b807ecc00a483d328edcacb7ebb8d57",
        []
       ],
       "helpers.js": [
@@ -377512,7 +377524,7 @@
       []
      ],
      "soft-navigation-helper.js": [
-      "0dd39d827e94bed5c497c1265b3419419cefaa75",
+      "d1a60c15ef406be36a05f602315561cc3225790e",
       []
      ]
     }
@@ -377624,7 +377636,7 @@
       []
      ],
      "activation-start.html.ini": [
-      "6292f6caa3de1e81e060a2e479c384176463261a",
+      "aaf926f537bade7b5dbbf89c2c8514b8363b9918",
       []
      ],
      "cache-storage.https.html.ini": [
@@ -377652,7 +377664,7 @@
       []
      ],
      "csp-prefetch-src-allow.html.ini": [
-      "14ac2c2f95adbee7a88c78c1a27fbcc60b6f7928",
+      "f180003f1d7192ece696047c0edebbb124bef4fe",
       []
      ],
      "csp-prefetch-src-disallow.html.ini": [
@@ -377664,7 +377676,7 @@
       []
      ],
      "fetch-intercepted-by-service-worker.https.html.ini": [
-      "21fe7dffdc7518dc9b13d8d064a05714196d1cb5",
+      "8ce695e6448ac02cd213c88b9756158738a39c63",
       []
      ],
      "iframe-added-post-activation.html.ini": [
@@ -377672,7 +377684,7 @@
       []
      ],
      "indexeddb.html.ini": [
-      "e16ee6be70082c5413fcb5624aed940a342e2447",
+      "3dd4ff19b55d1fb59cc6a5c63cbde535ba936cd9",
       []
      ],
      "local-storage.html.ini": [
@@ -377684,7 +377696,7 @@
       []
      ],
      "media-autoplay.html.ini": [
-      "18c590d7ab79148d377ac760bc1bb55715aad61e",
+      "12abdfdd57a96f1d46e72d7aab8b6fb66a315608",
       []
      ],
      "navigation-intercepted-by-service-worker.https.html.ini": [
@@ -377700,7 +377712,7 @@
       []
      ],
      "referrer-policy-from-rules.html.ini": [
-      "c96a9be02b0806a01546d4b2c341b10d0ac3dc43",
+      "d0cdf48e1836c842433cf2c8d731e59a18443330",
       []
      ],
      "referrer-policy-mismatch.html.ini": [
@@ -377708,7 +377720,7 @@
       []
      ],
      "referrer-policy-no-referrer.html.ini": [
-      "9c2d1085fbbd59397e4aa1bd782ed2d8edf8d454",
+      "76132cd0681cf55ee750ed7b3503eb2dc77b5e30",
       []
      ],
      "referrer-policy-origin.html.ini": [
@@ -378118,11 +378130,11 @@
       ]
      },
      "response-code-non-successful.html.ini": [
-      "6b4be6c2ff40a82c0d73795ade83618b5b82df36",
+      "2f36c9081a863abce9dc7cd7054e5d991209da8e",
       []
      ],
      "response-code-successful.html.ini": [
-      "c0a75137f41a9d98bccbb6dc85ea49824a26dcec",
+      "e0df30226eae4875f62ff195334f951d36485414",
       []
      ],
      "restriction-audio-setSinkId-with-invalid-sinkId.https.tentative.html.ini": [
@@ -378146,7 +378158,7 @@
       []
      ],
      "restriction-bluetooth.tentative.https.html.ini": [
-      "430d214a46243795c50eef1a5dbe7e0ecce35eac",
+      "ebc3e375c39a321111cc155ac1f4dd9137b73fb7",
       []
      ],
      "restriction-broadcast-channel.html.ini": [
@@ -378154,7 +378166,7 @@
       []
      ],
      "restriction-dedicated-worker.https.html.ini": [
-      "96308d6c197c8fe0a32447ed8562049972471ed4",
+      "4aeadc53fb826a843e3a9ceedf09e3d68e77daa4",
       []
      ],
      "restriction-encrypted-media-unsupported-config.https.html.ini": [
@@ -378162,7 +378174,7 @@
       []
      ],
      "restriction-encrypted-media.https.html.ini": [
-      "a72b2256c439a5be422d5893a270d1937bab5749",
+      "e09bff4cfff69008182740923a0853b57ab7b591",
       []
      ],
      "restriction-focus.html.ini": [
@@ -378170,7 +378182,7 @@
       []
      ],
      "restriction-idle-detection.https.html.ini": [
-      "f9c08def1f4bbd3f39648fd0af9d2505164882c8",
+      "74b7f115a09ae20005650173df4d747a1f213e12",
       []
      ],
      "restriction-local-file-system-access.https.html.ini": [
@@ -378178,7 +378190,7 @@
       []
      ],
      "restriction-media-auto-play-attribute.html.ini": [
-      "66ea6cb7d2ce1982cbd5b55389211dd5ff9b5f9e",
+      "163886691748f1816ef13538f5ddc7a19a4e1873",
       []
      ],
      "restriction-media-camera.https.html.ini": [
@@ -378190,7 +378202,7 @@
       []
      ],
      "restriction-media-microphone.https.html.ini": [
-      "3191a4d4c722c047b1c3b58b024314a07dae7913",
+      "9cafd156134b1a9ba6f34d472d34e8b8e6af6035",
       []
      ],
      "restriction-media-play.html.ini": [
@@ -378198,7 +378210,7 @@
       []
      ],
      "restriction-message-boxes.html.ini": [
-      "a19061396a8e8780f34563f70ec2627d23d9f65a",
+      "aeb2a55b80067815a8f7a29f90ebe9516a3f2544",
       []
      ],
      "restriction-midi-sysex.https.html.ini": [
@@ -378222,7 +378234,7 @@
       []
      ],
      "restriction-prompt-by-before-unload.html.ini": [
-      "24bdd394661e9618d70c4712ff3d71174a96f032",
+      "465f205d31b2c64fbf8abc8dfd6932d663df3e38",
       []
      ],
      "restriction-push.https.html.ini": [
@@ -378230,7 +378242,7 @@
       []
      ],
      "restriction-request-picture-in-picture.html.ini": [
-      "745c20dc1c7da6527d59ddd93af071fed58d22c6",
+      "9bfa95ff89d6b4a022ac7a56aa4a2714c610007a",
       []
      ],
      "restriction-screen-capture.https.html.ini": [
@@ -378258,7 +378270,7 @@
       []
      ],
      "restriction-service-worker-postmessage.https.html.ini": [
-      "3cb7332888cd824bca0b46e9f2aa661e57c49dcc",
+      "7b07883516ff22329c9128a6aabf12ccc501c50f",
       []
      ],
      "restriction-service-worker-unregister.https.html.ini": [
@@ -378266,11 +378278,11 @@
       []
      ],
      "restriction-service-worker-update.https.html.ini": [
-      "f0afa05263b0f0e6cf6d67fa8dc79e0298784281",
+      "fb6c6b0ed6665fbfd6a343a00bbd1bb2c0bc17ac",
       []
      ],
      "restriction-speech-synthesis.html.ini": [
-      "c8b329d54aa3a58e3d46a6bcf37e2690d62df42e",
+      "ad1ad4c2b02022f3bdfe9a9b47eb552ff4a2e77f",
       []
      ],
      "restriction-storage-persist.https.html.ini": [
@@ -378294,7 +378306,7 @@
       []
      ],
      "restriction-web-serial.tentative.https.html.ini": [
-      "5b44cb6670ba91fd42154802cb65915cc71327e0",
+      "84ffcd7dca7e6eff8869ae3a80841d23c0a02cfa",
       []
      ],
      "restriction-web-share.https.html.ini": [
@@ -378302,7 +378314,7 @@
       []
      ],
      "restriction-web-usb.https.html.ini": [
-      "2930410061ae675e7ec7d80d8ecae7a7b00cdbfb",
+      "7cbd1ebd15260386a2272efc12970bbf8b631950",
       []
      ],
      "restriction-web-xr-immersive-vr-session.https.html.ini": [
@@ -378322,7 +378334,7 @@
       []
      ],
      "restriction-window-resize.html.ini": [
-      "625e373b23f8bdbbe135dc5d79cef6af15b7682f",
+      "f7758699c05f12148afe5b2709a284ef58a39369",
       []
      ],
      "restrictions.html.ini": [
@@ -378350,7 +378362,7 @@
       []
      ],
      "session-history-pushstate.https.html.ini": [
-      "d5dc8a78457b6e460ca8afba3270f63e9cc03376",
+      "c514647ec1025d04841cc69501f5a3463d5b9865",
       []
      ],
      "session-history-subframe-navigation.https.html.ini": [
@@ -378394,7 +378406,7 @@
       []
      ],
      "workers.html.ini": [
-      "cb1cc7d4271fc18a3ad4537d2ed9e94b18de69f9",
+      "3c4ccbeb3af30c8efdd8e44bf6a3fa372a3fa3ea",
       []
      ]
     }
@@ -378505,7 +378517,7 @@
      []
     ],
     "partitioned-estimate-usage-details-caches.tentative.https.sub.html.ini": [
-     "0dbdc28ed095c3a0814715041bf077384bfd2b08",
+     "4e84a278083098435780c5c54a0fc7c8507cfadb",
      []
     ],
     "partitioned-estimate-usage-details-indexeddb.tentative.https.sub-expected.txt": [
@@ -381684,7 +381696,7 @@
       []
      ],
      "mousemove_prevent_default_action.tentative.html.ini": [
-      "0152fe0f1acaf9058da0dd5bfb7816bfdefdcf66",
+      "f2a82b71d2bbdea08e4f89982552c1a3e9ed0655",
       []
      ],
      "resources": {
@@ -382215,7 +382227,7 @@
      []
     ],
     "a-element-xhtml.xhtml.ini": [
-     "12a232e87cd71f110645f72ef5ceddb999f36d4b",
+     "395c5d81d4a9d7ad48e4039ec3630a5b9dc1534f",
      []
     ],
     "a-element.html.ini": [
@@ -382223,7 +382235,7 @@
      []
     ],
     "failure.html.ini": [
-     "f9957840ee8e94fc6e080ff207d0e92be84d9285",
+     "ffbf7fd0190e4229a3e9fa1ffb2751aa5f0b445a",
      []
     ],
     "idlharness-shadowrealm.window-expected.txt": [
@@ -382231,11 +382243,11 @@
      []
     ],
     "idlharness-shadowrealm.window.js.ini": [
-     "0c7e3284847a27d3473c7cd5edd910dd3a28ed6a",
+     "1fb49415db04546f898a6416b2794ee4d1c1e4ad",
      []
     ],
     "percent-encoding.window.js.ini": [
-     "36d57023fae6a0fbf2d834ab075a368470e527de",
+     "1091bffa2c6ebfc3c45547eb4ba0f53edaab55cc",
      []
     ],
     "resources": {
@@ -382273,7 +382285,7 @@
      []
     ],
     "toascii.window.js.ini": [
-     "e3a339e2fa129840e0704ed9c0219c85774dc69b",
+     "841d15cbe1f477fc7a5ad9a1c021b2798c8b5253",
      []
     ],
     "url-constructor.any.js.ini": [
@@ -382293,7 +382305,7 @@
      []
     ],
     "url-setters-stripping.any.js.ini": [
-     "cfd90cbff89ad339de12e555432b92e327c6dbbd",
+     "d2c3ff181aaf8d67b9845359f03b64478e9a4982",
      []
     ],
     "url-setters-stripping.any.worker-expected.txt": [
@@ -382304,12 +382316,16 @@
      "9d62ebfc729144c9ebb991895b4799e0cc97295f",
      []
     ],
+    "urlsearchparams-delete.any.js.ini": [
+     "52902dae3e80bd36963e43ab61098828efd2bea8",
+     []
+    ],
     "urlsearchparams-get.any.js.ini": [
-     "e0afce635f0b70de1d746af7d99c52f03a2f4aab",
+     "3c8d8fe063c7c49fbcb1055276c06a368a83863c",
      []
     ],
     "urlsearchparams-stringifier.any.js.ini": [
-     "300c68e6d26bc214cea1efe653cd37d06f3fbd38",
+     "54b6ffd33da703b0350363d114d6d85e214f79b4",
      []
     ]
    },
@@ -382331,7 +382347,11 @@
       "f774699bff99c3b78e342bf4a8da9207aa8c84dd",
       []
      ]
-    }
+    },
+    "urlpattern-compare.https.any.js.ini": [
+     "8d42eeba66fabfcd7706efeef02f99e0204fb709",
+     []
+    ]
    },
    "user-timing": {
     "DIR_METADATA": [
@@ -382385,6 +382405,10 @@
     "META.yml": [
      "411450e0b142931544fbaac5669352201ee37328",
      []
+    ],
+    "api-is-present.html.ini": [
+     "f3986b9f072a5c70b6b0f78149145adf85ca8c83",
+     []
     ]
    },
    "video-rvfc": {
@@ -382404,8 +382428,12 @@
      "d923efb529a55552b6f150b217f7dcbafe689644",
      []
     ],
+    "request-video-frame-callback-webrtc.https.html.ini": [
+     "447e1523bdef4f7e5ddb4c4907807f1302add84c",
+     []
+    ],
     "request-video-frame-callback.html.ini": [
-     "9b8c640f506fd952561f5fe96abea5a549d4231a",
+     "9dc95511b66f44ff4912e5aadac37064d9afddc5",
      []
     ]
    },
@@ -382448,10 +382476,6 @@
      "934674a51a6a68dd80f6faebb34b2b969ccf6925",
      []
     ],
-    "viewport-unscaled-scroll.html.ini": [
-     "2d42feda37bed7a41230da6527117d3c11df7cf5",
-     []
-    ],
     "viewport_support.js": [
      "a82bd2b028010e053199e55bd7bb357361581e6f",
      []
@@ -383395,7 +383419,7 @@
        []
       ],
       "seamlessly-updating-the-playback-rate-of-an-animation.html.ini": [
-       "5b52b13818b5c4cf5f0a2492030df06d1c56f00b",
+       "d31b9b028d3c95a3453f248eb3a2616861036d6c",
        []
       ],
       "setting-the-current-time-of-an-animation-expected.txt": [
@@ -383429,7 +383453,7 @@
      },
      "timelines": {
       "document-timelines.html.ini": [
-       "8c474c4dac8bc4767a86e055c819fe3f07b63f59",
+       "08dcd48709615c9a9b1a969e392a50990c32d801",
        []
       ],
       "resources": {
@@ -383447,7 +383471,7 @@
        []
       ],
       "sibling-iframe-timeline.html.ini": [
-       "675b3f1bf576cac09b7b92d0a3579e3d0c26c018",
+       "3c560e37d3bff3f35108e8d9d66c5c150b4afe25",
        []
       ],
       "timelines.html.ini": [
@@ -383920,6 +383944,10 @@
      "release.tentative.https.html.ini": [
       "f580f5e14398488bb0ca0d1b7db19639af60315f",
       []
+     ],
+     "sharedworker-multiple.tentative.https.html.ini": [
+      "d8bf264011d4080217ef892d547ee92890c3aed3",
+      []
      ]
     },
     "clientids.tentative.https.html.ini": [
@@ -383942,10 +383970,6 @@
      "13f71e7392da4a06d59d94556165c20c6217c713",
      []
     ],
-    "query-ordering.tentative.https.html.ini": [
-     "b63d722ab7dd33bb4eac37228311c006f2ed749b",
-     []
-    ],
     "query.tentative.https.any.js.ini": [
      "ce2966b3d29a183be238c0953ecf1f9b92275f21",
      []
@@ -384347,7 +384371,7 @@
        ]
       },
       "suspend-with-navigation.html.ini": [
-       "e57ed119bd4bc1b98fe774920e906e6ddc38c73f",
+       "652f921b58208a55ae0c677fae9d6c009d6c5240",
        []
       ]
      },
@@ -384370,6 +384394,10 @@
        "63b60e490f47f4db77d33d7a4ca2f5b9a4181de8",
        []
       ],
+      "audioworkletnode-output-channel-count.https.html.ini": [
+       "97f1aa6933157db4fc4564d7095f4c274919d1ec",
+       []
+      ],
       "audioworkletprocessor-promises.https-expected.txt": [
        "ecc24fe05e8a87fcd79a9de92e21f7e38207ca0f",
        []
@@ -384551,7 +384579,7 @@
      },
      "the-mediaelementaudiosourcenode-interface": {
       "mediaElementAudioSourceToScriptProcessorTest.html.ini": [
-       "f6eb33aae0c2b229ea3d2406b62ec9d8f8cd1b2e",
+       "a15dd774800d188750cbfff43df80bc648648aec",
        []
       ]
      },
@@ -385563,7 +385591,7 @@
        []
       ],
       "OwnPropertyKeys.html.ini": [
-       "fc898402003b9cdf2c45c907876fa7195f2061a3",
+       "3856f1b4592c0142731d6972ad58a005d2f0a147",
        []
       ],
       "helper.js": [
@@ -385646,7 +385674,7 @@
       []
      ],
      "origin.window.js.ini": [
-      "cdb616cc1387455567a580a04b52598e97e408e2",
+      "df1f5ad7646d059bae0d9e4c1b34180c99a3e8e3",
       []
      ],
      "resources": {
@@ -385676,7 +385704,7 @@
       ]
      },
      "workers.html.ini": [
-      "cd3a12a28e5dca97c0fb00dfc49942158391e59e",
+      "49c27878b8e2dd76c9318c237adb8158c68ad935",
       []
      ]
     },
@@ -385714,10 +385742,6 @@
      "user-activation.tentative.any.worker-expected.txt": [
       "f953e25d9ef727b48984300d1e79ce87c71f2400",
       []
-     ],
-     "worker-post-after-close.any.js.ini": [
-      "c24d6cfcdb04cfd44b9aee25bf6aedf762a263d4",
-      []
      ]
     },
     "multi-globals": {
@@ -385734,7 +385758,7 @@
       []
      ],
      "broadcastchannel-incumbent.sub.html.ini": [
-      "6742e10278a81a61ec2e9df0addcb894fba30326",
+      "b15baab7faf137cd6228e0ad84e836adfd76dd0e",
       []
      ],
      "support": {
@@ -385796,7 +385820,7 @@
       []
      ],
      "020.html.ini": [
-      "b35e66e6b3ce06b2885f4808ec48df56a5e255f0",
+      "921da39ff76a5d9ec53d7a5487f54afcfb1a5e0a",
       []
      ]
     },
@@ -385813,8 +385837,12 @@
       "225bd7a41e38280bdb0891ecbf8cd4c39a4c3029",
       []
      ],
+     "020.html.ini": [
+      "265c7a6def4cc8db611bbcb8f304bdfab086a23c",
+      []
+     ],
      "021.html.ini": [
-      "8e4edd6f2b7ce7d102fac824b0012ac26abd9da4",
+      "fd4aad14082878fb8cd021b5a6791e1d0e4ec620",
       []
      ],
      "025-1.js": [
@@ -385851,7 +385879,7 @@
      []
     ],
     "idlharness.https.any.js.ini": [
-     "76d37ab7844b19ed5bcf589750bb8c8ac7bfa4c5",
+     "4cdf45bec0739ec6e3036d65fc34a1d4052a8a59",
      []
     ],
     "idlharness.https.any.worker-expected.txt": [
@@ -385927,7 +385955,7 @@
      []
     ],
     "RTCDTMFSender-ontonechange.https.html.ini": [
-     "7f85bcb60e81dc7eacbe1f70e19e66fc60d77b48",
+     "0efeed630eebcdf500fcad91c3fbddd31e368718",
      []
     ],
     "RTCDataChannel-binaryType.window-expected.txt": [
@@ -386198,10 +386226,6 @@
      "cb23952f507e98502144fda6b281bbbc55503746",
      []
     ],
-    "RTCTrackEvent-fire.html.ini": [
-     "b2400113b598e96db2123a2065ca5b844025dba3",
-     []
-    ],
     "__dir__.ini": [
      "8a6d4ac2deeae799bbc07bba5d584cc2ea73c5ab",
      []
@@ -386773,7 +386797,7 @@
      []
     ],
     "Create-url-with-space.any.js.ini": [
-     "3bd2fc13372f6f3c007eee512a64d801d90bba69",
+     "9cb0261edf12d7c445841c14b958015531c0eeac",
      []
     ],
     "Create-url-with-space.any.worker-expected.txt": [
@@ -387358,7 +387382,7 @@
       []
      ],
      "002.html.ini": [
-      "c10c381c04dbb7f62a9ed3afbd236de720d3b970",
+      "87223f2052037984f207acdd518e54ab240911fa",
       []
      ],
      "002_wpt_flags=h2-expected.txt": [
@@ -388395,10 +388419,6 @@
         "d4bd2b74c2db0e560114109af960c7f38cb38575",
         []
        ],
-       "audio_has_no_subtitles.html.ini": [
-        "f817e95249a7a1930250e1ed52459c2f5b0bac19",
-        []
-       ],
        "background.png": [
         "6d16cc84c4dd3b8777bd83d97888eaf8d351f6b5",
         []
@@ -390869,7 +390889,7 @@
      []
     ],
     "events_referenceSpace_reset_inline.https.html.ini": [
-     "4a08b260731f7aaa929f4f15d054fb9cb05d8d8e",
+     "00c1d56bf0b835c4ab75baee491703b102791134",
      []
     ],
     "events_session_select.https.html.ini": [
@@ -391233,7 +391253,7 @@
      []
     ],
     "xrSession_requestReferenceSpace_features.https.html.ini": [
-     "eee061a4d3e9901842289175021b3c5646433659",
+     "2e02a8cdd773669852af2fbffb2c8a445e254dc2",
      []
     ],
     "xrSession_requestSessionDuringEnd.https.html.ini": [
@@ -391257,7 +391277,7 @@
      []
     ],
     "xrStationaryReferenceSpace_floorlevel_updates.https.html.ini": [
-     "66f1822acf687c891474dcea9dd63a3f4c5537c5",
+     "44b157f567f2c63c9bad86c1d713324836d84e1b",
      []
     ],
     "xrView_eyes.https.html.ini": [
@@ -391643,7 +391663,7 @@
      []
     ],
     "dedicated-worker-from-blob-url.window.js.ini": [
-     "b6f8e24e5a0d7742cdd446ae46283964140925f2",
+     "1f41aff0a7de53851d266ce0855bfc593c0d3b1e",
      []
     ],
     "dedicated-worker-in-data-url-context.window-expected.txt": [
@@ -391651,7 +391671,7 @@
      []
     ],
     "dedicated-worker-in-data-url-context.window.js.ini": [
-     "0521a49adf986aad676dc8ffe895e8b2b9128685",
+     "8e3ebef3e6e51467127721e825be154a6e3bcac3",
      []
     ],
     "dedicated-worker-parse-error-failure-expected.txt": [
@@ -391781,10 +391801,6 @@
         "1c6515f8e201ef9439a48434033acafaecd68517",
         []
        ],
-       "redirect.html.ini": [
-        "fd33d33be2f9c0d25ef8afed8d0a024b96686d2f",
-        []
-       ],
        "redirect.js": [
         "2db48544a2d7d7f55201043e73297283cd99c263",
         []
@@ -391800,7 +391816,7 @@
       },
       "onerror": {
        "exception-in-onerror.html.ini": [
-        "17e256848e0ec3017bdaaed10d2db031e1b84eb6",
+        "4d5ef8601f8de459265e274d3716d94d2f7a4db7",
         []
        ],
        "handled.js": [
@@ -391996,7 +392012,7 @@
       []
      ],
      "dedicated-worker-import-meta.html.ini": [
-      "f8185f10976eba9cc50ff6423ba9337629f38735",
+      "1457ee30dc6f11cbb7c828c35e02aecbb3d8d32a",
       []
      ],
      "dedicated-worker-options-credentials.html.headers": [
@@ -392198,7 +392214,7 @@
       ]
      },
      "shared-worker-import-csp.html.ini": [
-      "1231f0993a9d177483b89fab79e93c279527af23",
+      "ab9b6834f98a0b9b2ec9d6555935184a715dbd90",
       []
      ],
      "shared-worker-options-credentials.html.headers": [
@@ -392233,7 +392249,7 @@
      ]
     },
     "nested_worker_close_self.worker.js.ini": [
-     "8a8a551834f4698a6d74582c504522a8baed1207",
+     "520cb653d31af629c9cad252e9501fbb83026df1",
      []
     ],
     "non-automated": {
@@ -392351,7 +392367,7 @@
        []
       ],
       "003.any.js.ini": [
-       "daf7342229920cccb5d18dd504dbcfd4a46fa29c",
+       "d5372c4caecc9f3bc8cd86e7968b82c118dee5ee",
        []
       ],
       "003.any.sharedworker-expected.txt": [
@@ -392770,6 +392786,14 @@
      "b06ea33cd926fd99d890b0dd7544213170a15e8e",
      []
     ],
+    "animation-worklet-import.https.html.ini": [
+     "bcf7103f2760520d76d6f4a44033e3ef89dc0f98",
+     []
+    ],
+    "audio-worklet-service-worker-interception.https.html.ini": [
+     "c76f84db537c8f44b86338431f0a13b210a3ae81",
+     []
+    ],
     "idlharness.https.any-expected.txt": [
      "5ae5361d00ca8b11eac4498deb5a35a86b059d52",
      []
@@ -392979,13 +393003,17 @@
      []
     ],
     "abort-after-send.any.js.ini": [
-     "a0be80752e1abc36ff12ec082de76186d44a3711",
+     "e3c68023891b3a82acfde20d5fb3dc438a9d4a7a",
      []
     ],
     "abort-after-send.any.worker-expected.txt": [
      "0f10f7ee18013666b3206dddc19955439d9d162c",
      []
     ],
+    "anonymous-mode-unsupported.htm.ini": [
+     "f1cae53c6c1a1b508374f99cb72c72642c0392f8",
+     []
+    ],
     "data-uri-expected.txt": [
      "c0d444f8132ff4f4691880be13c562e5e42b355b",
      []
@@ -393012,7 +393040,7 @@
       []
      ],
      "set-blob.any.js.ini": [
-      "f188fd27f0a9fea72faf2b387b8a966a845f7598",
+      "d834c1b7caee979114b7db1f619c487aee1e0bb7",
       []
      ],
      "set-blob.any.worker-expected.txt": [
@@ -451875,13 +451903,6 @@
          {}
         ]
        ],
-       "line-height-step.html": [
-        "2a25562f0f5b533590cfb58eb94f71078269e3aa",
-        [
-         null,
-         {}
-        ]
-       ],
        "line-height.html": [
         "c09c404617e7fee1cbe37500cf83a0ac1dc41e66",
         [
@@ -459311,14 +459332,14 @@
        ]
       ],
       "parse-has-disallow-nesting-has-inside-has.html": [
-       "0a30718df04f61a6aad451daad841147b616dc38",
+       "9cf989fcbeb7409208199e5ad96211a353e847e7",
        [
         null,
         {}
        ]
       ],
       "parse-has.html": [
-       "e15d33532bc4a1a255cd1d965fa6a2e6864e335b",
+       "5d071010b42f9b726490b53cfeb8da75b20159ad",
        [
         null,
         {}
@@ -496198,6 +496219,15 @@
        }
       ]
      ],
+     "element-request-fullscreen-consume-user-activation.html": [
+      "cc4806711dab97d7ef69995aca1d69f77a408f6b",
+      [
+       null,
+       {
+        "testdriver": true
+       }
+      ]
+     ],
      "element-request-fullscreen-dialog.html": [
       "08091ddc01fb62568f55e64a1f45336a29194e67",
       [
@@ -496230,6 +496260,15 @@
        }
       ]
      ],
+     "element-request-fullscreen-same-element.html": [
+      "a2b04dd173989b61a7423bba94fe4e49ba87ec2a",
+      [
+       null,
+       {
+        "testdriver": true
+       }
+      ]
+     ],
      "element-request-fullscreen.html": [
       "23b4d2f5bfbed1f84f0b51494bdc394fe56ebcb8",
       [
@@ -539062,14 +539101,14 @@
        ]
       ],
       "popover-animation-corner-cases.tentative.html": [
-       "16426bc2ab953f8a8b41041e2c84c8065568a52d",
+       "f41f7a68df9058dee90de4ece70b753a801d6a49",
        [
         null,
         {}
        ]
       ],
       "popover-attribute-basic.tentative.html": [
-       "ba09380f0195b72f9fb3a0e368b2e3ada9b966d0",
+       "ae4807974619d46e88f9b60e3187e187c93ed922",
        [
         null,
         {
@@ -539077,6 +539116,13 @@
         }
        ]
       ],
+      "popover-beforetoggle-opening-event.tentative.html": [
+       "b2c3fa5d68bf051e2faf5d83e765de1ed42397b6",
+       [
+        null,
+        {}
+       ]
+      ],
       "popover-document-open.tentative.html": [
        "429fd89d3ba68d9588b66e696095e5007eaccc9a",
        [
@@ -539085,7 +539131,7 @@
        ]
       ],
       "popover-events.tentative.html": [
-       "78d4a22c78e7be447eb1ef007c2ee29e192919b3",
+       "7d63ce74b7f68155346231b13dcf1e11ba2a47d2",
        [
         null,
         {}
@@ -539111,7 +539157,7 @@
        ]
       ],
       "popover-invoking-attribute.tentative.html": [
-       "affe201b69a4a217cbab95ba9015486fbdb81251",
+       "5ce315ef1d9ea7269950a1e651a77b177d5b8fc5",
        [
         null,
         {
@@ -539121,14 +539167,14 @@
        ]
       ],
       "popover-light-dismiss-on-scroll.tentative.html": [
-       "7a09712d8149a6fef8cf0f15d14042a1c46d2ea4",
+       "73b3a2d6193bc6f5a120a583a7a7e6169a34487f",
        [
         null,
         {}
        ]
       ],
       "popover-light-dismiss.tentative.html": [
-       "2a101483cb8c8e1896244fd4f04c43be5380a4a0",
+       "bdd0d12545f03e54f1b111cb492899373eddad7a",
        [
         null,
         {
@@ -539167,13 +539213,6 @@
         {}
        ]
       ],
-      "popover-show-event.tentative.html": [
-       "69996bd65daba304c31e32a06f6d45fc69d7c24c",
-       [
-        null,
-        {}
-       ]
-      ],
       "popover-stacking.tentative.html": [
        "dc07c1c208473cc96ba0e63d1369f17b01f503df",
        [
@@ -539205,6 +539244,13 @@
         null,
         {}
        ]
+      ],
+      "toggleevent-interface.tentative.html": [
+       "8ee63c4071856c0132f952c4799f95c44ee0b446",
+       [
+        null,
+        {}
+       ]
       ]
      },
      "rellist-feature-detection.html": [
@@ -556576,7 +556622,7 @@
      ]
     ],
     "setactionhandler.html": [
-     "80dee47a4c28a5addd2929504f787e16934477f9",
+     "a9df51968c6a5ef2fc2efe81008408e61572fd01",
      [
       null,
       {}
@@ -585286,6 +585332,13 @@
        {}
       ]
      ],
+     "scroll-timeline-name-tree-scoped.html": [
+      "622a582cce9d2704139f5e7c7a363e00d7581e91",
+      [
+       null,
+       {}
+      ]
+     ],
      "scroll-timeline-nearest-dirty.html": [
       "6914fc616a485f5b604123e374f917f8d1e1a026",
       [
@@ -585412,6 +585465,13 @@
        {}
       ]
      ],
+     "view-timeline-name-tree-scoped.html": [
+      "c216c345ed97a30b7f6892c802c14c8c3ffc4554",
+      [
+       null,
+       {}
+      ]
+     ],
      "view-timeline-shorthand.tentative.html": [
       "f3efa88c923f20b60fd887ca8143926eeeeaf4a9",
       [
@@ -588424,7 +588484,7 @@
       ]
      ],
      "cache-storage-buckets.https.any.js": [
-      "749b7c5efe8da15123eef984dab47c2d2f8d390f",
+      "0b5ef7b298df64d9df1a79fa7e1fe3cd00178333",
       [
        "service-workers/cache-storage/cache-storage-buckets.https.any.html",
        {
@@ -590984,77 +591044,77 @@
     ],
     "declarative": {
      "declarative-after-attachshadow.tentative.html": [
-      "bb409d9b97fce6ccb3da3f4d0eb63820dc8adab8",
+      "bfe2d66cfa9d3921bcdb046285fdb0af69b7354a",
       [
        null,
        {}
       ]
      ],
      "declarative-parser-interaction.tentative.html": [
-      "473131ed251588f7fab7f729eee1bf5823ca1426",
+      "f5ff13822b04c8776326bc2b2dcb7b4501c953c0",
       [
        null,
        {}
       ]
      ],
      "declarative-shadow-dom-attachment.tentative.html": [
-      "f277dc77b4ed03dfb92f1e84cb6acfcfac88ffb2",
+      "d752b62d31d47fdce6ba8e55fda7b7cabe8de24a",
       [
        null,
        {}
       ]
      ],
      "declarative-shadow-dom-basic.tentative.html": [
-      "50c8346791c972ffcc1811c5c15eec44850bb9f2",
+      "b71f7d1a3778e722693742d783b3ddeb0a0775c4",
       [
        null,
        {}
       ]
      ],
      "declarative-shadow-dom-opt-in.tentative.html": [
-      "4c95e476abd2051f76ea5a28e9236b9283bda291",
+      "0a59768d22e04dbde6fc4cec4061371efbb8c6e4",
       [
        null,
        {}
       ]
      ],
      "declarative-with-disabled-shadow.tentative.html": [
-      "e075a4f8a7d1638214238bb78c89346c482cbcdb",
+      "849bffa5a7f6e8b9417f2a030b36ff408c117256",
       [
        null,
        {}
       ]
      ],
      "getinnerhtml.tentative.html": [
-      "f105a9b9d89c0919ed89dbad0d1085a4d5545ffe",
+      "ad7734d51e692f839627804d779190bdd85b244d",
       [
        null,
        {}
       ]
      ],
      "innerhtml-before-closing-tag.tentative.html": [
-      "51ee667164234a8613a444f8ae43537f91ae31ed",
+      "e87c425860004f512b5ed330614af78818ad4ef4",
       [
        null,
        {}
       ]
      ],
      "innerhtml-on-ordinary-template.tentative.html": [
-      "221b252ae96dbf8d04054d074d20e4b0426fbc4a",
+      "87260013def7fd7efc9ea89bf5bece36d2af348b",
       [
        null,
        {}
       ]
      ],
      "move-template-before-closing-tag.tentative.html": [
-      "46e604148740668d2f0a5791b8aaec05fc8a076d",
+      "a3d7806f5d668c32e77e013d88cd4b82ff6d40b5",
       [
        null,
        {}
       ]
      ],
      "script-access.tentative.html": [
-      "cbe61dcd28375515201426a0a4ee71e7d315c4bd",
+      "6c927b1bd75258520b6035fec9d179152ae6218a",
       [
        null,
        {}
@@ -592868,7 +592928,7 @@
      ]
     ],
     "dropped-entries.tentative.html": [
-     "9c3ea473f2e8eb792a473bf771422696e0ff7239",
+     "a1db721837748ebdec23cd740936948458c9044c",
      [
       null,
       {
@@ -592905,7 +592965,7 @@
      ]
     ],
     "image-lcp-followed-by-two-image-softnavs-lcp.tentative.html": [
-     "09259b19eae7612643e925e27bf50109f1d3b557",
+     "7f5bafb5e685d9c07eb16663af823d0f06e9023e",
      [
       null,
       {
@@ -592913,6 +592973,16 @@
       }
      ]
     ],
+    "multiple-paint-entries-buffered.tentative.html": [
+     "f88fb9530129ab501a138a823b492c5661553091",
+     [
+      null,
+      {
+       "testdriver": true,
+       "timeout": "long"
+      }
+     ]
+    ],
     "navigate-child.html": [
      "63a8adb208f2a0c8cfeae4f36871578bb0bf20e4",
      [
@@ -603458,7 +603528,7 @@
       ]
      ],
      "mousemove_prevent_default_action.tentative.html": [
-      "480535da23e43511db94176bcce0edcf364688fd",
+      "376a110fa5b965c5f6a7eb3df92bb5a8c1563afe",
       [
        null,
        {
diff --git a/third_party/blink/web_tests/external/wpt/IndexedDB/bindings-inject-values-bypass-chain.html.ini b/third_party/blink/web_tests/external/wpt/IndexedDB/bindings-inject-values-bypass-chain.html.ini
index ab75b1b..321c5fd 100644
--- a/third_party/blink/web_tests/external/wpt/IndexedDB/bindings-inject-values-bypass-chain.html.ini
+++ b/third_party/blink/web_tests/external/wpt/IndexedDB/bindings-inject-values-bypass-chain.html.ini
@@ -1,3 +1,3 @@
 [bindings-inject-values-bypass-chain.html]
   expected:
-    if product == "chrome": [OK, ERROR]
+    if product == "chrome": ERROR
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 6f6a8d00..93a6866 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,6 +1,7 @@
 [idbobjectstore_batchGetAll_largeValue.tentative.any.html]
   expected:
-    if product == "chrome": OK
+    if (flag_specific == "") and (os == "linux") and (product == "chrome"): OK
+    if (flag_specific == "") and (os == "win"): OK
     TIMEOUT
   [Get upper/lower excluded]
     expected: [PASS, TIMEOUT]
@@ -11,6 +12,7 @@
 
 [idbobjectstore_batchGetAll_largeValue.tentative.any.worker.html]
   expected:
+    if (flag_specific == "") and (os == "win"): OK
     if flag_specific == "disable-site-isolation-trials": OK
     TIMEOUT
   [Get upper/lower excluded]
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/content-security-policy/inheritance/history-iframe.sub.html.ini
similarity index 63%
rename from third_party/blink/web_tests/external/wpt/workers/interfaces/WorkerGlobalScope/location/redirect.html.ini
rename to third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/history-iframe.sub.html.ini
index fd33d33..3d47c07 100644
--- a/third_party/blink/web_tests/external/wpt/workers/interfaces/WorkerGlobalScope/location/redirect.html.ini
+++ b/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/history-iframe.sub.html.ini
@@ -1,3 +1,3 @@
-[redirect.html]
+[history-iframe.sub.html]
   expected:
     if os == "win": [OK, TIMEOUT]
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/popup-so.https.html.ini b/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/history.sub.html.ini
similarity index 69%
rename from third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/popup-so.https.html.ini
rename to third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/history.sub.html.ini
index 463b52a..9728b70 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/popup-so.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/content-security-policy/inheritance/history.sub.html.ini
@@ -1,3 +1,3 @@
-[popup-so.https.html]
+[history.sub.html]
   expected:
     if product == "chrome": [OK, ERROR]
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 7b5686f3..035485e0 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,18 +1,11 @@
 [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
+      if os == "win": [PASS, FAIL]
 
   [CookieListItem - cookieStore.set with expires set to a Date 10 years in the future]
     expected:
-      if os == "win": FAIL
+      if os == "win": [PASS, FAIL]
 
 
 [cookieListItem_attributes.https.any.html]
-  [CookieListItem - cookieStore.set with expires set to a Date 10 years in the future]
-    expected:
-      if os == "win": FAIL
-
-  [CookieListItem - cookieStore.set with expires set to a timestamp 10 years in the future]
-    expected:
-      if os == "win": FAIL
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 7495e61..71af6b8 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,6 +1,18 @@
 [cookieStore_set_arguments.https.any.html]
+  [cookieStore.set with expires set to a future Date]
+    expected:
+      if os == "win": [PASS, FAIL]
+
+  [cookieStore.set with expires set to a future timestamp]
+    expected:
+      if os == "win": [PASS, FAIL]
+
 
 [cookieStore_set_arguments.https.any.serviceworker.html]
   [cookieStore.set with expires set to a future timestamp]
     expected:
       if os == "win": FAIL
+
+  [cookieStore.set with expires set to a future Date]
+    expected:
+      if os == "win": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/cookies/samesite/form-post-blank-reload.https.html.ini b/third_party/blink/web_tests/external/wpt/cookies/samesite/form-post-blank-reload.https.html.ini
index 474bdcb9..25c3e4a 100644
--- a/third_party/blink/web_tests/external/wpt/cookies/samesite/form-post-blank-reload.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/cookies/samesite/form-post-blank-reload.https.html.ini
@@ -1,3 +1,5 @@
 [form-post-blank-reload.https.html]
+  expected:
+    if product == "chrome": ERROR
   [Reloaded cross-site top-level form POSTs are strictly same-site]
     expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/credential-management/fedcm-network-requests.https.html.ini b/third_party/blink/web_tests/external/wpt/credential-management/fedcm-network-requests.https.html.ini
index d894972..313555b 100644
--- a/third_party/blink/web_tests/external/wpt/credential-management/fedcm-network-requests.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/credential-management/fedcm-network-requests.https.html.ini
@@ -1,4 +1,63 @@
 [fedcm-network-requests.https.html]
   expected:
-    if (os == "linux") and (product == "chrome"): CRASH
-    if os == "win": TIMEOUT
+    if (product == "content_shell") and (os == "win"): TIMEOUT
+    if product == "chrome": [TIMEOUT, CRASH]
+  [Reject when provider list is empty]
+    expected:
+      if product == "chrome": NOTRUN
+
+  [Reject when configURL is missing]
+    expected:
+      if product == "chrome": NOTRUN
+
+  [Reject when clientId is empty]
+    expected:
+      if product == "chrome": NOTRUN
+
+  [When there's a pending request, a second `get` call should be rejected. ]
+    expected:
+      if product == "chrome": NOTRUN
+
+  [Get after abort should work]
+    expected:
+      if product == "chrome": NOTRUN
+
+  [Test client_metadata request]
+    expected:
+      if product == "chrome": NOTRUN
+
+  [Reject when clientId is missing]
+    expected:
+      if product == "chrome": NOTRUN
+
+  [Reject when configURL is invalid]
+    expected:
+      if product == "chrome": NOTRUN
+
+  [Test that the promise is rejected if the manifest is not in the manifest list]
+    expected:
+      if product == "chrome": NOTRUN
+
+  [Test that service worker cannot observe fetches performed by FedCM API]
+    expected:
+      if product == "chrome": NOTRUN
+
+  [Test the abort signal]
+    expected:
+      if product == "chrome": NOTRUN
+
+  [Test that token endpoint does not follow redirects]
+    expected:
+      if product == "chrome": NOTRUN
+
+  [Successfully obtaining token should resolve the promise.]
+    expected:
+      if product == "chrome": TIMEOUT
+
+  [Test that promise is rejected if accounts endpoint redirects]
+    expected:
+      if product == "chrome": NOTRUN
+
+  [nonce is not required in FederatedIdentityProvider.]
+    expected:
+      if product == "chrome": NOTRUN
diff --git a/third_party/blink/web_tests/external/wpt/css/css-animations/Element-getAnimations-dynamic-changes.tentative.html.ini b/third_party/blink/web_tests/external/wpt/css/css-animations/Element-getAnimations-dynamic-changes.tentative.html.ini
index cd79bce..9037285 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-animations/Element-getAnimations-dynamic-changes.tentative.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-animations/Element-getAnimations-dynamic-changes.tentative.html.ini
@@ -7,3 +7,7 @@
 
   [Animation state is preserved when interleaving animations in list]
     expected: FAIL
+
+  [Animations preserve their startTime when changed]
+    expected:
+      if product == "chrome": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-flexbox/image-as-flexitem-size-001v.html.ini b/third_party/blink/web_tests/external/wpt/css/css-flexbox/image-as-flexitem-size-001v.html.ini
index fc1afa3..0c78572 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-flexbox/image-as-flexitem-size-001v.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/image-as-flexitem-size-001v.html.ini
@@ -5,32 +5,32 @@
 
   [.flexbox > img 11]
     expected:
-      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+      if flag_specific == "disable-layout-ng": FAIL
 
   [.flexbox > img 1]
     expected:
-      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+      if flag_specific == "disable-layout-ng": FAIL
 
   [.flexbox > img 10]
     expected:
-      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+      if flag_specific == "disable-layout-ng": FAIL
 
   [.flexbox > img 14]
     expected:
-      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+      if flag_specific == "disable-layout-ng": FAIL
 
   [.flexbox > img 7]
     expected:
-      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+      if flag_specific == "disable-layout-ng": FAIL
 
   [.flexbox > img 9]
     expected:
-      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+      if flag_specific == "disable-layout-ng": FAIL
 
   [.flexbox > img 12]
     expected:
-      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+      if flag_specific == "disable-layout-ng": FAIL
 
   [.flexbox > img 6]
     expected:
-      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+      if flag_specific == "disable-layout-ng": FAIL
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..5d58a48a 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 10]
+    expected:
+      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+
+  [.flexbox > img 7]
+    expected:
+      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+
+  [.flexbox > img 1]
+    expected:
+      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+
+  [.flexbox > img 14]
+    expected:
+      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+
+  [.flexbox > img 12]
+    expected:
+      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+
+  [.flexbox > img 6]
+    expected:
+      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+
+  [.flexbox > img 9]
+    expected:
+      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+
+  [.flexbox > img 11]
+    expected:
+      if flag_specific == "disable-layout-ng": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/crash-large-grapheme-cluster.html.ini b/third_party/blink/web_tests/external/wpt/css/css-fonts/crash-large-grapheme-cluster.html.ini
index 83547c68..be7498a 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-fonts/crash-large-grapheme-cluster.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/crash-large-grapheme-cluster.html.ini
@@ -1,4 +1,3 @@
 [crash-large-grapheme-cluster.html]
   expected:
-    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): TIMEOUT
     if flag_specific == "disable-layout-ng": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/Initial-letter-breaking-vlr.html.ini b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/Initial-letter-breaking-vlr.html.ini
index 0b139d8c..a76ddebb 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/Initial-letter-breaking-vlr.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/Initial-letter-breaking-vlr.html.ini
@@ -1,4 +1,4 @@
 [Initial-letter-breaking-vlr.html]
   expected:
-    if (flag_specific == "") and (product == "chrome"): [PASS, FAIL]
-    if flag_specific == "disable-layout-ng": FAIL
+    if (product == "content_shell") and (flag_specific == "disable-layout-ng"): FAIL
+    if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/Initial-letter-breaking-vrl.html.ini b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/Initial-letter-breaking-vrl.html.ini
index a3abcef..95bff10 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/Initial-letter-breaking-vrl.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/Initial-letter-breaking-vrl.html.ini
@@ -1,4 +1,4 @@
 [Initial-letter-breaking-vrl.html]
   expected:
-    if (product == "content_shell") and (flag_specific == "disable-layout-ng"): FAIL
-    if product == "chrome": 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/css/css-inline/initial-letter/initial-letter-block-position-drop-over-ruby-tall.html.ini b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-drop-over-ruby-tall.html.ini
index 6c27752..7ba52f0 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-drop-over-ruby-tall.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-drop-over-ruby-tall.html.ini
@@ -1,4 +1,4 @@
 [initial-letter-block-position-drop-over-ruby-tall.html]
   expected:
-    if (os == "linux") and (product == "content_shell") and (flag_specific == "disable-layout-ng"): FAIL
-    if (os == "linux") and (product == "chrome"): FAIL
+    if (product == "content_shell") and (flag_specific == "disable-layout-ng"): FAIL
+    if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins-vrl.html.ini b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins-vrl.html.ini
index b5f8d7b..24a438372 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins-vrl.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-margins-vrl.html.ini
@@ -1,4 +1,4 @@
 [initial-letter-block-position-margins-vrl.html]
   expected:
-    if (flag_specific == "") and (product == "chrome"): [PASS, FAIL]
-    if flag_specific == "disable-layout-ng": FAIL
+    if (product == "content_shell") and (flag_specific == ""): PASS
+    FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-raise-over-ruby-tall.html.ini b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-raise-over-ruby-tall.html.ini
index 50a3c7cc..4b8cec5 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-raise-over-ruby-tall.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-block-position-raise-over-ruby-tall.html.ini
@@ -1,4 +1,4 @@
 [initial-letter-block-position-raise-over-ruby-tall.html]
   expected:
-    if (product == "content_shell") and (flag_specific == "disable-layout-ng"): FAIL
-    if product == "chrome": 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/css/css-inline/initial-letter/initial-letter-drop-initial-rtl.html.ini b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial-rtl.html.ini
index 04516eb..d6e8699 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial-rtl.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial-rtl.html.ini
@@ -1,4 +1,4 @@
 [initial-letter-drop-initial-rtl.html]
   expected:
-    if (product == "content_shell") and (flag_specific == "disable-layout-ng"): FAIL
-    if product == "chrome": 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/css/css-inline/initial-letter/initial-letter-drop-initial-vrl.html.ini b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial-vrl.html.ini
index 6c731bb..9324bd34 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial-vrl.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-drop-initial-vrl.html.ini
@@ -1,4 +1,4 @@
 [initial-letter-drop-initial-vrl.html]
   expected:
-    if (product == "content_shell") and (flag_specific == "disable-layout-ng"): FAIL
-    if product == "chrome": [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/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 72b9d1f..c90a4c2 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,3 +1,4 @@
 [initial-letter-float-001-vlr.html]
   expected:
+    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/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 d320f2a..7d4942a 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,4 +1,4 @@
 [initial-letter-float-001-vrl.html]
   expected:
-    if (product == "content_shell") and (flag_specific == "disable-layout-ng"): FAIL
-    if product == "chrome": 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/css/css-inline/initial-letter/initial-letter-float-002.html.ini b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-float-002.html.ini
index 3555bde..eeb0e18 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-float-002.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-float-002.html.ini
@@ -1,3 +1,4 @@
 [initial-letter-float-002.html]
   expected:
+    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/css/css-inline/initial-letter/initial-letter-float-005.html.ini b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-float-005.html.ini
index e71bd47..702ca03f 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-float-005.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-float-005.html.ini
@@ -1,3 +1,4 @@
 [initial-letter-float-005.html]
   expected:
+    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/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 2f25a7a..fbc24c2 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,4 @@
 [initial-letter-indentation.html]
   expected:
-    if (flag_specific == "") and (product == "chrome"): [PASS, FAIL]
-    if flag_specific == "disable-layout-ng": FAIL
+    if (product == "content_shell") and (flag_specific == "disable-layout-ng"): FAIL
+    if product == "chrome": 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 24aef2d..87a653d8 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,4 @@
 [initial-letter-layout-text-decoration-underline.html]
   expected:
-    if (flag_specific == "") and (product == "chrome"): [FAIL, PASS]
+    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/css/css-inline/initial-letter/initial-letter-raise-initial-vlr.html.ini b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-vlr.html.ini
index 71ec40f..3487598f 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-vlr.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raise-initial-vlr.html.ini
@@ -1,4 +1,4 @@
 [initial-letter-raise-initial-vlr.html]
   expected:
-    if (flag_specific == "") and (product == "chrome"): [PASS, FAIL]
-    if flag_specific == "disable-layout-ng": FAIL
+    if (product == "content_shell") and (flag_specific == "disable-layout-ng"): FAIL
+    if 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 88381390..0d15c00 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,4 +1,4 @@
 [initial-letter-raised-sunken-caps-raise.html]
   expected:
-    if (product == "content_shell") and (flag_specific == "disable-layout-ng"): FAIL
-    if product == "chrome": 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/css/css-inline/initial-letter/initial-letter-raised-sunken-caps-sunken.html.ini b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raised-sunken-caps-sunken.html.ini
index 858a0ee..9280e8e 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raised-sunken-caps-sunken.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-raised-sunken-caps-sunken.html.ini
@@ -1,4 +1,4 @@
 [initial-letter-raised-sunken-caps-sunken.html]
   expected:
-    if (product == "content_shell") and (flag_specific == "disable-layout-ng"): FAIL
-    if product == "chrome": 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/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 017a0f1..84fa955 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,4 @@
 [initial-letter-sunk-initial-vlr.html]
   expected:
-    if (product == "content_shell") and (flag_specific == "disable-layout-ng"): FAIL
-    if product == "chrome": [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/css/css-inline/initial-letter/initial-letter-sunk-initial-vrl.html.ini b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial-vrl.html.ini
index 48e8fe1..68a12ebb 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial-vrl.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-sunk-initial-vrl.html.ini
@@ -1,3 +1,4 @@
 [initial-letter-sunk-initial-vrl.html]
   expected:
-    if (product == "content_shell") and (flag_specific == "disable-layout-ng"): 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/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 5170dd0..dd1718d 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,4 +1,4 @@
 [initial-letter-with-first-line.html]
   expected:
-    if (flag_specific == "") and (product == "chrome"): [PASS, FAIL]
-    if flag_specific == "disable-layout-ng": FAIL
+    if (product == "content_shell") and (flag_specific == "disable-layout-ng"): FAIL
+    if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-with-tab-rtl.html.ini b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-with-tab-rtl.html.ini
index 2085f9a..c20c7725 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-with-tab-rtl.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-with-tab-rtl.html.ini
@@ -1,3 +1,4 @@
 [initial-letter-with-tab-rtl.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-tab.html.ini b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-with-tab.html.ini
index dbd3639..8bc01f5 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-with-tab.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/initial-letter/initial-letter-with-tab.html.ini
@@ -1,4 +1,4 @@
 [initial-letter-with-tab.html]
   expected:
-    if (product == "content_shell") and (flag_specific == "disable-layout-ng"): FAIL
-    if product == "chrome": 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/css/css-layout-api/fallback-intrinsic-sizes/constructor-error.https.html.ini b/third_party/blink/web_tests/external/wpt/css/css-layout-api/fallback-intrinsic-sizes/constructor-error.https.html.ini
new file mode 100644
index 0000000..1244ec0
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-layout-api/fallback-intrinsic-sizes/constructor-error.https.html.ini
@@ -0,0 +1,3 @@
+[constructor-error.https.html]
+  expected:
+    if product == "chrome": [ERROR, PASS]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-layout-api/intrinsic-sizes/negative-min.https.html.ini b/third_party/blink/web_tests/external/wpt/css/css-layout-api/intrinsic-sizes/negative-min.https.html.ini
new file mode 100644
index 0000000..a42ed9d4
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-layout-api/intrinsic-sizes/negative-min.https.html.ini
@@ -0,0 +1,3 @@
+[negative-min.https.html]
+  expected:
+    if os == "win": [PASS, TIMEOUT]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path/clip-path-inline-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path/clip-path-inline-001.html.ini
index c87eb823..3917a43 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path/clip-path-inline-001.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path/clip-path-inline-001.html.ini
@@ -1,3 +1,3 @@
 [clip-path-inline-001.html]
   expected:
-    if product == "chrome": FAIL
+    if product == "chrome": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-multicol/getclientrects-000.html.ini b/third_party/blink/web_tests/external/wpt/css/css-multicol/getclientrects-000.html.ini
index 7dcf0d3..bd86605e 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-multicol/getclientrects-000.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-multicol/getclientrects-000.html.ini
@@ -1,24 +1,24 @@
 [getclientrects-000.html]
   [horizontal-tb ltr]
     expected:
-      if product == "chrome": FAIL
+      if product == "chrome": [PASS, FAIL]
 
   [vertical-lr ltr]
     expected:
-      if product == "chrome": FAIL
+      if product == "chrome": [PASS, FAIL]
 
   [vertical-rl ltr]
     expected:
-      if product == "chrome": FAIL
+      if product == "chrome": [PASS, FAIL]
 
   [horizontal-tb rtl]
     expected:
-      if product == "chrome": FAIL
+      if product == "chrome": [PASS, FAIL]
 
   [vertical-lr rtl]
     expected:
-      if product == "chrome": FAIL
+      if product == "chrome": [PASS, FAIL]
 
   [vertical-rl rtl]
     expected:
-      if product == "chrome": FAIL
+      if product == "chrome": [PASS, FAIL]
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
index 1d32d95..38d7beae 100644
--- 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
@@ -1,24 +1,24 @@
 [getclientrects-001.html]
   [horizontal-tb ltr]
     expected:
-      if product == "chrome": FAIL
+      if product == "chrome": [PASS, FAIL]
 
   [vertical-lr ltr]
     expected:
-      if product == "chrome": FAIL
+      if product == "chrome": [PASS, FAIL]
 
   [vertical-rl ltr]
     expected:
-      if product == "chrome": FAIL
+      if product == "chrome": [PASS, FAIL]
 
   [horizontal-tb rtl]
     expected:
-      if product == "chrome": FAIL
+      if product == "chrome": [PASS, FAIL]
 
   [vertical-lr rtl]
     expected:
-      if product == "chrome": FAIL
+      if product == "chrome": [PASS, FAIL]
 
   [vertical-rl rtl]
     expected:
-      if product == "chrome": FAIL
+      if product == "chrome": [PASS, 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 53c5a71..af5b11c 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,4 +1,4 @@
 [scrollable-overflow-input-001.html]
   expected:
-    if (flag_specific == "") and (product == "chrome"): [PASS, FAIL]
-    if flag_specific == "disable-layout-ng": FAIL
+    if (product == "content_shell") and (flag_specific == "disable-layout-ng"): FAIL
+    if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollable-overflow-input-002.html.ini b/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollable-overflow-input-002.html.ini
index 6e03ac5..eba9b19 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollable-overflow-input-002.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-overflow/scrollable-overflow-input-002.html.ini
@@ -1,3 +1,3 @@
 [scrollable-overflow-input-002.html]
   expected:
-    if product == "chrome": FAIL
+    if product == "chrome": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-paint-api/parse-input-arguments-018.https.html.ini b/third_party/blink/web_tests/external/wpt/css/css-paint-api/parse-input-arguments-018.https.html.ini
index 9905f9f8..30ab18d 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-paint-api/parse-input-arguments-018.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-paint-api/parse-input-arguments-018.https.html.ini
@@ -1,2 +1,4 @@
 [parse-input-arguments-018.https.html]
-  expected: CRASH
+  expected:
+    if (flag_specific == "") and (product == "content_shell"): [PASS, CRASH]
+    CRASH
diff --git a/third_party/blink/web_tests/external/wpt/css/css-shapes/shape-outside/shape-image/shape-image-026.html.ini b/third_party/blink/web_tests/external/wpt/css/css-shapes/shape-outside/shape-image/shape-image-026.html.ini
new file mode 100644
index 0000000..d20ff4ec
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-shapes/shape-outside/shape-image/shape-image-026.html.ini
@@ -0,0 +1,3 @@
+[shape-image-026.html]
+  expected:
+    if os == "win": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-003.html.ini b/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-003.html.ini
index 6fa8326a..38e66a2 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-003.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-003.html.ini
@@ -1,3 +1,3 @@
 [text-transform-capitalize-003.html]
   expected:
-    if (flag_specific == "") and (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-018.html.ini b/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-018.html.ini
new file mode 100644
index 0000000..87e5140
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-text/text-transform/text-transform-capitalize-018.html.ini
@@ -0,0 +1,3 @@
+[text-transform-capitalize-018.html]
+  expected:
+    if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/line-height-step.html b/third_party/blink/web_tests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/line-height-step.html
deleted file mode 100644
index 2a25562f..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/line-height-step.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!doctype html>
-<meta charset="utf-8">
-<title>'line-height-step' property</title>
-<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-get">
-<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-set">
-<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#property-stle-value-normalization">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../../resources/testhelper.js"></script>
-<script src="resources/testsuite.js"></script>
-<body>
-<div id="log"></div>
-<script>
-'use strict';
-
-runPropertyTests('line-height-step', [
-  {
-    syntax: '<length>',
-    specified: assert_is_equal_with_range_handling
-  }
-]);
-
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/printing/input-file-print.html.ini b/third_party/blink/web_tests/external/wpt/css/printing/input-file-print.html.ini
index 1ec656f..be2fa576 100644
--- a/third_party/blink/web_tests/external/wpt/css/printing/input-file-print.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/printing/input-file-print.html.ini
@@ -1,3 +1,3 @@
 [input-file-print.html]
   expected:
-    if product == "chrome": FAIL
+    if product == "chrome": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/parsing/parse-has-disallow-nesting-has-inside-has-expected.txt b/third_party/blink/web_tests/external/wpt/css/selectors/parsing/parse-has-disallow-nesting-has-inside-has-expected.txt
deleted file mode 100644
index daddf3a..0000000
--- a/third_party/blink/web_tests/external/wpt/css/selectors/parsing/parse-has-disallow-nesting-has-inside-has-expected.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-This is a testharness.js-based test.
-FAIL ".a:has(.b:has(.c))" should be a valid selector Failed to execute 'querySelector' on 'Document': '.a:has(.b:has(.c))' is not a valid selector.
-PASS ".a:has(.b:has(.c), .d)" should be a valid selector
-PASS ".a:has(.b:is(.c:has(.d) .e))" should be a valid selector
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/parsing/parse-has-disallow-nesting-has-inside-has.html b/third_party/blink/web_tests/external/wpt/css/selectors/parsing/parse-has-disallow-nesting-has-inside-has.html
index 0a30718d..9cf989f 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/parsing/parse-has-disallow-nesting-has-inside-has.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/parsing/parse-has-disallow-nesting-has-inside-has.html
@@ -7,7 +7,7 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="/css/support/parsing-testcommon.js"></script>
 <script>
-  test_valid_selector('.a:has(.b:has(.c))', '.a:has()');
-  test_valid_selector('.a:has(.b:has(.c), .d)', '.a:has(.d)');
-  test_valid_selector('.a:has(.b:is(.c:has(.d) .e))', '.a:has(.b:is())');
+  test_invalid_selector('.a:has(.b:has(.c))');
+  test_valid_selector('.a:has(:is(.b:has(.c)))', '.a:has(:is())');
+  test_valid_selector('.a:has(:is(.b:has(.c), .d))', '.a:has(:is(.d))');
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/parsing/parse-has-disallow-nesting-has-inside-has.html.ini b/third_party/blink/web_tests/external/wpt/css/selectors/parsing/parse-has-disallow-nesting-has-inside-has.html.ini
deleted file mode 100644
index 8c2bec6..0000000
--- a/third_party/blink/web_tests/external/wpt/css/selectors/parsing/parse-has-disallow-nesting-has-inside-has.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[parse-has-disallow-nesting-has-inside-has.html]
-  [".a:has(.b:has(.c))" should be a valid selector]
-    expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/parsing/parse-has-expected.txt b/third_party/blink/web_tests/external/wpt/css/selectors/parsing/parse-has-expected.txt
index f10c3be..d486ca05e 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/parsing/parse-has-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/parsing/parse-has-expected.txt
@@ -22,9 +22,12 @@
 PASS ".a:has(.b):has(.c)" should be a valid selector
 PASS "*|*:has(*)" should be a valid selector
 PASS ":has(*|*)" should be a valid selector
-FAIL ".a:has()" should be a valid selector Failed to execute 'querySelector' on 'Document': '.a:has()' is not a valid selector.
 PASS ":has" should be an invalid selector
 PASS ".a:has" should be an invalid selector
 PASS ".a:has b" should be an invalid selector
+PASS ":has()" should be an invalid selector
+PASS ":has(123)" should be an invalid selector
+FAIL ":has(.a, 123)" should be an invalid selector assert_throws_dom: ":has(.a, 123)" should throw in querySelector function "() => document.querySelector(selector)" did not throw
+PASS ":has(:is(.a, 123))" should be a valid selector
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/parsing/parse-has.html b/third_party/blink/web_tests/external/wpt/css/selectors/parsing/parse-has.html
index e15d335..5d071010 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/parsing/parse-has.html
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/parsing/parse-has.html
@@ -30,8 +30,12 @@
   test_valid_selector('.a:has(.b):has(.c)');
   test_valid_selector('*|*:has(*)', ':has(*)');
   test_valid_selector(':has(*|*)', ':has(*)');
-  test_valid_selector('.a:has()', '.a:has()');
   test_invalid_selector(':has');
   test_invalid_selector('.a:has');
   test_invalid_selector('.a:has b');
+  /* :has() is unforgiving, but :is() can still forgive */
+  test_invalid_selector(':has()');
+  test_invalid_selector(':has(123)');
+  test_invalid_selector(':has(.a, 123)');
+  test_valid_selector(':has(:is(.a, 123))', ':has(:is(.a))');
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/parsing/parse-has.html.ini b/third_party/blink/web_tests/external/wpt/css/selectors/parsing/parse-has.html.ini
index d35c1f9..4f611c9 100644
--- a/third_party/blink/web_tests/external/wpt/css/selectors/parsing/parse-has.html.ini
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/parsing/parse-has.html.ini
@@ -1,3 +1,3 @@
 [parse-has.html]
-  [".a:has()" should be a valid selector]
+  [":has(.a, 123)" should be an invalid selector]
     expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/dom/ranges/Range-mutations-dataChange.html.ini b/third_party/blink/web_tests/external/wpt/dom/ranges/Range-mutations-dataChange.html.ini
index 7158a50..c1f1d46 100644
--- a/third_party/blink/web_tests/external/wpt/dom/ranges/Range-mutations-dataChange.html.ini
+++ b/third_party/blink/web_tests/external/wpt/dom/ranges/Range-mutations-dataChange.html.ini
@@ -1,3 +1,3 @@
 [Range-mutations-dataChange.html]
   expected:
-    if flag_specific == "disable-site-isolation-trials": CRASH
+    if flag_specific == "disable-site-isolation-trials": [OK, CRASH]
diff --git a/third_party/blink/web_tests/external/wpt/dom/ranges/Range-mutations-replaceData.html.ini b/third_party/blink/web_tests/external/wpt/dom/ranges/Range-mutations-replaceData.html.ini
index 51870a6..8b10363 100644
--- a/third_party/blink/web_tests/external/wpt/dom/ranges/Range-mutations-replaceData.html.ini
+++ b/third_party/blink/web_tests/external/wpt/dom/ranges/Range-mutations-replaceData.html.ini
@@ -1,3 +1,3 @@
 [Range-mutations-replaceData.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/domxpath/xml_xpath_runner.html.ini b/third_party/blink/web_tests/external/wpt/domxpath/xml_xpath_runner.html.ini
new file mode 100644
index 0000000..b9af709d7
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/domxpath/xml_xpath_runner.html.ini
@@ -0,0 +1,3 @@
+[xml_xpath_runner.html]
+  expected:
+    if flag_specific == "disable-layout-ng": [OK, CRASH]
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 793ad47..5baa190 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
@@ -13,6 +13,22 @@
 [join-pre-and-other-block.html?method=select-boundary&block=div]
 
 [join-pre-and-other-block.html?method=forwarddelete&block=p]
+  expected: [OK, TIMEOUT]
+  [forwarddelete at <p>abc[\]</p>\\n<pre><b>def\\n</b>ghi</pre> (with <style>pre { white-space: pre; }</style>)]
+    expected: [PASS, TIMEOUT]
+
+  [forwarddelete at <p>abc[\]</p>\\n<pre>\\ndef\\nghi</pre> (with <style>pre { white-space: pre; }</style>)]
+    expected: [PASS, NOTRUN]
+
+  [forwarddelete at <p>abc[\]</p><pre>\\ndef\\nghi</pre> (with <style>pre { white-space: pre; }</style>)]
+    expected: [PASS, NOTRUN]
+
+  [forwarddelete at <p>abc[\]</p>\\n<pre><b>def<br></b>ghi</pre> (with <style>pre { white-space: pre; }</style>)]
+    expected: [PASS, NOTRUN]
+
+  [forwarddelete at <p>abc[\]</p><pre><b>def<br></b>ghi</pre> (with <style>pre { white-space: pre; }</style>)]
+    expected: [PASS, NOTRUN]
+
 
 [join-pre-and-other-block.html?method=backspace&block=p]
 
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
deleted file mode 100644
index d439e022d..0000000
--- a/third_party/blink/web_tests/external/wpt/encoding/legacy-mb-japanese/euc-jp/eucjp-encode-href-errors-han.html.ini
+++ /dev/null
@@ -1,45 +0,0 @@
-[eucjp-encode-href-errors-han.html?2001-3000]
-
-[eucjp-encode-href-errors-han.html?7001-8000]
-
-[eucjp-encode-href-errors-han.html?6001-7000]
-
-[eucjp-encode-href-errors-han.html?21001-last]
-
-[eucjp-encode-href-errors-han.html?13001-14000]
-
-[eucjp-encode-href-errors-han.html?16001-17000]
-
-[eucjp-encode-href-errors-han.html?20001-21000]
-
-[eucjp-encode-href-errors-han.html?1001-2000]
-
-[eucjp-encode-href-errors-han.html?1-1000]
-
-[eucjp-encode-href-errors-han.html?5001-6000]
-
-[eucjp-encode-href-errors-han.html?15001-16000]
-
-[eucjp-encode-href-errors-han.html?14001-15000]
-
-[eucjp-encode-href-errors-han.html?3001-4000]
-  expected:
-    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): CRASH
-
-[eucjp-encode-href-errors-han.html?19001-20000]
-
-[eucjp-encode-href-errors-han.html?10001-11000]
-
-[eucjp-encode-href-errors-han.html?8001-9000]
-
-[eucjp-encode-href-errors-han.html?12001-13000]
-
-[eucjp-encode-href-errors-han.html?18001-19000]
-
-[eucjp-encode-href-errors-han.html?17001-18000]
-
-[eucjp-encode-href-errors-han.html?9001-10000]
-
-[eucjp-encode-href-errors-han.html?11001-12000]
-
-[eucjp-encode-href-errors-han.html?4001-5000]
diff --git a/third_party/blink/web_tests/external/wpt/encoding/legacy-mb-japanese/shift_jis/sjis-decode-ms_kanji.html.ini b/third_party/blink/web_tests/external/wpt/encoding/legacy-mb-japanese/shift_jis/sjis-decode-ms_kanji.html.ini
new file mode 100644
index 0000000..521412a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/encoding/legacy-mb-japanese/shift_jis/sjis-decode-ms_kanji.html.ini
@@ -0,0 +1,17 @@
+[sjis-decode-ms_kanji.html?6001-7000]
+
+[sjis-decode-ms_kanji.html?4001-5000]
+
+[sjis-decode-ms_kanji.html?3001-4000]
+  expected:
+    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [OK, CRASH]
+
+[sjis-decode-ms_kanji.html?5001-6000]
+
+[sjis-decode-ms_kanji.html?2001-3000]
+
+[sjis-decode-ms_kanji.html?7001-last]
+
+[sjis-decode-ms_kanji.html?1001-2000]
+
+[sjis-decode-ms_kanji.html?1-1000]
diff --git a/third_party/blink/web_tests/external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-decode-ksc5601.html.ini b/third_party/blink/web_tests/external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-decode-ksc5601.html.ini
index 0bcc6595..9df145d 100644
--- a/third_party/blink/web_tests/external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-decode-ksc5601.html.ini
+++ b/third_party/blink/web_tests/external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-decode-ksc5601.html.ini
@@ -3,8 +3,6 @@
 [euckr-decode-ksc5601.html?8001-9000]
 
 [euckr-decode-ksc5601.html?10001-11000]
-  expected:
-    if os == "win": [OK, CRASH]
 
 [euckr-decode-ksc5601.html?2001-3000]
 
@@ -19,6 +17,8 @@
 [euckr-decode-ksc5601.html?15001-16000]
 
 [euckr-decode-ksc5601.html?17001-last]
+  expected:
+    if os == "win": [OK, CRASH]
 
 [euckr-decode-ksc5601.html?7001-8000]
 
diff --git a/third_party/blink/web_tests/external/wpt/encoding/legacy-mb-tchinese/big5/big5-decode-csbig5.html.ini b/third_party/blink/web_tests/external/wpt/encoding/legacy-mb-tchinese/big5/big5-decode-csbig5.html.ini
new file mode 100644
index 0000000..0dbbd06
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/encoding/legacy-mb-tchinese/big5/big5-decode-csbig5.html.ini
@@ -0,0 +1,31 @@
+[big5-decode-csbig5.html?2001-3000]
+
+[big5-decode-csbig5.html?1-1000]
+
+[big5-decode-csbig5.html?7001-8000]
+
+[big5-decode-csbig5.html?12001-13000]
+
+[big5-decode-csbig5.html?13001-14000]
+
+[big5-decode-csbig5.html?14001-last]
+
+[big5-decode-csbig5.html?3001-4000]
+
+[big5-decode-csbig5.html?6001-7000]
+
+[big5-decode-csbig5.html?4001-5000]
+
+[big5-decode-csbig5.html?9001-10000]
+  expected:
+    if flag_specific == "disable-layout-ng": [OK, CRASH]
+
+[big5-decode-csbig5.html?8001-9000]
+
+[big5-decode-csbig5.html?1001-2000]
+
+[big5-decode-csbig5.html?10001-11000]
+
+[big5-decode-csbig5.html?5001-6000]
+
+[big5-decode-csbig5.html?11001-12000]
diff --git a/third_party/blink/web_tests/external/wpt/encoding/unsupported-labels.window.js.ini b/third_party/blink/web_tests/external/wpt/encoding/unsupported-labels.window.js.ini
index a9762cc..ff6ba32 100644
--- a/third_party/blink/web_tests/external/wpt/encoding/unsupported-labels.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/encoding/unsupported-labels.window.js.ini
@@ -1,6 +1,6 @@
 [unsupported-labels.window.html]
   expected:
-    if product == "chrome": [OK, ERROR]
+    if product == "chrome": [OK, TIMEOUT]
     TIMEOUT
   [x-mac-gurmukhi is not supported by the Encoding Standard]
     expected: [PASS, TIMEOUT]
@@ -70,3 +70,63 @@
 
   [x-mac-vt100 is not supported by the Encoding Standard]
     expected: [PASS, TIMEOUT]
+
+  [x-iscii-pa is not supported by the Encoding Standard]
+    expected: [PASS, TIMEOUT]
+
+  [x-mac-ce is not supported by the Encoding Standard]
+    expected: [PASS, TIMEOUT]
+
+  [x-iscii-ka is not supported by the Encoding Standard]
+    expected: [PASS, TIMEOUT]
+
+  [x-mac-arabic is not supported by the Encoding Standard]
+    expected: [PASS, TIMEOUT]
+
+  [x-mac-centraleurroman is not supported by the Encoding Standard]
+    expected: [PASS, TIMEOUT]
+
+  [x-mac-chinesetrad is not supported by the Encoding Standard]
+    expected: [PASS, TIMEOUT]
+
+  [x-iscii-ta is not supported by the Encoding Standard]
+    expected: [PASS, TIMEOUT]
+
+  [x-iscii-ma is not supported by the Encoding Standard]
+    expected: [PASS, TIMEOUT]
+
+  [x-iscii-t is not supported by the Encoding Standard]
+    expected: [PASS, TIMEOUT]
+
+  [x-iscii-te is not supported by the Encoding Standard]
+    expected: [PASS, TIMEOUT]
+
+  [x-mac-chinesesimp is not supported by the Encoding Standard]
+    expected: [PASS, TIMEOUT]
+
+  [x-iscii-or is not supported by the Encoding Standard]
+    expected: [PASS, TIMEOUT]
+
+  [x-ia5-swedish is not supported by the Encoding Standard]
+    expected: [PASS, TIMEOUT]
+
+  [x-iscii-be is not supported by the Encoding Standard]
+    expected: [PASS, TIMEOUT]
+
+  [x-iscii-as is not supported by the Encoding Standard]
+    expected: [PASS, TIMEOUT]
+
+  [x-iscii-de is not supported by the Encoding Standard]
+    expected: [PASS, TIMEOUT]
+
+  [x-ia5-norwegian is not supported by the Encoding Standard]
+    expected: [PASS, TIMEOUT]
+
+  [x-iscii-gu is not supported by the Encoding Standard]
+    expected: [PASS, TIMEOUT]
+
+  [x-ia5-german is not supported by the Encoding Standard]
+    expected: [PASS, TIMEOUT]
+
+  [x-ia5 is not supported by the Encoding Standard]
+    expected: [PASS, TIMEOUT]
diff --git a/third_party/blink/web_tests/external/wpt/fetch/metadata/generated/element-iframe.sub.html.ini b/third_party/blink/web_tests/external/wpt/fetch/metadata/generated/element-iframe.sub.html.ini
index 96b1dbd1f..11568fc 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/metadata/generated/element-iframe.sub.html.ini
+++ b/third_party/blink/web_tests/external/wpt/fetch/metadata/generated/element-iframe.sub.html.ini
@@ -1,3 +1,3 @@
 [element-iframe.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/element-input-image.https.sub.html.ini b/third_party/blink/web_tests/external/wpt/fetch/metadata/generated/element-input-image.https.sub.html.ini
index 7570dde..09e396b 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/metadata/generated/element-input-image.https.sub.html.ini
+++ b/third_party/blink/web_tests/external/wpt/fetch/metadata/generated/element-input-image.https.sub.html.ini
@@ -1,3 +1,5 @@
 [element-input-image.https.sub.html]
+  expected:
+    if os == "win": [OK, TIMEOUT]
   [sec-fetch-site - HTTPS downgrade-upgrade, no attributes]
     expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/iframe.tentative.https.window.js.ini b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/iframe.tentative.https.window.js.ini
index feb27192..b72e9d8 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/iframe.tentative.https.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/iframe.tentative.https.window.js.ini
@@ -1,6 +1,6 @@
 [iframe.tentative.https.window.html]
   expected:
-    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [OK, TIMEOUT]
+    if flag_specific == "disable-site-isolation-trials": [OK, TIMEOUT]
   [private to local: success.]
     expected: FAIL
 
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 352bde5..8f76e15 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,13 +1,12 @@
 [service-worker-background-fetch.https.window.html]
   [local to local: success.]
     expected:
-      if (product == "content_shell") and (flag_specific == "") and (os == "linux"): [PASS, FAIL]
-      if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
       if product == "chrome": FAIL
 
   [private to local: success.]
     expected:
       if (flag_specific == "") and (product == "chrome"): FAIL
+      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
 
   [private to private: success.]
     expected:
@@ -15,9 +14,9 @@
 
   [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-site-isolation-trials"): [PASS, FAIL]
-      if product == "chrome": FAIL
+      if (flag_specific == "") and (product == "chrome"): FAIL
+      if flag_specific == "disable-layout-ng": PASS
+      [PASS, FAIL]
 
   [public to private: success.]
     expected:
diff --git a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/service-worker-fetch.https.window.js.ini b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/service-worker-fetch.https.window.js.ini
index ed7c7004..21e60215 100644
--- a/third_party/blink/web_tests/external/wpt/fetch/private-network-access/service-worker-fetch.https.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/fetch/private-network-access/service-worker-fetch.https.window.js.ini
@@ -1,10 +1,3 @@
 [service-worker-fetch.https.window.html]
   expected:
-    if product == "chrome": [OK, TIMEOUT]
-  [treat-as-public to private: success.]
-    expected:
-      if product == "chrome": [PASS, TIMEOUT]
-
-  [treat-as-public to public: success.]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
+    if (product == "content_shell") and (flag_specific == "") and (os == "linux"): [OK, TIMEOUT]
diff --git a/third_party/blink/web_tests/external/wpt/focus/activeelement-after-immediately-focusing-same-site-iframe.html.ini b/third_party/blink/web_tests/external/wpt/focus/activeelement-after-immediately-focusing-same-site-iframe.html.ini
new file mode 100644
index 0000000..75cf448d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/focus/activeelement-after-immediately-focusing-same-site-iframe.html.ini
@@ -0,0 +1,3 @@
+[activeelement-after-immediately-focusing-same-site-iframe.html]
+  expected:
+    if product == "chrome": [OK, ERROR]
diff --git a/third_party/blink/web_tests/external/wpt/focus/iframe-contentwindow-focus-with-different-site-intermediate-frame.html.ini b/third_party/blink/web_tests/external/wpt/focus/iframe-contentwindow-focus-with-different-site-intermediate-frame.html.ini
index 0a09915..c06c0e7b 100644
--- a/third_party/blink/web_tests/external/wpt/focus/iframe-contentwindow-focus-with-different-site-intermediate-frame.html.ini
+++ b/third_party/blink/web_tests/external/wpt/focus/iframe-contentwindow-focus-with-different-site-intermediate-frame.html.ini
@@ -1,3 +1,5 @@
 [iframe-contentwindow-focus-with-different-site-intermediate-frame.html]
+  expected:
+    if product == "chrome": [OK, ERROR]
   [Check result]
     expected: FAIL
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 a4e9ffe..5019503 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,3 +1,5 @@
 [iframe-focus-with-different-site-intermediate-frame.html]
+  expected:
+    if flag_specific == "disable-site-isolation-trials": [OK, 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
deleted file mode 100644
index 76445ac..0000000
--- a/third_party/blink/web_tests/external/wpt/fs/FileSystemFileHandle-create-sync-access-handle.https.tentative.window.js.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[FileSystemFileHandle-create-sync-access-handle.https.tentative.window.html]
-  [Attempt to create a sync access handle.]
-    expected:
-      if (flag_specific == "") and (os == "win"): [PASS, FAIL]
-      if flag_specific == "disable-site-isolation-trials": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-consume-user-activation.html b/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-consume-user-activation.html
new file mode 100644
index 0000000..cc480671
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-consume-user-activation.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>Element#requestFullscreen() consumes user activation</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<div id="log"></div>
+<script>
+promise_test(async (t) => {
+    t.add_cleanup(() => {
+        if (document.fullscreenElement) return document.exitFullscreen();
+    });
+    const div = document.querySelector("div");
+
+    await test_driver.bless("fullscreen");
+    assert_true(navigator.userActivation.isActive, "Activation must be active");
+    // Request fullscreen twice in a row. The first request should consume the
+    // user activation and succeed, and the second request should fail because
+    // of the user activation requirement.
+    const p1 = div.requestFullscreen();
+    assert_false(navigator.userActivation.isActive, "Transient activation is consumed");
+    const p2 = promise_rejects_js(t, TypeError, div.requestFullscreen());
+    await Promise.all([p1, p2]);
+});
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-consume-user-activation.html.ini b/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-consume-user-activation.html.ini
new file mode 100644
index 0000000..83b659bf
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-consume-user-activation.html.ini
@@ -0,0 +1,4 @@
+[element-request-fullscreen-consume-user-activation.html]
+  expected: TIMEOUT
+  [Element#requestFullscreen() consumes user activation]
+    expected: TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-same-element.html b/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-same-element.html
new file mode 100644
index 0000000..a2b04dd1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-same-element.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Element#requestFullscreen() on the current fullscreen element</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<div id="log"></div>
+<script>
+promise_test(async (t) => {
+    t.add_cleanup(() => {
+        if (document.fullscreenElement) return document.exitFullscreen();
+    });
+
+    // Use the body element as the fullscreen element, because the second
+    // test_driver.bless() call needs to insert a button inside of it, which
+    // can't be clicked if another element is already fullscreen.
+    const target = document.body;
+
+    // First enter fullscreen.
+    await test_driver.bless("fullscreen", () => target.requestFullscreen());
+    assert_equals(document.fullscreenElement, target, "fullscreen element after first request");
+
+    // Now request fullscreen again, which should be a no-op.
+    await test_driver.bless("fullscreen", () => target.requestFullscreen());
+    assert_equals(document.fullscreenElement, target, "fullscreen element after second request");
+});
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-same-element.html.ini b/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-same-element.html.ini
new file mode 100644
index 0000000..21020b07
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-same-element.html.ini
@@ -0,0 +1,4 @@
+[element-request-fullscreen-same-element.html]
+  expected: TIMEOUT
+  [Element#requestFullscreen() on the current fullscreen element]
+    expected: TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-same-manual.html b/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-same-manual.html
deleted file mode 100644
index defe9ce5..0000000
--- a/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-same-manual.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!DOCTYPE html>
-<title>Element#requestFullscreen() on the current fullscreen element</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../trusted-click.js"></script>
-<div id="log"></div>
-<div id="target"></div>
-<script>
-async_test(t => {
-  var target = document.getElementById("target");
-
-  document.onfullscreenchange = t.step_func(() => {
-    assert_equals(document.fullscreenElement, target);
-
-    // The next requestFullscreen() should fire no events due to "If element is
-    // doc's fullscreen element, terminate these subsubsteps."
-    document.onfullscreenchange = t.unreached_func("fullscreenchange event");
-
-    trusted_click(t, () => {
-      target.requestFullscreen();
-
-      // Wait until after the next animation frame.
-      requestAnimationFrame(t.step_func_done());
-    }, target);
-  });
-  document.onfullscreenerror = t.unreached_func("fullscreenerror event");
-
-  trusted_request(t, target);
-});
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-twice-manual.html b/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-twice-manual.html
deleted file mode 100644
index 06641de..0000000
--- a/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-twice-manual.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!DOCTYPE html>
-<title>Element#requestFullscreen() twice</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../trusted-click.js"></script>
-<div id="log"></div>
-<script>
-async_test(t => {
-  const div = document.querySelector("div");
-
-  document.onfullscreenchange = t.step_func(() => {
-    assert_equals(document.fullscreenElement, div);
-    // Done, but ensure that there's only one fullscreenchange event.
-    document.onfullscreenchange = t.unreached_func("second fullscreenchange event");
-    step_timeout(t.step_func_done());
-  });
-  document.onfullscreenerror = t.unreached_func("fullscreenerror event");
-
-  trusted_click(t, () => {
-    // Request fullscreen twice.
-    div.requestFullscreen();
-    assert_equals(document.fullscreenElement, null, "fullscreenElement after first requestFullscreen()");
-    div.requestFullscreen();
-    assert_equals(document.fullscreenElement, null, "fullscreenElement after second requestFullscreen()");
-  }, document.body);
-});
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-twice-manual.tentative.html b/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-twice-manual.tentative.html
deleted file mode 100644
index a8b5531f..0000000
--- a/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-twice-manual.tentative.html
+++ /dev/null
@@ -1,46 +0,0 @@
-<!DOCTYPE html>
-<!--
-   Tentative due to:
-    https://github.com/whatwg/fullscreen/issues/152
-
--->
-<title>Element#requestFullscreen() twice</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../trusted-click.js"></script>
-<div id="log"></div>
-<script>
-promise_test(async (test) => {
-  const div = document.querySelector("div");
-
-  const fullscreenChangePromise = new Promise((resolve, reject) => {
-    document.onfullscreenchange = test.step_func(() => {
-      assert_equals(document.fullscreenElement, div);
-      // Ensure that there's only one fullscreenchange event.
-      document.onfullscreenchange = test.unreached_func("second fullscreenchange event");
-      resolve();
-    });
-  });
-
-  const fullscreenErrorPromise = new Promise((resolve, reject) => {
-    document.onfullscreenerror = test.step_func(() => {
-      resolve();
-    });
-  });
-
-  trusted_click(test, () => {
-    // Request fullscreen twice.
-    div.requestFullscreen();
-    assert_equals(document.fullscreenElement, null, "fullscreenElement after first requestFullscreen()");
-    var p = div.requestFullscreen();
-    if (p) {
-      p.then(test.unreached_func("promise unexpectedly resolved"), ()=>{});
-    }
-  }, document.body);
-
-  await Promise.all([
-    fullscreenChangePromise,
-    fullscreenErrorPromise,
-  ]);
-});
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-two-elements-manual.html b/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-two-elements-manual.html
deleted file mode 100644
index 11baad7..0000000
--- a/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-two-elements-manual.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!DOCTYPE html>
-<title>Element#requestFullscreen() on two elements in the same document</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../trusted-click.js"></script>
-<div id="log"></div>
-<div id="a"></div>
-<div id="b"></div>
-<script>
-async_test(t => {
-  // Request fullscreen on both elements, but in reverse tree order.
-  const a = document.getElementById('a');
-  const b = document.getElementById('b');
-
-  // Expect two fullscreenchange events, with document.fullscreenElement
-  // changing in the same order as the requests.
-  const order = [];
-  document.onfullscreenchange = t.step_func(() => {
-    assert_in_array(document.fullscreenElement, [a, b]);
-    order.push(document.fullscreenElement.id);
-    if (order.length == 2) {
-      // Since fullscreenchange event occurs at animation frame timing we might
-      // have not seen the transition from null -> 'b' but just see the
-      // resulting 'a' transition twice.
-      assert_true(order[0] == 'a' || order[0] == 'b', 'first id seen is a or b');
-      assert_equals(order[1], 'a', 'second id seen is b');
-      t.done();
-    }
-  });
-  document.onfullscreenerror = t.unreached_func('fullscreenerror event');
-
-  trusted_click(t, () => {
-    b.requestFullscreen();
-    a.requestFullscreen();
-  }, document.body);
-});
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-two-elements-manual.tentative.html b/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-two-elements-manual.tentative.html
deleted file mode 100644
index 5ebc628b..0000000
--- a/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-two-elements-manual.tentative.html
+++ /dev/null
@@ -1,56 +0,0 @@
-<!DOCTYPE html>
-<!--
-   Tentative due to:
-    https://github.com/whatwg/fullscreen/issues/152
-
--->
-<title>Element#requestFullscreen() on two elements in the same document</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../trusted-click.js"></script>
-<div id="log"></div>
-<div id="a"></div>
-<div id="b"></div>
-<script>
-promise_test(async (test) => {
-  // Request fullscreen on both elements, but in reverse tree order.
-  const a = document.getElementById('a');
-  const b = document.getElementById('b');
-
-  // Expect two fullscreenchange events, with document.fullscreenElement
-  // changing in the same order as the requests.
-  const order = [];
-  const fullscreenChangePromise = new Promise((resolve, reject) => {
-    document.onfullscreenchange = test.step_func(() => {
-      assert_in_array(document.fullscreenElement, [a, b]);
-      order.push(document.fullscreenElement.id);
-      if (order.length == 2) {
-        // Since fullscreenchange event occurs at animation frame timing we might
-        // have not seen the transition from null -> 'b' but just see the
-        // resulting 'a' transition twice.
-        assert_true(order[0] == 'a' || order[0] == 'b', 'first id seen is a or b');
-        assert_equals(order[1], 'a', 'second id seen is b');
-      }
-      resolve();
-    });
-  });
-  const fullscreenErrorPromise = new Promise((resolve, reject) => {
-    document.onfullscreenerror = test.step_func(() => {
-      resolve();
-    });
-  });
-
-  trusted_click(test, () => {
-    b.requestFullscreen();
-    var p = a.requestFullscreen();
-    if (p) {
-      p.then(test.unreached_func("promise unexpectedly resolved"), ()=>{});
-    }
-  }, document.body);
-
-  await Promise.all([
-    fullscreenChangePromise,
-    fullscreenErrorPromise,
-  ]);
-});
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-two-iframes-manual.html b/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-two-iframes-manual.html
deleted file mode 100644
index 916ae79..0000000
--- a/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-two-iframes-manual.html
+++ /dev/null
@@ -1,48 +0,0 @@
-<!DOCTYPE html>
-<title>Element#requestFullscreen() on two elements in different iframes</title>
-<meta name="timeout" content="long">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../trusted-click.js"></script>
-<div id="log"></div>
-<iframe id="a" allowfullscreen></iframe>
-<iframe id="b" allowfullscreen></iframe>
-<script>
-async_test(t => {
-  // Request fullscreen on the body elements of both iframes, but in reverse
-  // tree order.
-  const a = document.getElementById('a');
-  const b = document.getElementById('b');
-
-  // Expect two fullscreenchange events, with document.fullscreenElement
-  // changing in the same order as the requests. (Events should also fire on the
-  // iframes' documents, but this is not covered by this test.)
-  const order = [];
-  document.onfullscreenchange = t.step_func(() => {
-    assert_in_array(document.fullscreenElement, [a, b]);
-    order.push(document.fullscreenElement.id);
-    if (order.length == 2) {
-      // When the second event arrived, the fullscreen element may still be the
-      // old one.
-      //
-      // TODO(mustaq): We need a better explanation here to cover the tree-order
-      // idea of the spec.
-      assert_true(order[0] == 'a' || order[0] == 'b', 'first id seen is a or b');
-      assert_equals(order[1], 'a', 'second id seen is a');
-      t.done();
-    }
-  });
-  document.onfullscreenerror = t.unreached_func('fullscreenerror event');
-
-  // Make a trusted click on frame 'b' to activate it.
-  trusted_click(t, () => {
-    // Now queue a trusted click on frame 'a' to make back-to-back calls.
-    setTimeout(() => {
-      trusted_click(t, () => {
-        b.contentDocument.body.requestFullscreen();
-        a.contentDocument.body.requestFullscreen();
-      }, a.contentDocument.body);
-    }, 0);
-  }, b.contentDocument.body);
-});
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-two-iframes-manual.tentative.html b/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-two-iframes-manual.tentative.html
deleted file mode 100644
index 691c221..0000000
--- a/third_party/blink/web_tests/external/wpt/fullscreen/api/element-request-fullscreen-two-iframes-manual.tentative.html
+++ /dev/null
@@ -1,65 +0,0 @@
-<!DOCTYPE html>
-<!--
-   Tentative due to:
-    https://github.com/whatwg/fullscreen/issues/152
-
--->
-<title>Element#requestFullscreen() on two elements in different iframes</title>
-<meta name="timeout" content="long">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../trusted-click.js"></script>
-<div id="log"></div>
-<iframe id="a" allowfullscreen></iframe>
-<iframe id="b" allowfullscreen></iframe>
-<script>
-promise_test(async (test) => {
-  // Request fullscreen on the body elements of both iframes, but in reverse
-  // tree order.
-  const a = document.getElementById('a');
-  const b = document.getElementById('b');
-  var rejected = false;
-
-  // Expect two fullscreenchange events, with document.fullscreenElement
-  // changing in the same order as the requests. (Events should also fire on the
-  // iframes' documents, but this is not covered by this test.)
-  const order = [];
-  const fullscreenChangePromise = new Promise((resolve, reject) => {
-    document.onfullscreenchange = test.step_func(() => {
-      assert_in_array(document.fullscreenElement, [a, b]);
-      order.push(document.fullscreenElement.id);
-      if (order.length == 2) {
-        // When the second event arrived, the fullscreen element may still be the
-        // old one.
-        //
-        // TODO(mustaq): We need a better explanation here to cover the tree-order
-        // idea of the spec.
-        assert_true(order[0] == 'a' || order[0] == 'b', 'first id seen is a or b');
-        assert_equals(order[1], 'a', 'second id seen is a');
-      }
-      resolve();
-    });
-  });
-  const fullscreenErrorPromise = new Promise((resolve, reject) => {
-    document.onfullscreenerror = test.step_func(() => {
-      resolve();
-    });
-  });
-
-  // Make a trusted click on frame 'b' to activate it.
-  trusted_click(test, () => {
-    // Now queue a trusted click on frame 'a' to make back-to-back calls.
-    setTimeout(() => {
-      trusted_click(test, () => {
-        b.contentDocument.body.requestFullscreen();
-        a.contentDocument.body.requestFullscreen().catch(test.step_func_done());
-      }, a.contentDocument.body);
-    }, 0);
-  }, b.contentDocument.body);
-
-  await Promise.all([
-    fullscreenChangePromise,
-    fullscreenErrorPromise,
-  ]);
-});
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/hr-time/clamped-time-origin.html.ini b/third_party/blink/web_tests/external/wpt/hr-time/clamped-time-origin.html.ini
index aefff52..9082a0b2 100644
--- a/third_party/blink/web_tests/external/wpt/hr-time/clamped-time-origin.html.ini
+++ b/third_party/blink/web_tests/external/wpt/hr-time/clamped-time-origin.html.ini
@@ -1,3 +1,3 @@
 [clamped-time-origin.html]
   expected:
-    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/html/anonymous-iframe/anonymous-iframe-popup.tentative.https.window.js.ini b/third_party/blink/web_tests/external/wpt/html/anonymous-iframe/anonymous-iframe-popup.tentative.https.window.js.ini
index e222dfd..76ec160 100644
--- a/third_party/blink/web_tests/external/wpt/html/anonymous-iframe/anonymous-iframe-popup.tentative.https.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/html/anonymous-iframe/anonymous-iframe-popup.tentative.https.window.js.ini
@@ -1,3 +1,3 @@
 [anonymous-iframe-popup.tentative.https.window.html]
   expected:
-    if product == "chrome": ERROR
+    if product == "chrome": [OK, ERROR]
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 316e6541..e332734a 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
@@ -3,8 +3,6 @@
     if product == "chrome": [OK, ERROR]
 
 [embedding.tentative.https.window.html?13-last]
-  expected:
-    if product == "chrome": [OK, ERROR]
 
 [embedding.tentative.https.window.html?3-4]
   expected:
@@ -19,8 +17,6 @@
     if product == "chrome": ERROR
 
 [embedding.tentative.https.window.html?11-11]
-  expected:
-    if product == "chrome": ERROR
 
 [embedding.tentative.https.window.html?5-5]
 
@@ -38,12 +34,8 @@
 [embedding.tentative.https.window.html?12-12]
 
 [embedding.tentative.https.window.html?4-4]
-  expected:
-    if product == "chrome": ERROR
 
 [embedding.tentative.https.window.html?8-8]
-  expected:
-    if product == "chrome": ERROR
 
 [embedding.tentative.https.window.html?3-3]
 
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/focus.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/focus.html.ini
index 622a0b9..8bb63c5 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/focus.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/focus.html.ini
@@ -1,6 +1,5 @@
 [focus.html]
   [Focus should be kept when page gets into and out of BFCache]
     expected:
-      if (os == "linux") and (product == "chrome"): PRECONDITION_FAILED
-      if os == "win": PRECONDITION_FAILED
+      if product == "chrome": PRECONDITION_FAILED
       FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/event-order/before-load-hash-twice.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/event-order/before-load-hash-twice.html.ini
index 8c2aa5c1..2f3190e 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/event-order/before-load-hash-twice.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/event-order/before-load-hash-twice.html.ini
@@ -1,4 +1,4 @@
 [before-load-hash-twice.html]
   [when changing hash twice, before load]
     expected:
-      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+      if (product == "content_shell") and (flag_specific == "disable-layout-ng"): [FAIL, PASS]
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
new file mode 100644
index 0000000..460c4ca
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/event-order/before-load-hash.html.ini
@@ -0,0 +1,5 @@
+[before-load-hash.html]
+  [when changing hash, before load]
+    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/browsing-the-web/overlapping-navigations-and-traversals/cross-document-traversal-cross-document-traversal.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/overlapping-navigations-and-traversals/cross-document-traversal-cross-document-traversal.html.ini
index ba066142..8452eaf 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/overlapping-navigations-and-traversals/cross-document-traversal-cross-document-traversal.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/overlapping-navigations-and-traversals/cross-document-traversal-cross-document-traversal.html.ini
@@ -1,8 +1,3 @@
 [cross-document-traversal-cross-document-traversal.html]
   [cross-document traversals in opposite directions, second traversal invalid at queuing time but valid at the time it is run: the result is going nowhere]
     expected: FAIL
-
-  [cross-document traversals in opposite directions: the result is going nowhere]
-    expected:
-      if (flag_specific == "") and (os == "win"): FAIL
-      if flag_specific == "disable-layout-ng": [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 62a41e2..cef5e4f 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,6 +1,7 @@
 [same-document-traversal-cross-document-traversal.html]
   expected:
-    if flag_specific == "disable-layout-ng": [OK, TIMEOUT]
+    if flag_specific == "disable-layout-ng": TIMEOUT
+    if flag_specific == "disable-site-isolation-trials": [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/browsing-the-web/remote-context-helper/resources/remote-context-helper.js b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js
index 7a4b399a..6978cef8 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js
@@ -237,6 +237,15 @@
         extraConfig,
       });
     }
+
+    async createContextWithUrl(extraConfig) {
+      let saveUrl;
+      let wrapper = await this.createContext({
+        executorCreator: (url) => {saveUrl = url},
+        extraConfig,
+      });
+      return [wrapper, saveUrl];
+    }
   }
   // Export this class.
   self.RemoteContextHelper = RemoteContextHelper;
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 504d86a..1af48f8 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,6 +4,6 @@
 
   [Set data URL frame location.protocol to data]
     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 (flag_specific == "") and (os == "linux") and (product == "chrome"): FAIL
+      if (flag_specific == "") and (os == "win"): [PASS, FAIL]
+      if flag_specific == "disable-site-isolation-trials": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-name.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-name.html.ini
index ab20f7d..df543428 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-name.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-function-name.html.ini
@@ -1,6 +1,4 @@
 [cross-origin-objects-function-name.html]
-  expected:
-    if flag_specific == "disable-site-isolation-trials": [OK, CRASH]
   [Cross-origin Window methods have correct 'name']
     expected: FAIL
 
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/1-iframe/parent-no-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-no-child-yes-subdomain.sub.https.html.ini
deleted file mode 100644
index 25b59d5..0000000
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/1-iframe/parent-no-child-yes-subdomain.sub.https.html.ini
+++ /dev/null
@@ -1,8 +0,0 @@
-[parent-no-child-yes-subdomain.sub.https.html]
-  [setting document.domain must not give sync access]
-    expected:
-      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
-
-  [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/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 de4b97c..5383b4d 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,10 +1,10 @@
 [parent-yes-child-no-port.sub.https.html]
   [setting document.domain must not give sync access]
     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
 
   [parent: originAgentCluster must equal true]
     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
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 7683c12..2066f0aa 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,10 +1,8 @@
 [parent-yes-child-no-same.sub.https.html]
   [parent: originAgentCluster must equal true]
     expected:
-      if (flag_specific == "") and (product == "chrome"): FAIL
-      if flag_specific == "disable-site-isolation-trials": FAIL
+      if product == "chrome": FAIL
 
   [child: originAgentCluster must equal true]
     expected:
-      if (flag_specific == "") and (product == "chrome"): FAIL
-      if flag_specific == "disable-site-isolation-trials": 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 4df55d70..ebb9852b 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
@@ -8,3 +8,4 @@
     expected:
       if (flag_specific == "") and (product == "chrome"): FAIL
       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/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..1fe7649 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,4 @@
 [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
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/1-iframe/parent-yes-child-yes-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-yes-same.sub.https.html.ini
index e3a89c0f..2b7fa4f 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/1-iframe/parent-yes-child-yes-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-yes-same.sub.https.html.ini
@@ -1,8 +1,10 @@
 [parent-yes-child-yes-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-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 bb7bb06a..fff3f00c 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,6 @@
 [parent-yes-child-yes-subdomain.sub.https.html]
   expected:
-    if flag_specific == "disable-site-isolation-trials": [OK, CRASH]
+    if (flag_specific == "") and (os == "win"): [OK, TIMEOUT]
   [parent: originAgentCluster must equal true]
     expected:
-      if (flag_specific == "") and (product == "chrome"): FAIL
+      if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-no-child1-no-subdomain-child2-yes-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-no-subdomain-child2-yes-subdomain.sub.https.html.ini
index 9be6e053..bd99113 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-no-child1-no-subdomain-child2-yes-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-no-subdomain-child2-yes-subdomain.sub.https.html.ini
@@ -10,3 +10,11 @@
       if (flag_specific == "") and (product == "chrome"): PASS
       if flag_specific == "disable-site-isolation-trials": PASS
       FAIL
+
+  [child2: originAgentCluster must equal false]
+    expected:
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
+
+  [child1: originAgentCluster must equal false]
+    expected:
+      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/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 d350ba9..ff06302c 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
@@ -1,10 +1,9 @@
 [parent-no-child1-no-subdomain1-child2-yes-subdomain2.sub.https.html]
   [Parent to child1: 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
       FAIL
 
   [parent: originAgentCluster must equal false]
     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-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 25a89075..d91cf4a 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,18 +1,21 @@
 [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
+      if (flag_specific == "") and (product == "content_shell"): FAIL
+      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
 
   [child1 to child2: setting document.domain must not give sync access]
     expected:
-      if flag_specific == "disable-site-isolation-trials": FAIL
+      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
 
   [child2 to child1: setting document.domain must not give sync access]
     expected:
-      if flag_specific == "disable-site-isolation-trials": FAIL
+      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
 
-  [Parent to child1: setting document.domain must not give sync access]
+  [parent: originAgentCluster must equal false]
     expected:
-      if flag_specific == "disable-site-isolation-trials": FAIL
+      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+
+  [Parent to child2: setting document.domain must 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-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 404db30..aa399ed5 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
@@ -1,27 +1,25 @@
 [parent-yes-child1-no-subdomain-child2-no-subdomain2.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
+      if (flag_specific == "") and (product == "chrome"): FAIL
+      if flag_specific == "disable-site-isolation-trials": FAIL
 
   [child2 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
+      if (flag_specific == "") and (product == "content_shell"): FAIL
+      if flag_specific == "disable-layout-ng": FAIL
 
   [child1 to child2: setting document.domain must give sync access]
     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/html/browsers/origin/origin-keyed-agent-clusters/2-iframes/parent-yes-child1-no-subdomain-child2-yes-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-yes-subdomain.sub.https.html.ini
index 870d618..55c95079 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-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-yes-subdomain.sub.https.html.ini
@@ -1,15 +1,12 @@
 [parent-yes-child1-no-subdomain-child2-yes-subdomain.sub.https.html]
   [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
+      if product == "chrome": 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
+      if product == "chrome": FAIL
 
   [parent: originAgentCluster must equal true]
     expected:
-      if (flag_specific == "") and (product == "chrome"): FAIL
-      if flag_specific == "disable-site-isolation-trials": FAIL
+      if product == "chrome": 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-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-yes-subdomain2.sub.https.html.ini
index 21a86a7c..7b86435 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-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-yes-subdomain2.sub.https.html.ini
@@ -1,8 +1,12 @@
 [parent-yes-child1-no-subdomain-child2-yes-subdomain2.sub.https.html]
-  [Parent to child1: setting document.domain must not give sync access]
+  [child1 to child2: setting document.domain must not give sync access]
     expected:
       if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
 
-  [parent: originAgentCluster must equal true]
+  [child2: originAgentCluster must equal true]
+    expected:
+      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+
+  [child2 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-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 55806ef..7ba4e73 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
@@ -9,4 +9,4 @@
 
   [child1: originAgentCluster must equal false]
     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-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 0a4b7f80f..54fc998 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,20 +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 == "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 == "chrome": FAIL
+      if (flag_specific == "") and (product == "chrome"): 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
+
+  [Parent to child1: setting document.domain must not give sync access]
+    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-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 2c6c938..6e06935 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,13 +1,23 @@
 [parent-yes-child1-yes-subdomain-child2-no-subdomain.sub.https.html]
   [parent: originAgentCluster must equal true]
     expected:
-      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
-      if (flag_specific == "") and (os == "linux") and (product == "chrome"): FAIL
+      if (flag_specific == "") and (product == "chrome"): FAIL
+      if flag_specific == "disable-site-isolation-trials": FAIL
 
   [child1: originAgentCluster must equal true]
     expected:
       if (flag_specific == "") and (os == "win"): FAIL
+      if flag_specific == "disable-site-isolation-trials": FAIL
 
   [child2: originAgentCluster must equal true]
     expected:
       if (flag_specific == "") and (os == "win"): 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": FAIL
+
+  [Parent to child2: setting document.domain must not give sync access]
+    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-yes-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-yes-subdomain.sub.https.html.ini
index 7542bf6..3be8b66 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-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-yes-subdomain.sub.https.html.ini
@@ -1,8 +1,7 @@
 [parent-yes-child1-yes-subdomain-child2-yes-subdomain.sub.https.html]
   [parent: originAgentCluster must equal true]
     expected:
-      if (flag_specific == "") and (product == "chrome"): FAIL
-      if flag_specific == "disable-site-isolation-trials": FAIL
+      if product == "chrome": FAIL
 
   [child1: originAgentCluster must equal true]
     expected:
@@ -11,11 +10,3 @@
   [child2: originAgentCluster must equal true]
     expected:
       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": FAIL
-
-  [Parent to child2: setting document.domain must not give sync access]
-    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-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 aa87e78..985a657 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 @@
   [child1 to child2: 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]
+
+  [Parent to child1: setting document.domain must not give sync access]
+    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]
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..cb8c40e 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,8 +1,14 @@
 [parent-yes-child1-yes-subdomain-child2-yes-subdomainport.sub.https.html]
   [parent: originAgentCluster must equal true]
     expected:
-      if product == "chrome": FAIL
+      if (flag_specific == "") and (product == "chrome"): FAIL
+      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
 
   [child1: originAgentCluster must equal true]
     expected:
+      if (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
       if os == "win": 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/document-domain.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/document-domain.sub.https.html.ini
index 0303cd30..b9c6e71f 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/document-domain.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/document-domain.sub.https.html.ini
@@ -1,5 +1,4 @@
 [document-domain.sub.https.html]
   [Setting document.domain must not change same-originness]
     expected:
-      if (product == "content_shell") and (flag_specific == "") and (os == "linux"): [PASS, FAIL]
-      if product == "chrome": FAIL
+      if product == "chrome": [PASS, FAIL]
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
new file mode 100644
index 0000000..300ae43
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/getter-special-cases/javascript-url-yes.https.html.ini
@@ -0,0 +1,3 @@
+[javascript-url-yes.https.html]
+  expected:
+    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/removed-iframe.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/getter-special-cases/removed-iframe.sub.https.html.ini
index dda6109..80f7bcf2 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/getter-special-cases/removed-iframe.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/getter-special-cases/removed-iframe.sub.https.html.ini
@@ -1,5 +1,5 @@
 [removed-iframe.sub.https.html]
   [Removing the iframe does not change originAgentCluster]
     expected:
-      if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
-      if product == "chrome": FAIL
+      if (flag_specific == "") and (product == "chrome"): [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/getter-special-cases/sandboxed-same-origin-iframe-no.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-no.https.html.ini
index 27d7b90..6739f44 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/getter-special-cases/sandboxed-same-origin-iframe-no.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-no.https.html.ini
@@ -2,4 +2,3 @@
   [originAgentCluster must equal false]
     expected:
       if (flag_specific == "") and (product == "content_shell"): 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-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 ec2a502..43e1bec 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,15 @@
 [parent-no-1-no-same-2-yes-port.sub.https.html]
   [before parent: originAgentCluster must equal false]
     expected:
-      if os == "win": [PASS, FAIL]
+      if (os == "linux") and (flag_specific == "") and (product == "content_shell"): [PASS, FAIL]
+      if os == "win": FAIL
 
   [before child: originAgentCluster must equal false]
     expected:
-      if os == "win": [PASS, FAIL]
+      if (os == "linux") and (flag_specific == "") and (product == "content_shell"): [PASS, FAIL]
+      if os == "win": FAIL
 
   [after parent: originAgentCluster must equal false]
     expected:
-      if os == "win": [PASS, FAIL]
+      if (os == "linux") and (flag_specific == "") and (product == "content_shell"): [PASS, FAIL]
+      if os == "win": 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 0a52bd7..e824e343 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,19 +1,15 @@
 [parent-no-1-no-same-2-yes-subdomain.sub.https.html]
   [before parent: originAgentCluster must equal false]
     expected:
-      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
-      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): FAIL
+      if (flag_specific == "") and (os == "win"): [PASS, FAIL]
 
   [before child: originAgentCluster must equal false]
     expected:
-      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
-      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): FAIL
+      if (flag_specific == "") and (os == "win"): [PASS, FAIL]
 
   [after parent: originAgentCluster must equal false]
     expected:
-      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
-      if flag_specific == "disable-layout-ng": [PASS, FAIL]
-
-  [after child: originAgentCluster must equal true]
-    expected:
-      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): FAIL
+      if (flag_specific == "") and (os == "win"): [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-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 6470857b..bc42911 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
@@ -13,10 +13,18 @@
 
   [after parent: 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]
+      if (flag_specific == "") and (product == "content_shell"): FAIL
+      if flag_specific == "disable-layout-ng": [PASS, FAIL]
 
   [before parent: originAgentCluster must equal false]
     expected:
-      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
+      if (flag_specific == "") and (product == "content_shell"): FAIL
+      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+
+  [after child: originAgentCluster must equal false]
+    expected:
+      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+
+  [before child: originAgentCluster must equal false]
+    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-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 5f9d08c..ea522458 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,14 +1,13 @@
 [parent-no-1-no-subdomain-2-yes-subdomain2.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
-      FAIL
+      if (flag_specific == "") and (product == "content_shell"): FAIL
+      if flag_specific == "disable-layout-ng": FAIL
 
-  [before child: originAgentCluster must equal false]
+  [After: parent to child: setting document.domain must not give sync access]
     expected:
-      if os == "win": FAIL
+      if flag_specific == "disable-site-isolation-trials": [PASS, 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]
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 1473b34..d6d82be 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,16 +2,17 @@
   [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
 
   [after parent: originAgentCluster must equal false]
     expected:
-      if flag_specific == "disable-site-isolation-trials": FAIL
+      if os == "win": [PASS, FAIL]
 
   [before parent: originAgentCluster must equal false]
     expected:
-      if flag_specific == "disable-site-isolation-trials": FAIL
+      if os == "win": [PASS, FAIL]
 
   [before child: originAgentCluster must equal true]
     expected:
-      if flag_specific == "disable-site-isolation-trials": FAIL
+      if os == "win": [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-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 8215e4c..b88a901 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,10 +1,12 @@
 [parent-yes-1-no-same-2-no-port.sub.https.html]
   [before parent: originAgentCluster must equal true]
     expected:
+      if (product == "content_shell") and (flag_specific == "disable-layout-ng"): [PASS, FAIL]
       if product == "chrome": FAIL
 
   [before child: originAgentCluster must equal true]
     expected:
+      if (product == "content_shell") and (flag_specific == "disable-layout-ng"): [PASS, FAIL]
       if product == "chrome": FAIL
 
   [After: parent to child: setting document.domain must not give sync access]
@@ -13,4 +15,9 @@
 
   [after parent: originAgentCluster must equal true]
     expected:
+      if (product == "content_shell") and (flag_specific == "disable-layout-ng"): [PASS, FAIL]
       if product == "chrome": FAIL
+
+  [after child: originAgentCluster must equal false]
+    expected:
+      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-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 8de18d4..1f51943 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
@@ -5,16 +5,19 @@
 
   [after child: originAgentCluster must equal false]
     expected:
-      if (flag_specific == "") and (os == "win"): [PASS, FAIL]
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): FAIL
 
   [before parent: originAgentCluster must equal true]
     expected:
-      if product == "chrome": FAIL
+      if (os == "linux") and (product == "chrome"): FAIL
+      if os == "win": FAIL
 
   [after parent: originAgentCluster must equal true]
     expected:
-      if product == "chrome": FAIL
+      if (os == "linux") and (product == "chrome"): FAIL
+      if os == "win": FAIL
 
   [before child: originAgentCluster must equal true]
     expected:
-      if product == "chrome": FAIL
+      if (os == "linux") and (product == "chrome"): FAIL
+      if os == "win": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-no-openee-yes-port.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-no-openee-yes-port.sub.https.html.ini
index 2d3830c..31826e4 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-no-openee-yes-port.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-no-openee-yes-port.sub.https.html.ini
@@ -1,5 +1,4 @@
 [opener-no-openee-yes-port.sub.https.html]
   [opener: originAgentCluster must equal false]
     expected:
-      if (flag_specific == "") and (os == "win"): [PASS, FAIL]
-      if flag_specific == "disable-layout-ng": [PASS, 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-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
new file mode 100644
index 0000000..3383d84
--- /dev/null
+++ 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
@@ -0,0 +1,10 @@
+[opener-no-openee-yes-same.sub.https.html]
+  [opener: originAgentCluster must equal false]
+    expected:
+      if (flag_specific == "") and (product == "content_shell"): [PASS, FAIL]
+      if flag_specific == "disable-site-isolation-trials": FAIL
+
+  [openee: originAgentCluster must equal false]
+    expected:
+      if (flag_specific == "") and (product == "content_shell"): [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/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
new file mode 100644
index 0000000..cd6ff86
--- /dev/null
+++ 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
@@ -0,0 +1,9 @@
+[opener-no-openee-yes-subdomain.sub.https.html]
+  [opener: originAgentCluster must equal false]
+    expected:
+      if flag_specific == "disable-layout-ng": FAIL
+      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+
+  [openee: 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/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 6cfbabf..8af48a3 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,10 +1,10 @@
 [opener-yes-openee-no-port.sub.https.html]
   [setting document.domain must not give sync access]
     expected:
-      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): FAIL
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
       if flag_specific == "disable-layout-ng": FAIL
 
   [opener: originAgentCluster must equal true]
     expected:
-      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): FAIL
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, 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-yes-openee-no-same.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-yes-openee-no-same.sub.https.html.ini
index 6919e10..053a0b7 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-yes-openee-no-same.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-yes-openee-no-same.sub.https.html.ini
@@ -1,10 +1,10 @@
 [opener-yes-openee-no-same.sub.https.html]
   [opener: originAgentCluster must equal true]
     expected:
-      if (flag_specific == "") and (os == "linux") and (product == "chrome"): FAIL
-      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+      if (flag_specific == "") and (product == "chrome"): FAIL
+      if flag_specific == "disable-site-isolation-trials": FAIL
 
   [openee: originAgentCluster must equal true]
     expected:
-      if (flag_specific == "") and (os == "linux") and (product == "chrome"): FAIL
-      if flag_specific == "disable-site-isolation-trials": [PASS, 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/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 9c5a85f..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,5 +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": 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-port.sub.https.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-yes-openee-yes-port.sub.https.html.ini
index 91c6bca92..e143134 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-yes-openee-yes-port.sub.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-yes-openee-yes-port.sub.https.html.ini
@@ -3,4 +3,3 @@
     expected:
       if (flag_specific == "") and (product == "chrome"): FAIL
       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/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 ae30272..776bd28 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,8 @@
 [opener-yes-openee-yes-same.sub.https.html]
   [opener: originAgentCluster must equal true]
     expected:
-      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
-      if (flag_specific == "") and (os == "linux") and (product == "chrome"): [PASS, FAIL]
+      if (flag_specific == "") and (product == "chrome"): FAIL
 
   [openee: originAgentCluster must equal true]
     expected:
-      if (flag_specific == "") and (os == "linux") and (product == "chrome"): [PASS, FAIL]
-      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
+      if (flag_specific == "") and (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 b6c7af3..5ec4080 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
@@ -1,14 +1,4 @@
 [opener-yes-openee-yes-subdomain.sub.https.html]
   [openee: 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 == "disable-site-isolation-trials": FAIL
-
-  [opener: originAgentCluster must equal true]
-    expected:
-      if flag_specific == "disable-site-isolation-trials": FAIL
-
-  [setting document.domain must not give sync access]
-    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/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 5557c803..be224fc 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
@@ -1,19 +1,24 @@
 [removing-iframes.sub.https.html]
   [parent: originAgentCluster must equal true]
     expected:
-      if product == "chrome": [PASS, FAIL]
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
+      if (flag_specific == "") and (os == "linux") 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 == "chrome": [PASS, FAIL]
+      if (flag_specific == "") and (product == "chrome"): FAIL
+      if flag_specific == "disable-site-isolation-trials": FAIL
 
   [Before: setting document.domain must not give sync access]
     expected:
-      if product == "chrome": [PASS, FAIL]
+      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 product == "chrome": [PASS, FAIL]
+      if (flag_specific == "") and (product == "chrome"): FAIL
+      if flag_specific == "disable-site-isolation-trials": FAIL
 
   [child2 to child3: setting document.domain must give sync access]
     expected:
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
index af7186e..bd8e1e94 100644
--- 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
@@ -1,11 +1,9 @@
 [open-features-is-popup-condition.html?position]
-  expected:
-    if product == "chrome": [OK, ERROR]
 
 [open-features-is-popup-condition.html?combination]
+  expected:
+    if product == "chrome": [OK, ERROR]
 
 [open-features-is-popup-condition.html?single-1]
 
 [open-features-is-popup-condition.html?single-2]
-  expected:
-    if product == "chrome": [OK, ERROR]
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/open-close/open-features-non-integer-screeny.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/open-close/open-features-non-integer-screeny.html.ini
index 980af6d6..2fbad0d 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/open-close/open-features-non-integer-screeny.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/open-close/open-features-non-integer-screeny.html.ini
@@ -1,4 +1,6 @@
 [open-features-non-integer-screeny.html]
+  expected:
+    if product == "chrome": [OK, ERROR]
   [features "screeny=405.5" should set "height=405"]
     expected: FAIL
 
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/open-close/open-features-non-integer-width.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/open-close/open-features-non-integer-width.html.ini
index 497b762..bb49dcd 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/open-close/open-features-non-integer-width.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/open-close/open-features-non-integer-width.html.ini
@@ -1,2 +1,3 @@
 [open-features-non-integer-width.html]
-  expected: [ERROR, OK]
+  expected:
+    if product == "chrome": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/open-close/open-features-tokenization-innerheight-innerwidth.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/open-close/open-features-tokenization-innerheight-innerwidth.html.ini
deleted file mode 100644
index 646e2a2a..0000000
--- a/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/open-close/open-features-tokenization-innerheight-innerwidth.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[open-features-tokenization-innerheight-innerwidth.html]
-  expected:
-    if product == "chrome": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/open-close/open-features-tokenization-top-left.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/open-close/open-features-tokenization-top-left.html.ini
index d713e6c8a..a5ba4c24d 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/open-close/open-features-tokenization-top-left.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/open-close/open-features-tokenization-top-left.html.ini
@@ -1,81 +1,50 @@
 [open-features-tokenization-top-left.html]
-  expected: [OK, ERROR]
+  expected:
+    if product == "chrome": ERROR
   [",,top= 152, left=152" should set top and left position of opened window]
-    expected:
-      if product == "chrome": PASS
-      FAIL
+    expected: FAIL
 
   [" left = 141" should set left position of opened window]
-    expected:
-      if product == "chrome": PASS
-      FAIL
+    expected: FAIL
 
   ["LEFT=141" should set left position of opened window]
-    expected:
-      if product == "chrome": PASS
-      FAIL
+    expected: FAIL
 
   ["top=142" should set top position of opened window]
-    expected:
-      if product == "chrome": PASS
-      FAIL
+    expected: FAIL
 
   ["top=152,,left=152," should set top and left position of opened window]
-    expected:
-      if product == "chrome": PASS
-      FAIL
+    expected: FAIL
 
   ["left==141" should set left position of opened window]
-    expected:
-      if product == "chrome": PASS
-      FAIL
+    expected: FAIL
 
   ["top=152,left=152" should set top and left position of opened window]
-    expected:
-      if product == "chrome": PASS
-      FAIL
+    expected: FAIL
 
   [" top = 142" should set top position of opened window]
-    expected:
-      if product == "chrome": PASS
-      FAIL
+    expected: FAIL
 
   ["\\ttop= 142" should set top position of opened window]
-    expected:
-      if product == "chrome": PASS
-      FAIL
+    expected: FAIL
 
   ["top=152==left=152" should set top and left position of opened window]
-    expected:
-      if product == "chrome": PASS
-      FAIL
+    expected: FAIL
 
   [",left=141,," should set left position of opened window]
-    expected:
-      if product == "chrome": PASS
-      FAIL
+    expected: FAIL
 
   ["TOP=142" should set top position of opened window]
-    expected:
-      if product == "chrome": PASS
-      FAIL
+    expected: FAIL
 
   ["left=141" should set left position of opened window]
-    expected:
-      if product == "chrome": PASS
-      FAIL
+    expected: FAIL
 
   ["\nleft= 141" should set left position of opened window]
-    expected:
-      if product == "chrome": PASS
-      FAIL
+    expected: FAIL
 
   [",top=142,," should set top position of opened window]
-    expected:
-      if product == "chrome": PASS
-      FAIL
+    expected: FAIL
 
   ["top==142" should set top position of opened window]
-    expected:
-      if product == "chrome": PASS
-      FAIL
+    expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/window-open-popup-behavior.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/window-open-popup-behavior.html.ini
deleted file mode 100644
index 892817e..0000000
--- a/third_party/blink/web_tests/external/wpt/html/browsers/the-window-object/window-open-popup-behavior.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[window-open-popup-behavior.html]
-  expected:
-    if product == "chrome": [OK, ERROR]
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/filters/tentative/canvas-filter-object-turbulence.html.ini b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/filters/tentative/canvas-filter-object-turbulence.html.ini
index af2297c..64be7110 100644
--- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/filters/tentative/canvas-filter-object-turbulence.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/filters/tentative/canvas-filter-object-turbulence.html.ini
@@ -1,2 +1,4 @@
 [canvas-filter-object-turbulence.html]
-  expected: FAIL
+  expected:
+    if flag_specific == "disable-layout-ng": [FAIL, TIMEOUT]
+    FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-video.html.ini b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-video.html.ini
index 76b154a..311dd8dd 100644
--- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-video.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/wide-gamut-canvas/canvas-display-p3-drawImage-video.html.ini
@@ -1,40 +1,32 @@
 [canvas-display-p3-drawImage-video.html]
-  expected:
-    if flag_specific == "disable-site-isolation-trials": [OK, TIMEOUT]
   [Rec2020-3FF000000, Context srgb, ImageData srgb, scaleImage=false]
     expected:
-      if (os == "linux") and (product == "chrome"): [PASS, FAIL]
-      if os == "win": PASS
+      if product == "chrome": PASS
       FAIL
 
   [Rec2020-3FF000000, Context srgb, ImageData srgb, scaleImage=true]
     expected:
-      if (flag_specific == "") and (os == "linux") and (product == "chrome"): PASS
-      if (flag_specific == "") and (os == "win"): PASS
+      if product == "chrome": PASS
       FAIL
 
   [Rec2020-3FF000000, Context srgb, ImageData display-p3, scaleImage=false]
     expected:
-      if (flag_specific == "") and (os == "linux") and (product == "chrome"): PASS
-      if (flag_specific == "") and (os == "win"): PASS
+      if product == "chrome": PASS
       FAIL
 
   [Rec2020-3FF000000, Context srgb, ImageData display-p3, scaleImage=true]
     expected:
-      if (flag_specific == "") and (os == "linux") and (product == "chrome"): PASS
-      if (flag_specific == "") and (os == "win"): PASS
+      if product == "chrome": PASS
       FAIL
 
   [Rec2020-3FF000000, Context display-p3, ImageData srgb, scaleImage=false]
     expected:
-      if (flag_specific == "") and (os == "linux") and (product == "chrome"): PASS
-      if (flag_specific == "") and (os == "win"): PASS
+      if product == "chrome": PASS
       FAIL
 
   [Rec2020-3FF000000, Context display-p3, ImageData srgb, scaleImage=true]
     expected:
-      if (flag_specific == "") and (os == "linux") and (product == "chrome"): PASS
-      if (flag_specific == "") and (os == "win"): PASS
+      if product == "chrome": PASS
       FAIL
 
   [Rec2020-3FF000000, Context display-p3, ImageData display-p3, scaleImage=false]
@@ -69,4 +61,4 @@
 
   [sRGB-BB0000, Context srgb, ImageData srgb, scaleImage=false]
     expected:
-      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+      if flag_specific == "disable-layout-ng": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.pattern.paint.repeat.basic.html.ini b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.pattern.paint.repeat.basic.html.ini
index 59c6d7d..1f019e86 100644
--- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.pattern.paint.repeat.basic.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/fill-and-stroke-styles/2d.pattern.paint.repeat.basic.html.ini
@@ -1,3 +1,3 @@
 [2d.pattern.paint.repeat.basic.html]
   expected:
-    if product == "chrome": ERROR
+    if product == "chrome": [OK, 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 763b2bf..06d83dc 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,11 +1,12 @@
 [offscreencanvas.resize.html]
   [Verify that resizing an OffscreenCanvas with a webgl context propagates the new size to its placeholder canvas asynchronously.]
     expected:
-      if (os == "linux") and (product == "chrome"): FAIL
+      if (flag_specific == "") and (product == "chrome"): FAIL
 
   [Verify that drawImage uses the size of the frame as the intinsic size of a placeholder canvas.]
     expected:
-      if (os == "linux") and (product == "chrome"): FAIL
+      if (flag_specific == "") and (os == "linux"): FAIL
+      if flag_specific == "disable-layout-ng": [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/fetch.https.window.js.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/credentialless/fetch.https.window.js.ini
deleted file mode 100644
index 3b8a30b9..0000000
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/credentialless/fetch.https.window.js.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[fetch.https.window.html]
-  expected:
-    if product == "chrome": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/reporting-navigation.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/reporting-navigation.https.html.ini
index 360865ce..a972216 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/reporting-navigation.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/reporting-navigation.https.html.ini
@@ -1,6 +1,10 @@
 [reporting-navigation.https.html]
   [parent: |header(cross-origin-embedder-policy,require-corp), target: |header(cross-origin-resource-policy,cross-origin)|header(content-security-policy,frame-ancestors 'none'), with empty frame: false]
-    expected: FAIL
+    expected:
+      if product == "chrome": [PASS, FAIL]
+      FAIL
 
   [parent: |header(cross-origin-embedder-policy,require-corp), target: |header(cross-origin-resource-policy,cross-origin)|header(content-security-policy,frame-ancestors 'none'), with empty frame: true]
-    expected: FAIL
+    expected:
+      if product == "chrome": [PASS, FAIL]
+      FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/coep-with-same-site.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/coep-with-same-site.https.html.ini
deleted file mode 100644
index 7938d8f..0000000
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/coep-with-same-site.https.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[coep-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/coop-navigate-same-origin-csp-sandbox.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/coop-navigate-same-origin-csp-sandbox.html.ini
deleted file mode 100644
index a7102153..0000000
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/coop-navigate-same-origin-csp-sandbox.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[coop-navigate-same-origin-csp-sandbox.html]
-  expected:
-    if product == "chrome": ERROR
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 21617c9..52441529 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
@@ -1,10 +1,9 @@
 [header-parsing-failures.https.html?1-4]
 
 [header-parsing-failures.https.html?5-8]
-  expected:
-    if product == "chrome": ERROR
 
 [header-parsing-failures.https.html?12-last]
-  expected: [OK, ERROR]
+  expected:
+    if product == "chrome": ERROR
 
 [header-parsing-failures.https.html?9-12]
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/header-parsing-non-ascii.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/header-parsing-non-ascii.https.html.ini
deleted file mode 100644
index fdad5f3..0000000
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/header-parsing-non-ascii.https.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[header-parsing-non-ascii.https.html]
-  expected: [OK, ERROR]
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/header-parsing-repeated.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/header-parsing-repeated.https.html.ini
deleted file mode 100644
index 0ff03121..0000000
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/header-parsing-repeated.https.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[header-parsing-repeated.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-origin-unsafe-allow-outgoing-with-same-origin.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/historical/popup-same-origin-unsafe-allow-outgoing-with-same-origin.https.html.ini
index 6095039..0dbd28d2 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/historical/popup-same-origin-unsafe-allow-outgoing-with-same-origin.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/historical/popup-same-origin-unsafe-allow-outgoing-with-same-origin.https.html.ini
@@ -1,3 +1,3 @@
 [popup-same-origin-unsafe-allow-outgoing-with-same-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-origin-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-origin-unsafe-allow-outgoing-with-same-site.https.html.ini
index d9c553b..a39425e 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/historical/popup-same-origin-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-origin-unsafe-allow-outgoing-with-same-site.https.html.ini
@@ -1,2 +1,3 @@
 [popup-same-origin-unsafe-allow-outgoing-with-same-site.https.html]
-  expected: [OK, ERROR]
+  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-allow-popups.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-allow-popups.https.html.ini
index 4963b2f..c563da9 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-same-origin-allow-popups.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-allow-popups.https.html.ini
@@ -4,7 +4,7 @@
 
 [iframe-popup-same-origin-allow-popups-to-same-origin-allow-popups.https.html?3-4]
   expected:
-    if product == "chrome": [OK, ERROR]
+    if product == "chrome": ERROR
 
 [iframe-popup-same-origin-allow-popups-to-same-origin-allow-popups.https.html?5-6]
   expected:
@@ -16,4 +16,4 @@
 
 [iframe-popup-same-origin-allow-popups-to-same-origin-allow-popups.https.html?9-last]
   expected:
-    if product == "chrome": ERROR
+    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 249776d..9efa1fc 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
@@ -3,14 +3,12 @@
     if product == "chrome": ERROR
 
 [iframe-popup-same-origin-allow-popups-to-same-origin.https.html?9-last]
+  expected:
+    if product == "chrome": ERROR
 
 [iframe-popup-same-origin-allow-popups-to-same-origin.https.html?3-4]
-  expected:
-    if product == "chrome": ERROR
 
 [iframe-popup-same-origin-allow-popups-to-same-origin.https.html?1-2]
-  expected:
-    if product == "chrome": ERROR
 
 [iframe-popup-same-origin-allow-popups-to-same-origin.https.html?7-8]
   expected:
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-unsafe-none.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-unsafe-none.https.html.ini
index a82ac75..4af327b 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-unsafe-none.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/iframe-popup-same-origin-allow-popups-to-unsafe-none.https.html.ini
@@ -1,6 +1,6 @@
 [iframe-popup-same-origin-allow-popups-to-unsafe-none.https.html?9-last]
   expected:
-    if product == "chrome": [OK, ERROR]
+    if product == "chrome": ERROR
 
 [iframe-popup-same-origin-allow-popups-to-unsafe-none.https.html?5-6]
   expected:
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/iframe-popup-unsafe-none-to-same-origin.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/iframe-popup-unsafe-none-to-same-origin.https.html.ini
index 69ae4a6..0412b324 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/iframe-popup-unsafe-none-to-same-origin.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/iframe-popup-unsafe-none-to-same-origin.https.html.ini
@@ -4,15 +4,15 @@
 
 [iframe-popup-unsafe-none-to-same-origin.https.html?9-last]
   expected:
-    if product == "chrome": [OK, ERROR]
+    if product == "chrome": ERROR
 
 [iframe-popup-unsafe-none-to-same-origin.https.html?7-8]
   expected:
-    if product == "chrome": ERROR
+    if product == "chrome": [OK, ERROR]
 
 [iframe-popup-unsafe-none-to-same-origin.https.html?3-4]
   expected:
-    if product == "chrome": [OK, ERROR]
+    if product == "chrome": ERROR
 
 [iframe-popup-unsafe-none-to-same-origin.https.html?5-6]
   expected:
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/iframe-popup-unsafe-none-to-unsafe-none.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/iframe-popup-unsafe-none-to-unsafe-none.https.html.ini
index 3deb888f..c1f50620 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/iframe-popup-unsafe-none-to-unsafe-none.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/iframe-popup-unsafe-none-to-unsafe-none.https.html.ini
@@ -11,6 +11,8 @@
     if product == "chrome": ERROR
 
 [iframe-popup-unsafe-none-to-unsafe-none.https.html?9-last]
+  expected:
+    if product == "chrome": ERROR
 
 [iframe-popup-unsafe-none-to-unsafe-none.https.html?1-2]
   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 bad4145..232f5c1 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
@@ -1,6 +1,6 @@
 [javascript-url.https.html?1-2]
   expected:
-    if product == "chrome": [OK, ERROR]
+    if product == "chrome": ERROR
 
 [javascript-url.https.html?3-4]
   expected:
@@ -8,7 +8,7 @@
 
 [javascript-url.https.html?11-12]
   expected:
-    if product == "chrome": ERROR
+    if product == "chrome": [OK, ERROR]
 
 [javascript-url.https.html?13-14]
   expected:
@@ -28,7 +28,7 @@
 
 [javascript-url.https.html?7-8]
   expected:
-    if product == "chrome": ERROR
+    if product == "chrome": [OK, ERROR]
 
 [javascript-url.https.html?9-10]
   expected:
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-meta-http-equiv.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-meta-http-equiv.https.html.ini
deleted file mode 100644
index 4dcab80a..0000000
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-meta-http-equiv.https.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[popup-meta-http-equiv.https.html]
-  expected:
-    if product == "chrome": [OK, ERROR]
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 46717b7e..cc11c621 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
@@ -1,14 +1,11 @@
 [popup-redirect-cache.https.html?6-7]
-  expected:
-    if product == "chrome": ERROR
 
 [popup-redirect-cache.https.html?2-3]
 
 [popup-redirect-cache.https.html?0-1]
-  expected: [OK, ERROR]
+  expected:
+    if product == "chrome": ERROR
 
 [popup-redirect-cache.https.html?4-5]
 
 [popup-redirect-cache.https.html?8-last]
-  expected:
-    if product == "chrome": 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
deleted file mode 100644
index 4cc8d43..0000000
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-redirect-same-origin-allow-popups.https.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[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-allow-popups-with-same-origin.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-same-origin-allow-popups-with-same-origin.https.html.ini
new file mode 100644
index 0000000..b3e0ea1fa
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-same-origin-allow-popups-with-same-origin.https.html.ini
@@ -0,0 +1,3 @@
+[popup-same-origin-allow-popups-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/popup-same-origin-with-same-origin.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-same-origin-with-same-origin.https.html.ini
new file mode 100644
index 0000000..817cd70
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-same-origin-with-same-origin.https.html.ini
@@ -0,0 +1,3 @@
+[popup-same-origin-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/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-cross-origin.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-unsafe-none-with-cross-origin.https.html.ini
new file mode 100644
index 0000000..1693ee1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-unsafe-none-with-cross-origin.https.html.ini
@@ -0,0 +1,3 @@
+[popup-unsafe-none-with-cross-origin.https.html]
+  expected:
+    if product == "chrome": [OK, 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
index 604de218..c087e209 100644
--- 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
@@ -1,3 +1,3 @@
 [popup-unsafe-none-with-same-site.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/popup-unspecified-with-cross-origin.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-unspecified-with-cross-origin.https.html.ini
index 6f1e8725..856b722 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-unspecified-with-cross-origin.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-unspecified-with-cross-origin.https.html.ini
@@ -1,3 +1,3 @@
 [popup-unspecified-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/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
deleted file mode 100644
index 0d2dc3b..0000000
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-unspecified-with-same-origin.https.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[popup-unspecified-with-same-origin.https.html]
-  expected:
-    if product == "chrome": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-unspecified-with-same-site.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-unspecified-with-same-site.https.html.ini
new file mode 100644
index 0000000..1819e21
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-unspecified-with-same-site.https.html.ini
@@ -0,0 +1,3 @@
+[popup-unspecified-with-same-site.https.html]
+  expected:
+    if product == "chrome": [ERROR, OK]
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-with-structured-header.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-with-structured-header.https.html.ini
index 6da6ff1..b824bdd4 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-with-structured-header.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/popup-with-structured-header.https.html.ini
@@ -1,3 +1,3 @@
 [popup-with-structured-header.https.html]
   expected:
-    if product == "chrome": ERROR
+    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 0ee8233d..4ca363c7 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,4 +1,6 @@
 [access-from-coop-page-to-openee_coop-ro.https.html]
+  expected:
+    if product == "chrome": [OK, ERROR]
   [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-from-coop-page-to-openee_coop-ro_cross-origin.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_cross-origin.https.html.ini
index e85ff72..c525d52 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_cross-origin.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_cross-origin.https.html.ini
@@ -1,10 +1,3 @@
 [access-from-coop-page-to-openee_coop-ro_cross-origin.https.html]
   expected:
-    if product == "chrome": [OK, ERROR]
-  [access-from-coop-page-to-openee, cross-origin + redirect]
-    expected:
-      if product == "chrome": FAIL
-
-  [access-from-coop-page-to-openee, cross-origin]
-    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/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 9945127..45761bca 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,8 +1,3 @@
 [access-to-coop-page-from-openee_coop-ro.https.html]
-  [access-to-coop-page-from-openee, same-origin]
-    expected:
-      if product == "chrome": FAIL
-
-  [access-to-coop-page-from-openee, same-origin + redirect]
-    expected:
-      if product == "chrome": FAIL
+  expected:
+    if product == "chrome": ERROR
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_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-openee_coop-ro_cross-origin.https.html.ini
index a6093885..f90dfad 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_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-openee_coop-ro_cross-origin.https.html.ini
@@ -1,10 +1,3 @@
 [access-to-coop-page-from-openee_coop-ro_cross-origin.https.html]
   expected:
-    if product == "chrome": [OK, ERROR]
-  [access-to-coop-page-from-openee, cross-origin]
-    expected:
-      if product == "chrome": FAIL
-
-  [access-to-coop-page-from-openee, cross-origin + redirect)]
-    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/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 235fd40..cde27b4c 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,4 +1,6 @@
 [access-to-coop-page-from-opener_coop-ro.https.html]
+  expected:
+    if product == "chrome": [OK, ERROR]
   [access-to-coop-page-from-opener, 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-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-blur.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-blur.https.html.ini
index 15edb0a..9bb724a 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-blur.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-blur.https.html.ini
@@ -1,3 +1,10 @@
 [property-blur.https.html]
   expected:
-    if product == "chrome": ERROR
+    if product == "chrome": [OK, ERROR]
+  [cross-origin > w => w.blur()]
+    expected:
+      if product == "chrome": FAIL
+
+  [same-origin > w => w.blur()]
+    expected:
+      if product == "chrome": FAIL
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 3c5b98ea..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,8 +1,3 @@
 [property-focus.https.html]
-  [cross-origin > w => w.focus()]
-    expected:
-      if product == "chrome": FAIL
-
-  [same-origin > w => w.focus()]
-    expected:
-      if product == "chrome": FAIL
+  expected:
+    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 01f4fcd..bba3c33 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,3 +1,8 @@
 [property-frames.https.html]
-  expected:
-    if product == "chrome": ERROR
+  [same-origin > w => w.frames]
+    expected:
+      if product == "chrome": FAIL
+
+  [cross-origin > w => w.frames]
+    expected:
+      if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-length.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-length.https.html.ini
index 20d6b23..adac8732 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-length.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-length.https.html.ini
@@ -1,6 +1,4 @@
 [property-length.https.html]
-  expected:
-    if product == "chrome": [OK, ERROR]
   [same-origin > w => w.length]
     expected:
       if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-location-get.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-location-get.https.html.ini
index 205cfdd..e48075c 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-location-get.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-location-get.https.html.ini
@@ -1,4 +1,6 @@
 [property-location-get.https.html]
+  expected:
+    if product == "chrome": [OK, ERROR]
   [same-origin > w => w.location]
     expected:
       if product == "chrome": FAIL
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 2f71178..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]
-  [same-origin > w => w.location = "#"]
-    expected:
-      if product == "chrome": FAIL
-
-  [cross-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-postmessage-2.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-postmessage-2.https.html.ini
index 426cf305..586bba13 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-postmessage-2.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-postmessage-2.https.html.ini
@@ -1,10 +1,3 @@
 [property-postmessage-2.https.html]
   expected:
-    if product == "chrome": [OK, ERROR]
-  [cross-origin > w => w.postMessage("")]
-    expected:
-      if product == "chrome": FAIL
-
-  [same-origin > w => w.postMessage("")]
-    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-self.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-self.https.html.ini
index 911a48f..189215bc 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-self.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-self.https.html.ini
@@ -1,10 +1,3 @@
 [property-self.https.html]
   expected:
-    if product == "chrome": [OK, ERROR]
-  [cross-origin > w => w.self]
-    expected:
-      if product == "chrome": FAIL
-
-  [same-origin > w => w.self]
-    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-top.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-top.https.html.ini
index e3a7586a..86f71d589 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-top.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-top.https.html.ini
@@ -1,3 +1,10 @@
 [property-top.https.html]
   expected:
-    if product == "chrome": ERROR
+    if product == "chrome": [OK, ERROR]
+  [same-origin > w => w.top]
+    expected:
+      if product == "chrome": FAIL
+
+  [cross-origin > w => w.top]
+    expected:
+      if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-window.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-window.https.html.ini
index 799db67..78ab09d 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-window.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/access-reporting/property-window.https.html.ini
@@ -1,10 +1,3 @@
 [property-window.https.html]
   expected:
-    if product == "chrome": [OK, ERROR]
-  [same-origin > w => w.window]
-    expected:
-      if product == "chrome": FAIL
-
-  [cross-origin > w => w.window]
-    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/document-reporting/report-to-both_coop-ro.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/document-reporting/report-to-both_coop-ro.https.html.ini
index 46d3e245..cfda1f9 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/document-reporting/report-to-both_coop-ro.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/document-reporting/report-to-both_coop-ro.https.html.ini
@@ -1,3 +1,10 @@
 [report-to-both_coop-ro.https.html]
   expected:
-    if product == "chrome": ERROR
+    if product == "chrome": [OK, ERROR]
+  [Access from opener]
+    expected:
+      if product == "chrome": FAIL
+
+  [Access from openee]
+    expected:
+      if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/document-reporting/reporting-redirect-with-same-origin-allow-popups.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/document-reporting/reporting-redirect-with-same-origin-allow-popups.https.html.ini
index 18bb1f2..80bec0a 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/document-reporting/reporting-redirect-with-same-origin-allow-popups.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/document-reporting/reporting-redirect-with-same-origin-allow-popups.https.html.ini
@@ -1,3 +1,10 @@
 [reporting-redirect-with-same-origin-allow-popups.https.html]
   expected:
-    if product == "chrome": ERROR
+    if product == "chrome": [OK, ERROR]
+  [Same origin openee redirected to same-origin with same-origin-allow-popups]
+    expected:
+      if product == "chrome": FAIL
+
+  [Cross origin openee redirected to same-origin with same-origin-allow-popups]
+    expected:
+      if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/document-reporting/reporting-redirect-with-unsafe-none.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/document-reporting/reporting-redirect-with-unsafe-none.https.html.ini
index 7b11492b..f600281 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/document-reporting/reporting-redirect-with-unsafe-none.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/document-reporting/reporting-redirect-with-unsafe-none.https.html.ini
@@ -1,10 +1,3 @@
 [reporting-redirect-with-unsafe-none.https.html]
   expected:
-    if product == "chrome": [OK, ERROR]
-  [Cross origin openee redirected to same-origin with unsafe-none]
-    expected:
-      if product == "chrome": FAIL
-
-  [Same origin openee redirected to same-origin with unsafe-none]
-    expected:
-      if product == "chrome": FAIL
+    if product == "chrome": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/resource-popup.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/resource-popup.https.html.ini
index 6772889..a51cce9 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/resource-popup.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/resource-popup.https.html.ini
@@ -1,3 +1,3 @@
 [resource-popup.https.html]
   expected:
-    if (product == "content_shell") and (flag_specific == ""): [OK, TIMEOUT]
+    if (flag_specific == "") and (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/popup-un.https.html.ini b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/popup-un.https.html.ini
index 3a961ac..3825ee4b5 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/popup-un.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/popup-un.https.html.ini
@@ -1,5 +1,6 @@
 [popup-un.https.html]
-  expected: [OK, ERROR]
+  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/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..4bbf824 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.cookie 1]
+    expected:
+      if product == "chrome": [PASS, FAIL]
+
+  [document has no cookie]
+    expected:
+      if product == "chrome": [PASS, FAIL]
+
+  [document.cookie]
+    expected:
+      if product == "chrome": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/parser-inserted-async-script.tentative.html.ini b/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/parser-inserted-async-script.tentative.html.ini
index fdd58756..430f7e9 100644
--- a/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/parser-inserted-async-script.tentative.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/parser-inserted-async-script.tentative.html.ini
@@ -1,4 +1,5 @@
 [parser-inserted-async-script.tentative.html]
   [Rendering is blocked before render-blocking resources are loaded]
     expected:
-      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
+      if (flag_specific == "") and (product == "content_shell") and (os == "win"): [PASS, FAIL]
+      if (flag_specific == "") and (product == "content_shell") and (os == "linux"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/script-inserted-module-script.tentative.html.ini b/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/script-inserted-module-script.tentative.html.ini
index d44d37c..f99eaff 100644
--- a/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/script-inserted-module-script.tentative.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/script-inserted-module-script.tentative.html.ini
@@ -1,4 +1,4 @@
 [script-inserted-module-script.tentative.html]
   [Rendering is blocked before render-blocking resources are loaded]
     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/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
deleted file mode 100644
index ead65bc..0000000
--- a/third_party/blink/web_tests/external/wpt/html/dom/render-blocking/script-inserted-script.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[script-inserted-script.html]
-  [Rendering is blocked before render-blocking resources are loaded]
-    expected:
-      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/html/interaction/focus/the-autofocus-attribute/spin-by-blocking-style-sheet.html.ini b/third_party/blink/web_tests/external/wpt/html/interaction/focus/the-autofocus-attribute/spin-by-blocking-style-sheet.html.ini
index 00570c37..a197e599 100644
--- a/third_party/blink/web_tests/external/wpt/html/interaction/focus/the-autofocus-attribute/spin-by-blocking-style-sheet.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/interaction/focus/the-autofocus-attribute/spin-by-blocking-style-sheet.html.ini
@@ -1,4 +1,6 @@
 [spin-by-blocking-style-sheet.html]
-  expected: [OK, TIMEOUT]
+  expected:
+    if product == "chrome": TIMEOUT
   [Script-blocking style sheet should pause flushing autofocus candidates.]
-    expected: [PASS, TIMEOUT]
+    expected:
+      if product == "chrome": TIMEOUT
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 c3afabd..832554d 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,5 +1,3 @@
 [resource-selection-invoke-audio-constructor.html]
   [invoking resource selection with new Audio(src)]
-    expected:
-      if (product == "content_shell") and (flag_specific == "") and (os == "linux"): PASS
-      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-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 39ff443e..3829b48 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,6 +1,5 @@
 [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 == "") and (os == "linux") and (product == "content_shell"): 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-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 e410f12..b9e4785 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,5 +1,5 @@
 [resource-selection-invoke-insert-source.html]
   [invoking resource selection by inserting <source>]
     expected:
-      if (product == "content_shell") and (flag_specific == "disable-layout-ng"): [PASS, FAIL]
+      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-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 25cb22e..e889ab7 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,3 @@
 [resource-selection-invoke-pause-networkState.html]
   [NOT invoking resource selection with pause() when networkState is not NETWORK_EMPTY]
-    expected:
-      if (flag_specific == "") and (product == "chrome"): PASS
-      if flag_specific == "disable-layout-ng": [PASS, FAIL]
-      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-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
new file mode 100644
index 0000000..ed1c736b
--- /dev/null
+++ 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
@@ -0,0 +1,4 @@
+[resource-selection-invoke-remove-src.html]
+  [NOT invoking media load or resource selection when removing the src attribute]
+    expected:
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [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-set-src-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-set-src-not-in-document.html.ini
index 9ba4e89b..f899a93 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-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-set-src-not-in-document.html.ini
@@ -1,5 +1,5 @@
 [resource-selection-invoke-set-src-not-in-document.html]
   [invoking load by setting src on video not in a document]
     expected:
-      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+      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/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 0b019614..dc0f147 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,3 +1,4 @@
 [track-cue-rendering-after-controls-removed.html]
   expected:
-    if (flag_specific == "") and (os == "win"): [PASS, FAIL]
+    if (flag_specific == "") and (product == "content_shell") and (os == "win"): [PASS, FAIL]
+    if (flag_specific == "") and (product == "content_shell") and (os == "linux"): [PASS, 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 f9911a23d..142c71c 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,4 +1,5 @@
 [sandbox-top-navigation-child-special-cases.tentative.sub.window.html]
   expected:
-    if (os == "linux") and (product == "content_shell") and (flag_specific == ""): [OK, TIMEOUT]
-    if (os == "linux") and (product == "chrome"): ERROR
+    if (product == "content_shell") and (flag_specific == "") and (os == "linux"): TIMEOUT
+    if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [OK, 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 97ef093..51b5920 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,5 +1,4 @@
 [sandbox-top-navigation-escalate-privileges.tentative.sub.window.html]
   expected:
-    if (flag_specific == "") and (product == "content_shell") and (os == "linux"): [OK, TIMEOUT]
-    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 == "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 0f880d1..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,3 +1,4 @@
 [sandbox-top-navigation-grandchild.tentative.sub.window.html]
   expected:
-    if product == "chrome": ERROR
+    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/browsers/history/the-history-interface/011.html.ini b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox_026.htm.ini
similarity index 81%
copy from third_party/blink/web_tests/external/wpt/html/browsers/history/the-history-interface/011.html.ini
copy to third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox_026.htm.ini
index 96c1a362..882568f 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/history/the-history-interface/011.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/sandbox_026.htm.ini
@@ -1,3 +1,3 @@
-[011.html]
+[sandbox_026.htm]
   expected:
     if flag_specific == "disable-site-isolation-trials": [OK, CRASH]
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-img-element/image-loading-lazy-base-url-2.html.ini b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-img-element/image-loading-lazy-base-url-2.html.ini
index 2e3fbd9..b0363e4 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-img-element/image-loading-lazy-base-url-2.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-img-element/image-loading-lazy-base-url-2.html.ini
@@ -1,5 +1,5 @@
 [image-loading-lazy-base-url-2.html]
   expected:
-    if product == "chrome": ERROR
+    if product == "chrome": [OK, ERROR]
   [When a loading=lazy image is loaded, it loads relative to the document's base URL computed at parse-time.]
     expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-0/urlencoded2.window.js.ini b/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-0/urlencoded2.window.js.ini
index 7b41c1dc..f3533e60 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-0/urlencoded2.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-0/urlencoded2.window.js.ini
@@ -29,10 +29,6 @@
     expected:
       if product == "chrome": [PASS, NOTRUN]
 
-  [application/x-www-form-urlencoded: \\r\\n in filename (formdata event)]
-    expected:
-      if product == "chrome": [PASS, TIMEOUT]
-
   [application/x-www-form-urlencoded: double quote in filename (formdata event)]
     expected:
       if product == "chrome": [PASS, NOTRUN]
@@ -41,10 +37,6 @@
     expected:
       if product == "chrome": [PASS, NOTRUN]
 
-  [application/x-www-form-urlencoded: \\n\\r in filename (normal form)]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-
   [application/x-www-form-urlencoded: non-ASCII in name and value (formdata event)]
     expected:
       if product == "chrome": [PASS, NOTRUN]
@@ -59,7 +51,7 @@
 
   [application/x-www-form-urlencoded: double quote in name (normal form)]
     expected:
-      if product == "chrome": [PASS, NOTRUN]
+      if product == "chrome": [PASS, TIMEOUT]
 
   [application/x-www-form-urlencoded: backslash in filename (formdata event)]
     expected:
@@ -89,10 +81,6 @@
     expected:
       if product == "chrome": [PASS, NOTRUN]
 
-  [application/x-www-form-urlencoded: \\n\\r in filename (formdata event)]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-
   [application/x-www-form-urlencoded: single quote in name (formdata event)]
     expected:
       if product == "chrome": [PASS, NOTRUN]
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-target/rel-base-target.html.ini b/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-target/rel-base-target.html.ini
deleted file mode 100644
index 790eba9e..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-target/rel-base-target.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[rel-base-target.html]
-  expected:
-    if product == "chrome": [OK, ERROR]
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-target/rel-input-target.html.ini b/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-target/rel-input-target.html.ini
deleted file mode 100644
index b9b05574..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/form-submission-target/rel-input-target.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[rel-input-target.html]
-  expected:
-    if product == "chrome": ERROR
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 6a35a5d5..961645c 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,5 @@
 [selectmenu-form-state-restore.tentative.html]
   expected:
-    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [OK, ERROR]
+    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): OK
+    if flag_specific == "disable-site-isolation-trials": [OK, ERROR]
     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 b60fec3..4f7ebf5 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,9 +1,9 @@
 [activation-behavior.window.html]
   [<area> that is not connected should not be followed]
     expected:
-      if os == "win": PASS
+      if (flag_specific == "") and (product == "content_shell"): [PASS, FAIL]
       FAIL
 
   [<a> that is not connected should be followed]
     expected:
-      if (flag_specific == "") and (product == "content_shell"): FAIL
+      if (flag_specific == "") and (product == "content_shell"): [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-animation-corner-cases.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-animation-corner-cases.tentative.html
index 16426bc..f41f7a6 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-animation-corner-cases.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-animation-corner-cases.tentative.html
@@ -100,7 +100,9 @@
   assert_true(isElementVisible(popover));
   assert_equals(popover.getAnimations({subtree: true}).length,0);
   let animation;
-  popover.addEventListener('popoverhide', () => {
+  popover.addEventListener('beforetoggle', (e) => {
+    if (e.newState !== "closed")
+      return;
     animation = popover.animate([{opacity: 1},{opacity: 0}],1000000);
   });
   assert_equals(popover.getAnimations({subtree: true}).length,0,'There should be no animations yet');
@@ -111,7 +113,7 @@
   animation.finish();
   await waitForRender();
   assert_false(isElementVisible(popover),'Once the animation ends, the popover is hidden');
-},'It should be possible to use the "popoverhide" event handler to animate the hide');
+},'It should be possible to use the "beforetoggle" event handler to animate the hide');
 
 
 promise_test(async (t) => {
@@ -121,8 +123,10 @@
   popover.showPopover();
   assert_true(isElementVisible(popover));
   assert_equals(popover.getAnimations({subtree: true}).length,0);
-  let animation
-  popover.addEventListener('popoverhide', () => {
+  let animation;
+  popover.addEventListener('beforetoggle', (e) => {
+    if (e.newState !== "closed")
+      return;
     animation = popover.animate([{opacity: 1},{opacity: 0}],1000000);
   });
   assert_equals(popover.getAnimations({subtree: true}).length,0,'There should be no animations yet');
@@ -133,19 +137,17 @@
   animation.finish();
   await waitForRender();
   assert_false(isElementVisible(popover),'Once the animation ends, the popover is hidden');
-},'It should be possible to use the "popoverhide" event handler to animate the hide, even when the hide is due to dialog.showModal');
+},'It should be possible to use the "beforetoggle" event handler to animate the hide, even when the hide is due to dialog.showModal');
 
 promise_test(async (t) => {
   const {popover, descendent} = createPopover(t,'');
   popover.showPopover();
   assert_true(isElementVisible(popover));
-  popover.addEventListener('popoverhide', (e) => {
-    e.preventDefault();
-  });
+  popover.addEventListener('beforetoggle', (e) => e.preventDefault());
   popover.hidePopover();
   await waitForRender();
   assert_false(isElementVisible(popover),'Even if hide event is cancelled, the popover still closes');
-},'hide event cannot be cancelled');
+},'toggle event cannot be cancelled');
 
 promise_test(async (t) => {
   const {popover, descendent} = createPopover(t,'animation');
@@ -173,7 +175,9 @@
   popover.showPopover();
   assert_true(isElementVisible(popover));
   assert_equals(popover.getAnimations({subtree: true}).length,0);
-  popover.addEventListener('popoverhide', () => {
+  popover.addEventListener('beforetoggle', (e) => {
+    if (e.newState !== "closed")
+      return;
     popover.animate([{opacity: 1},{opacity: 0}],1000000);
   });
   assert_equals(popover.getAnimations({subtree: true}).length,0,'There should be no animations yet');
@@ -197,7 +201,9 @@
 promise_test(async (t) => {
   const {popover, descendent} = createPopover(t,'');
   popover.showPopover();
-  popover.addEventListener('popoverhide', () => {
+  popover.addEventListener('beforetoggle', (e) => {
+    if (e.newState !== "closed")
+      return;
     popover.animate([{opacity: 1},{opacity: 0}],1000000);
   });
   popover.hidePopover();
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-attribute-basic.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-attribute-basic.tentative.html
index ba09380f..ae48079 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-attribute-basic.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-attribute-basic.tentative.html
@@ -275,7 +275,8 @@
     other_popover.showPopover();
     const popover = createPopover(t);
     popover.setAttribute('popover','auto');
-    other_popover.addEventListener('popoverhide',() => {
+    other_popover.addEventListener('toggle', (e) => {
+      if (e.state !== "closing") return;
       popover.setAttribute('popover','manual');
     },{once: true});
     assert_true(other_popover.matches(':open'));
@@ -283,7 +284,7 @@
     popover.showPopover();
     assert_false(other_popover.matches(':open'),'unrelated popover is hidden');
     assert_false(popover.matches(':open'),'popover is not shown if its type changed during show');
-  },`Changing the popover type in a "popoverhide" event handler should not cause problems (during showPopover())`);
+  },`Changing the popover type in a "toggle" event handler should not cause problems (during showPopover())`);
 
   test((t) => {
     const popover = createPopover(t);
@@ -294,11 +295,13 @@
     popover.showPopover();
     other_popover.showPopover();
     let nested_popover_hidden=false;
-    other_popover.addEventListener('popoverhide',() => {
+    other_popover.addEventListener('toggle', (e) => {
+      if (e.state !== "closing") return;
       nested_popover_hidden = true;
       popover.setAttribute('popover','manual');
     },{once: true});
-    popover.addEventListener('popoverhide',() => {
+    popover.addEventListener('toggle', (e) => {
+      if (e.state !== "closing") return;
       assert_true(nested_popover_hidden,'The nested popover should be hidden first');
     },{once: true});
     assert_true(popover.matches(':open'));
@@ -307,7 +310,7 @@
     assert_false(other_popover.matches(':open'),'unrelated popover is hidden');
     assert_false(popover.matches(':open'),'popover is still hidden if its type changed during hide event');
     assert_throws_dom("InvalidStateError",() => other_popover.hidePopover(),'Nested popover should already be hidden');
-  },`Changing the popover type in a "popoverhide" event handler should not cause problems (during hidePopover())`);
+  },`Changing the popover type in a "toggle" event handler should not cause problems (during hidePopover())`);
 
   function interpretedType(typeString,method) {
     if (validTypes.includes(typeString))
@@ -344,7 +347,8 @@
             popover.showPopover();
             assert_true(popover.matches(':open'));
             let gotEvent = false;
-            popover.addEventListener('popoverhide',() => {
+            popover.addEventListener('toggle', (e) => {
+              if (e.state !== "closing") return;
               gotEvent = true;
               setPopoverValue(popover,inEventType,method);
             },{once:true});
@@ -380,7 +384,7 @@
                 }
               }
             }
-          },`Changing a popover from ${type} to ${newType} (via ${method}), and then ${inEventType} during 'popoverhide' works`);
+          },`Changing a popover from ${type} to ${newType} (via ${method}), and then ${inEventType} during 'toggle' works`);
         });
       });
     });
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-show-event.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-beforetoggle-opening-event.tentative.html
similarity index 82%
rename from third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-show-event.tentative.html
rename to third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-beforetoggle-opening-event.tentative.html
index 69996bd..b2c3fa5 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-show-event.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-beforetoggle-opening-event.tentative.html
@@ -14,7 +14,9 @@
   requestAnimationFrame(() => {++frameCount;});
   const popover = document.querySelector('[popover]');
   const testText = 'Show Event Occurred';
-  popover.addEventListener('popovershow',() => {
+  popover.addEventListener('beforetoggle',(e) => {
+    if (e.newState !== "open")
+      return;
     popover.textContent = testText;
   })
   popover.offsetHeight;
@@ -25,5 +27,5 @@
   assert_equals(popover.textContent,testText);
   assert_equals(frameCount,0,'nothing should be rendered before the popover is updated');
   popover.hidePopover(); // Cleanup
-},'Ensure the `show` event can be used to populate content before the popover renders');
+},'Ensure the `beforetoggle` event can be used to populate content before the popover renders');
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-events.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-events.tentative.html
index 78d4a22..7d63ce74 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-events.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-events.tentative.html
@@ -17,31 +17,32 @@
       assert_false(popover.matches(':open'));
       let showCount = 0;
       let hideCount = 0;
-      function showListener(e) {
-        assert_true(e.target.matches(':closed'),'The popover should be in the :closed state when the popovershow event fires.');
-        assert_false(e.target.matches(':open'),'The popover should *not* be in the :open state when the popovershow event fires.');
-        ++showCount;
-      };
-      function hideListener(e) {
-        assert_true(e.target.matches(':open'),'The popover should be in the :open state when the popoverhide event fires.');
-        assert_false(e.target.matches(':closed'),'The popover should *not* be in the :closed state when the popoverhide event fires.');
-        ++hideCount;
+      function listener(e) {
+        if (e.newState === "open") {
+          assert_equals(e.currentState,"closed",'Popover toggleevent states should be "open" and "closed"')
+          assert_true(e.target.matches(':closed'),'The popover should be in the :closed state when the opening event fires.');
+          assert_false(e.target.matches(':open'),'The popover should *not* be in the :open state when the opening event fires.');
+          ++showCount;
+        } else {
+          assert_equals(e.currentState,"open",'Popover toggleevent states should be "open" and "closed"')
+          assert_equals(e.newState,"closed",'Popover toggleevent states should be "open" and "closed"')
+          assert_true(e.target.matches(':open'),'The popover should be in the :open state when the hiding event fires.');
+          assert_false(e.target.matches(':closed'),'The popover should *not* be in the :closed state when the hiding event fires.');
+          ++hideCount;
+        }
       };
       switch (method) {
         case "listener":
           const controller = new AbortController();
           const signal = controller.signal;
           t.add_cleanup(() => controller.abort());
-          document.addEventListener('popovershow',showListener, {signal});
-          document.addEventListener('popoverhide',hideListener, {signal});
+          // The 'beforetoggle' event bubbles.
+          document.addEventListener('beforetoggle', listener, {signal});
           break;
         case "attribute":
-          assert_false(popover.hasAttribute('onpopovershow'));
-          assert_false(popover.hasAttribute('onpopoverhide'));
-          t.add_cleanup(() => popover.removeAttribute('onpopovershow'));
-          t.add_cleanup(() => popover.removeAttribute('onpopoverhide'));
-          popover.onpopovershow = showListener;
-          popover.onpopoverhide = hideListener;
+          assert_false(popover.hasAttribute('onbeforetoggle'));
+          t.add_cleanup(() => popover.removeAttribute('onbeforetoggle'));
+          popover.onbeforetoggle = listener;
           break;
         default: assert_unreached();
       }
@@ -62,7 +63,7 @@
       assert_false(popover.matches(':open'));
       assert_equals(1,showCount);
       assert_equals(1,hideCount);
-    }, `Popovershow and popoverhide events (${method}) get properly dispatched for popovers`);
+    }, `Toggle event (${method}) get properly dispatched for popovers`);
   }
 
   promise_test(async t => {
@@ -71,18 +72,20 @@
     const signal = controller.signal;
     t.add_cleanup(() => controller.abort());
     let cancel = true;
-    popover.addEventListener('popovershow',(e) => {
+    popover.addEventListener('beforetoggle',(e) => {
+      if (e.newState !== "open")
+        return;
       if (cancel)
         e.preventDefault();
     }, {signal});
     assert_false(popover.matches(':open'));
     popover.showPopover();
-    assert_false(popover.matches(':open'),'The "popovershow" event should be cancelable');
+    assert_false(popover.matches(':open'),'The "beforetoggle" event should be cancelable for the "opening" transition');
     cancel = false;
     popover.showPopover();
     assert_true(popover.matches(':open'));
     popover.hidePopover();
     assert_false(popover.matches(':open'));
-  }, 'Popovershow event is cancelable');
+  }, 'Toggle event is cancelable for the "opening" transition');
 };
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-invoking-attribute.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-invoking-attribute.tentative.html
index affe201..5ce315ef 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-invoking-attribute.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-invoking-attribute.tentative.html
@@ -175,8 +175,12 @@
 const button = document.querySelector('button');
 let showCount = 0;
 let hideCount = 0;
-popover.addEventListener('popovershow',() => ++showCount);
-popover.addEventListener('popoverhide',() => ++hideCount);
+popover.addEventListener('beforetoggle',(e) => {
+  if (e.newState === "open")
+      ++showCount;
+    else
+      ++hideCount;
+  });
 
 async function assertState(expectOpen,expectShow,expectHide) {
   assert_equals(popover.matches(':open'),expectOpen,'Popover open state is incorrect');
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-light-dismiss-on-scroll.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-light-dismiss-on-scroll.tentative.html
index 7a09712..73b3a2d61 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-light-dismiss-on-scroll.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-light-dismiss-on-scroll.tentative.html
@@ -44,7 +44,9 @@
   }
   async_test(t => {
     for(let popover of popovers) {
-      popover.addEventListener('popoverhide',e => {
+      popover.addEventListener('beforetoggle',e => {
+        if (e.newState !== "closed")
+          return;
         assert_unreached('Scrolling should not light-dismiss a popover');
       });
     }
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-light-dismiss.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-light-dismiss.tentative.html
index 2a10148..bdd0d12 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-light-dismiss.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-light-dismiss.tentative.html
@@ -47,14 +47,18 @@
   const afterp1 = document.querySelector('#after_p1');
 
   let popover1HideCount = 0;
-  popover1.addEventListener('popoverhide',(e) => {
+  popover1.addEventListener('beforetoggle',(e) => {
+    if (e.newState !== "closed")
+      return;
     ++popover1HideCount;
-    e.preventDefault(); // 'popoverhide' should not be cancellable.
+    e.preventDefault(); // 'beforetoggle' should not be cancellable.
   });
   let popover2HideCount = 0;
-  popover2.addEventListener('popoverhide',(e) => {
+  popover2.addEventListener('beforetoggle',(e) => {
+    if (e.newState !== "closed")
+      return;
     ++popover2HideCount;
-    e.preventDefault(); // 'popoverhide' should not be cancellable.
+    e.preventDefault(); // 'beforetoggle' should not be cancellable.
   });
   promise_test(async () => {
     assert_false(popover1.matches(':open'));
@@ -482,7 +486,9 @@
   p13.showPopover();
   p14.showPopover();
   p15.showPopover();
-  p15.addEventListener('popoverhide',() => {
+  p15.addEventListener('beforetoggle', (e) => {
+    if (e.newState !== "closed")
+      return;
     p14.hidePopover();
   },{once:true});
   assert_true(p13.matches(':open') && p14.matches(':open') && p15.matches(':open'),'all three should be open');
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/toggleevent-interface.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/toggleevent-interface.tentative.html
new file mode 100644
index 0000000..8ee63c40
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/toggleevent-interface.tentative.html
@@ -0,0 +1,207 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<link rel="author" href="mailto:masonf@chromium.org">
+<link rel=help href="https://open-ui.org/components/popup.research.explainer">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<script>
+test(function() {
+  var event = new BeforeToggleEvent("");
+  assert_true(event instanceof window.BeforeToggleEvent);
+}, "the event is an instance of BeforeToggleEvent");
+
+test(function() {
+  var event = new BeforeToggleEvent("");
+  assert_true(event instanceof window.Event);
+}, "the event inherts from Event");
+
+test(function() {
+  assert_throws_js(TypeError, function() {
+    new BeforeToggleEvent();
+  }, 'First argument (type) is required, so was expecting a TypeError.');
+}, 'Missing type argument');
+
+test(function() {
+  var event = new BeforeToggleEvent("test");
+  assert_equals(event.type, "test");
+}, "type argument is string");
+
+test(function() {
+  var event = new BeforeToggleEvent(null);
+  assert_equals(event.type, "null");
+}, "type argument is null");
+
+test(function() {
+  var event = new BeforeToggleEvent(undefined);
+  assert_equals(event.type, "undefined");
+}, "event type set to undefined");
+
+test(function() {
+  var event = new BeforeToggleEvent("test");
+  assert_equals(event.currentState, "");
+}, "currentState has default value of empty string");
+
+test(function() {
+  var event = new BeforeToggleEvent("test");
+  assert_readonly(event, "currentState", "readonly attribute value");
+}, "currentState is readonly");
+
+test(function() {
+  var event = new BeforeToggleEvent("test");
+  assert_equals(event.newState, "");
+}, "newState has default value of empty string");
+
+test(function() {
+  var event = new BeforeToggleEvent("test");
+  assert_readonly(event, "newState", "readonly attribute value");
+}, "newState is readonly");
+
+test(function() {
+  var event = new BeforeToggleEvent("test", null);
+  assert_equals(event.currentState, "");
+  assert_equals(event.newState, "");
+}, "BeforeToggleEventInit argument is null");
+
+test(function() {
+  var event = new BeforeToggleEvent("test", undefined);
+  assert_equals(event.currentState, "");
+  assert_equals(event.newState, "");
+}, "BeforeToggleEventInit argument is undefined");
+
+test(function() {
+  var event = new BeforeToggleEvent("test", {});
+  assert_equals(event.currentState, "");
+  assert_equals(event.newState, "");
+}, "BeforeToggleEventInit argument is empty dictionary");
+
+test(function() {
+  var event = new BeforeToggleEvent("test", {currentState: "sample"});
+  assert_equals(event.currentState, "sample");
+}, "currentState set to 'sample'");
+
+test(function() {
+  var event = new BeforeToggleEvent("test", {currentState: undefined});
+  assert_equals(event.currentState, "");
+}, "currentState set to undefined");
+
+test(function() {
+  var event = new BeforeToggleEvent("test", {currentState: null});
+  assert_equals(event.currentState, "null");
+}, "currentState set to null");
+
+test(function() {
+  var event = new BeforeToggleEvent("test", {currentState: false});
+  assert_equals(event.currentState, "false");
+}, "currentState set to false");
+
+test(function() {
+  var event = new BeforeToggleEvent("test", {currentState: true});
+  assert_equals(event.currentState, "true");
+}, "currentState set to true");
+
+test(function() {
+  var event = new BeforeToggleEvent("test", {currentState: 0.5});
+  assert_equals(event.currentState, "0.5");
+}, "currentState set to a number");
+
+test(function() {
+  var event = new BeforeToggleEvent("test", {currentState: []});
+  assert_equals(event.currentState, "");
+}, "currentState set to []");
+
+test(function() {
+  var event = new BeforeToggleEvent("test", {currentState: [1, 2, 3]});
+  assert_equals(event.currentState, "1,2,3");
+}, "currentState set to [1, 2, 3]");
+
+test(function() {
+  var event = new BeforeToggleEvent("test", {currentState: {sample: 0.5}});
+  assert_equals(event.currentState, "[object Object]");
+}, "currentState set to an object");
+
+test(function() {
+  var event = new BeforeToggleEvent("test",
+      {currentState: {valueOf: function () { return 'sample'; }}});
+  assert_equals(event.currentState, "[object Object]");
+}, "currentState set to an object with a valueOf function");
+
+test(function() {
+  var eventInit = {currentState: "sample",newState: "sample2"};
+  var event = new BeforeToggleEvent("test", eventInit);
+  assert_equals(event.currentState, "sample");
+  assert_equals(event.newState, "sample2");
+}, "BeforeToggleEventInit properties set value");
+
+test(function() {
+  var eventInit = {currentState: "open",newState: "closed"};
+  var event = new BeforeToggleEvent("beforetoggle", eventInit);
+  assert_equals(event.currentState, "open");
+  assert_equals(event.newState, "closed");
+}, "BeforeToggleEventInit properties set value 2");
+
+test(function() {
+  var eventInit = {currentState: "closed",newState: "open"};
+  var event = new BeforeToggleEvent("beforetoggle", eventInit);
+  assert_equals(event.currentState, "closed");
+  assert_equals(event.newState, "open");
+}, "BeforeToggleEventInit properties set value 3");
+
+test(function() {
+  var eventInit = {currentState: "open",newState: "open"};
+  var event = new BeforeToggleEvent("beforetoggle", eventInit);
+  assert_equals(event.currentState, "open");
+  assert_equals(event.newState, "open");
+}, "BeforeToggleEventInit properties set value 4");
+
+test(function() {
+  var event = new BeforeToggleEvent("test", {newState: "sample"});
+  assert_equals(event.newState, "sample");
+}, "newState set to 'sample'");
+
+test(function() {
+  var event = new BeforeToggleEvent("test", {newState: undefined});
+  assert_equals(event.newState, "");
+}, "newState set to undefined");
+
+test(function() {
+  var event = new BeforeToggleEvent("test", {newState: null});
+  assert_equals(event.newState, "null");
+}, "newState set to null");
+
+test(function() {
+  var event = new BeforeToggleEvent("test", {newState: false});
+  assert_equals(event.newState, "false");
+}, "newState set to false");
+
+test(function() {
+  var event = new BeforeToggleEvent("test", {newState: true});
+  assert_equals(event.newState, "true");
+}, "newState set to true");
+
+test(function() {
+  var event = new BeforeToggleEvent("test", {newState: 0.5});
+  assert_equals(event.newState, "0.5");
+}, "newState set to a number");
+
+test(function() {
+  var event = new BeforeToggleEvent("test", {newState: []});
+  assert_equals(event.newState, "");
+}, "newState set to []");
+
+test(function() {
+  var event = new BeforeToggleEvent("test", {newState: [1, 2, 3]});
+  assert_equals(event.newState, "1,2,3");
+}, "newState set to [1, 2, 3]");
+
+test(function() {
+  var event = new BeforeToggleEvent("test", {newState: {sample: 0.5}});
+  assert_equals(event.newState, "[object Object]");
+}, "newState set to an object");
+
+test(function() {
+  var event = new BeforeToggleEvent("test",
+      {newState: {valueOf: function () { return 'sample'; }}});
+  assert_equals(event.newState, "[object Object]");
+}, "newState set to an object with a valueOf function");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-job-queue/promise-job-entry.html.ini b/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-job-queue/promise-job-entry.html.ini
index 64a96d3e..c7de4281d 100644
--- a/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-job-queue/promise-job-entry.html.ini
+++ b/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/processing-model-2/integration-with-the-javascript-job-queue/promise-job-entry.html.ini
@@ -1,2 +1,3 @@
 [promise-job-entry.html]
-  expected: [OK, ERROR]
+  expected:
+    if product == "chrome": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/html/webappapis/timers/negative-settimeout.any.js.ini b/third_party/blink/web_tests/external/wpt/html/webappapis/timers/negative-settimeout.any.js.ini
new file mode 100644
index 0000000..4160c845
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/webappapis/timers/negative-settimeout.any.js.ini
@@ -0,0 +1,5 @@
+[negative-settimeout.any.html]
+
+[negative-settimeout.any.worker.html]
+  expected:
+    if product == "chrome": [OK, ERROR]
diff --git a/third_party/blink/web_tests/external/wpt/idle-detection/idle-detection-allowed-by-permissions-policy.https.sub.html.ini b/third_party/blink/web_tests/external/wpt/idle-detection/idle-detection-allowed-by-permissions-policy.https.sub.html.ini
index f6cc69d..6f363c1 100644
--- a/third_party/blink/web_tests/external/wpt/idle-detection/idle-detection-allowed-by-permissions-policy.https.sub.html.ini
+++ b/third_party/blink/web_tests/external/wpt/idle-detection/idle-detection-allowed-by-permissions-policy.https.sub.html.ini
@@ -14,6 +14,3 @@
 
   [Permissions-Policy idle-detection=* explicity set by top-level frame allows workers in cross-origin iframes.]
     expected: NOTRUN
-
-  [Inherited header permissions policy allows dedicated workers.]
-    expected: TIMEOUT
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 b8a3be5..bd9c4f8 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
@@ -1,10 +1,14 @@
 [webtransport-h3.https.sub.any.sharedworker.html]
   [WebTransport server should be running and should handle a bidirectional stream]
     expected:
-      if os == "win": FAIL
+      if os == "win": [PASS, FAIL]
 
 
 [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.serviceworker.html]
   [WebTransport server should be running and should handle a bidirectional stream]
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/picture-in-picture.idl b/third_party/blink/web_tests/external/wpt/interfaces/picture-in-picture.idl
index 19a3608b..516fb59 100644
--- a/third_party/blink/web_tests/external/wpt/interfaces/picture-in-picture.idl
+++ b/third_party/blink/web_tests/external/wpt/interfaces/picture-in-picture.idl
@@ -9,7 +9,6 @@
   attribute EventHandler onenterpictureinpicture;
   attribute EventHandler onleavepictureinpicture;
 
-  [CEReactions] attribute boolean autoPictureInPicture;
   [CEReactions] attribute boolean disablePictureInPicture;
 };
 
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 0558ad8..b179752 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,18 +1,5 @@
 [cross-origin-iframe.sub.html]
   [topDocument.scrollingElement.scrollTop = 200]
     expected:
-      if (flag_specific == "") and (product == "content_shell") and (os == "linux"): PASS
-      if (flag_specific == "") and (product == "chrome"): FAIL
+      if (flag_specific == "") and (os == "linux") and (product == "chrome"): FAIL
       if flag_specific == "disable-site-isolation-trials": FAIL
-      [PASS, FAIL]
-
-  [topDocument.scrollingElement.scrollTop = 100]
-    expected:
-      if (flag_specific == "") and (product == "content_shell") and (os == "win"): [FAIL, PASS]
-      if (flag_specific == "") and (product == "content_shell") and (os == "linux"): [PASS, FAIL]
-      if flag_specific == "disable-layout-ng": [PASS, FAIL]
-
-  [iframeDocument.scrollingElement.scrollTop = 250]
-    expected:
-      if (flag_specific == "") and (os == "win"): [PASS, FAIL]
-      if flag_specific == "disable-layout-ng": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/loading/early-hints/404-with-early-hints.h2.window.js.ini b/third_party/blink/web_tests/external/wpt/loading/early-hints/404-with-early-hints.h2.window.js.ini
index d1b88bd..e965035 100644
--- a/third_party/blink/web_tests/external/wpt/loading/early-hints/404-with-early-hints.h2.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/loading/early-hints/404-with-early-hints.h2.window.js.ini
@@ -1,2 +1,5 @@
 [404-with-early-hints.h2.window.html]
-  expected: ERROR
+  expected:
+    if (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [ERROR, CRASH]
+    if product == "chrome": OK
+    ERROR
diff --git a/third_party/blink/web_tests/external/wpt/loading/early-hints/csp-early-hints-disallowed-final-disallowed.h2.window.js.ini b/third_party/blink/web_tests/external/wpt/loading/early-hints/csp-early-hints-disallowed-final-disallowed.h2.window.js.ini
index 2aa08d2c..3e11622 100644
--- a/third_party/blink/web_tests/external/wpt/loading/early-hints/csp-early-hints-disallowed-final-disallowed.h2.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/loading/early-hints/csp-early-hints-disallowed-final-disallowed.h2.window.js.ini
@@ -1,4 +1,4 @@
 [csp-early-hints-disallowed-final-disallowed.h2.window.html]
   expected:
-    if product == "chrome": [OK, ERROR]
+    if product == "chrome": OK
     ERROR
diff --git a/third_party/blink/web_tests/external/wpt/loading/early-hints/preload-in-flight-when-consumed.h2.window.js.ini b/third_party/blink/web_tests/external/wpt/loading/early-hints/preload-in-flight-when-consumed.h2.window.js.ini
index 426ffab..1cff5a1 100644
--- a/third_party/blink/web_tests/external/wpt/loading/early-hints/preload-in-flight-when-consumed.h2.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/loading/early-hints/preload-in-flight-when-consumed.h2.window.js.ini
@@ -1,4 +1,2 @@
 [preload-in-flight-when-consumed.h2.window.html]
-  expected:
-    if product == "chrome": [OK, ERROR]
-    ERROR
+  expected: ERROR
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
deleted file mode 100644
index 05e26df..0000000
--- a/third_party/blink/web_tests/external/wpt/longtask-timing/longtask-in-sibling-iframe-crossorigin.html.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[longtask-in-sibling-iframe-crossorigin.html]
-  [Performance longtask entries from cross-origin iframe are observable in its sibling.]
-    expected:
-      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): FAIL
-      if flag_specific == "disable-site-isolation-trials": 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
index f0fa72f4..97bb31e 100644
--- 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
@@ -1,3 +1,3 @@
 [operator-dictionary-arabic-002.html]
   expected:
-    if product == "chrome": FAIL
+    if product == "chrome": [PASS, 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 2dbc02c..ebd26616 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,7 +1,7 @@
 [ignored-properties-001.html]
   expected:
-    if (os == "linux") and (product == "content_shell") and (flag_specific == "disable-site-isolation-trials"): [OK, TIMEOUT]
-    if (os == "linux") and (product == "content_shell") and (flag_specific == ""): [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/html/browsers/history/the-history-interface/011.html.ini b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/lengths-2.html.ini
similarity index 82%
rename from third_party/blink/web_tests/external/wpt/html/browsers/history/the-history-interface/011.html.ini
rename to third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/lengths-2.html.ini
index 96c1a362..6da6b90 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/history/the-history-interface/011.html.ini
+++ b/third_party/blink/web_tests/external/wpt/mathml/relations/css-styling/lengths-2.html.ini
@@ -1,3 +1,3 @@
-[011.html]
+[lengths-2.html]
   expected:
     if flag_specific == "disable-site-isolation-trials": [OK, CRASH]
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 580d0699..fe1dd28 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,5 @@
 
   [Media tracks must be removed when the SourceBuffer is removed from the MediaSource]
     expected:
-      if (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL]
-      if (os == "linux") and (flag_specific == "disable-layout-ng"): [PASS, FAIL]
-      if os == "win": FAIL
+      if (flag_specific == "") and (os == "win"): FAIL
+      if flag_specific == "disable-site-isolation-trials": 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 6c3d571c..3627867 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,8 +1,5 @@
 [mediasource-duration.html]
   expected:
-    if flag_specific == "disable-site-isolation-trials": ERROR
-    if flag_specific == "disable-layout-ng": ERROR
-  [Test appendBuffer completes previous seek to truncated duration]
-    expected:
-      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
-      if flag_specific == "disable-layout-ng": [PASS, FAIL]
+    if (os == "linux") and (product == "chrome"): [OK, ERROR]
+    if os == "win": OK
+    ERROR
diff --git a/third_party/blink/web_tests/external/wpt/media-source/mediasource-endofstream.html.ini b/third_party/blink/web_tests/external/wpt/media-source/mediasource-endofstream.html.ini
index eb2f72d..da1986cf 100644
--- a/third_party/blink/web_tests/external/wpt/media-source/mediasource-endofstream.html.ini
+++ b/third_party/blink/web_tests/external/wpt/media-source/mediasource-endofstream.html.ini
@@ -1,3 +1,9 @@
 [mediasource-endofstream.html]
+  expected:
+    if product == "chrome": [OK, TIMEOUT]
   [MediaSource.endOfStream(): duration truncated to 0 when there are no buffered coded frames]
     expected: FAIL
+
+  [MediaSource.endOfStream(): media element notified that it now has all of the media data]
+    expected:
+      if product == "chrome": [PASS, TIMEOUT]
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
index 9621dd61..81430e8 100644
--- 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
@@ -1,3 +1,5 @@
 [detach_iframe_during_open.https.window.html]
   expected:
-    if flag_specific == "disable-layout-ng": CRASH
+    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): CRASH
+    if flag_specific == "disable-site-isolation-trials": [OK, CRASH]
+    if flag_specific == "disable-layout-ng": [OK, CRASH]
diff --git a/third_party/blink/web_tests/external/wpt/navigation-api/focus-reset/change-focus-then-remove-during-intercept.html.ini b/third_party/blink/web_tests/external/wpt/navigation-api/focus-reset/change-focus-then-remove-during-intercept.html.ini
new file mode 100644
index 0000000..a220549
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/navigation-api/focus-reset/change-focus-then-remove-during-intercept.html.ini
@@ -0,0 +1,4 @@
+[change-focus-then-remove-during-intercept.html]
+  [change-focus-then-remove-during-intercept]
+    expected:
+      if (flag_specific == "") and (product == "content_shell"): [PASS, FAIL]
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
index 53ea8ed36..0adc9d25 100644
--- 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
@@ -1,3 +1,3 @@
 [navigate-initial-about-blank.html]
   expected:
-    if os == "win": [OK, ERROR]
+    if flag_specific == "disable-layout-ng": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/navigation-api/scroll-behavior/after-transition-intercept-handler-modifies.html.ini b/third_party/blink/web_tests/external/wpt/navigation-api/scroll-behavior/after-transition-intercept-handler-modifies.html.ini
index 61cb165..411718d 100644
--- a/third_party/blink/web_tests/external/wpt/navigation-api/scroll-behavior/after-transition-intercept-handler-modifies.html.ini
+++ b/third_party/blink/web_tests/external/wpt/navigation-api/scroll-behavior/after-transition-intercept-handler-modifies.html.ini
@@ -1,4 +1,4 @@
 [after-transition-intercept-handler-modifies.html]
   [scroll: state should be saved before intercept handlers run]
     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/navigation-timing/test-performance-attributes.sub.html.ini b/third_party/blink/web_tests/external/wpt/navigation-timing/test-performance-attributes.sub.html.ini
index 6b901ee..45c94f0 100644
--- 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
@@ -1,5 +1,4 @@
 [test-performance-attributes.sub.html]
   [Check that performance.timing has reasonable values for secureConnectionStart and other attributes]
     expected:
-      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [PASS, FAIL]
-      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
+      if os == "win": [PASS, 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 e569d9aa..cd98792 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,10 +3,4 @@
     if product == "chrome": ERROR
   [A discarded document does not send an already sent beacon.]
     expected:
-      if (flag_specific == "") and (os == "linux"): FAIL
-      if flag_specific == "disable-layout-ng": PASS
-      [FAIL, PASS]
-
-  [A discarded document sends all its beacons of which timeouts are not\n    default.]
-    expected:
-      if (flag_specific == "") and (os == "linux"): FAIL
+      if os == "win": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-bfcache-reasons-stay.window.js b/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-bfcache-reasons-stay.tentative.window.js
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-bfcache-reasons-stay.window.js
rename to third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-bfcache-reasons-stay.tentative.window.js
diff --git a/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-bfcache.window.js b/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-bfcache.tentative.window.js
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-bfcache.window.js
rename to third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-bfcache.tentative.window.js
diff --git a/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-cross-origin-bfcache.window.js b/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-cross-origin-bfcache.tentative.window.js
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-cross-origin-bfcache.window.js
rename to third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-cross-origin-bfcache.tentative.window.js
diff --git a/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-not-bfcached.window.js b/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-not-bfcached.tentative.window.js
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-not-bfcached.window.js
rename to third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-not-bfcached.tentative.window.js
diff --git a/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-redirect-on-history.tentative.window.js b/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-redirect-on-history.tentative.window.js
new file mode 100644
index 0000000..a9d9fac
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-redirect-on-history.tentative.window.js
@@ -0,0 +1,52 @@
+// META: title=RemoteContextHelper navigation using BFCache
+// META: script=./test-helper.js
+// META: script=/common/dispatcher/dispatcher.js
+// META: script=/common/get-host-info.sub.js
+// META: script=/common/utils.js
+// META: script=/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js
+// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js
+// META: script=/websockets/constants.sub.js
+
+'use strict';
+const {ORIGIN, REMOTE_ORIGIN} = get_host_info();
+
+// Ensure that notRestoredReasons reset after the server redirect.
+promise_test(async t => {
+  const rcHelper = new RemoteContextHelper();
+  // Open a window with noopener so that BFCache will work.
+  const rc1 = await rcHelper.addWindow(
+      /*config=*/ null, /*options=*/ {features: 'noopener'});
+  // Use WebSocket to block BFCache.
+  await useWebSocket(rc1);
+
+  // Create a remote context with the redirected URL.
+  let [rc1_redirected, saveUrl] =
+      await rcHelper.createContextWithUrl(/*extraConfig=*/ {
+        origin: 'HTTP_ORIGIN',
+        scripts: [],
+        headers: [],
+      });
+
+  const redirectUrl = `${ORIGIN}/common/redirect.py?location=${encodeURIComponent(saveUrl)}`;
+  // Replace the history state.
+  await rc1.executeScript((url) => {
+    window.history.replaceState(null, '', url);
+  }, [redirectUrl]);
+
+  // Navigate away.
+  const newRemoteContextHelper = await rc1.navigateToNew();
+
+  // Go back.
+  await newRemoteContextHelper.historyBack();
+
+  const navigation_entry = await rc1_redirected.executeScript(() => {
+    return performance.getEntriesByType('navigation')[0];
+  });
+  assert_equals(
+    navigation_entry.redirectCount, 1,
+    'Expected redirectCount is 1.');
+  // Becauase of the redirect, notRestoredReasons is reset.
+  assert_equals(
+      navigation_entry.notRestoredReasons, null,
+      'Expected notRestoredReasons is null.');
+});
diff --git a/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-same-origin-bfcache.window.js b/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-same-origin-bfcache.tentative.window.js
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-same-origin-bfcache.window.js
rename to third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-same-origin-bfcache.tentative.window.js
diff --git a/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-same-origin-bfcache.window.js.ini b/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-same-origin-bfcache.window.js.ini
index ce013cd..891fe82e 100644
--- a/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-same-origin-bfcache.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-same-origin-bfcache.window.js.ini
@@ -1,5 +1,6 @@
 [performance-navigation-timing-same-origin-bfcache.window.html]
   [RemoteContextHelper navigation using BFCache]
     expected:
-      if (product == "content_shell") and (os == "win"): [PASS, FAIL]
-      if product == "chrome": FAIL
+      if (flag_specific == "") and (os == "linux") and (product == "chrome"): FAIL
+      if (flag_specific == "") and (os == "win"): [FAIL, PASS]
+      if flag_specific == "disable-layout-ng": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-same-origin-replace.tentative.window.js b/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-same-origin-replace.tentative.window.js
new file mode 100644
index 0000000..5ee3c30
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-same-origin-replace.tentative.window.js
@@ -0,0 +1,46 @@
+// META: title=RemoteContextHelper navigation using BFCache
+// META: script=./test-helper.js
+// META: script=/common/dispatcher/dispatcher.js
+// META: script=/common/get-host-info.sub.js
+// META: script=/common/utils.js
+// META: script=/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js
+// META: script=/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js
+// META: script=/websockets/constants.sub.js
+
+'use strict';
+
+// Ensure that notRestoredReasons are accessible after history replace.
+promise_test(async t => {
+  const rcHelper = new RemoteContextHelper();
+  // Open a window with noopener so that BFCache will work.
+  const rc1 = await rcHelper.addWindow(
+      /*config=*/ null, /*options=*/ {features: 'noopener'});
+  const rc1_url = await rc1.executeScript(() => {
+    return location.href;
+  });
+
+  // Use WebSocket to block BFCache.
+  await useWebSocket(rc1);
+  // Navigate away.
+  const newRemoteContextHelper = await rc1.navigateToNew();
+  // Replace the history state to a same-origin site.
+  await newRemoteContextHelper.executeScript((destUrl) => {
+    window.history.replaceState(null, '', '#');
+  });
+  // Go back.
+  await newRemoteContextHelper.historyBack();
+
+  const navigation_entry = await rc1.executeScript(() => {
+    return performance.getEntriesByType('navigation')[0];
+  });
+  // Reasons are not reset for same-origin replace.
+  await assertNotRestoredReasonsEquals(
+      rc1,
+      /*blocked=*/ true,
+      /*url=*/ rc1_url,
+      /*src=*/ '',
+      /*id=*/ '',
+      /*name=*/ '',
+      /*reasons=*/['WebSocket'],
+      /*children=*/[]);
+});
diff --git a/third_party/blink/web_tests/external/wpt/permissions-policy/experimental-features/unload-allowed-by-default.tentative.window.js.ini b/third_party/blink/web_tests/external/wpt/permissions-policy/experimental-features/unload-allowed-by-default.tentative.window.js.ini
new file mode 100644
index 0000000..041aee22
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/permissions-policy/experimental-features/unload-allowed-by-default.tentative.window.js.ini
@@ -0,0 +1,3 @@
+[unload-allowed-by-default.tentative.window.html]
+  expected:
+    if os == "win": [OK, TIMEOUT]
diff --git a/third_party/blink/web_tests/external/wpt/permissions/permissions-garbage-collect.https.html.ini b/third_party/blink/web_tests/external/wpt/permissions/permissions-garbage-collect.https.html.ini
new file mode 100644
index 0000000..93acc40
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/permissions/permissions-garbage-collect.https.html.ini
@@ -0,0 +1,4 @@
+[permissions-garbage-collect.https.html]
+  expected: [OK, TIMEOUT]
+  [Events fire even if the status object is garbage collected]
+    expected: [PASS, TIMEOUT]
diff --git a/third_party/blink/web_tests/external/wpt/requestidlecallback/callback-invoked.html.ini b/third_party/blink/web_tests/external/wpt/requestidlecallback/callback-invoked.html.ini
new file mode 100644
index 0000000..da0f2fa
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/requestidlecallback/callback-invoked.html.ini
@@ -0,0 +1,3 @@
+[callback-invoked.html]
+  expected:
+    if flag_specific == "disable-site-isolation-trials": [OK, TIMEOUT]
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
new file mode 100644
index 0000000..a3741db8
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/requestidlecallback/deadline-max-rAF-dynamic.html.ini
@@ -0,0 +1,3 @@
+[deadline-max-rAF-dynamic.html]
+  expected:
+    if (flag_specific == "") and (product == "content_shell"): [OK, TIMEOUT]
diff --git a/third_party/blink/web_tests/external/wpt/requestidlecallback/deadline-max-rAF.html.ini b/third_party/blink/web_tests/external/wpt/requestidlecallback/deadline-max-rAF.html.ini
index d24dbbff..c2a9bbc 100644
--- a/third_party/blink/web_tests/external/wpt/requestidlecallback/deadline-max-rAF.html.ini
+++ b/third_party/blink/web_tests/external/wpt/requestidlecallback/deadline-max-rAF.html.ini
@@ -1,4 +1,3 @@
 [deadline-max-rAF.html]
-  [Check that the deadline is less than 16ms when there is a pending animation frame.]
-    expected:
-      if product == "chrome": [PASS, FAIL]
+  expected:
+    if os == "win": 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 ccb8083..960c1ca9 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,5 +1,5 @@
 [deadline-max-timeout-dynamic.html]
   expected:
-    if flag_specific == "disable-site-isolation-trials": [OK, TIMEOUT]
+    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [OK, 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/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..3ca68dd
--- /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 cross-site 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/object-not-found-after-cross-origin-redirect.html.ini b/third_party/blink/web_tests/external/wpt/resource-timing/object-not-found-after-cross-origin-redirect.html.ini
new file mode 100644
index 0000000..e13c217
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/resource-timing/object-not-found-after-cross-origin-redirect.html.ini
@@ -0,0 +1,6 @@
+[object-not-found-after-cross-origin-redirect.html]
+  expected:
+    if product == "chrome": [OK, TIMEOUT]
+  [Verify that cross-origin object resources don't implicitly expose their redirect timings]
+    expected:
+      if product == "chrome": [PASS, TIMEOUT]
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resource_timing.worker.js.ini b/third_party/blink/web_tests/external/wpt/resource-timing/resource_timing.worker.js.ini
new file mode 100644
index 0000000..6a6e5c2d4
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/resource-timing/resource_timing.worker.js.ini
@@ -0,0 +1,3 @@
+[resource_timing.worker.html]
+  expected:
+    if flag_specific == "disable-layout-ng": [OK, CRASH]
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 6babe41..8d5241ad 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,4 +1,6 @@
 [response-status-code.html]
+  expected:
+    if (flag_specific == "") and (product == "content_shell"): [OK, TIMEOUT]
   [This test validates the response status of resources. 145]
     expected: [PASS, NOTRUN]
 
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/cache-abort.https.any.js.ini b/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/cache-abort.https.any.js.ini
new file mode 100644
index 0000000..d6cfd5d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/cache-abort.https.any.js.ini
@@ -0,0 +1,9 @@
+[cache-abort.https.any.worker.html]
+
+[cache-abort.https.any.sharedworker.html]
+
+[cache-abort.https.any.html]
+  expected:
+    if os == "win": CRASH
+
+[cache-abort.https.any.serviceworker.html]
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 3bc5319..6be50b16 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
@@ -9,7 +9,7 @@
 
   [Cache.addAll should succeed when entries differ by vary header]
     expected:
-      if product == "chrome": [PASS, FAIL]
+      if product == "chrome": FAIL
 
 
 [cache-add.https.any.serviceworker.html]
@@ -20,3 +20,7 @@
 [cache-add.https.any.html]
   [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]
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 a7e1546..4769a3b3 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,18 +1,12 @@
 [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]
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [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]
+      if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [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-layout-ng": [PASS, FAIL]
-      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/service-workers/service-worker/same-site-cookies.https.html.ini b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/same-site-cookies.https.html.ini
index 3413342b..a1f53e1 100644
--- a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/same-site-cookies.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/same-site-cookies.https.html.ini
@@ -1,5 +1,4 @@
 [same-site-cookies.https.html]
-  expected: [OK, TIMEOUT]
   [same-origin, nested set location with cross-site middle frame and passthrough service worker]
     expected: 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 b72385b9..66a27a1 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,6 +1,7 @@
 [unregister-immediately-during-extendable-events.https.html]
   expected:
-    if flag_specific == "disable-site-isolation-trials": [TIMEOUT, OK]
+    if flag_specific == "disable-site-isolation-trials": OK
+    if flag_specific == "disable-layout-ng": [OK, TIMEOUT]
     TIMEOUT
   [Clear-Site-Data must fail pending subresource fetch events.]
     expected:
diff --git a/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/getinnerhtml.tentative.html.ini b/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/getinnerhtml.tentative.html.ini
new file mode 100644
index 0000000..7ab1125
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/getinnerhtml.tentative.html.ini
@@ -0,0 +1,432 @@
+[getinnerhtml.tentative.html]
+  [Element.getInnerHTML() on <article>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <article>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <article>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <article>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <article>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <article>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <article>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <article>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <aside>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <aside>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <aside>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <aside>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <aside>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <aside>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <aside>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <aside>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <blockquote>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <blockquote>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <blockquote>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <blockquote>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <blockquote>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <blockquote>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <blockquote>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <blockquote>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <body>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <body>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <body>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <body>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <body>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <body>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <body>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <body>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <div>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <div>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <div>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <div>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <div>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <div>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <div>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <div>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <footer>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <footer>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <footer>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <footer>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <footer>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <footer>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <footer>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <footer>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <h1>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <h1>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <h1>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <h1>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <h1>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <h1>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <h1>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <h1>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <h2>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <h2>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <h2>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <h2>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <h2>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <h2>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <h2>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <h2>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <h3>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <h3>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <h3>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <h3>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <h3>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <h3>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <h3>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <h3>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <h4>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <h4>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <h4>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <h4>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <h4>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <h4>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <h4>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <h4>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <h5>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <h5>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <h5>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <h5>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <h5>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <h5>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <h5>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <h5>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <h6>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <h6>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <h6>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <h6>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <h6>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <h6>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <h6>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <h6>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <header>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <header>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <header>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <header>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <header>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <header>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <header>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <header>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <main>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <main>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <main>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <main>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <main>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <main>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <main>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <main>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <nav>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <nav>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <nav>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <nav>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <nav>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <nav>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <nav>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <nav>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <p>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <p>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <p>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <p>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <p>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <p>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <p>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <p>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <section>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <section>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <section>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <section>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <section>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <section>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <section>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <section>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <span>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <span>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <span>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [Element.getInnerHTML() on <span>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <span>, with mode=open, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <span>, with mode=closed, delegatesFocus=false.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <span>, with mode=open, delegatesFocus=true.]
+    expected: FAIL
+
+  [ShadowRoot.getInnerHTML() on <span>, with mode=closed, delegatesFocus=true.]
+    expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/activation-start.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/activation-start.html.ini
index 6292f6c..aaf926f 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/activation-start.html.ini
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/activation-start.html.ini
@@ -3,8 +3,8 @@
   disabled:
     if flag_specific == "force-renderer-accessibility": was skipped in 'FlagExpectations/force-renderer-accessibility'
   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
   [PerformanceNavigationTiming's activationStart in prerendered page]
     expected:
       if product == "chrome": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/csp-prefetch-src-allow.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/csp-prefetch-src-allow.html.ini
index 14ac2c2f9..f180003 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/csp-prefetch-src-allow.html.ini
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/csp-prefetch-src-allow.html.ini
@@ -1,5 +1,6 @@
 [csp-prefetch-src-allow.html]
   expected:
+    if (product == "content_shell") and (os == "win"): [OK, ERROR]
     if product == "chrome": TIMEOUT
   [Test if CSP prefetch-src permit prerendering correctly.]
     expected:
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/fetch-intercepted-by-service-worker.https.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/fetch-intercepted-by-service-worker.https.html.ini
index 21fe7df..8ce695e 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/fetch-intercepted-by-service-worker.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/fetch-intercepted-by-service-worker.https.html.ini
@@ -1,7 +1,6 @@
 [fetch-intercepted-by-service-worker.https.html]
   expected:
-    if (os == "linux") and (product == "chrome"): TIMEOUT
-    if os == "win": TIMEOUT
+    if product == "chrome": TIMEOUT
   [fetch() in a prerendering page should go through a service worker]
     expected:
       if product == "chrome": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/indexeddb.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/indexeddb.html.ini
index e16ee6b..3dd4ff1 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/indexeddb.html.ini
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/indexeddb.html.ini
@@ -1,5 +1,6 @@
 [indexeddb.html]
   expected:
+    if (product == "content_shell") and (os == "win"): [OK, TIMEOUT]
     if product == "chrome": TIMEOUT
   [prerendering page should be able to access Indexed DataBase]
     expected:
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 18c590d..12abdfd 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
@@ -1,9 +1,10 @@
 [media-autoplay.html]
-  expected:
-    if product == "chrome": TIMEOUT
   bug: crbug.com/626703
   disabled:
     if os == "mac": was skipped in 'TestExpectations'
+  expected:
+    if (product == "content_shell") and (os == "win"): [OK, 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/referrer-policy-from-rules.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/referrer-policy-from-rules.html.ini
index c96a9be..d0cdf48 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/referrer-policy-from-rules.html.ini
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/referrer-policy-from-rules.html.ini
@@ -1,6 +1,4 @@
 [referrer-policy-from-rules.html?2-last]
-  expected:
-    if product == "chrome": [OK, ERROR]
 
 [referrer-policy-from-rules.html?1-1]
   expected: 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..76132cd0 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,6 +1,5 @@
 [referrer-policy-no-referrer.html]
   expected:
-    if (product == "content_shell") and (os == "win"): [OK, TIMEOUT]
     if product == "chrome": TIMEOUT
   [no referrer]
     expected:
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 6b4be6c2..2f36c908 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
@@ -4,13 +4,12 @@
 [response-code-non-successful.html?code=402]
 
 [response-code-non-successful.html?code=204]
-  expected: [OK, ERROR]
 
 [response-code-non-successful.html?code=404]
+  expected:
+    if product == "chrome": [OK, ERROR]
 
 [response-code-non-successful.html?code=500]
   expected: [OK, ERROR]
 
 [response-code-non-successful.html?code=205]
-  expected:
-    if product == "chrome": [OK, ERROR]
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 c0a75137..e0df3022 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,24 +1,28 @@
 [response-code-successful.html?code=203]
+  expected:
+    if product == "chrome": [ERROR, OK]
   [Responses with code 203 should be activated]
     expected:
       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 == "content_shell") and (os == "win"): [PASS, FAIL]
-      if product == "chrome": FAIL
+      if (os == "linux") and (product == "chrome"): FAIL
 
 
 [response-code-successful.html?code=201]
   [Responses with code 201 should be activated]
     expected:
-      if (os == "linux") and (product == "chrome"): FAIL
-      if os == "win": FAIL
+      if product == "chrome": FAIL
 
 
 [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-bluetooth.tentative.https.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-bluetooth.tentative.https.html.ini
index 430d214a..ebc3e37 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-bluetooth.tentative.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-bluetooth.tentative.https.html.ini
@@ -1,5 +1,6 @@
 [restriction-bluetooth.tentative.https.html]
   expected:
+    if (product == "content_shell") and (os == "win"): [OK, ERROR]
     if product == "chrome": TIMEOUT
   [the access to the Bluetooth API should be deferred until the\n   prerendered page is activated]
     expected:
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-dedicated-worker.https.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-dedicated-worker.https.html.ini
index 96308d6c..4aeadc5 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-dedicated-worker.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-dedicated-worker.https.html.ini
@@ -1,6 +1,7 @@
 [restriction-dedicated-worker.https.html]
   expected:
     if (os == "linux") and (product == "chrome"): TIMEOUT
+    if os == "win": ERROR
   [The access to the Dedicated Worker 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-encrypted-media.https.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-encrypted-media.https.html.ini
index a72b225..e09bff4 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-encrypted-media.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-encrypted-media.https.html.ini
@@ -3,8 +3,8 @@
   disabled:
     if flag_specific == "force-renderer-accessibility": was skipped in 'FlagExpectations/force-renderer-accessibility'
   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 Encrypted Media 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-idle-detection.https.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-idle-detection.https.html.ini
index f9c08def..74b7f115 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-idle-detection.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-idle-detection.https.html.ini
@@ -1,7 +1,6 @@
 [restriction-idle-detection.https.html]
   expected:
-    if (os == "linux") and (product == "chrome"): TIMEOUT
-    if os == "win": TIMEOUT
+    if product == "chrome": TIMEOUT
   [prerendering pages should not be able to invoke the Idle Detection API]
     expected:
       if product == "chrome": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-media-auto-play-attribute.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-media-auto-play-attribute.html.ini
index 66ea6cb7..1638866 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-media-auto-play-attribute.html.ini
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-media-auto-play-attribute.html.ini
@@ -3,8 +3,7 @@
   disabled:
     if flag_specific == "force-renderer-accessibility": was skipped in 'FlagExpectations/force-renderer-accessibility'
   expected:
-    if (os == "linux") and (product == "chrome"): TIMEOUT
-    if os == "win": ERROR
+    if product == "chrome": TIMEOUT
   [autoplay of the audio media should be deferred until the prerendered page is activated]
     expected:
       if product == "chrome": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-media-microphone.https.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-media-microphone.https.html.ini
index 3191a4d..9cafd15 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-media-microphone.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-media-microphone.https.html.ini
@@ -1,7 +1,6 @@
 [restriction-media-microphone.https.html]
   expected:
-    if (os == "linux") and (product == "chrome"): TIMEOUT
-    if os == "win": ERROR
+    if product == "chrome": TIMEOUT
   [the access to the Microphone of the user media 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-message-boxes.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-message-boxes.html.ini
index a190613..aeb2a55 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,7 +1,6 @@
 [restriction-message-boxes.html]
   expected:
-    if (os == "linux") and (product == "chrome"): TIMEOUT
-    if os == "win": ERROR
+    if product == "chrome": TIMEOUT
   [alert() does not display the modal and returns immediately]
     expected:
       if product == "chrome": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-prompt-by-before-unload.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-prompt-by-before-unload.html.ini
index 24bdd39..465f205d3 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-prompt-by-before-unload.html.ini
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-prompt-by-before-unload.html.ini
@@ -1,9 +1,10 @@
 [restriction-prompt-by-before-unload.html]
-  expected:
-    if product == "chrome": TIMEOUT
   bug: [crbug.com/1226461, crbug.com/1350124, crbug.com/1126305]
   disabled:
     if flag_specific == "force-renderer-accessibility": was skipped in 'FlagExpectations/force-renderer-accessibility'
+  expected:
+    if (product == "content_shell") and (os == "win"): [OK, TIMEOUT]
+    if product == "chrome": TIMEOUT
   [Prerendering cannot invoke the prompt by the beforeunload event.]
     expected:
       if product == "chrome": TIMEOUT
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-service-worker-postmessage.https.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-service-worker-postmessage.https.html.ini
index 3cb7332..7b078835 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-service-worker-postmessage.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-service-worker-postmessage.https.html.ini
@@ -1,7 +1,7 @@
 [restriction-service-worker-postmessage.https.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
   [ServiceWorker#postMessage() from a prerendered page should be deferred until page activation.]
     expected:
       if product == "chrome": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-service-worker-update.https.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-service-worker-update.https.html.ini
index f0afa05..fb6c6b0 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-service-worker-update.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-service-worker-update.https.html.ini
@@ -1,6 +1,5 @@
 [restriction-service-worker-update.https.html]
   expected:
-    if (product == "content_shell") and (os == "win"): [OK, ERROR]
     if product == "chrome": TIMEOUT
   [ServiceWorkerRegistration.update() should be deferred in a prerendered page]
     expected:
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 c8b329d..ad1ad4c 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,7 +1,6 @@
 [restriction-speech-synthesis.html]
   expected:
-    if (os == "linux") and (product == "chrome"): TIMEOUT
-    if os == "win": ERROR
+    if product == "chrome": TIMEOUT
   [speechSynthesis.speak(utterance) should be deferred until the prerendered page is activated]
     expected:
       if product == "chrome": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-web-serial.tentative.https.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-web-serial.tentative.https.html.ini
index 5b44cb6..84ffcd7 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-web-serial.tentative.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-web-serial.tentative.https.html.ini
@@ -1,7 +1,6 @@
 [restriction-web-serial.tentative.https.html]
   expected:
-    if (os == "linux") and (product == "chrome"): TIMEOUT
-    if os == "win": ERROR
+    if product == "chrome": TIMEOUT
   [the access to the Web Serial 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-usb.https.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/restriction-web-usb.https.html.ini
index 29304100..7cbd1eb 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,6 +1,5 @@
 [restriction-web-usb.https.html]
   expected:
-    if (product == "content_shell") and (os == "win"): [OK, ERROR]
     if product == "chrome": TIMEOUT
   [the access to the Web USB API should be deferred until the prerendered\n    page is activated]
     expected:
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/session-history-pushstate.https.html.ini b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/session-history-pushstate.https.html.ini
index d5dc8a7..c514647e 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/session-history-pushstate.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prerender/session-history-pushstate.https.html.ini
@@ -1,6 +1,5 @@
 [session-history-pushstate.https.html]
   expected:
-    if (product == "content_shell") and (os == "win"): [OK, TIMEOUT]
     if product == "chrome": TIMEOUT
   [history.pushState navigates independently with replacement in a prerender]
     expected:
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 cb1cc7d4..3c4ccbe 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,7 +1,6 @@
 [workers.html]
   expected:
     if (os == "linux") and (product == "chrome"): TIMEOUT
-    if os == "win": [TIMEOUT, OK]
   [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
index 0dbdc28e..4e84a27 100644
--- 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
@@ -1,5 +1,5 @@
 [partitioned-estimate-usage-details-caches.tentative.https.sub.html]
   expected:
-    if flag_specific == "disable-site-isolation-trials": [OK, TIMEOUT]
+    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [OK, TIMEOUT]
   [Partitioned estimate() usage details for caches test.]
     expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/svg/text/scripted/textlength-inconsistent.svg b/third_party/blink/web_tests/external/wpt/svg/text/scripted/textlength-inconsistent.svg
new file mode 100644
index 0000000..ca899de
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/svg/text/scripted/textlength-inconsistent.svg
@@ -0,0 +1,19 @@
+<svg xmlns="http://www.w3.org/2000/svg"
+     xmlns:html="http://www.w3.org/1999/xhtml">
+  <title>Inconsistent two 'textLength' attributes</title>
+  <html:script src="/resources/testharness.js"/>
+  <html:script src="/resources/testharnessreport.js"/>
+  <html:link rel="help" href="https://crbug.com/1399351"/>
+  <g>
+    <text textLength="150" x="10" y="100">
+    <tspan textLength="300">Scalable Vector</tspan>
+    </text>
+  </g>
+  <html:script>
+test(() => {
+  const tspan = document.querySelector('tspan');
+  assert_less_than(tspan.getStartPositionOfChar(0).x,
+                   tspan.getStartPositionOfChar(1).x);
+}, 'The first characters should be on the left of the second character.');
+  </html:script>
+</svg>
diff --git a/third_party/blink/web_tests/external/wpt/uievents/mouse/mousemove_prevent_default_action.tentative.html.ini b/third_party/blink/web_tests/external/wpt/uievents/mouse/mousemove_prevent_default_action.tentative.html.ini
index 0152fe0..f2a82b7 100644
--- a/third_party/blink/web_tests/external/wpt/uievents/mouse/mousemove_prevent_default_action.tentative.html.ini
+++ b/third_party/blink/web_tests/external/wpt/uievents/mouse/mousemove_prevent_default_action.tentative.html.ini
@@ -1,3 +1,6 @@
 [mousemove_prevent_default_action.tentative.html]
   [selectionchange event firing when mousemove event is prevented]
     expected: FAIL
+
+  [dragstart event firing when mousemove event is prevented]
+    expected: FAIL
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 12a232e8..395c5d8 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
@@ -1,8 +1,8 @@
 [a-element-xhtml.xhtml]
   expected:
     if (os == "linux") and (product == "chrome"): OK
-    if os == "win": [OK, TIMEOUT]
-    CRASH
+    if os == "win": TIMEOUT
+    [OK, CRASH]
   [Parsing: <non-special://test:@test/x> against <about:blank>]
     expected: FAIL
 
@@ -55,16 +55,13 @@
     expected: FAIL
 
   [Parsing: <C|/foo/bar> against <file:///tmp/mock/path>]
-    expected:
-      if os == "linux": FAIL
+    expected: FAIL
 
   [Parsing: </C|\\foo\\bar> against <file:///tmp/mock/path>]
-    expected:
-      if os == "linux": FAIL
+    expected: FAIL
 
   [Parsing: <//C|/foo/bar> against <file:///tmp/mock/path>]
-    expected:
-      if os == "linux": FAIL
+    expected: FAIL
 
   [Parsing: <file://localhost> against <file:///tmp/mock/path>]
     expected: FAIL
@@ -556,16 +553,13 @@
     expected: FAIL
 
   [Parsing: <..> against <file:///C:/>]
-    expected:
-      if os == "linux": FAIL
+    expected: FAIL
 
   [Parsing: </> against <file:///C:/a/b>]
-    expected:
-      if os == "linux": FAIL
+    expected: FAIL
 
   [Parsing: </> against <file://h/C:/a/b>]
-    expected:
-      if os == "linux": FAIL
+    expected: FAIL
 
   [Parsing: <//d:> against <file:///C:/a/b>]
     expected: FAIL
@@ -634,20 +628,16 @@
     expected: FAIL
 
   [Parsing: <//C:/> against <file://host/>]
-    expected:
-      if os == "linux": FAIL
+    expected: FAIL
 
   [Parsing: <file://C:/> against <file://host/>]
-    expected:
-      if os == "linux": FAIL
+    expected: FAIL
 
   [Parsing: <file:/C|/> against <about:blank>]
-    expected:
-      if os == "linux": FAIL
+    expected: FAIL
 
   [Parsing: <file://C|/> against <about:blank>]
-    expected:
-      if os == "linux": FAIL
+    expected: FAIL
 
   [Parsing: <\\\\\\.\\Y:> against <about:blank>]
     expected: FAIL
@@ -966,95 +956,3 @@
 
   [Parsing: <http://💩.123/> against <about:blank>]
     expected: FAIL
-
-  [Parsing: <file:#frag> 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: <test-a-colon-slash.html> against <a:/>]
-    expected:
-      if os == "win": FAIL
-
-  [Parsing: <file:///y:/> against <about:blank>]
-    expected:
-      if os == "win": FAIL
-
-  [Parsing: <c:/foo> against <http://example.org/foo/bar>]
-    expected:
-      if os == "win": FAIL
-
-  [Parsing: <a:\t foo.com> against <http://example.org/foo/bar>]
-    expected:
-      if os == "win": FAIL
-
-  [Parsing: </C:/> against <file://host/>]
-    expected:
-      if os == "win": FAIL
-
-  [Parsing: <file:a> against <http://www.example.com/test>]
-    expected:
-      if os == "win": FAIL
-
-  [Parsing: <test-a-colon-slash-b.html> against <a:/b>]
-    expected:
-      if os == "win": FAIL
-
-  [Parsing: </c:/foo/bar> against <file:///c:/baz/qux>]
-    expected:
-      if os == "win": FAIL
-
-  [Parsing: <file:/example.com/> against <http://example.org/foo/bar>]
-    expected:
-      if os == "win": FAIL
-
-  [Parsing: <file:.//p> against <about:blank>]
-    expected:
-      if os == "win": FAIL
-
-  [Parsing: <file:?q=v> 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
-
-  [Parsing: <file:///./y:> against <about:blank>]
-    expected:
-      if os == "win": FAIL
-
-  [Parsing: <\\\\x\\hello> against <http://example.org/foo/bar>]
-    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: </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:/example.com/> against <about:blank>]
-    expected:
-      if os == "win": 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 f995784..ffbf7fd 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,6 +1,5 @@
 [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
@@ -1018,19 +1017,3 @@
 
   [Location's href: http://💩.123/ should throw]
     expected: FAIL
-
-  [URL's href: \\\\\\.\\y: should throw]
-    expected:
-      if os == "win": FAIL
-
-  [URL's constructor's base argument: \\\\\\.\\Y: should throw]
-    expected:
-      if os == "win": FAIL
-
-  [URL's constructor's base argument: \\\\\\.\\y: should throw]
-    expected:
-      if os == "win": FAIL
-
-  [URL's href: \\\\\\.\\Y: should throw]
-    expected:
-      if os == "win": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/url/idlharness-shadowrealm.window.js.ini b/third_party/blink/web_tests/external/wpt/url/idlharness-shadowrealm.window.js.ini
index 0c7e328..1fb49415 100644
--- a/third_party/blink/web_tests/external/wpt/url/idlharness-shadowrealm.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/url/idlharness-shadowrealm.window.js.ini
@@ -1,4 +1,4 @@
 [idlharness-shadowrealm.window.html]
   expected:
-    if flag_specific == "disable-site-isolation-trials": CRASH
+    if flag_specific == "disable-site-isolation-trials": [ERROR, CRASH]
     ERROR
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 36d5702..1091bffa 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": CRASH
+    if flag_specific == "disable-site-isolation-trials": [OK, CRASH]
diff --git a/third_party/blink/web_tests/external/wpt/url/toascii.window.js.ini b/third_party/blink/web_tests/external/wpt/url/toascii.window.js.ini
index e3a339e..841d15c 100644
--- a/third_party/blink/web_tests/external/wpt/url/toascii.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/url/toascii.window.js.ini
@@ -1,4 +1,6 @@
 [toascii.window.html]
+  expected:
+    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): CRASH
   [-x.ß (using URL)]
     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 cfd90cbf..d2c3ff18 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,6 +1,6 @@
 [url-setters-stripping.any.html]
   expected:
-    if os == "win": [OK, TIMEOUT]
+    if os == "win": TIMEOUT
   [Setting pathname with leading U+0000 (https:)]
     expected: FAIL
 
@@ -318,8 +318,6 @@
 
 
 [url-setters-stripping.any.worker.html]
-  expected:
-    if os == "win": [TIMEOUT, OK]
   [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
new file mode 100644
index 0000000..52902dae
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/url/urlsearchparams-delete.any.js.ini
@@ -0,0 +1,5 @@
+[urlsearchparams-delete.any.html]
+  expected:
+    if flag_specific == "disable-site-isolation-trials": [CRASH, OK]
+
+[urlsearchparams-delete.any.worker.html]
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..3c8d8fe 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]
+  expected:
+    if flag_specific == "disable-layout-ng": CRASH
 
 [urlsearchparams-get.any.html]
-  expected:
-    if flag_specific == "disable-layout-ng": [OK, CRASH]
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
index 300c68e..54b6ffd 100644
--- 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
@@ -1,7 +1,7 @@
 [urlsearchparams-stringifier.any.worker.html]
   expected:
-    if os == "win": [OK, TIMEOUT]
+    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [OK, CRASH]
 
 [urlsearchparams-stringifier.any.html]
   expected:
-    if (os == "linux") and (flag_specific == "") and (product == "content_shell"): CRASH
+    if os == "win": [OK, TIMEOUT]
diff --git a/third_party/blink/web_tests/external/wpt/urlpattern/urlpattern-compare.https.any.js.ini b/third_party/blink/web_tests/external/wpt/urlpattern/urlpattern-compare.https.any.js.ini
new file mode 100644
index 0000000..8d42eeb
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/urlpattern/urlpattern-compare.https.any.js.ini
@@ -0,0 +1,9 @@
+[urlpattern-compare.https.any.worker.html]
+
+[urlpattern-compare.https.any.sharedworker.html]
+
+[urlpattern-compare.https.any.serviceworker.html]
+
+[urlpattern-compare.https.any.html]
+  expected:
+    if (flag_specific == "") and (product == "content_shell"): [OK, CRASH]
diff --git a/third_party/blink/web_tests/external/wpt/vibration/api-is-present.html.ini b/third_party/blink/web_tests/external/wpt/vibration/api-is-present.html.ini
new file mode 100644
index 0000000..f3986b9f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/vibration/api-is-present.html.ini
@@ -0,0 +1,3 @@
+[api-is-present.html]
+  expected:
+    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [OK, CRASH]
diff --git a/third_party/blink/web_tests/external/wpt/video-rvfc/request-video-frame-callback-webrtc.https.html.ini b/third_party/blink/web_tests/external/wpt/video-rvfc/request-video-frame-callback-webrtc.https.html.ini
new file mode 100644
index 0000000..447e1523
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/video-rvfc/request-video-frame-callback-webrtc.https.html.ini
@@ -0,0 +1,3 @@
+[request-video-frame-callback-webrtc.https.html]
+  expected:
+    if os == "win": [OK, TIMEOUT]
diff --git a/third_party/blink/web_tests/external/wpt/video-rvfc/request-video-frame-callback.html.ini b/third_party/blink/web_tests/external/wpt/video-rvfc/request-video-frame-callback.html.ini
index 9b8c640f..9dc95511 100644
--- a/third_party/blink/web_tests/external/wpt/video-rvfc/request-video-frame-callback.html.ini
+++ b/third_party/blink/web_tests/external/wpt/video-rvfc/request-video-frame-callback.html.ini
@@ -1,3 +1,3 @@
 [request-video-frame-callback.html]
   expected:
-    if product == "chrome": CRASH
+    if product == "chrome": [CRASH, OK]
diff --git a/third_party/blink/web_tests/external/wpt/visual-viewport/viewport-unscaled-scroll.html.ini b/third_party/blink/web_tests/external/wpt/visual-viewport/viewport-unscaled-scroll.html.ini
deleted file mode 100644
index 2d42fed..0000000
--- a/third_party/blink/web_tests/external/wpt/visual-viewport/viewport-unscaled-scroll.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[viewport-unscaled-scroll.html]
-  expected:
-    if os == "win": [OK, TIMEOUT]
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/timing-model/animations/seamlessly-updating-the-playback-rate-of-an-animation.html.ini b/third_party/blink/web_tests/external/wpt/web-animations/timing-model/animations/seamlessly-updating-the-playback-rate-of-an-animation.html.ini
index 5b52b138..d31b9b02 100644
--- a/third_party/blink/web_tests/external/wpt/web-animations/timing-model/animations/seamlessly-updating-the-playback-rate-of-an-animation.html.ini
+++ b/third_party/blink/web_tests/external/wpt/web-animations/timing-model/animations/seamlessly-updating-the-playback-rate-of-an-animation.html.ini
@@ -1,3 +1,5 @@
 [seamlessly-updating-the-playback-rate-of-an-animation.html]
+  expected:
+    if flag_specific == "disable-layout-ng": [OK, CRASH]
   [Updating the negative playback rate with the unresolved current time and a positive infinite associated effect end should not throw an exception]
     expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/timing-model/timelines/document-timelines.html.ini b/third_party/blink/web_tests/external/wpt/web-animations/timing-model/timelines/document-timelines.html.ini
index 8c474c4..08dcd48 100644
--- a/third_party/blink/web_tests/external/wpt/web-animations/timing-model/timelines/document-timelines.html.ini
+++ b/third_party/blink/web_tests/external/wpt/web-animations/timing-model/timelines/document-timelines.html.ini
@@ -1,4 +1,4 @@
 [document-timelines.html]
   [Document timelines report current time relative to navigationStart]
     expected:
-      if product == "chrome": [PASS, FAIL]
+      if product == "chrome": FAIL
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 675b3f1..3c560e3 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 (flag_specific == "") and (os == "win"): FAIL
-      if flag_specific == "disable-layout-ng": FAIL
+      if (flag_specific == "") and (product == "content_shell"): FAIL
+      if flag_specific == "disable-layout-ng": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/web-locks/bfcache/sharedworker-multiple.tentative.https.html.ini b/third_party/blink/web_tests/external/wpt/web-locks/bfcache/sharedworker-multiple.tentative.https.html.ini
new file mode 100644
index 0000000..d8bf264
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/web-locks/bfcache/sharedworker-multiple.tentative.https.html.ini
@@ -0,0 +1,3 @@
+[sharedworker-multiple.tentative.https.html]
+  expected:
+    if os == "win": [OK, TIMEOUT]
diff --git a/third_party/blink/web_tests/external/wpt/web-locks/crashtests/worker-termination.https.html b/third_party/blink/web_tests/external/wpt/web-locks/crashtests/worker-termination.https.html
new file mode 100644
index 0000000..b9b988b3
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/web-locks/crashtests/worker-termination.https.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html class="test-wait">
+<meta charset="utf-8">
+<script>
+  var worker = new Worker(URL.createObjectURL(new Blob([`
+    postMessage("hi");
+    (async () => {
+      const abort = new AbortController()
+      await navigator.locks.request("weblock_0", { signal: abort.signal }, () => {})
+    })()
+  `])));
+  worker.onmessage = () => {
+    worker.terminate();
+    document.documentElement.classList.remove("test-wait");
+  };
+</script>
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
deleted file mode 100644
index b63d722..0000000
--- a/third_party/blink/web_tests/external/wpt/web-locks/query-ordering.tentative.https.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[query-ordering.tentative.https.html]
-  expected:
-    if flag_specific == "disable-site-isolation-trials": [OK, CRASH]
diff --git a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audiocontext-interface/suspend-with-navigation.html.ini b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audiocontext-interface/suspend-with-navigation.html.ini
index e57ed11..652f921 100644
--- a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audiocontext-interface/suspend-with-navigation.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audiocontext-interface/suspend-with-navigation.html.ini
@@ -1,4 +1,6 @@
 [suspend-with-navigation.html]
+  expected:
+    if flag_specific == "disable-layout-ng": [OK, CRASH]
   [suspend() with navigation]
     expected:
       if product == "chrome": PRECONDITION_FAILED
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
new file mode 100644
index 0000000..97f1aa6
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-audioworklet-interface/audioworkletnode-output-channel-count.https.html.ini
@@ -0,0 +1,9 @@
+[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 f6eb33a..a15dd77 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,6 +1,4 @@
 [mediaElementAudioSourceToScriptProcessorTest.html]
   [All data processed correctly]
     expected:
-      if (flag_specific == "") and (product == "content_shell") and (os == "win"): [PASS, FAIL]
-      if flag_specific == "disable-site-isolation-trials": [FAIL, PASS]
-      if flag_specific == "disable-layout-ng": FAIL
+      if (product == "content_shell") and (os == "win"): [FAIL, PASS]
diff --git a/third_party/blink/web_tests/external/wpt/webidl/ecmascript-binding/legacy-platform-object/OwnPropertyKeys.html.ini b/third_party/blink/web_tests/external/wpt/webidl/ecmascript-binding/legacy-platform-object/OwnPropertyKeys.html.ini
index fc89840..3856f1b 100644
--- a/third_party/blink/web_tests/external/wpt/webidl/ecmascript-binding/legacy-platform-object/OwnPropertyKeys.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webidl/ecmascript-binding/legacy-platform-object/OwnPropertyKeys.html.ini
@@ -1,4 +1,6 @@
 [OwnPropertyKeys.html]
+  expected:
+    if flag_specific == "highdpi": CRASH
   [must enumerate own properties after indexed and named properties even when they're added first]
     expected: FAIL
 
diff --git a/third_party/blink/web_tests/external/wpt/webmessaging/broadcastchannel/origin.window.js.ini b/third_party/blink/web_tests/external/wpt/webmessaging/broadcastchannel/origin.window.js.ini
index cdb616cc..df1f5ad 100644
--- a/third_party/blink/web_tests/external/wpt/webmessaging/broadcastchannel/origin.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/webmessaging/broadcastchannel/origin.window.js.ini
@@ -1,3 +1,3 @@
 [origin.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/webmessaging/broadcastchannel/workers.html.ini b/third_party/blink/web_tests/external/wpt/webmessaging/broadcastchannel/workers.html.ini
index cd3a12a2..49c2787 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": [TIMEOUT, OK]
+    if flag_specific == "disable-site-isolation-trials": [OK, TIMEOUT]
diff --git a/third_party/blink/web_tests/external/wpt/webmessaging/message-channels/worker-post-after-close.any.js.ini b/third_party/blink/web_tests/external/wpt/webmessaging/message-channels/worker-post-after-close.any.js.ini
deleted file mode 100644
index c24d6cf..0000000
--- a/third_party/blink/web_tests/external/wpt/webmessaging/message-channels/worker-post-after-close.any.js.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[worker-post-after-close.any.worker.html]
-  expected:
-    if os == "win": [OK, TIMEOUT]
-
-[worker-post-after-close.any.html]
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 6742e102..b15baab 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,4 +1,6 @@
 [broadcastchannel-incumbent.sub.html]
+  expected:
+    if os == "win": [OK, TIMEOUT]
   [The incumbent page being cross-origin must not prevent the BroadcastChannel message from being seen]
     expected:
       if (flag_specific == "") and (product == "chrome"): PASS
diff --git a/third_party/blink/web_tests/external/wpt/webmessaging/with-ports/020.html.ini b/third_party/blink/web_tests/external/wpt/webmessaging/with-ports/020.html.ini
index b35e66e..921da39 100644
--- a/third_party/blink/web_tests/external/wpt/webmessaging/with-ports/020.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webmessaging/with-ports/020.html.ini
@@ -1,4 +1,4 @@
 [020.html]
   [cross-origin test]
     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/webmessaging/without-ports/020.html.ini b/third_party/blink/web_tests/external/wpt/webmessaging/without-ports/020.html.ini
new file mode 100644
index 0000000..265c7a6
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/webmessaging/without-ports/020.html.ini
@@ -0,0 +1,4 @@
+[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/webmessaging/without-ports/021.html.ini b/third_party/blink/web_tests/external/wpt/webmessaging/without-ports/021.html.ini
index 8e4edd6f..fd4aad1 100644
--- a/third_party/blink/web_tests/external/wpt/webmessaging/without-ports/021.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webmessaging/without-ports/021.html.ini
@@ -1,4 +1,4 @@
 [021.html]
   [cross-origin test]
     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/webnn/idlharness.https.any.js.ini b/third_party/blink/web_tests/external/wpt/webnn/idlharness.https.any.js.ini
index 76d37ab..4cdf45b 100644
--- a/third_party/blink/web_tests/external/wpt/webnn/idlharness.https.any.js.ini
+++ b/third_party/blink/web_tests/external/wpt/webnn/idlharness.https.any.js.ini
@@ -1,4 +1,6 @@
 [idlharness.https.any.html]
+  expected:
+    if product == "chrome": [ERROR, OK]
   [idl_test setup]
     expected: FAIL
 
diff --git a/third_party/blink/web_tests/external/wpt/webrtc-stats/hardware-capability-stats.https.html b/third_party/blink/web_tests/external/wpt/webrtc-stats/hardware-capability-stats.https.html
index 1cd3a370..49f80d4 100644
--- a/third_party/blink/web_tests/external/wpt/webrtc-stats/hardware-capability-stats.https.html
+++ b/third_party/blink/web_tests/external/wpt/webrtc-stats/hardware-capability-stats.https.html
@@ -76,8 +76,10 @@
     const stream = await getNoiseStream({video: true, audio: true});
     const statsEntry = await setupPcAndGetStatEntry(t, stream, type, kind, stat);
     assert_not_own_property(statsEntry, stat);
-  }, stat + " not exposed when not capturing or fullscreen.");
+  }, stat + " not exposed when not capturing.");
 
+  // Exposing hardware capabilities when a there is a fullscreen element was
+  // removed with https://github.com/w3c/webrtc-stats/pull/713.
   promise_test(async (t) => {
     const stream = await getNoiseStream({video: true, audio: true});
 
@@ -87,8 +89,8 @@
 
     const statsEntry = await setupPcAndGetStatEntry(
       t, stream, type, kind, stat);
-    assert_own_property(statsEntry, stat);
-  }, stat + " exposed when fullscreen.");
+    assert_not_own_property(statsEntry, stat);
+  }, stat + " not exposed when fullscreen and not capturing.");
 
   promise_test(async (t) => {
     const stream = await navigator.mediaDevices.getUserMedia(
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCDTMFSender-ontonechange.https.html.ini b/third_party/blink/web_tests/external/wpt/webrtc/RTCDTMFSender-ontonechange.https.html.ini
index 7f85bcb..0efeed6 100644
--- a/third_party/blink/web_tests/external/wpt/webrtc/RTCDTMFSender-ontonechange.https.html.ini
+++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCDTMFSender-ontonechange.https.html.ini
@@ -1,3 +1,7 @@
 [RTCDTMFSender-ontonechange.https.html]
   [Tone change event init optional parameters]
     expected: FAIL
+
+  [Setting transceiver.currentDirection to recvonly in the middle of tonechange events should stop future tonechange events from firing]
+    expected:
+      if flag_specific == "disable-site-isolation-trials": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCTrackEvent-fire.html.ini b/third_party/blink/web_tests/external/wpt/webrtc/RTCTrackEvent-fire.html.ini
deleted file mode 100644
index b240011..0000000
--- a/third_party/blink/web_tests/external/wpt/webrtc/RTCTrackEvent-fire.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[RTCTrackEvent-fire.html]
-  [Duplicate a=msid should result in a track event with one stream]
-    expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/websockets/Create-url-with-space.any.js.ini b/third_party/blink/web_tests/external/wpt/websockets/Create-url-with-space.any.js.ini
index 3bd2fc1..9cb0261ed 100644
--- a/third_party/blink/web_tests/external/wpt/websockets/Create-url-with-space.any.js.ini
+++ b/third_party/blink/web_tests/external/wpt/websockets/Create-url-with-space.any.js.ini
@@ -19,6 +19,8 @@
 
 
 [Create-url-with-space.any.worker.html?wss]
+  expected:
+    if os == "win": [OK, CRASH]
   [Create WebSocket - Pass a URL with a space - SYNTAX_ERR should be thrown]
     expected: FAIL
 
diff --git a/third_party/blink/web_tests/external/wpt/websockets/unload-a-document/002.html.ini b/third_party/blink/web_tests/external/wpt/websockets/unload-a-document/002.html.ini
index c10c381..87223f20 100644
--- a/third_party/blink/web_tests/external/wpt/websockets/unload-a-document/002.html.ini
+++ b/third_party/blink/web_tests/external/wpt/websockets/unload-a-document/002.html.ini
@@ -4,6 +4,8 @@
 
 
 [002.html?wss]
+  expected:
+    if product == "chrome": [OK, ERROR]
   [WebSockets: navigating top-level browsing context with closed websocket]
     expected: FAIL
 
diff --git a/third_party/blink/web_tests/external/wpt/webvtt/rendering/cues-with-video/processing-model/audio_has_no_subtitles.html.ini b/third_party/blink/web_tests/external/wpt/webvtt/rendering/cues-with-video/processing-model/audio_has_no_subtitles.html.ini
deleted file mode 100644
index f817e95..0000000
--- a/third_party/blink/web_tests/external/wpt/webvtt/rendering/cues-with-video/processing-model/audio_has_no_subtitles.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[audio_has_no_subtitles.html]
-  expected: [PASS, 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 4a08b26..00c1d56 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,11 +1,7 @@
 [events_referenceSpace_reset_inline.https.html]
-  expected:
-    if os == "win": OK
-    TIMEOUT
+  expected: TIMEOUT
   [XRSession resetpose from a device properly fires off the right events for non-immersive sessions - webgl]
-    expected:
-      if os == "linux": FAIL
+    expected: FAIL
 
   [XRSession resetpose from a device properly fires off the right events for non-immersive sessions - webgl2]
-    expected:
-      if os == "linux": TIMEOUT
+    expected: TIMEOUT
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 eee061a..2e02a8c 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,30 +1,6 @@
 [xrSession_requestReferenceSpace_features.https.html]
   expected:
-    if product == "chrome": [OK, TIMEOUT]
+    if (product == "content_shell") and (flag_specific == "") and (os == "linux"): [OK, TIMEOUT]
   [Non-immersive session supports viewer space by default - webgl]
     expected:
       if product == "chrome": FAIL
-
-  [Immersive session rejects local-floor space if not requested - webgl]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-
-  [Immersive session rejects local-floor space if not requested - webgl2]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-
-  [Non-immersive session rejects local space if not requested - webgl2]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-
-  [Non-immersive session rejects unbounded space even when requested - webgl]
-    expected:
-      if product == "chrome": [PASS, TIMEOUT]
-
-  [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]
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..44b157f5 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
@@ -3,6 +3,6 @@
     expected:
       if product == "chrome": FAIL
 
-  ['floor-level' XRStationaryReferenceSpace updates properly when the transform changes for non-immersive sessions - webgl]
+  ['floor-level' XRStationaryReferenceSpace updates properly when the transform changes for non-immersive sessions - webgl2]
     expected:
-      if product == "chrome": FAIL
+      if product == "chrome": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/workers/dedicated-worker-from-blob-url.window.js.ini b/third_party/blink/web_tests/external/wpt/workers/dedicated-worker-from-blob-url.window.js.ini
index b6f8e24..1f41aff 100644
--- a/third_party/blink/web_tests/external/wpt/workers/dedicated-worker-from-blob-url.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/workers/dedicated-worker-from-blob-url.window.js.ini
@@ -1,4 +1,4 @@
 [dedicated-worker-from-blob-url.window.html]
   expected:
-    if (flag_specific == "") and (os == "win"): [OK, TIMEOUT]
+    if (flag_specific == "") and (os == "win"): TIMEOUT
     if flag_specific == "disable-layout-ng": TIMEOUT
diff --git a/third_party/blink/web_tests/external/wpt/workers/dedicated-worker-in-data-url-context.window.js.ini b/third_party/blink/web_tests/external/wpt/workers/dedicated-worker-in-data-url-context.window.js.ini
index 0521a49..8e3ebef 100644
--- a/third_party/blink/web_tests/external/wpt/workers/dedicated-worker-in-data-url-context.window.js.ini
+++ b/third_party/blink/web_tests/external/wpt/workers/dedicated-worker-in-data-url-context.window.js.ini
@@ -1,6 +1,4 @@
 [dedicated-worker-in-data-url-context.window.html]
-  expected:
-    if flag_specific == "disable-site-isolation-trials": TIMEOUT
   [Create a dedicated worker in a data url frame]
     expected: FAIL
 
diff --git a/third_party/blink/web_tests/external/wpt/workers/interfaces/WorkerGlobalScope/onerror/exception-in-onerror.html.ini b/third_party/blink/web_tests/external/wpt/workers/interfaces/WorkerGlobalScope/onerror/exception-in-onerror.html.ini
index 17e25684..4d5ef860 100644
--- a/third_party/blink/web_tests/external/wpt/workers/interfaces/WorkerGlobalScope/onerror/exception-in-onerror.html.ini
+++ b/third_party/blink/web_tests/external/wpt/workers/interfaces/WorkerGlobalScope/onerror/exception-in-onerror.html.ini
@@ -1,3 +1,3 @@
 [exception-in-onerror.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/modules/dedicated-worker-import-meta.html.ini b/third_party/blink/web_tests/external/wpt/workers/modules/dedicated-worker-import-meta.html.ini
index f8185f10..1457ee30 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,3 @@
 [dedicated-worker-import-meta.html]
-  expected:
-    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/workers/modules/shared-worker-import-csp.html.ini b/third_party/blink/web_tests/external/wpt/workers/modules/shared-worker-import-csp.html.ini
index 1231f09..ab9b683 100644
--- a/third_party/blink/web_tests/external/wpt/workers/modules/shared-worker-import-csp.html.ini
+++ b/third_party/blink/web_tests/external/wpt/workers/modules/shared-worker-import-csp.html.ini
@@ -1,7 +1,5 @@
 [shared-worker-import-csp.html]
+  expected:
+    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [OK, ERROR]
   [script-src 'self' directive should disallow cross origin static import.]
     expected: [PASS, FAIL]
-
-  [worker-src 'self' directive should override script-src * directive and disallow cross origin static import.]
-    expected:
-      if product == "chrome": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/workers/nested_worker_close_self.worker.js.ini b/third_party/blink/web_tests/external/wpt/workers/nested_worker_close_self.worker.js.ini
index 8a8a551..520cb653 100644
--- a/third_party/blink/web_tests/external/wpt/workers/nested_worker_close_self.worker.js.ini
+++ b/third_party/blink/web_tests/external/wpt/workers/nested_worker_close_self.worker.js.ini
@@ -1,3 +1,3 @@
 [nested_worker_close_self.worker.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
diff --git a/third_party/blink/web_tests/external/wpt/workers/semantics/interface-objects/003.any.js.ini b/third_party/blink/web_tests/external/wpt/workers/semantics/interface-objects/003.any.js.ini
index daf7342..d5372c4 100644
--- a/third_party/blink/web_tests/external/wpt/workers/semantics/interface-objects/003.any.js.ini
+++ b/third_party/blink/web_tests/external/wpt/workers/semantics/interface-objects/003.any.js.ini
@@ -1,6 +1,4 @@
 [003.any.sharedworker.html]
-  expected:
-    if os == "win": TIMEOUT
   [The ApplicationCache interface object should be exposed]
     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
new file mode 100644
index 0000000..bcf7103f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/worklets/animation-worklet-import.https.html.ini
@@ -0,0 +1,3 @@
+[animation-worklet-import.https.html]
+  expected:
+    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [OK, TIMEOUT]
diff --git a/third_party/blink/web_tests/external/wpt/worklets/audio-worklet-service-worker-interception.https.html.ini b/third_party/blink/web_tests/external/wpt/worklets/audio-worklet-service-worker-interception.https.html.ini
new file mode 100644
index 0000000..c76f84d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/worklets/audio-worklet-service-worker-interception.https.html.ini
@@ -0,0 +1,3 @@
+[audio-worklet-service-worker-interception.https.html]
+  expected:
+    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [OK, CRASH]
diff --git a/third_party/blink/web_tests/external/wpt/xhr/abort-after-send.any.js.ini b/third_party/blink/web_tests/external/wpt/xhr/abort-after-send.any.js.ini
index a0be8075..e3c68023 100644
--- a/third_party/blink/web_tests/external/wpt/xhr/abort-after-send.any.js.ini
+++ b/third_party/blink/web_tests/external/wpt/xhr/abort-after-send.any.js.ini
@@ -1,4 +1,6 @@
 [abort-after-send.any.html]
+  expected:
+    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [OK, TIMEOUT]
   [XMLHttpRequest: abort() after send()]
     expected: FAIL
 
diff --git a/third_party/blink/web_tests/external/wpt/xhr/anonymous-mode-unsupported.htm.ini b/third_party/blink/web_tests/external/wpt/xhr/anonymous-mode-unsupported.htm.ini
new file mode 100644
index 0000000..f1cae53
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/xhr/anonymous-mode-unsupported.htm.ini
@@ -0,0 +1,4 @@
+[anonymous-mode-unsupported.htm]
+  [XMLHttpRequest: anonymous mode unsupported]
+    expected:
+      if product == "chrome": [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/xhr/formdata/set-blob.any.js.ini b/third_party/blink/web_tests/external/wpt/xhr/formdata/set-blob.any.js.ini
index f188fd27..d834c1b 100644
--- a/third_party/blink/web_tests/external/wpt/xhr/formdata/set-blob.any.js.ini
+++ b/third_party/blink/web_tests/external/wpt/xhr/formdata/set-blob.any.js.ini
@@ -4,5 +4,7 @@
 
 
 [set-blob.any.worker.html]
+  expected:
+    if (flag_specific == "") and (os == "linux") and (product == "content_shell"): [OK, TIMEOUT]
   [blob without type]
     expected: FAIL
diff --git a/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-listing-expected.txt b/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-listing-expected.txt
index ee497d2..095ea9f 100644
--- a/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-listing-expected.txt
+++ b/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-listing-expected.txt
@@ -219,7 +219,6 @@
 lighting-color: rgb(255, 255, 255)
 line-break: auto
 line-height: normal
-line-height-step: 0px
 list-style-image: none
 list-style-position: outside
 list-style-type: disc
diff --git a/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt b/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt
index 339c11e..43521eb 100644
--- a/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt
+++ b/third_party/blink/web_tests/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt
@@ -219,7 +219,6 @@
 lighting-color: rgb(255, 255, 255)
 line-break: auto
 line-height: normal
-line-height-step: 0px
 list-style-image: none
 list-style-position: outside
 list-style-type: disc
diff --git a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
index 9bf94b7..84e6b0c 100644
--- a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
+++ b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
@@ -110,6 +110,7 @@
 PASS oldChildWindow.onbeforeinstallprompt is newChildWindow.onbeforeinstallprompt
 PASS oldChildWindow.onbeforematch is newChildWindow.onbeforematch
 PASS oldChildWindow.onbeforeprint is newChildWindow.onbeforeprint
+PASS oldChildWindow.onbeforetoggle is newChildWindow.onbeforetoggle
 PASS oldChildWindow.onbeforeunload is newChildWindow.onbeforeunload
 PASS oldChildWindow.onbeforexrselect is newChildWindow.onbeforexrselect
 PASS oldChildWindow.onblur is newChildWindow.onblur
diff --git a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt
index c8e76ad9..ddea9ccc 100644
--- a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt
+++ b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt
@@ -55,6 +55,7 @@
 PASS childWindow.onbeforeinstallprompt is null
 PASS childWindow.onbeforematch is null
 PASS childWindow.onbeforeprint is null
+PASS childWindow.onbeforetoggle is null
 PASS childWindow.onbeforeunload is null
 PASS childWindow.onbeforexrselect is null
 PASS childWindow.onblur is null
diff --git a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt
index 7879a77..140f23d4 100644
--- a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt
+++ b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt
@@ -55,6 +55,7 @@
 PASS childWindow.onbeforeinstallprompt is null
 PASS childWindow.onbeforematch is null
 PASS childWindow.onbeforeprint is null
+PASS childWindow.onbeforetoggle is null
 PASS childWindow.onbeforeunload is null
 PASS childWindow.onbeforexrselect is null
 PASS childWindow.onblur is null
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-rhythm/line-height-step-dynamic-001-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-rhythm/line-height-step-dynamic-001-expected.txt
deleted file mode 100644
index 5952b13e..0000000
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-rhythm/line-height-step-dynamic-001-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-This is a testharness.js-based test.
-PASS Height must change when line-height-step changes
-PASS Height must not change after relayout
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/css/getComputedStyle/computed-style-listing-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/css/getComputedStyle/computed-style-listing-expected.txt
index a0db527a..5c660b3 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/css/getComputedStyle/computed-style-listing-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/css/getComputedStyle/computed-style-listing-expected.txt
@@ -218,7 +218,6 @@
 lighting-color: rgb(255, 255, 255)
 line-break: auto
 line-height: normal
-line-height-step: 0px
 list-style-image: none
 list-style-position: outside
 list-style-type: disc
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt
index 9df5c16..91e937b 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/css/getComputedStyle/computed-style-without-renderer-listing-expected.txt
@@ -218,7 +218,6 @@
 lighting-color: rgb(255, 255, 255)
 line-break: auto
 line-height: normal
-line-height-step: 0px
 list-style-image: none
 list-style-position: outside
 list-style-type: disc
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/svg/css/getComputedStyle-listing-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/svg/css/getComputedStyle-listing-expected.txt
index 312ce29..9b9a9702 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/svg/css/getComputedStyle-listing-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/svg/css/getComputedStyle-listing-expected.txt
@@ -218,7 +218,6 @@
 lighting-color: rgb(255, 255, 255)
 line-break: auto
 line-height: normal
-line-height-step: 0px
 list-style-image: none
 list-style-position: outside
 list-style-type: disc
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/webexposed/css-properties-as-js-properties-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/webexposed/css-properties-as-js-properties-expected.txt
index dba4640..32fe4917 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/webexposed/css-properties-as-js-properties-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/webexposed/css-properties-as-js-properties-expected.txt
@@ -249,7 +249,6 @@
 lineBreak
 lineGapOverride
 lineHeight
-lineHeightStep
 listStyle
 listStyleImage
 listStylePosition
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/webexposed/css-property-listing-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/webexposed/css-property-listing-expected.txt
index 3ea6a42..82febf21 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/webexposed/css-property-listing-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/webexposed/css-property-listing-expected.txt
@@ -234,7 +234,6 @@
     lighting-color
     line-break
     line-height
-    line-height-step
     list-style-image
     list-style-position
     list-style-type
diff --git a/third_party/blink/web_tests/svg/css/getComputedStyle-listing-expected.txt b/third_party/blink/web_tests/svg/css/getComputedStyle-listing-expected.txt
index d59b9a04..5686baf 100644
--- a/third_party/blink/web_tests/svg/css/getComputedStyle-listing-expected.txt
+++ b/third_party/blink/web_tests/svg/css/getComputedStyle-listing-expected.txt
@@ -219,7 +219,6 @@
 lighting-color: rgb(255, 255, 255)
 line-break: auto
 line-height: normal
-line-height-step: 0px
 list-style-image: none
 list-style-position: outside
 list-style-type: disc
diff --git a/third_party/blink/web_tests/virtual/popover-disabled/popover-disabled-expected.txt b/third_party/blink/web_tests/virtual/popover-disabled/popover-disabled-expected.txt
index dd7f1e9..58123bd 100644
--- a/third_party/blink/web_tests/virtual/popover-disabled/popover-disabled-expected.txt
+++ b/third_party/blink/web_tests/virtual/popover-disabled/popover-disabled-expected.txt
@@ -3,44 +3,13 @@
 CONSOLE ERROR: Found a 'popover' attribute. If you are testing the popover API, you must enable Experimental Web Platform Features. If not, note that custom attributes must start with 'data-': https://html.spec.whatwg.org/multipage/dom.html#custom-data-attribute. This usage will *likely cause site breakage* when the popover API ships: https://chromestatus.com/feature/5463833265045504.
 CONSOLE ERROR: Found a 'popover' attribute. If you are testing the popover API, you must enable Experimental Web Platform Features. If not, note that custom attributes must start with 'data-': https://html.spec.whatwg.org/multipage/dom.html#custom-data-attribute. This usage will *likely cause site breakage* when the popover API ships: https://chromestatus.com/feature/5463833265045504.
 CONSOLE ERROR: Found a 'popover' attribute. If you are testing the popover API, you must enable Experimental Web Platform Features. If not, note that custom attributes must start with 'data-': https://html.spec.whatwg.org/multipage/dom.html#custom-data-attribute. This usage will *likely cause site breakage* when the popover API ships: https://chromestatus.com/feature/5463833265045504.
-CONSOLE ERROR: Found a 'popover' attribute. If you are testing the popover API, you must enable Experimental Web Platform Features. If not, note that custom attributes must start with 'data-': https://html.spec.whatwg.org/multipage/dom.html#custom-data-attribute. This usage will *likely cause site breakage* when the popover API ships: https://chromestatus.com/feature/5463833265045504.
-This content should be visible, if HTMLPopoverAttribute is disabled
-This content should be visible, if HTMLPopoverAttribute is disabled
-This content should be visible, if HTMLPopoverAttribute is disabled
-This content should be visible, if HTMLPopoverAttribute is disabled
-This content should be visible, if HTMLPopoverAttribute is disabled
-This content should be visible, if HTMLPopoverAttribute is disabled
-Summary
+This is a testharness.js-based test.
+PASS Basic tests
+PASS <div popover="auto">This content should be visible, if HTMLPopoverAttribute is disabled</div> should be stylable/visible and not display:none
+PASS <div popover="async">This content should be visible, if HTMLPopoverAttribute is disabled</div> should be stylable/visible and not display:none
+PASS <div popover="invalid">This content should be visible, if HTMLPopoverAttribute is disabled</div> should be stylable/visible and not display:none
+PASS <div popover="">This content should be visible, if HTMLPopoverAttribute is disabled</div> should be stylable/visible and not display:none
+PASS <div popover="" id="foo">This content should be visible, if HTMLPopoverAttribute is disabled</div> should be stylable/visible and not display:none
+PASS The popover IDL attribute should not be present on Element
+Harness: the test ran to completion.
 
-Harness status: OK
-
-Rerun
-
-Found 8 tests
-
-8 Pass
-Details
-Result	Test Name	Message
-Pass	Basic tests	
-Asserts run
-
-Pass	<div popover="auto">This content should be visible, if HTMLPopoverAttribute is disabled</div> should be stylable/visible and not display:none	
-Asserts run
-
-Pass	<div popover="hint">This content should be visible, if HTMLPopoverAttribute is disabled</div> should be stylable/visible and not display:none	
-Asserts run
-
-Pass	<div popover="async">This content should be visible, if HTMLPopoverAttribute is disabled</div> should be stylable/visible and not display:none	
-Asserts run
-
-Pass	<div popover="invalid">This content should be visible, if HTMLPopoverAttribute is disabled</div> should be stylable/visible and not display:none	
-Asserts run
-
-Pass	<div popover="">This content should be visible, if HTMLPopoverAttribute is disabled</div> should be stylable/visible and not display:none	
-Asserts run
-
-Pass	<div popover="" id="foo">This content should be visible, if HTMLPopoverAttribute is disabled</div> should be stylable/visible and not display:none	
-Asserts run
-
-Pass	The popover IDL attribute should not be present on Element	
-Asserts run
diff --git a/third_party/blink/web_tests/virtual/popover-disabled/popover-disabled.html b/third_party/blink/web_tests/virtual/popover-disabled/popover-disabled.html
index 487c1f3..22162035 100644
--- a/third_party/blink/web_tests/virtual/popover-disabled/popover-disabled.html
+++ b/third_party/blink/web_tests/virtual/popover-disabled/popover-disabled.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
 <meta charset="utf-8">
 <script src='../../resources/testharness.js'></script>
+<script src="../../resources/testharnessreport.js"></script>
 
 <div id=elements>
   <div popover=auto>This content should be visible, if HTMLPopoverAttribute is disabled</div>
-  <div popover=hint>This content should be visible, if HTMLPopoverAttribute is disabled</div>
   <div popover=async>This content should be visible, if HTMLPopoverAttribute is disabled</div>
   <div popover=invalid>This content should be visible, if HTMLPopoverAttribute is disabled</div>
   <div popover="">This content should be visible, if HTMLPopoverAttribute is disabled</div>
@@ -12,6 +12,7 @@
 </div>
 
 <script>
+window.onload = () => {
   if (window.testRunner)
     testRunner.dumpAsText();
 
@@ -40,5 +41,5 @@
   test(() => {
     assert_false(supportsPopover());
   },`The popover IDL attribute should not be present on Element`);
-
+};
 </script>
diff --git a/third_party/blink/web_tests/webexposed/css-properties-as-js-properties-expected.txt b/third_party/blink/web_tests/webexposed/css-properties-as-js-properties-expected.txt
index 9fdcd6e..bd65e199 100644
--- a/third_party/blink/web_tests/webexposed/css-properties-as-js-properties-expected.txt
+++ b/third_party/blink/web_tests/webexposed/css-properties-as-js-properties-expected.txt
@@ -250,7 +250,6 @@
 lineBreak
 lineGapOverride
 lineHeight
-lineHeightStep
 listStyle
 listStyleImage
 listStylePosition
diff --git a/third_party/blink/web_tests/webexposed/css-property-listing-expected.txt b/third_party/blink/web_tests/webexposed/css-property-listing-expected.txt
index 7f74212f..a40b1d85 100644
--- a/third_party/blink/web_tests/webexposed/css-property-listing-expected.txt
+++ b/third_party/blink/web_tests/webexposed/css-property-listing-expected.txt
@@ -235,7 +235,6 @@
     lighting-color
     line-break
     line-height
-    line-height-step
     list-style-image
     list-style-position
     list-style-type
diff --git a/third_party/blink/web_tests/webexposed/element-instance-property-listing-expected.txt b/third_party/blink/web_tests/webexposed/element-instance-property-listing-expected.txt
index 82c33ce..0c555c0 100644
--- a/third_party/blink/web_tests/webexposed/element-instance-property-listing-expected.txt
+++ b/third_party/blink/web_tests/webexposed/element-instance-property-listing-expected.txt
@@ -185,6 +185,7 @@
     property onbeforeinput
     property onbeforematch
     property onbeforepaste
+    property onbeforetoggle
     property onbeforexrselect
     property onblur
     property oncancel
@@ -1187,7 +1188,6 @@
     property NETWORK_NO_SOURCE
     property addTextTrack
     property audioTracks
-    property autoPictureInPicture
     property autoplay
     property buffered
     property canPlayType
@@ -1418,6 +1418,7 @@
     property onbeforeinput
     property onbeforematch
     property onbeforepaste
+    property onbeforetoggle
     property onbeforexrselect
     property onblur
     property oncancel
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
index 0aabb65..116fcb0b1 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -546,6 +546,11 @@
     getter userChoice
     method constructor
     method prompt
+interface BeforeToggleEvent : Event
+    attribute @@toStringTag
+    getter currentState
+    getter newState
+    method constructor
 interface BeforeUnloadEvent : Event
     attribute @@toStringTag
     getter returnValue
@@ -1855,6 +1860,7 @@
     getter onbeforeinput
     getter onbeforematch
     getter onbeforepaste
+    getter onbeforetoggle
     getter onbeforexrselect
     getter onblur
     getter oncancel
@@ -2070,6 +2076,7 @@
     setter onbeforeinput
     setter onbeforematch
     setter onbeforepaste
+    setter onbeforetoggle
     setter onbeforexrselect
     setter onblur
     setter oncancel
@@ -3300,6 +3307,7 @@
     getter onauxclick
     getter onbeforeinput
     getter onbeforematch
+    getter onbeforetoggle
     getter onbeforexrselect
     getter onblur
     getter oncancel
@@ -3435,6 +3443,7 @@
     setter onauxclick
     setter onbeforeinput
     setter onbeforematch
+    setter onbeforetoggle
     setter onbeforexrselect
     setter onblur
     setter oncancel
@@ -4639,7 +4648,6 @@
     method constructor
 interface HTMLVideoElement : HTMLMediaElement
     attribute @@toStringTag
-    getter autoPictureInPicture
     getter disablePictureInPicture
     getter height
     getter onenterpictureinpicture
@@ -4662,7 +4670,6 @@
     method webkitEnterFullscreen
     method webkitExitFullScreen
     method webkitExitFullscreen
-    setter autoPictureInPicture
     setter disablePictureInPicture
     setter height
     setter onenterpictureinpicture
@@ -5278,6 +5285,7 @@
     getter onauxclick
     getter onbeforeinput
     getter onbeforematch
+    getter onbeforetoggle
     getter onbeforexrselect
     getter onblur
     getter oncancel
@@ -5390,6 +5398,7 @@
     setter onauxclick
     setter onbeforeinput
     setter onbeforematch
+    setter onbeforetoggle
     setter onbeforexrselect
     setter onblur
     setter oncancel
@@ -7561,6 +7570,7 @@
     getter onauxclick
     getter onbeforeinput
     getter onbeforematch
+    getter onbeforetoggle
     getter onbeforexrselect
     getter onblur
     getter oncancel
@@ -7675,6 +7685,7 @@
     setter onauxclick
     setter onbeforeinput
     setter onbeforematch
+    setter onbeforetoggle
     setter onbeforexrselect
     setter onblur
     setter oncancel
@@ -11904,6 +11915,7 @@
     getter onbeforeinstallprompt
     getter onbeforematch
     getter onbeforeprint
+    getter onbeforetoggle
     getter onbeforeunload
     getter onbeforexrselect
     getter onblur
@@ -12127,6 +12139,7 @@
     setter onbeforeinstallprompt
     setter onbeforematch
     setter onbeforeprint
+    setter onbeforetoggle
     setter onbeforeunload
     setter onbeforexrselect
     setter onblur
diff --git a/third_party/blink/web_tests/wpt_internal/html/interaction/focus/the-autofocus-attribute/object-fallback.html.ini b/third_party/blink/web_tests/wpt_internal/html/interaction/focus/the-autofocus-attribute/object-fallback.html.ini
index b946504..7c75a1f 100644
--- a/third_party/blink/web_tests/wpt_internal/html/interaction/focus/the-autofocus-attribute/object-fallback.html.ini
+++ b/third_party/blink/web_tests/wpt_internal/html/interaction/focus/the-autofocus-attribute/object-fallback.html.ini
@@ -1,6 +1,4 @@
 [object-fallback.html]
-  expected:
-    if os == "win": TIMEOUT
   [An autofocus element in an OBJECT with a loaded frame should not be processed]
     expected:
       if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/wpt_internal/prerender/restriction-pointer-lock.html.ini b/third_party/blink/web_tests/wpt_internal/prerender/restriction-pointer-lock.html.ini
index 4b9f70e..b8379f0 100644
--- a/third_party/blink/web_tests/wpt_internal/prerender/restriction-pointer-lock.html.ini
+++ b/third_party/blink/web_tests/wpt_internal/prerender/restriction-pointer-lock.html.ini
@@ -1,9 +1,10 @@
 [restriction-pointer-lock.html]
-  expected:
-    if product == "chrome": TIMEOUT
   bug: [crbug.com/1226461, crbug.com/1350124, crbug.com/1126305]
   disabled:
     if flag_specific == "force-renderer-accessibility": @False
+  expected:
+    if (product == "content_shell") and (os == "win"): [OK, TIMEOUT]
+    if product == "chrome": TIMEOUT
   [prerendering pages should not be able to request pointer lock]
     expected:
       if product == "chrome": TIMEOUT
diff --git a/third_party/closure_compiler/externs/accessibility_features.js b/third_party/closure_compiler/externs/accessibility_features.js
index 61e2bef4..ef8a9dea 100644
--- a/third_party/closure_compiler/externs/accessibility_features.js
+++ b/third_party/closure_compiler/externs/accessibility_features.js
@@ -8,9 +8,9 @@
 //   'chrome.accessibilityFeatures.FooType'.
 // Please run the closure compiler before committing changes.
 // See https://chromium.googlesource.com/chromium/src/+/main/docs/closure_compilation.md
-// NOTE: This file was modified by hand after it was generated. All instances of
-// chrome.accessibilityFeatures.types.ChromeSetting must be changed to
-// ChromeSetting after this file is generated.
+
+// TODO(crbug.com/543822): Disable automatic extern generation until fixed.
+// s/chrome.accessibilityFeatures.types.ChromeSetting/ChromeSetting/
 
 /**
  * @fileoverview Externs generated from namespace: accessibilityFeatures
diff --git a/third_party/closure_compiler/externs/autofill_private.js b/third_party/closure_compiler/externs/autofill_private.js
index 8e863df..a5cc6cd 100644
--- a/third_party/closure_compiler/externs/autofill_private.js
+++ b/third_party/closure_compiler/externs/autofill_private.js
@@ -219,8 +219,8 @@
 
 /**
  * Enrolls a credit card into virtual cards.
- * @param {string} cardId The server side id of the credit card to be
- *     enrolled. Note it refers to the legacy server id of credit cards, not the
+ * @param {string} cardId The server side id of the credit card to be enrolled.
+ *     Note it refers to the legacy server id of credit cards, not the
  *     instrument ids.
  */
 chrome.autofillPrivate.addVirtualCard = function(cardId) {};
diff --git a/third_party/closure_compiler/externs/automation.js b/third_party/closure_compiler/externs/automation.js
index e0b442ed..67a9760 100644
--- a/third_party/closure_compiler/externs/automation.js
+++ b/third_party/closure_compiler/externs/automation.js
@@ -9,6 +9,9 @@
 // Please run the closure compiler before committing changes.
 // See https://chromium.googlesource.com/chromium/src/+/main/docs/closure_compilation.md
 
+// TODO(b/242243189): Disable automatic extern generation until fixed.
+// The longClick method was manually inserted.
+
 /**
  * @fileoverview Externs generated from namespace: automation
  * @externs
@@ -405,6 +408,7 @@
   INCREMENT: 'increment',
   INTERNAL_INVALIDATE_TREE: 'internalInvalidateTree',
   LOAD_INLINE_TEXT_BOXES: 'loadInlineTextBoxes',
+  LONG_CLICK: 'longClick',
   REPLACE_SELECTED_TEXT: 'replaceSelectedText',
   RESUME_MEDIA: 'resumeMedia',
   SCROLL_BACKWARD: 'scrollBackward',
@@ -427,7 +431,6 @@
   START_DUCKING_MEDIA: 'startDuckingMedia',
   STOP_DUCKING_MEDIA: 'stopDuckingMedia',
   SUSPEND_MEDIA: 'suspendMedia',
-  LONG_CLICK: 'longClick',
 };
 
 /**
@@ -2427,14 +2430,6 @@
 chrome.automation.AutomationNode.prototype.scrollToPoint = function(x, y) {};
 
 /**
- * Scrolls this scrollable grid to the given row and column index.
- * @param {number} row
- * @param {number} column
- * @see https://developer.chrome.com/extensions/automation#method-scrollToPositionAtRowColumn
- */
- chrome.automation.AutomationNode.prototype.scrollToPositionAtRowColumn = function(row, column) {};
-
-/**
  * Sets this scrollable container's scroll offset.
  * @param {number} x
  * @param {number} y
diff --git a/third_party/closure_compiler/externs/bluetooth_private.js b/third_party/closure_compiler/externs/bluetooth_private.js
index 97a5b321..46801ebd 100644
--- a/third_party/closure_compiler/externs/bluetooth_private.js
+++ b/third_party/closure_compiler/externs/bluetooth_private.js
@@ -9,7 +9,7 @@
 // Please run the closure compiler before committing changes.
 // See https://chromium.googlesource.com/chromium/src/+/main/docs/closure_compilation.md
 
-// IMPORTANT NOTE: Work-around for crbug.com/543822
+// TODO(crbug.com/543822): Disable automatic extern generation until fixed.
 // s/chrome.bluetoothPrivate.bluetooth.Device/chrome.bluetooth.Device/
 // s/chrome.bluetoothPrivate.bluetooth.Transport/chrome.bluetooth.Transport/
 
diff --git a/third_party/closure_compiler/externs/developer_private.js b/third_party/closure_compiler/externs/developer_private.js
index aa7c74f5..6111a07 100644
--- a/third_party/closure_compiler/externs/developer_private.js
+++ b/third_party/closure_compiler/externs/developer_private.js
@@ -886,6 +886,9 @@
 chrome.developerPrivate.getMatchingExtensionsForSite = function(site, callback) {};
 
 /**
+ * Updates the site access settings for multiple extensions for the given `site`
+ * and calls `callback` once all updates have been finished. Each update species
+ * an extension id an a new HostAccess setting.
  * @param {string} site
  * @param {!Array<!chrome.developerPrivate.ExtensionSiteAccessUpdate>} updates
  * @param {function(): void=} callback
diff --git a/third_party/closure_compiler/externs/file_manager_private.js b/third_party/closure_compiler/externs/file_manager_private.js
index 129a6529..769a975 100644
--- a/third_party/closure_compiler/externs/file_manager_private.js
+++ b/third_party/closure_compiler/externs/file_manager_private.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.
 
+// TODO(crbug.com/1086381): Disable automatic extern generation until fixed.
+
 /**
  * @fileoverview Externs generated from namespace: fileManagerPrivate
  * @externs
diff --git a/third_party/closure_compiler/externs/media_player_private.js b/third_party/closure_compiler/externs/media_player_private.js
index fa8332e..5428a549 100644
--- a/third_party/closure_compiler/externs/media_player_private.js
+++ b/third_party/closure_compiler/externs/media_player_private.js
@@ -1,7 +1,14 @@
-// Copyright 2014 The Chromium Authors
+// 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.
 
+// This file was generated by:
+//   tools/json_schema_compiler/compiler.py.
+// NOTE: The format of types has changed. 'FooType' is now
+//   'chrome.mediaPlayerPrivate.FooType'.
+// Please run the closure compiler before committing changes.
+// See https://chromium.googlesource.com/chromium/src/+/main/docs/closure_compilation.md
+
 /**
  * @fileoverview Externs generated from namespace: mediaPlayerPrivate
  * @externs
@@ -10,13 +17,20 @@
 /** @const */
 chrome.mediaPlayerPrivate = {};
 
-/** @type {!ChromeEvent} */
+/**
+ * Notifies that the next track was requested.
+ * @type {!ChromeEvent}
+ */
 chrome.mediaPlayerPrivate.onNextTrack;
 
-/** @type {!ChromeEvent} */
+/**
+ * Notifies that the previous tack was requested.
+ * @type {!ChromeEvent}
+ */
 chrome.mediaPlayerPrivate.onPrevTrack;
 
-/** @type {!ChromeEvent} */
+/**
+ * Notifies that a play/pause toggle was requested.
+ * @type {!ChromeEvent}
+ */
 chrome.mediaPlayerPrivate.onTogglePlayState;
-
-
diff --git a/third_party/closure_compiler/externs/runtime.js b/third_party/closure_compiler/externs/runtime.js
index b541acd..e6e6935 100644
--- a/third_party/closure_compiler/externs/runtime.js
+++ b/third_party/closure_compiler/externs/runtime.js
@@ -9,7 +9,7 @@
 // Please run the closure compiler before committing changes.
 // See https://chromium.googlesource.com/chromium/src/+/main/docs/closure_compilation.md
 
-// IMPORTANT NOTE: Work-around for crbug.com/543822
+// TODO(crbug.com/543822): Disable automatic extern generation until fixed.
 // s/chrome.runtime.tabs.Tab/chrome.tabs.Tab/
 
 /**
diff --git a/third_party/closure_compiler/externs/system_display.js b/third_party/closure_compiler/externs/system_display.js
index fdbb71e9..43d57429 100644
--- a/third_party/closure_compiler/externs/system_display.js
+++ b/third_party/closure_compiler/externs/system_display.js
@@ -9,6 +9,7 @@
 // Please run the closure compiler before committing changes.
 // See https://chromium.googlesource.com/chromium/src/+/main/docs/closure_compilation.md
 
+// TODO(crbug.com/1086377): Disable automatic extern generation until fixed.
 // This was modified to add 'chrome.system = {};'
 // If the above tool that generates this file removes it, please readd it or
 // the closure compiler will fail.
diff --git a/third_party/closure_compiler/externs/tabs.js b/third_party/closure_compiler/externs/tabs.js
index 053f773..8e01dcae 100644
--- a/third_party/closure_compiler/externs/tabs.js
+++ b/third_party/closure_compiler/externs/tabs.js
@@ -9,7 +9,7 @@
 // Please run the closure compiler before committing changes.
 // See https://chromium.googlesource.com/chromium/src/+/main/docs/closure_compilation.md
 
-// IMPORTANT NOTE: Work-around for crbug.com/543822
+// TODO(crbug.com/543822): Disable automatic extern generation until fixed.
 // s/chrome.tabs.extensionTypes.ImageDetails/chrome.extensionTypes.ImageDetails/
 // s/chrome.tabs.extensionTypes.InjectDetails/chrome.extensionTypes.InjectDetails/
 // s/chrome.tabs.runtime.Port/chrome.runtime.Port/
diff --git a/third_party/closure_compiler/externs/windows.js b/third_party/closure_compiler/externs/windows.js
index f353936..49950fe 100644
--- a/third_party/closure_compiler/externs/windows.js
+++ b/third_party/closure_compiler/externs/windows.js
@@ -9,7 +9,7 @@
 // Please run the closure compiler before committing changes.
 // See https://chromium.googlesource.com/chromium/src/+/main/docs/closure_compilation.md
 
-// IMPORTANT NOTE: Work-around for crbug.com/543822
+// TODO(crbug.com/543822): Disable automatic extern generation until fixed.
 // s/chrome.windows.tabs.Tab/chrome.tabs.Tab/
 
 /**
diff --git a/third_party/ipcz/src/ipcz/local_router_link.cc b/third_party/ipcz/src/ipcz/local_router_link.cc
index c6df993..19d62a5 100644
--- a/third_party/ipcz/src/ipcz/local_router_link.cc
+++ b/third_party/ipcz/src/ipcz/local_router_link.cc
@@ -16,6 +16,9 @@
 
 namespace ipcz {
 
+// This object is shared between the two Routers on either end of a
+// LocalRouterLink. The Routers access each other through references owned by
+// this object.
 class LocalRouterLink::SharedState : public RefCounted {
  public:
   SharedState(LinkType type,
@@ -34,6 +37,9 @@
 
   RouterLinkState& link_state() { return link_state_; }
 
+  // Returns the Router on the given `side` of this link. Note that this may
+  // return null if the Router in question has been deactivated, for example due
+  // to the application closing the Router's controlling portal.
   Ref<Router> GetRouter(LinkSide side) {
     absl::MutexLock lock(&mutex_);
     switch (side.value()) {
@@ -162,8 +168,9 @@
 bool LocalRouterLink::FlushOtherSideIfWaiting(const OperationContext& context) {
   const LinkSide other_side = side_.opposite();
   if (state_->link_state().ResetWaitingBit(other_side)) {
-    state_->GetRouter(other_side)
-        ->Flush(context, Router::kForceProxyBypassAttempt);
+    if (Ref<Router> receiver = state_->GetRouter(side_.opposite())) {
+      receiver->Flush(context, Router::kForceProxyBypassAttempt);
+    }
     return true;
   }
   return false;
diff --git a/third_party/zlib/contrib/optimizations/insert_string.h b/third_party/zlib/contrib/optimizations/insert_string.h
index 2a04f699..c6a296a 100644
--- a/third_party/zlib/contrib/optimizations/insert_string.h
+++ b/third_party/zlib/contrib/optimizations/insert_string.h
@@ -57,10 +57,9 @@
 TARGET_CPU_WITH_CRC
 local INLINE Pos insert_string_simd(deflate_state* const s, const Pos str) {
   Pos ret;
-  unsigned *ip, val, h = 0;
+  unsigned val, h = 0;
 
-  ip = (unsigned*)&s->window[str];
-  val = *ip;
+  zmemcpy(&val, &s->window[str], sizeof(val));
 
   if (s->level >= 6)
     val &= 0xFFFFFF;
diff --git a/tools/json_schema_compiler/PRESUBMIT.py b/tools/json_schema_compiler/PRESUBMIT.py
index ca013e3..cf1502e 100644
--- a/tools/json_schema_compiler/PRESUBMIT.py
+++ b/tools/json_schema_compiler/PRESUBMIT.py
@@ -8,16 +8,35 @@
 for more details about the presubmit API built into depot_tools.
 """
 
+import sys
+
 FILE_PATTERN = [ r'.+_test.py$' ]
 USE_PYTHON3 = True
 
+
+def _CheckExterns(input_api, output_api):
+  """Make sure tool changes update the generated externs."""
+  original_sys_path = sys.path
+  try:
+    sys.path.insert(0, input_api.PresubmitLocalPath())
+    from generate_all_externs import Generate
+  finally:
+    sys.path = original_sys_path
+
+  return Generate(input_api, output_api, dryrun=True)
+
+
 def CheckChangeOnUpload(input_api, output_api):
-  return input_api.canned_checks.RunUnitTestsInDirectory(
+  ret = input_api.canned_checks.RunUnitTestsInDirectory(
       input_api, output_api, '.', files_to_check=FILE_PATTERN,
       run_on_python2=False)
+  ret += _CheckExterns(input_api, output_api)
+  return ret
 
 
 def CheckChangeOnCommit(input_api, output_api):
-  return input_api.canned_checks.RunUnitTestsInDirectory(
+  ret = input_api.canned_checks.RunUnitTestsInDirectory(
       input_api, output_api, '.', files_to_check=FILE_PATTERN,
       run_on_python2=False)
+  ret += _CheckExterns(input_api, output_api)
+  return ret
diff --git a/tools/json_schema_compiler/generate_all_externs.py b/tools/json_schema_compiler/generate_all_externs.py
new file mode 100755
index 0000000..a910f9e
--- /dev/null
+++ b/tools/json_schema_compiler/generate_all_externs.py
@@ -0,0 +1,188 @@
+#!/usr/bin/env python3
+# 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.
+
+"""Helper for quickly generating all known JS externs."""
+
+import argparse
+import os
+import re
+import sys
+
+from compiler import GenerateSchema
+
+# APIs with generated externs.
+API_SOURCES = (
+    ('chrome', 'common', 'apps', 'platform_apps', 'api'),
+    ('chrome', 'common', 'extensions', 'api'),
+    ('extensions', 'common', 'api'),
+)
+
+_EXTERNS_UPDATE_MESSAGE = """Please run one of:
+ src/ $ tools/json_schema_compiler/generate_all_externs.py
+OR
+ src/ $ tools/json_schema_compiler/compiler.py\
+ %(source)s --root=. --generator=externs > %(externs)s"""
+
+DIR = os.path.dirname(os.path.realpath(__file__))
+REPO_ROOT = os.path.dirname(os.path.dirname(DIR))
+
+# Import the helper module.
+sys.path.insert(0, os.path.join(REPO_ROOT, 'extensions', 'common', 'api'))
+from externs_checker import ExternsChecker
+sys.path.pop(0)
+
+
+class FakeChange:
+  """Stand-in for PRESUBMIT input_api.change.
+
+  Enough to make ExternsChecker happy.
+  """
+
+  @staticmethod
+  def RepositoryRoot():
+    return REPO_ROOT
+
+
+class FakeInputApi:
+  """Stand in for PRESUBMIT input_api.
+
+  Enough to make ExternsChecker happy.
+  """
+
+  change = FakeChange()
+  os_path = os.path
+  re = re
+
+  @staticmethod
+  def PresubmitLocalPath():
+    return DIR
+
+  @staticmethod
+  def ReadFile(path):
+    with open(path) as fp:
+      return fp.read()
+
+
+class FakeOutputApi:
+  """Stand in for PRESUBMIT input_api.
+
+  Enough to make CheckExterns happy.
+  """
+
+  class PresubmitResult:
+    def __init__(self, msg, long_text=None):
+      self.msg = msg
+      self.long_text = long_text
+
+
+def Generate(input_api, output_api, force=False, dryrun=False):
+  """(Re)generate all the externs."""
+  src_root = input_api.change.RepositoryRoot()
+  join = input_api.os_path.join
+
+  # Load the list of all generated externs.
+  api_pairs = {}
+  for api_source in API_SOURCES:
+    api_root = join(src_root, *api_source)
+    api_pairs.update(
+        ExternsChecker.ParseApiFileList(input_api, api_root=api_root))
+
+  # Unfortunately, our generator is still a bit buggy, so ignore externs that
+  # are known to be hand edited after the fact.  We require people to add an
+  # explicit TODO marker bound to a known bug.
+  # TODO(vapier): Improve the toolchain enough to not require this.
+  re_disabled = input_api.re.compile(
+      r'^// TODO\(crbug\.com/[0-9]+\): '
+      r'Disable automatic extern generation until fixed\.$',
+      flags=input_api.re.M)
+
+  # Make sure each one is up-to-date with our toolchain.
+  ret = []
+  msg_len = 0
+  for source, externs in sorted(api_pairs.items()):
+    try:
+      old_data = input_api.ReadFile(externs)
+    except OSError:
+      old_data = ''
+    if not force and re_disabled.search(old_data):
+      continue
+    source_relpath = input_api.os_path.relpath(source, src_root)
+    externs_relpath = input_api.os_path.relpath(externs, src_root)
+
+    print('\r' + ' ' * msg_len, end='\r')
+    msg = 'Checking %s ...' % (source_relpath,)
+    msg_len = len(msg)
+    print(msg, end='')
+    sys.stdout.flush()
+    try:
+      new_data = GenerateSchema('externs', [source], src_root, None, '', '',
+                                None, []) + '\n'
+    except Exception as e:
+      if not dryrun:
+        print('\n%s: %s' % (source_relpath, e))
+      ret.append(
+          output_api.PresubmitResult(
+              '%s: unable to generate' % (source_relpath,),
+              long_text=str(e)))
+      continue
+
+    # Ignore the first line (copyright) to avoid yearly thrashing.
+    if '\n' in old_data:
+      copyright, old_data = old_data.split('\n', 1)
+      assert 'Copyright' in copyright
+    copyright, new_data = new_data.split('\n', 1)
+    assert 'Copyright' in copyright
+
+    if old_data != new_data:
+      settings = {
+          'source': source_relpath,
+          'externs': externs_relpath,
+      }
+      ret.append(
+          output_api.PresubmitResult(
+              '%(source)s: file needs to be regenerated' % settings,
+              long_text=_EXTERNS_UPDATE_MESSAGE % settings))
+
+      if not dryrun:
+        print('\r' + ' ' * msg_len, end='\r')
+        msg_len = 0
+        print('Updating %s' % (externs_relpath,))
+        with open(externs, 'w', encoding='utf-8') as fp:
+          fp.write(copyright + '\n')
+          fp.write(new_data)
+
+  print('\r' + ' ' * msg_len, end='\r')
+
+  return ret
+
+
+def get_parser():
+  """Get CLI parser."""
+  parser = argparse.ArgumentParser(description=__doc__)
+  parser.add_argument('-n', '--dry-run', dest='dryrun', action='store_true',
+                      help="Don't make changes; only show changed files")
+  parser.add_argument('-f', '--force', action='store_true',
+                      help='Regenerate files even if they have a TODO '
+                           'disabling generation')
+  return parser
+
+
+def main(argv):
+  """The main entry point for scripts."""
+  parser = get_parser()
+  opts = parser.parse_args(argv)
+
+  results = Generate(FakeInputApi(), FakeOutputApi(), force=opts.force,
+                     dryrun=opts.dryrun)
+  if opts.dryrun and results:
+    for result in results:
+      print(result.msg + '\n' + result.long_text)
+      print()
+  else:
+    print('Done')
+
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv[1:]))
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 8fe461b8..61f19b4b 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -971,6 +971,7 @@
       'android-12l-x64-dbg': 'android_debug_trybot_x64_webview_trichrome_webview_shell',
       'android-arm64-all-targets-dbg': 'android_debug_trybot_compile_only_arm64_fastbuild_reclient',
       'android-arm64-rel': 'android_release_trybot_arm64_webview_monochrome_expectations_fastbuild',
+      'android-arm64-rel-inverse-fyi': 'android_release_trybot_arm64_webview_monochrome_expectations_fastbuild',
       'android-asan': 'android_clang_asan_release_trybot_reclient',
       'android-bfcache-rel': 'android_release_trybot_x86_fastbuild_webview_monochrome_reclient',
       'android-binary-size': 'android_binary_size_reclient',
@@ -1004,7 +1005,6 @@
       'android-pie-arm64-coverage-rel': 'android_release_trybot_arm64_webview_monochrome_native_coverage_reclient',
       'android-pie-arm64-dbg': 'android_debug_trybot_arm64_reclient',
       # TODO(crbug.com/1367393): Remove after android-arm64-rel is fully enabled.
-      'android-pie-arm64-rel': 'android_release_trybot_arm64_webview_monochrome_expectations_fastbuild_reclient',
       'android-pie-arm64-wpt-rel-non-cq': 'android_release_trybot_arm64_webview_monochrome',
       'android-pie-x86-rel': 'android_release_trybot_x86_fastbuild_webview_monochrome_reclient',
       'android-weblayer-marshmallow-x86-rel-tests': 'android_release_trybot_minimal_symbols_x86_fastbuild_disable_proguard_chrome_google',
@@ -4720,17 +4720,17 @@
 
     # Temporary configuration for testing remote linking on different worker sizes
     'use_remoteexec_links_large': {
-      'gn_args': 'use_remoteexec_links=true rbe_link_cfg_file="../../buildtools/reclient_cfgs/chromium-browser-clang/rewrapper_linux_link_large.cfg"',
+      'gn_args': 'use_remoteexec_links=true rbe_link_cfg_file="../../buildtools/reclient_cfgs/chromium-browser-clang/rewrapper_linux_link_large.cfg" concurrent_links=20',
     },
 
     # Temporary configuration for testing remote linking on different worker sizes
     'use_remoteexec_links_medium': {
-      'gn_args': 'use_remoteexec_links=true rbe_link_cfg_file="../../buildtools/reclient_cfgs/chromium-browser-clang/rewrapper_linux_link_medium.cfg"',
+      'gn_args': 'use_remoteexec_links=true rbe_link_cfg_file="../../buildtools/reclient_cfgs/chromium-browser-clang/rewrapper_linux_link_medium.cfg" concurrent_links=20',
     },
 
     # Temporary configuration for testing remote linking on different worker sizes
     'use_remoteexec_links_small': {
-      'gn_args': 'use_remoteexec_links=true rbe_link_cfg_file="../../buildtools/reclient_cfgs/chromium-browser-clang/rewrapper_linux_link_small.cfg"',
+      'gn_args': 'use_remoteexec_links=true rbe_link_cfg_file="../../buildtools/reclient_cfgs/chromium-browser-clang/rewrapper_linux_link_small.cfg" concurrent_links=20',
     },
 
     'v8_enable_debugging_features': {
diff --git a/tools/mb/mb_config_expectations/chromium.reclient.fyi.json b/tools/mb/mb_config_expectations/chromium.reclient.fyi.json
index ee489ff..685a325 100644
--- a/tools/mb/mb_config_expectations/chromium.reclient.fyi.json
+++ b/tools/mb/mb_config_expectations/chromium.reclient.fyi.json
@@ -36,6 +36,7 @@
     },
     "build2": {
       "gn_args": {
+        "concurrent_links": 20,
         "dcheck_always_on": false,
         "enable_nacl": false,
         "ffmpeg_branding": "Chrome",
@@ -62,6 +63,7 @@
     },
     "build2": {
       "gn_args": {
+        "concurrent_links": 20,
         "dcheck_always_on": false,
         "enable_nacl": false,
         "ffmpeg_branding": "Chrome",
@@ -88,6 +90,7 @@
     },
     "build2": {
       "gn_args": {
+        "concurrent_links": 20,
         "dcheck_always_on": false,
         "enable_nacl": false,
         "ffmpeg_branding": "Chrome",
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.android.json b/tools/mb/mb_config_expectations/tryserver.chromium.android.json
index 37da60d..67d3de8a 100644
--- a/tools/mb/mb_config_expectations/tryserver.chromium.android.json
+++ b/tools/mb/mb_config_expectations/tryserver.chromium.android.json
@@ -116,6 +116,25 @@
       "use_goma": true
     }
   },
+  "android-arm64-rel-inverse-fyi": {
+    "gn_args": {
+      "android_static_analysis": "off",
+      "dcheck_always_on": true,
+      "debuggable_apks": false,
+      "fail_on_android_expectations": true,
+      "ffmpeg_branding": "Chrome",
+      "is_component_build": false,
+      "is_debug": false,
+      "proprietary_codecs": true,
+      "skip_secondary_abi_for_cq": true,
+      "strip_debug_info": true,
+      "symbol_level": 0,
+      "system_webview_package_name": "com.google.android.apps.chrome",
+      "target_cpu": "arm64",
+      "target_os": "android",
+      "use_goma": true
+    }
+  },
   "android-asan": {
     "gn_args": {
       "dcheck_always_on": true,
@@ -715,25 +734,6 @@
       "use_remoteexec": true
     }
   },
-  "android-pie-arm64-rel": {
-    "gn_args": {
-      "android_static_analysis": "off",
-      "dcheck_always_on": true,
-      "debuggable_apks": false,
-      "fail_on_android_expectations": true,
-      "ffmpeg_branding": "Chrome",
-      "is_component_build": false,
-      "is_debug": false,
-      "proprietary_codecs": true,
-      "skip_secondary_abi_for_cq": true,
-      "strip_debug_info": true,
-      "symbol_level": 0,
-      "system_webview_package_name": "com.google.android.apps.chrome",
-      "target_cpu": "arm64",
-      "target_os": "android",
-      "use_remoteexec": true
-    }
-  },
   "android-pie-arm64-wpt-rel-non-cq": {
     "gn_args": {
       "dcheck_always_on": true,
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index c49b6b8..b03414b 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -39699,10 +39699,10 @@
   <int value="2731" label="DirectlyCompositedImage"/>
   <int value="2732" label="ForbiddenSyncXhrInPageDismissal"/>
   <int value="2733"
-      label="V8HTMLVideoElement_AutoPictureInPicture_AttributeGetter"/>
+      label="OBSOLETE_V8HTMLVideoElement_AutoPictureInPicture_AttributeGetter"/>
   <int value="2734"
-      label="V8HTMLVideoElement_AutoPictureInPicture_AttributeSetter"/>
-  <int value="2735" label="AutoPictureInPictureAttribute"/>
+      label="OBSOLETE_V8HTMLVideoElement_AutoPictureInPicture_AttributeSetter"/>
+  <int value="2735" label="OBSOLETE_AutoPictureInPictureAttribute"/>
   <int value="2736" label="OBSOLETE_RTCAudioJitterBufferRtxHandling"/>
   <int value="2737" label="WebShareCanShare"/>
   <int value="2738" label="PriorityHints"/>
@@ -52573,7 +52573,7 @@
   <summary>Whether lens is supported and if not the reason why.</summary>
   <int value="0" label="Lens Search Supported"/>
   <int value="1" label="Not Google Search Engine"/>
-  <int value="2" label="Unsupported Legacy OS"/>
+  <int value="2" label="Device was a tablet"/>
 </enum>
 
 <enum name="IOSLensWebUploadStatus">
@@ -58055,6 +58055,7 @@
   <int value="-1420848224" label="WebViewForceDarkModeMatchTheme:enabled"/>
   <int value="-1420542268" label="AutofillEnableAccountWalletStorage:disabled"/>
   <int value="-1420478723" label="EapGtcWifiAuthentication:enabled"/>
+  <int value="-1420228244" label="HttpsUpgrades:enabled"/>
   <int value="-1420160984" label="PasswordsGrouping:enabled"/>
   <int value="-1419908365"
       label="EnableWebHidOnExtensionServiceWorker:disabled"/>
@@ -60300,6 +60301,7 @@
       label="NTPArticleSuggestionsExpandableHeader:enabled"/>
   <int value="-110726049" label="KeyboardLockAPI:disabled"/>
   <int value="-110465424" label="PictureInPicture:enabled"/>
+  <int value="-109901772" label="HttpsUpgrades:disabled"/>
   <int value="-109569254" label="QueryTilesInOmnibox:enabled"/>
   <int value="-108881882" label="NTPCondensedTileLayout:enabled"/>
   <int value="-108468535" label="ChromeColorsCustomColorPicker:disabled"/>
@@ -69804,6 +69806,10 @@
   <int value="29" label="Offline error shown">
     The error page was shown because the device is offline (dino page).
   </int>
+  <int value="30" label="Sign in to network button clicked">
+    An error page was shown with at least a &quot;Sign in to network&quot;
+    button on it and the user pressed that button.
+  </int>
 </enum>
 
 <enum name="NetFilterType">
@@ -100863,6 +100869,7 @@
   <int value="19" label="Virtual Keyboard Tray, Status Area"/>
   <int value="20" label="Virtual Keyboard Tray, Accesibility Window"/>
   <int value="21" label="WM Mode Button"/>
+  <int value="22" label="Video Conferencing Tray"/>
 </enum>
 
 <enum name="TrendingQueryIndex">
@@ -103986,6 +103993,25 @@
   <int value="4" label="Toolbar button"/>
 </enum>
 
+<enum name="VoteForSelecteOptionValuesEvents">
+  <int value="0" label="ClassifiedAnyField">
+    A form had a non-empty list of determined field types.
+  </int>
+  <int value="1" label="ClassifiedMoreFields">
+    The form of the first bucket had more field types classified due to the
+    AutofillVoteForSelectOptionValues experiment.
+  </int>
+  <int value="2" label="ClassifiedFieldAsCountryField">
+    The form of the first bucket had at least one country field (as in
+    &quot;country name&quot;, not as in a &quot;phone country code field&quot;).
+  </int>
+  <int value="3" label="SwitchedFromCountryToPhoneCountryCode">
+    A form in the &quot;ClassifiedFieldAsCountryField&quot; bucket hat at least
+    one country field flipped to a &quot;phone country code field&quot; due to
+    the AutofillVoteForSelectOptionValues experiment.
+  </int>
+</enum>
+
 <enum name="VPDCacheReadResult">
   <int value="0" label="Success"/>
   <int value="1" label="File missing"/>
diff --git a/tools/metrics/histograms/metadata/autofill/histograms.xml b/tools/metrics/histograms/metadata/autofill/histograms.xml
index 183965b..5125d56 100644
--- a/tools/metrics/histograms/metadata/autofill/histograms.xml
+++ b/tools/metrics/histograms/metadata/autofill/histograms.xml
@@ -1756,25 +1756,6 @@
   </token>
 </histogram>
 
-<histogram name="Autofill.FormEvents.CreditCard.OnNonsecurePage"
-    enum="AutofillFormEvent" expires_after="M77">
-  <owner>estark@chromium.org</owner>
-  <summary>
-    Autofill form events for credit card forms on nonsecure pages. These are
-    recorded when the user interacts with a form requesting a credit card.
-
-    Important caveat about submission metrics: - Submission using autofill data
-    is determined by simply evaluating if there was a fill operation in this
-    page. So, if the user filled with local data, completed erased or modified
-    the data after and then submitted, we would only emit one &quot;Submitted
-    with server suggestion filled (once)&quot;; - The submission segmentation
-    works by checking what kind of data was last filled for this type of form in
-    the page load. So, if a user initially filled with local data and after that
-    filled with server, we will only emit &quot;Submitted with server suggestion
-    filled (once)&quot;.
-  </summary>
-</histogram>
-
 <histogram name="Autofill.FormEvents.CreditCard.WithOffer"
     enum="AutofillFormEvent" expires_after="2023-09-01">
   <owner>siyua@chromium.org</owner>
@@ -4580,6 +4561,17 @@
   </summary>
 </histogram>
 
+<histogram name="Autofill.VoteForSelecteOptionValues"
+    enum="VoteForSelecteOptionValuesEvents" expires_after="M112">
+  <owner>battre@chromium.org</owner>
+  <owner>chrome-autofill-team@google.com</owner>
+  <summary>
+    Logs the impact of the AutofillVoteForSelectOptionValues experiment. Metrics
+    are only recorded for submitted forms (not for blur votes) to prevent double
+    counting.
+  </summary>
+</histogram>
+
 <histogram name="Autofill.WalletAddressConversionType"
     enum="AutofillWalletAddressConversionType" expires_after="2023-12-12">
   <owner>battre@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/blink/histograms.xml b/tools/metrics/histograms/metadata/blink/histograms.xml
index fc33282a..ac257d6 100644
--- a/tools/metrics/histograms/metadata/blink/histograms.xml
+++ b/tools/metrics/histograms/metadata/blink/histograms.xml
@@ -2078,17 +2078,17 @@
   </summary>
 </histogram>
 
-<histogram name="Blink.MemoryCache.CrossDocumentCachedResource"
+<histogram name="Blink.MemoryCache.CrossDocumentCachedResource2"
     enum="ResourceType" expires_after="2023-06-04">
   <owner>gjc@chromium.org</owner>
   <owner>blink-network-dev@chromium.org</owner>
   <summary>
-    Type of cached resources reused across Documents when loading a new document
-    in the same renderer. Recorded by the ResourceFetcher when a resource is
-    requested for a new document. If the resource is available from the memory
-    cache and previously loaded by a different document, the resource will be
-    considered as reused. Repetitive requests to the same url in a document will
-    be counted only once.
+    Type of cached non-static resources reused across Documents when loading a
+    new document in the same renderer. Recorded by the ResourceFetcher when a
+    resource is requested for a new document and is not static. If the resource
+    is available from the memory cache and previously loaded by a different
+    document, the resource will be considered as reused. Repetitive requests to
+    the same url in a document will be counted only once.
   </summary>
 </histogram>
 
diff --git a/tools/metrics/histograms/metadata/file/histograms.xml b/tools/metrics/histograms/metadata/file/histograms.xml
index bd32dc5..fb3193a1 100644
--- a/tools/metrics/histograms/metadata/file/histograms.xml
+++ b/tools/metrics/histograms/metadata/file/histograms.xml
@@ -102,6 +102,11 @@
 
 <histogram name="FileBrowser.ArchiveSize.{Extension}" units="100MiB"
     expires_after="2022-12-01">
+  <obsolete>
+    Became obsolete on 2022-12-01 as we've collected enough data to understand
+    the user impact of attempting to open large slow mounters without progress
+    reporting.
+  </obsolete>
   <owner>msalomao@google.com</owner>
   <owner>src/ui/file_manager/OWNERS</owner>
   <summary>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 2d2adad..660bcb3 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,24 +5,24 @@
             "full_remote_path": "perfetto-luci-artifacts/v31.0/linux-arm64/trace_processor_shell"
         },
         "win": {
-            "hash": "218fb7ce584ae96320cc8944a6480bc3f1345878",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/db40f7acd7bca139bf4d48c94d6555b8a5bbf704/trace_processor_shell.exe"
+            "hash": "d769eee21661aeccb865b4315136a8d61b0374da",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/df18f444084aa1704b313ef9430026e81afb9677/trace_processor_shell.exe"
         },
         "linux_arm": {
             "hash": "6373f26144aad58f230d11d6a91efda5a09c9873",
             "full_remote_path": "perfetto-luci-artifacts/v31.0/linux-arm/trace_processor_shell"
         },
         "mac": {
-            "hash": "ddaeaf7c2a0d026f6340e14215c3561659d40414",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/db40f7acd7bca139bf4d48c94d6555b8a5bbf704/trace_processor_shell"
+            "hash": "67067844bff4df77622e76d06a6f94202c89c68c",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/df18f444084aa1704b313ef9430026e81afb9677/trace_processor_shell"
         },
         "mac_arm64": {
             "hash": "5f47ee79e59d00bf3889d30ca52315522c158040",
             "full_remote_path": "perfetto-luci-artifacts/v31.0/mac-arm64/trace_processor_shell"
         },
         "linux": {
-            "hash": "1559e8c78072dac12578436f610ce334134ec6ba",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/5c7badc60cb897107f5ec15677c2c29c3b5a91d5/trace_processor_shell"
+            "hash": "b96d4205afb7cff52ed1ff6f4667bcf18ee9a202",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/df18f444084aa1704b313ef9430026e81afb9677/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/tools/traffic_annotation/auditor/chromeos/safe_list.txt b/tools/traffic_annotation/auditor/chromeos/safe_list.txt
index 1781b5b..ae3db2e 100644
--- a/tools/traffic_annotation/auditor/chromeos/safe_list.txt
+++ b/tools/traffic_annotation/auditor/chromeos/safe_list.txt
@@ -19,7 +19,7 @@
 all,chrome/browser/apps/app_service/webapk/webapk_install_task.cc
 all,chrome/browser/ash/login/screens/recommend_apps/recommend_apps_fetcher_impl.cc
 all,chrome/browser/ash/wilco_dtc_supportd/wilco_dtc_supportd_web_request_service.cc
-all,chrome/browser/ui/app_list/search/arc/recommend_apps_fetcher_impl.cc
+all,chrome/browser/ash/app_list/search/arc/recommend_apps_fetcher_impl.cc
 all,chrome/browser/ui/ash/projector/screencast_manager.cc
 all,chrome/services/cups_proxy/socket_manager.cc
 all,chromeos/components/projector_app/projector_xhr_sender.cc
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml
index 763b86d..f7d24c40 100644
--- a/tools/traffic_annotation/summary/annotations.xml
+++ b/tools/traffic_annotation/summary/annotations.xml
@@ -228,7 +228,7 @@
  <item id="services_http_server_error_response" added_in_milestone="68" content_hash_code="079dad59" os_list="linux,windows,chromeos,android" file_path="services/network/public/cpp/server/http_server.cc" />
  <item id="shared_storage_worklet_module_script_downloader" added_in_milestone="95" content_hash_code="0367afa1" os_list="linux,windows,chromeos,android" file_path="content/services/shared_storage_worklet/module_script_downloader.cc" />
  <item id="sigined_exchange_cert_fetcher" added_in_milestone="66" content_hash_code="007c2dac" os_list="linux,windows,chromeos,android" file_path="content/browser/web_package/signed_exchange_cert_fetcher.cc" />
- <item id="signed_in_profile_avatar" added_in_milestone="62" content_hash_code="04579cbb" os_list="linux,windows,chromeos,android" file_path="chrome/browser/profiles/profile_downloader.cc" />
+ <item id="signed_in_profile_avatar" added_in_milestone="62" content_hash_code="00619a19" os_list="linux,windows,chromeos,android" file_path="chrome/browser/profiles/profile_downloader.cc" />
  <item id="socket_bio_adapter" added_in_milestone="66" content_hash_code="014a4058" os_list="linux,windows,chromeos,android" file_path="net/socket/socket_bio_adapter.cc" />
  <item id="spdy_push_stream" added_in_milestone="67" content_hash_code="042048b5" os_list="linux,windows,chromeos,android" file_path="net/spdy/spdy_session.cc" />
  <item id="spdy_session_control" added_in_milestone="66" content_hash_code="01c6f3f0" os_list="linux,windows,chromeos,android" file_path="net/spdy/spdy_session.cc" />
@@ -298,7 +298,7 @@
  <item id="tachyon_ice_config_fetcher" added_in_milestone="98" content_hash_code="01e878b0" os_list="chromeos" file_path="chrome/browser/nearby_sharing/tachyon_ice_config_fetcher.cc" />
  <item id="supervised_users_denylist" added_in_milestone="98" content_hash_code="01cebaff" os_list="chromeos,android" file_path="chrome/browser/supervised_user/supervised_user_service.cc" />
  <item id="app_suggestion_get_favicon" added_in_milestone="98" content_hash_code="07fca800" os_list="chromeos" file_path="chrome/browser/ui/app_list/search/app_service_app_result.cc" />
- <item id="launcher_item_suggest" added_in_milestone="98" content_hash_code="04a4041e" os_list="chromeos" file_path="chrome/browser/ui/app_list/search/files/item_suggest_cache.cc" />
+ <item id="launcher_item_suggest" added_in_milestone="98" content_hash_code="04a4041e" os_list="chromeos" file_path="chrome/browser/ash/app_list/search/files/item_suggest_cache.cc" />
  <item id="ambient_client" added_in_milestone="98" content_hash_code="062d821f" os_list="chromeos" file_path="chrome/browser/ui/ash/ambient/ambient_client_impl.cc" />
  <item id="calendar_get_events" added_in_milestone="98" content_hash_code="0603f52a" os_list="chromeos" file_path="chrome/browser/ui/ash/calendar/calendar_keyed_service.cc" />
  <item id="side_search_availability_test" added_in_milestone="98" content_hash_code="04b1ffa5" os_list="chromeos,linux,windows" file_path="chrome/browser/ui/side_search/side_search_tab_contents_helper.cc" />
diff --git a/tools/typescript/definitions/developer_private.d.ts b/tools/typescript/definitions/developer_private.d.ts
index e2f6e09..ceeec5d 100644
--- a/tools/typescript/definitions/developer_private.d.ts
+++ b/tools/typescript/definitions/developer_private.d.ts
@@ -415,6 +415,11 @@
         siteAccess: HostAccess;
       }
 
+      export interface ExtensionSiteAccessUpdate {
+        id: string;
+        siteAccess: HostAccess;
+      }
+
       type VoidCallback = () => void;
       type StringCallback = (s: string) => void;
 
@@ -464,6 +469,8 @@
       export function getUserAndExtensionSitesByEtld(): Promise<SiteGroup[]>;
       export function getMatchingExtensionsForSite(site: string):
           Promise<MatchingExtensionInfo[]>;
+      export function updateSiteAccess(
+          site: string, updates: ExtensionSiteAccessUpdate[]): Promise<void>;
 
       export const onItemStateChanged: ChromeEvent<(data: EventData) => void>;
       export const onProfileStateChanged:
diff --git a/ui/base/clipboard/BUILD.gn b/ui/base/clipboard/BUILD.gn
index 2b391b5..641f0c6 100644
--- a/ui/base/clipboard/BUILD.gn
+++ b/ui/base/clipboard/BUILD.gn
@@ -100,6 +100,9 @@
       "clipboard_util_mac.h",
       "clipboard_util_mac.mm",
     ]
+    weak_frameworks = [
+      "UniformTypeIdentifiers.framework",  # macOS 11
+    ]
   }
 
   if (is_win) {
diff --git a/ui/base/clipboard/clipboard_mac.mm b/ui/base/clipboard/clipboard_mac.mm
index 735c82ef..f4edb503 100644
--- a/ui/base/clipboard/clipboard_mac.mm
+++ b/ui/base/clipboard/clipboard_mac.mm
@@ -245,7 +245,7 @@
   if (!contents)
     result->clear();
   else
-    result->assign([contents UTF8String]);
+    result->assign(base::SysNSStringToUTF8(contents));
 }
 
 // |data_dst| is not used. It's only passed to be consistent with other
@@ -360,16 +360,16 @@
   NSPasteboard* pb = GetPasteboard();
 
   if (title) {
-    NSString* contents = ClipboardUtil::GetTitleFromPasteboardURL(pb);
+    NSString* contents = [pb stringForType:kUTTypeURLName];
     *title = base::SysNSStringToUTF16(contents);
   }
 
   if (url) {
-    NSString* url_string = ClipboardUtil::GetURLFromPasteboardURL(pb);
+    NSString* url_string = [pb stringForType:NSPasteboardTypeURL];
     if (!url_string)
       url->clear();
     else
-      url->assign([url_string UTF8String]);
+      url->assign(base::SysNSStringToUTF8(url_string));
   }
 }
 
@@ -450,9 +450,9 @@
   std::string url_str(url_data, url_len);
   NSString* url = base::SysUTF8ToNSString(url_str);
 
-  base::scoped_nsobject<NSPasteboardItem> item(
-      ClipboardUtil::PasteboardItemFromUrl(url, title));
-  ClipboardUtil::AddDataToPasteboard(GetPasteboard(), item);
+  NSArray<NSPasteboardItem*>* items =
+      ClipboardUtil::PasteboardItemsFromUrls(@[ url ], @[ title ]);
+  ClipboardUtil::AddDataToPasteboard(GetPasteboard(), items.firstObject);
 }
 
 void ClipboardMac::WriteBitmap(const SkBitmap& bitmap) {
diff --git a/ui/base/clipboard/clipboard_util_mac.h b/ui/base/clipboard/clipboard_util_mac.h
index a8a6120..36867c9 100644
--- a/ui/base/clipboard/clipboard_util_mac.h
+++ b/ui/base/clipboard/clipboard_util_mac.h
@@ -27,48 +27,38 @@
   base::scoped_nsobject<NSPasteboard> pasteboard_;
 };
 
-class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ClipboardUtil {
- public:
-  // Returns an NSPasteboardItem that represents the given |url|.
-  // |url| must not be nil.
-  // If |title| is nil, |url| is used in its place.
-  static base::scoped_nsobject<NSPasteboardItem> PasteboardItemFromUrl(
-      NSString* url,
-      NSString* title);
+namespace ClipboardUtil {
 
-  // Returns an NSPasteboardItem that represents the given |urls| and |titles|.
-  static base::scoped_nsobject<NSPasteboardItem> PasteboardItemFromUrls(
-      NSArray* urls,
-      NSArray* titles);
+// Returns an array of NSPasteboardItems that represent the given `urls` and
+// `titles`.
+COMPONENT_EXPORT(UI_BASE_CLIPBOARD)
+NSArray<NSPasteboardItem*>* PasteboardItemsFromUrls(NSArray<NSString*>* urls,
+                                                    NSArray<NSString*>* titles);
 
-  // Returns an NSPasteboardItem that represents the given string.
-  // |string| must not be nil.
-  static base::scoped_nsobject<NSPasteboardItem> PasteboardItemFromString(
-      NSString* string);
+// For each pasteboard type in `item` that is not in `pboard`, add the type
+// and its associated data.
+COMPONENT_EXPORT(UI_BASE_CLIPBOARD)
+void AddDataToPasteboard(NSPasteboard* pboard, NSPasteboardItem* item);
 
-  // Returns the title or url associated with a NSPasteboard which contains an
-  // url NSPasteboardItem.
-  static NSString* GetTitleFromPasteboardURL(NSPasteboard* pboard);
-  static NSString* GetURLFromPasteboardURL(NSPasteboard* pboard);
+// For a given pasteboard, reads and extracts the URLs to be found on it. The
+// two out-parameter arrays are guaranteed to be the same length when this
+// function completes. Returns true if at least one URL was successfully read,
+// and false otherwise.
+COMPONENT_EXPORT(UI_BASE_CLIPBOARD)
+bool URLsAndTitlesFromPasteboard(NSPasteboard* pboard,
+                                 NSArray<NSString*>** urls,
+                                 NSArray<NSString*>** titles);
 
-  // For each pasteboard type in |item| that is not in |pboard|, add the type
-  // and its associated data.
-  static void AddDataToPasteboard(NSPasteboard* pboard, NSPasteboardItem* item);
+// Gets the NSPasteboard specified from the clipboard buffer.
+COMPONENT_EXPORT(UI_BASE_CLIPBOARD)
+NSPasteboard* PasteboardFromBuffer(ClipboardBuffer buffer);
 
-  // Returns whether the operation was successful. On success, the two arrays
-  // are guaranteed to be equal length, and are populated with strings of |urls|
-  // and |titles|.
-  static bool URLsAndTitlesFromPasteboard(NSPasteboard* pboard,
-                                          NSArray** urls,
-                                          NSArray** titles);
+// If there is RTF data on the pasteboard, returns an HTML version of it.
+// Otherwise returns nil.
+COMPONENT_EXPORT(UI_BASE_CLIPBOARD)
+NSString* GetHTMLFromRTFOnPasteboard(NSPasteboard* pboard);
 
-  // Gets the NSPasteboard specified from the clipboard buffer.
-  static NSPasteboard* PasteboardFromBuffer(ClipboardBuffer buffer);
-
-  // If there is RTF data on the pasteboard, returns an HTML version of it.
-  // Otherwise returns nil.
-  static NSString* GetHTMLFromRTFOnPasteboard(NSPasteboard* pboard);
-};
+}  // namespace ClipboardUtil
 
 }  // namespace ui
 
diff --git a/ui/base/clipboard/clipboard_util_mac.mm b/ui/base/clipboard/clipboard_util_mac.mm
index 7c79ce0c..ae207134 100644
--- a/ui/base/clipboard/clipboard_util_mac.mm
+++ b/ui/base/clipboard/clipboard_util_mac.mm
@@ -4,9 +4,11 @@
 
 #include "ui/base/clipboard/clipboard_util_mac.h"
 
+#include <AppKit/AppKit.h>
+#include <CoreServices/CoreServices.h>                      // pre-macOS 11
+#include <UniformTypeIdentifiers/UniformTypeIdentifiers.h>  // macOS 11
+
 #include "base/mac/foundation_util.h"
-#import "base/mac/mac_util.h"
-#include "base/mac/scoped_cftyperef.h"
 #include "base/notreached.h"
 #include "ui/base/clipboard/clipboard_constants.h"
 
@@ -14,74 +16,150 @@
 
 namespace {
 
-// It's much more convenient to return an NSString than a
-// base::ScopedCFTypeRef<CFStringRef>, since the methods on NSPasteboardItem
-// require an NSString*.
-NSString* UTIFromPboardType(NSString* type) {
-  return [base::mac::CFToNSCast(UTTypeCreatePreferredIdentifierForTag(
-      kUTTagClassNSPboardType, base::mac::NSToCFCast(type), kUTTypeData))
-      autorelease];
-}
-
+// Reads the "WebKitWebURLsWithTitles" type put onto the clipboard by Safari and
+// returns the urls/titles found within. Returns true if this was successful, or
+// false if it was not.
 bool ReadWebURLsWithTitlesPboardType(NSPasteboard* pboard,
-                                     NSArray** urls,
-                                     NSArray** titles) {
-  NSArray* bookmarkPairs = base::mac::ObjCCast<NSArray>(
+                                     NSArray<NSString*>** urls,
+                                     NSArray<NSString*>** titles) {
+  NSArray* bookmark_pairs = base::mac::ObjCCast<NSArray>(
       [pboard propertyListForType:kUTTypeWebKitWebURLsWithTitles]);
-  if (!bookmarkPairs)
+  if (!bookmark_pairs) {
     return false;
-
-  if ([bookmarkPairs count] != 2)
+  }
+  if (bookmark_pairs.count != 2) {
     return false;
-
-  NSArray* urlsArr = base::mac::ObjCCast<NSArray>(bookmarkPairs[0]);
-  NSArray* titlesArr = base::mac::ObjCCast<NSArray>(bookmarkPairs[1]);
-
-  if (!urlsArr || !titlesArr)
-    return false;
-  if ([urlsArr count] < 1)
-    return false;
-  if ([urlsArr count] != [titlesArr count])
-    return false;
-
-  for (id obj in urlsArr) {
-    if (![obj isKindOfClass:[NSString class]])
-      return false;
   }
 
-  for (id obj in titlesArr) {
-    if (![obj isKindOfClass:[NSString class]])
-      return false;
+  NSArray<NSString*>* urls_array =
+      base::mac::ObjCCast<NSArray>(bookmark_pairs[0]);
+  NSArray<NSString*>* titles_array =
+      base::mac::ObjCCast<NSArray>(bookmark_pairs[1]);
+
+  if (!urls_array || !titles_array) {
+    return false;
   }
-
-  *urls = urlsArr;
-  *titles = titlesArr;
-  return true;
-}
-
-bool ReadURLItemsWithTitles(NSPasteboard* pboard,
-                            NSArray** urls,
-                            NSArray** titles) {
-  NSMutableArray* urlsArr = [NSMutableArray array];
-  NSMutableArray* titlesArr = [NSMutableArray array];
-
-  NSArray* items = [pboard pasteboardItems];
-  for (NSPasteboardItem* item : items) {
-    NSString* url = [item stringForType:base::mac::CFToNSCast(kUTTypeURL)];
-    NSString* title = [item stringForType:kUTTypeURLName];
-
-    if (url) {
-      [urlsArr addObject:url];
-      if (title)
-        [titlesArr addObject:title];
-      else
-        [titlesArr addObject:@""];
+  if (urls_array.count < 1) {
+    return false;
+  }
+  if (urls_array.count != titles_array.count) {
+    return false;
+  }
+  for (id obj in urls_array) {
+    if (![obj isKindOfClass:[NSString class]]) {
+      return false;
     }
   }
 
-  if ([urlsArr count]) {
-    *urls = urlsArr;
-    *titles = titlesArr;
+  for (id obj in titles_array) {
+    if (![obj isKindOfClass:[NSString class]]) {
+      return false;
+    }
+  }
+
+  *urls = urls_array;
+  *titles = titles_array;
+  return true;
+}
+
+// If the given pasteboard item is a drag of an internet location file, return
+// the title that should be used for for the URL. Returns nil if it is not a
+// file or if any error occurs.
+NSString* ExtractTitleFromFileURL(NSPasteboardItem* item) {
+  NSURL* file_url =
+      [NSURL URLWithString:[item stringForType:NSPasteboardTypeFileURL]];
+  if (!file_url) {
+    return nil;
+  }
+
+  // The UTType for .webloc files is com.apple.web-internet-location, but
+  // there is no official constant for that. However, that type does conform
+  // to the generic "internet location" type (aka .inetloc), so check for
+  // that.
+  NSDictionary* resource_values;
+  if (@available(macOS 11, *)) {
+    resource_values = [file_url resourceValuesForKeys:@[
+      NSURLContentTypeKey, NSURLLocalizedNameKey, NSURLHasHiddenExtensionKey
+    ]
+                                                error:nil];
+    if (!resource_values) {
+      return nil;
+    }
+
+    UTType* type = resource_values[NSURLContentTypeKey];
+    if (!type || ![type conformsToType:UTTypeInternetLocation]) {
+      return nil;
+    }
+  } else {
+    resource_values = [file_url resourceValuesForKeys:@[
+      NSURLTypeIdentifierKey, NSURLLocalizedNameKey, NSURLHasHiddenExtensionKey
+    ]
+                                                error:nil];
+    if (!resource_values) {
+      return nil;
+    }
+
+    NSString* type = resource_values[NSURLTypeIdentifierKey];
+    if (!type ||
+        ![NSWorkspace.sharedWorkspace
+                      type:type
+            conformsToType:base::mac::CFToNSCast(kUTTypeInternetLocation)]) {
+      return nil;
+    }
+  }
+
+  NSString* title = resource_values[NSURLLocalizedNameKey];
+  if (!title) {
+    return nil;
+  }
+
+  NSNumber* has_hidden_extension = resource_values[NSURLHasHiddenExtensionKey];
+  if (!has_hidden_extension || has_hidden_extension.boolValue) {
+    // If it's already hidden, or it's unknown if it's hidden, return it
+    // unaltered.
+    return title;
+  }
+
+  return [title stringByDeletingPathExtension];
+}
+
+// Reads the given pasteboard, and returns urls/titles found on it. Returns true
+// if at least one url was found on the pasteboard, and false if none were.
+bool ReadURLItemsWithTitles(NSPasteboard* pboard,
+                            NSArray<NSString*>** urls,
+                            NSArray<NSString*>** titles) {
+  NSMutableArray<NSString*>* urls_array = [NSMutableArray array];
+  NSMutableArray<NSString*>* titles_array = [NSMutableArray array];
+
+  NSArray<NSPasteboardItem*>* items = pboard.pasteboardItems;
+  for (NSPasteboardItem* item : items) {
+    NSString* url = [item stringForType:NSPasteboardTypeURL];
+    NSString* title = [item stringForType:kUTTypeURLName];
+
+    if (!url) {
+      continue;
+    }
+
+    if (!title) {
+      // If there is no title on the drag, check to see if it's a URL drag
+      // reconstituted from a Finder .webloc. If so, use the name of the file as
+      // the title.
+      title = ExtractTitleFromFileURL(item);
+    }
+
+    if (url) {
+      [urls_array addObject:url];
+      if (title) {
+        [titles_array addObject:title];
+      } else {
+        [titles_array addObject:@""];
+      }
+    }
+  }
+
+  if (urls_array.count) {
+    *urls = urls_array;
+    *titles = titles_array;
     return true;
   } else {
     return false;
@@ -97,85 +175,52 @@
   [pasteboard_ releaseGlobally];
 }
 
-// static
-base::scoped_nsobject<NSPasteboardItem> ClipboardUtil::PasteboardItemFromUrl(
-    NSString* urlString,
-    NSString* title) {
-  DCHECK(urlString);
-  if (!title)
-    title = urlString;
+NSArray<NSPasteboardItem*>* ClipboardUtil::PasteboardItemsFromUrls(
+    NSArray<NSString*>* urls,
+    NSArray<NSString*>* titles) {
+  DCHECK_EQ(urls.count, titles.count);
 
-  base::scoped_nsobject<NSPasteboardItem> item([[NSPasteboardItem alloc] init]);
+  NSMutableArray<NSPasteboardItem*>* items = [NSMutableArray array];
 
-  NSURL* url = [NSURL URLWithString:urlString];
-  if ([url isFileURL] &&
-      [[NSFileManager defaultManager] fileExistsAtPath:[url path]]) {
-    [item setPropertyList:@[ [url path] ]
-                  forType:UTIFromPboardType(NSFilenamesPboardType)];
+  for (NSUInteger i = 0; i < urls.count; ++i) {
+    NSPasteboardItem* item = [[[NSPasteboardItem alloc] init] autorelease];
+
+    NSString* url_string = urls[i];
+    NSString* title = titles[i];
+
+    NSURL* url = [NSURL URLWithString:url_string];
+    if (url.isFileURL &&
+        [NSFileManager.defaultManager fileExistsAtPath:url.path]) {
+      [item setString:url_string forType:NSPasteboardTypeFileURL];
+    }
+
+    [item setString:url_string forType:NSPasteboardTypeString];
+    [item setString:url_string forType:NSPasteboardTypeURL];
+    if (title.length) {
+      [item setString:title forType:kUTTypeURLName];
+    }
+
+    // Safari puts the "Web URLs and Titles" pasteboard type onto the first
+    // pasteboard item.
+    if (i == 0) {
+      [item setPropertyList:@[ urls, titles ]
+                    forType:kUTTypeWebKitWebURLsWithTitles];
+    }
+
+    [items addObject:item];
   }
 
-  // Set Safari's URL + title arrays Pboard type.
-  NSArray* urlsAndTitles = @[ @[ urlString ], @[ title ] ];
-  [item setPropertyList:urlsAndTitles forType:kUTTypeWebKitWebURLsWithTitles];
-
-  // Set NSURLPboardType. The format of the property list is divined from
-  // Webkit's function PlatformPasteboard::setStringForType.
-  // https://github.com/WebKit/webkit/blob/master/Source/WebCore/platform/mac/PlatformPasteboardMac.mm
-  NSURL* base = [url baseURL];
-  if (base) {
-    [item setPropertyList:@[ [url relativeString], [base absoluteString] ]
-                  forType:UTIFromPboardType(NSURLPboardType)];
-  } else if (url) {
-    [item setPropertyList:@[ [url absoluteString], @"" ]
-                  forType:UTIFromPboardType(NSURLPboardType)];
-  }
-
-  [item setString:urlString forType:NSPasteboardTypeString];
-  [item setString:urlString forType:base::mac::CFToNSCast(kUTTypeURL)];
-  [item setString:title forType:kUTTypeURLName];
-  return item;
+  return items;
 }
 
-// static
-base::scoped_nsobject<NSPasteboardItem> ClipboardUtil::PasteboardItemFromUrls(
-    NSArray* urls,
-    NSArray* titles) {
-  base::scoped_nsobject<NSPasteboardItem> item([[NSPasteboardItem alloc] init]);
-
-  // Set Safari's URL + title arrays Pboard type.
-  NSArray* urlsAndTitles = @[ urls, titles ];
-  [item setPropertyList:urlsAndTitles forType:kUTTypeWebKitWebURLsWithTitles];
-
-  return item;
-}
-
-// static
-base::scoped_nsobject<NSPasteboardItem> ClipboardUtil::PasteboardItemFromString(
-    NSString* string) {
-  base::scoped_nsobject<NSPasteboardItem> item([[NSPasteboardItem alloc] init]);
-  [item setString:string forType:NSPasteboardTypeString];
-  return item;
-}
-
-//static
-NSString* ClipboardUtil::GetTitleFromPasteboardURL(NSPasteboard* pboard) {
-  return [pboard stringForType:kUTTypeURLName];
-}
-
-//static
-NSString* ClipboardUtil::GetURLFromPasteboardURL(NSPasteboard* pboard) {
-  return [pboard stringForType:base::mac::CFToNSCast(kUTTypeURL)];
-}
-
-// static
 void ClipboardUtil::AddDataToPasteboard(NSPasteboard* pboard,
                                         NSPasteboardItem* item) {
-  NSSet* oldTypes = [NSSet setWithArray:[pboard types]];
-  NSMutableSet* newTypes = [NSMutableSet setWithArray:[item types]];
-  [newTypes minusSet:oldTypes];
+  NSSet* old_types = [NSSet setWithArray:[pboard types]];
+  NSMutableSet* new_types = [NSMutableSet setWithArray:[item types]];
+  [new_types minusSet:old_types];
 
-  [pboard addTypes:[newTypes allObjects] owner:nil];
-  for (NSString* type in newTypes) {
+  [pboard addTypes:[new_types allObjects] owner:nil];
+  for (NSString* type in new_types) {
     // Technically, the object associated with |type| might be an NSString or a
     // property list. It doesn't matter though, since the type gets pulled from
     // and shoved into an NSDictionary.
@@ -183,15 +228,13 @@
   }
 }
 
-// static
 bool ClipboardUtil::URLsAndTitlesFromPasteboard(NSPasteboard* pboard,
-                                                NSArray** urls,
-                                                NSArray** titles) {
+                                                NSArray<NSString*>** urls,
+                                                NSArray<NSString*>** titles) {
   return ReadWebURLsWithTitlesPboardType(pboard, urls, titles) ||
          ReadURLItemsWithTitles(pboard, urls, titles);
 }
 
-// static
 NSPasteboard* ClipboardUtil::PasteboardFromBuffer(ClipboardBuffer buffer) {
   NSString* buffer_type = nil;
   switch (buffer) {
@@ -209,24 +252,23 @@
   return [NSPasteboard pasteboardWithName:buffer_type];
 }
 
-// static
 NSString* ClipboardUtil::GetHTMLFromRTFOnPasteboard(NSPasteboard* pboard) {
-  NSData* rtfData = [pboard dataForType:NSRTFPboardType];
-  if (!rtfData)
+  NSData* rtf_data = [pboard dataForType:NSPasteboardTypeRTF];
+  if (!rtf_data)
     return nil;
 
   NSAttributedString* attributed =
-      [[[NSAttributedString alloc] initWithRTF:rtfData
+      [[[NSAttributedString alloc] initWithRTF:rtf_data
                             documentAttributes:nil] autorelease];
-  NSData* htmlData =
-      [attributed dataFromRange:NSMakeRange(0, [attributed length])
+  NSData* html_data =
+      [attributed dataFromRange:NSMakeRange(0, attributed.length)
              documentAttributes:@{
                NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType
              }
                           error:nil];
 
-  // According to the docs, NSHTMLTextDocumentType is UTF8.
-  return [[[NSString alloc] initWithData:htmlData
+  // According to the docs, NSHTMLTextDocumentType is UTF-8.
+  return [[[NSString alloc] initWithData:html_data
                                 encoding:NSUTF8StringEncoding] autorelease];
 }
 
diff --git a/ui/base/clipboard/clipboard_util_mac_unittest.mm b/ui/base/clipboard/clipboard_util_mac_unittest.mm
index 3bb842ae..04e3236 100644
--- a/ui/base/clipboard/clipboard_util_mac_unittest.mm
+++ b/ui/base/clipboard/clipboard_util_mac_unittest.mm
@@ -12,112 +12,65 @@
 #include "testing/gtest_mac.h"
 #include "testing/platform_test.h"
 #include "third_party/mozilla/NSPasteboard+Utils.h"
+#include "ui/base/clipboard/clipboard_constants.h"
 
 namespace ui {
 namespace {
 
-class ClipboardUtilMacTest : public PlatformTest {
- public:
-  ClipboardUtilMacTest() = default;
+using ClipboardUtilMacTest = PlatformTest;
 
-  // Given a pasteboard, returns a dictionary of the contents of the pasteboard
-  // for use in deep comparisons. This fully unpacks any plist-encoded items.
-  NSDictionary* DictionaryFromPasteboardForDeepComparisons(
-      NSPasteboard* pboard) {
-    NSMutableDictionary* result = [NSMutableDictionary dictionary];
-    for (NSString* type in [pboard types]) {
-      NSData* data = [pboard dataForType:type];
-      // Try to unpack the data as a plist, and if it succeeds, use that in the
-      // resulting dictionary rather than the raw NSData. This is needed because
-      // plists have multiple encodings, and the comparison should be made on
-      // the underlying data rather than the specific encoding used by the OS.
-      NSDictionary* unpacked_data = [NSPropertyListSerialization
-          propertyListWithData:data
-                       options:NSPropertyListImmutable
-                        format:nil
-                         error:nil];
-      if (unpacked_data)
-        result[type] = unpacked_data;
-      else
-        result[type] = data;
-    }
-    return result;
-  }
-};
-
-TEST_F(ClipboardUtilMacTest, PasteboardItemFromUrl) {
-  NSString* urlString =
+TEST_F(ClipboardUtilMacTest, PasteboardItemsFromUrls) {
+  NSString* url_string_1 =
       @"https://www.google.com/"
       @"search?q=test&oq=test&aqs=chrome..69i57l2j69i60l4.278j0j7&"
       @"sourceid=chrome&ie=UTF-8";
 
-  base::scoped_nsobject<NSPasteboardItem> item(
-      ClipboardUtil::PasteboardItemFromUrl(urlString, nil));
+  NSString* url_string_2 = @"https://www.google.com/";
+  NSString* title_2 = @"Burrowing Yams";
+
+  NSArray<NSPasteboardItem*>* items = ClipboardUtil::PasteboardItemsFromUrls(
+      @[ url_string_1, url_string_2 ], @[ @"", title_2 ]);
+
   scoped_refptr<UniquePasteboard> pasteboard = new UniquePasteboard;
-  [pasteboard->get() writeObjects:@[ item ]];
+  [pasteboard->get() writeObjects:items];
 
   NSArray* urls = nil;
   NSArray* titles = nil;
-  [pasteboard->get() getURLs:&urls
-                   andTitles:&titles
-         convertingFilenames:NO
-         convertingTextToURL:NO];
+  ClipboardUtil::URLsAndTitlesFromPasteboard(pasteboard->get(), &urls, &titles);
 
-  ASSERT_EQ(1u, [urls count]);
-  EXPECT_NSEQ(urlString, urls[0]);
-  ASSERT_EQ(1u, [titles count]);
-  EXPECT_NSEQ(urlString, titles[0]);
+  ASSERT_EQ(2u, urls.count);
+  EXPECT_NSEQ(url_string_1, urls[0]);
+  EXPECT_NSEQ(url_string_2, urls[1]);
+  ASSERT_EQ(2u, titles.count);
+  EXPECT_NSEQ(@"", titles[0]);
+  EXPECT_NSEQ(title_2, titles[1]);
 
   NSURL* url = [NSURL URLFromPasteboard:pasteboard->get()];
-  EXPECT_NSEQ([url absoluteString], urlString);
-}
+  EXPECT_NSEQ(url.absoluteString, url_string_1);
 
-TEST_F(ClipboardUtilMacTest, PasteboardItemWithTitle) {
-  NSString* urlString = @"https://www.google.com/";
-  NSString* title = @"Burrowing Yams";
-
-  base::scoped_nsobject<NSPasteboardItem> item(
-      ClipboardUtil::PasteboardItemFromUrl(urlString, title));
-  scoped_refptr<UniquePasteboard> pasteboard = new UniquePasteboard;
-  [pasteboard->get() writeObjects:@[ item ]];
-
-  NSArray* urls = nil;
-  NSArray* titles = nil;
-  [pasteboard->get() getURLs:&urls
-                   andTitles:&titles
-         convertingFilenames:NO
-         convertingTextToURL:NO];
-
-  ASSERT_EQ(1u, [urls count]);
-  EXPECT_NSEQ(urlString, urls[0]);
-  ASSERT_EQ(1u, [titles count]);
-  EXPECT_NSEQ(title, titles[0]);
-
-  NSURL* url = [NSURL URLFromPasteboard:pasteboard->get()];
-  EXPECT_NSEQ([url absoluteString], urlString);
+  // Only the first item should have the "web urls and titles" data.
+  EXPECT_TRUE([items[0].types containsObject:kUTTypeWebKitWebURLsWithTitles]);
+  EXPECT_FALSE([items[1].types containsObject:kUTTypeWebKitWebURLsWithTitles]);
 }
 
 TEST_F(ClipboardUtilMacTest, PasteboardItemWithFilePath) {
   NSURL* url = [NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES];
   ASSERT_TRUE(url);
-  NSString* urlString = [url absoluteString];
+  NSString* url_string = url.absoluteString;
 
-  base::scoped_nsobject<NSPasteboardItem> item(
-      ClipboardUtil::PasteboardItemFromUrl(urlString, nil));
+  NSArray<NSPasteboardItem*>* items =
+      ClipboardUtil::PasteboardItemsFromUrls(@[ url_string ], @[ @"" ]);
   scoped_refptr<UniquePasteboard> pasteboard = new UniquePasteboard;
-  [pasteboard->get() writeObjects:@[ item ]];
+  [pasteboard->get() writeObjects:items];
 
   NSArray* urls = nil;
   NSArray* titles = nil;
-  [pasteboard->get() getURLs:&urls
-                   andTitles:&titles
-         convertingFilenames:NO
-         convertingTextToURL:NO];
+  ClipboardUtil::URLsAndTitlesFromPasteboard(pasteboard->get(), &urls, &titles);
 
-  ASSERT_EQ(1u, [urls count]);
-  EXPECT_NSEQ(urlString, urls[0]);
-  ASSERT_EQ(1u, [titles count]);
-  EXPECT_NSEQ(urlString, titles[0]);
+  ASSERT_EQ(1u, urls.count);
+  EXPECT_NSEQ(url_string, urls[0]);
+  ASSERT_EQ(1u, titles.count);
+  EXPECT_NSEQ(@"", titles[0]);
 
   NSURL* urlFromPasteboard = [NSURL URLFromPasteboard:pasteboard->get()];
   EXPECT_NSEQ(urlFromPasteboard, url);
@@ -132,23 +85,5 @@
   }
 }
 
-TEST_F(ClipboardUtilMacTest, CompareToWriteToPasteboard) {
-  NSString* urlString = @"https://www.cnn.com/";
-
-  base::scoped_nsobject<NSPasteboardItem> item(
-      ClipboardUtil::PasteboardItemFromUrl(urlString, nil));
-  scoped_refptr<UniquePasteboard> pasteboard = new UniquePasteboard;
-  [pasteboard->get() writeObjects:@[ item ]];
-
-  scoped_refptr<UniquePasteboard> pboard = new UniquePasteboard;
-  [pboard->get() setDataForURL:urlString title:urlString];
-
-  NSDictionary* data1 =
-      DictionaryFromPasteboardForDeepComparisons(pasteboard->get());
-  NSDictionary* data2 =
-      DictionaryFromPasteboardForDeepComparisons(pboard->get());
-  EXPECT_NSEQ(data1, data2);
-}
-
 }  // namespace
 }  // namespace ui
diff --git a/ui/base/cocoa/base_view.mm b/ui/base/cocoa/base_view.mm
index 7a0c2642..69e510c 100644
--- a/ui/base/cocoa/base_view.mm
+++ b/ui/base/cocoa/base_view.mm
@@ -145,13 +145,6 @@
 }
 
 - (void)mouseExited:(NSEvent*)theEvent {
-  // Suppress spurious events that are out of the bounds of this view.
-  // For unknown reasons this happens shortly after mouseMoved on the toolbar if
-  // the overlay window is above the NSToolbarFullScreenWindow.
-  NSRect frameInWindow = [self convertRect:[self bounds] toView:nil];
-  if (NSPointInRect([theEvent locationInWindow], frameInWindow))
-    return;
-
   // The tracking area will send an exit event even during a drag, which isn't
   // how the event flow for drags should work. This stores the exit event, and
   // sends it when the drag completes instead.
diff --git a/ui/base/dragdrop/os_exchange_data_provider_mac.h b/ui/base/dragdrop/os_exchange_data_provider_mac.h
index b99c462a..804fd371 100644
--- a/ui/base/dragdrop/os_exchange_data_provider_mac.h
+++ b/ui/base/dragdrop/os_exchange_data_provider_mac.h
@@ -73,9 +73,8 @@
   // Gets the underlying pasteboard.
   virtual NSPasteboard* GetPasteboard() const = 0;
 
-  // Returns an NSDraggingItem useful for initiating a drag. (Currently
-  // OSExchangeDataProviderMac can only have one item.)
-  NSDraggingItem* GetDraggingItem() const;
+  // Returns NSDraggingItems for initiating a drag.
+  NSArray<NSDraggingItem*>* GetDraggingItems() const;
 
   // Returns an array of pasteboard types that can be supported by
   // OSExchangeData.
diff --git a/ui/base/dragdrop/os_exchange_data_provider_mac.mm b/ui/base/dragdrop/os_exchange_data_provider_mac.mm
index 0e23e2a..20547b0 100644
--- a/ui/base/dragdrop/os_exchange_data_provider_mac.mm
+++ b/ui/base/dragdrop/os_exchange_data_provider_mac.mm
@@ -80,8 +80,7 @@
 
 class OwningProvider : public OSExchangeDataProviderMac {
  public:
-  OwningProvider()
-      : OSExchangeDataProviderMac(), owned_pasteboard_(new UniquePasteboard) {}
+  OwningProvider() : owned_pasteboard_(new UniquePasteboard) {}
   OwningProvider(const OwningProvider& provider) = default;
 
   std::unique_ptr<OSExchangeDataProvider> Clone() const override {
@@ -98,8 +97,8 @@
 
 class WrappingProvider : public OSExchangeDataProviderMac {
  public:
-  WrappingProvider(NSPasteboard* pasteboard)
-      : OSExchangeDataProviderMac(), wrapped_pasteboard_([pasteboard retain]) {}
+  explicit WrappingProvider(NSPasteboard* pasteboard)
+      : wrapped_pasteboard_([pasteboard retain]) {}
   WrappingProvider(const WrappingProvider& provider) = default;
 
   std::unique_ptr<OSExchangeDataProvider> Clone() const override {
@@ -162,10 +161,10 @@
 
 void OSExchangeDataProviderMac::SetURL(const GURL& url,
                                        const std::u16string& title) {
-  base::scoped_nsobject<NSPasteboardItem> item =
-      ClipboardUtil::PasteboardItemFromUrl(base::SysUTF8ToNSString(url.spec()),
-                                           base::SysUTF16ToNSString(title));
-  ClipboardUtil::AddDataToPasteboard(GetPasteboard(), item);
+  NSArray<NSPasteboardItem*>* items = ClipboardUtil::PasteboardItemsFromUrls(
+      @[ base::SysUTF8ToNSString(url.spec()) ],
+      @[ base::SysUTF16ToNSString(title) ]);
+  ClipboardUtil::AddDataToPasteboard(GetPasteboard(), items.firstObject);
 }
 
 void OSExchangeDataProviderMac::SetFilename(const base::FilePath& path) {
@@ -331,30 +330,30 @@
   return cursor_offset_;
 }
 
-NSDraggingItem* OSExchangeDataProviderMac::GetDraggingItem() const {
+NSArray<NSDraggingItem*>* OSExchangeDataProviderMac::GetDraggingItems() const {
   // What's going on here is that initiating a drag (-[NSView
   // beginDraggingSessionWithItems...]) requires a dragging item. Even though
   // pasteboard items are NSPasteboardWriters, they are locked to their
   // pasteboard and cannot be used to initiate a drag with another pasteboard
   // (hello https://crbug.com/928684). Therefore, wrap them.
-  //
-  // OSExchangeDataProviderMac was written to the old NSPasteboard APIs that
-  // didn't account for more than one item. This kinda matches Views which also
-  // assumes that only one drag item can exist at a time. TODO(avi): Fix all of
-  // Views to be able to handle drags of more than one item. Then rewrite
-  // OSExchangeDataProviderMac to the new NSPasteboard item API.
 
-  NSArray* pasteboardItems = [GetPasteboard() pasteboardItems];
-  DCHECK(pasteboardItems);
-  DCHECK_EQ(1u, [pasteboardItems count]);
+  NSArray<NSPasteboardItem*>* pasteboard_items =
+      GetPasteboard().pasteboardItems;
+  if (!pasteboard_items) {
+    return nil;
+  }
 
-  CrPasteboardItemWrapper* wrapper = [[[CrPasteboardItemWrapper alloc]
-      initWithPasteboardItem:[pasteboardItems firstObject]] autorelease];
+  NSMutableArray<NSDraggingItem*>* drag_items = [NSMutableArray array];
+  for (NSPasteboardItem* item in pasteboard_items) {
+    CrPasteboardItemWrapper* wrapper = [[[CrPasteboardItemWrapper alloc]
+        initWithPasteboardItem:item] autorelease];
+    NSDraggingItem* drag_item =
+        [[[NSDraggingItem alloc] initWithPasteboardWriter:wrapper] autorelease];
 
-  NSDraggingItem* drag_item =
-      [[[NSDraggingItem alloc] initWithPasteboardWriter:wrapper] autorelease];
+    [drag_items addObject:drag_item];
+  }
 
-  return drag_item;
+  return drag_items;
 }
 
 // static
diff --git a/ui/base/test/ui_controls.h b/ui/base/test/ui_controls.h
index bd43c50..84cc638 100644
--- a/ui/base/test/ui_controls.h
+++ b/ui/base/test/ui_controls.h
@@ -62,14 +62,25 @@
                                 bool command,
                                 base::OnceClosure task);
 
-// Simulate a mouse move.
-bool SendMouseMove(int screen_x, int screen_y);
+// This value specifies that no window hint is given and an appropriate target
+// window should be deduced from the target or current mouse position.
+constexpr gfx::NativeWindow kNoWindowHint = gfx::kNullNativeWindow;
 
+// Simulate a mouse move.
+//
+// The `window_hint` - if specified - helps the method correctly target the
+// appropriate window on platforms where mouse events must be explicitly
+// targeted.
+//
 // Returns false on Windows if the desired position is not over a window
 // belonging to the current process.
+bool SendMouseMove(int screen_x,
+                   int screen_y,
+                   gfx::NativeWindow window_hint = kNoWindowHint);
 bool SendMouseMoveNotifyWhenDone(int screen_x,
                                  int screen_y,
-                                 base::OnceClosure task);
+                                 base::OnceClosure task,
+                                 gfx::NativeWindow window_hint = kNoWindowHint);
 
 enum MouseButton {
   LEFT = 0,
@@ -99,16 +110,24 @@
 // currently is, so be sure to move the cursor before calling this
 // (and be sure the cursor has arrived!).
 // |accelerator_state| is a bitmask of AcceleratorState.
+//
+// The `window_hint` - if specified - helps the method correctly target the
+// appropriate window on platforms where mouse events must be explicitly
+// targeted.
 bool SendMouseEvents(MouseButton type,
                      int button_state,
-                     int accelerator_state = kNoAccelerator);
-bool SendMouseEventsNotifyWhenDone(MouseButton type,
-                                   int button_state,
-                                   base::OnceClosure task,
-                                   int accelerator_state = kNoAccelerator);
+                     int accelerator_state = kNoAccelerator,
+                     gfx::NativeWindow window_hint = kNoWindowHint);
+bool SendMouseEventsNotifyWhenDone(
+    MouseButton type,
+    int button_state,
+    base::OnceClosure task,
+    int accelerator_state = kNoAccelerator,
+    gfx::NativeWindow window_hint = kNoWindowHint);
 
 // Same as SendMouseEvents with UP | DOWN.
-bool SendMouseClick(MouseButton type);
+bool SendMouseClick(MouseButton type,
+                    gfx::NativeWindow window_hint = kNoWindowHint);
 
 #if BUILDFLAG(IS_WIN)
 // Send WM_POINTER messages to generate touch events. There is no way to detect
diff --git a/ui/base/test/ui_controls_aura.cc b/ui/base/test/ui_controls_aura.cc
index 5993a12..b51b0516 100644
--- a/ui/base/test/ui_controls_aura.cc
+++ b/ui/base/test/ui_controls_aura.cc
@@ -8,6 +8,7 @@
 #include "base/check.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
+#include "ui/gfx/native_widget_types.h"
 
 namespace ui_controls {
 namespace {
@@ -45,13 +46,18 @@
 }
 
 // static
-bool SendMouseMove(int x, int y) {
+bool SendMouseMove(int x, int y, gfx::NativeWindow) {
+  // TODO(crbug.com/1396661): Maybe use the window hint on other platforms.
   CHECK(g_ui_controls_enabled);
   return instance_->SendMouseMove(x, y);
 }
 
 // static
-bool SendMouseMoveNotifyWhenDone(int x, int y, base::OnceClosure task) {
+bool SendMouseMoveNotifyWhenDone(int x,
+                                 int y,
+                                 base::OnceClosure task,
+                                 gfx::NativeWindow) {
+  // TODO(crbug.com/1396661): Maybe use the window hint on other platforms.
   CHECK(g_ui_controls_enabled);
   return instance_->SendMouseMoveNotifyWhenDone(x, y, std::move(task));
 }
@@ -59,7 +65,9 @@
 // static
 bool SendMouseEvents(MouseButton type,
                      int button_state,
-                     int accelerator_state) {
+                     int accelerator_state,
+                     gfx::NativeWindow) {
+  // TODO(crbug.com/1396661): Maybe use the window hint on other platforms.
   CHECK(g_ui_controls_enabled);
   return instance_->SendMouseEvents(type, button_state, accelerator_state);
 }
@@ -68,14 +76,17 @@
 bool SendMouseEventsNotifyWhenDone(MouseButton type,
                                    int button_state,
                                    base::OnceClosure task,
-                                   int accelerator_state) {
+                                   int accelerator_state,
+                                   gfx::NativeWindow) {
+  // TODO(crbug.com/1396661): Maybe use the window hint on other platforms.
   CHECK(g_ui_controls_enabled);
   return instance_->SendMouseEventsNotifyWhenDone(
       type, button_state, std::move(task), accelerator_state);
 }
 
 // static
-bool SendMouseClick(MouseButton type) {
+bool SendMouseClick(MouseButton type, gfx::NativeWindow) {
+  // TODO(crbug.com/1396661): Do any Aura platforms need to use the hint?
   CHECK(g_ui_controls_enabled);
   return instance_->SendMouseClick(type);
 }
diff --git a/ui/base/test/ui_controls_mac.mm b/ui/base/test/ui_controls_mac.mm
index 66dbd61..82ff55a 100644
--- a/ui/base/test/ui_controls_mac.mm
+++ b/ui/base/test/ui_controls_mac.mm
@@ -291,20 +291,24 @@
   return true;
 }
 
-bool SendMouseMove(int x, int y) {
+bool SendMouseMove(int x, int y, gfx::NativeWindow window_hint) {
   CHECK(g_ui_controls_enabled);
-  return SendMouseMoveNotifyWhenDone(x, y, base::OnceClosure());
+  return SendMouseMoveNotifyWhenDone(x, y, base::OnceClosure(), window_hint);
 }
 
 // Input position is in screen coordinates.  However, NSEventTypeMouseMoved
 // events require them window-relative, so we adjust.  We *DO* flip
 // the coordinate space, so input events can be the same for all
 // platforms.  E.g. (0,0) is upper-left.
-bool SendMouseMoveNotifyWhenDone(int x, int y, base::OnceClosure task) {
+bool SendMouseMoveNotifyWhenDone(int x,
+                                 int y,
+                                 base::OnceClosure task,
+                                 gfx::NativeWindow window_hint) {
   CHECK(g_ui_controls_enabled);
   g_mouse_location = gfx::ScreenPointToNSPoint(gfx::Point(x, y));  // flip!
 
-  NSWindow* window = WindowAtCurrentMouseLocation();
+  NSWindow* window = window_hint ? window_hint.GetNativeNSWindow()
+                                 : WindowAtCurrentMouseLocation();
 
   NSPoint pointInWindow = g_mouse_location;
   if (window)
@@ -342,23 +346,25 @@
 
 bool SendMouseEvents(MouseButton type,
                      int button_state,
-                     int accelerator_state) {
+                     int accelerator_state,
+                     gfx::NativeWindow window_hint) {
   CHECK(g_ui_controls_enabled);
   return SendMouseEventsNotifyWhenDone(type, button_state, base::OnceClosure(),
-                                       accelerator_state);
+                                       accelerator_state, window_hint);
 }
 
 bool SendMouseEventsNotifyWhenDone(MouseButton type,
                                    int button_state,
                                    base::OnceClosure task,
-                                   int accelerator_state) {
+                                   int accelerator_state,
+                                   gfx::NativeWindow window_hint) {
   CHECK(g_ui_controls_enabled);
   // Handle the special case of mouse clicking (UP | DOWN) case.
   if (button_state == (UP | DOWN)) {
     return (SendMouseEventsNotifyWhenDone(type, DOWN, base::OnceClosure(),
-                                          accelerator_state) &&
+                                          accelerator_state, window_hint) &&
             SendMouseEventsNotifyWhenDone(type, UP, std::move(task),
-                                          accelerator_state));
+                                          accelerator_state, window_hint));
   }
   NSEventType event_type = NSEventTypeLeftMouseDown;
   if (type == LEFT) {
@@ -385,7 +391,9 @@
   }
   g_mouse_button_down[type] = button_state == DOWN;
 
-  NSWindow* window = WindowAtCurrentMouseLocation();
+  NSWindow* window = window_hint ? window_hint.GetNativeNSWindow()
+                                 : WindowAtCurrentMouseLocation();
+
   NSPoint pointInWindow = g_mouse_location;
   if (window)
     pointInWindow = ui::ConvertPointFromScreenToWindow(window, pointInWindow);
@@ -421,9 +429,10 @@
   return true;
 }
 
-bool SendMouseClick(MouseButton type) {
+bool SendMouseClick(MouseButton type, gfx::NativeWindow window_hint) {
   CHECK(g_ui_controls_enabled);
-  return SendMouseEventsNotifyWhenDone(type, UP | DOWN, base::OnceClosure());
+  return SendMouseEventsNotifyWhenDone(type, UP | DOWN, base::OnceClosure(),
+                                       kNoAccelerator, window_hint);
 }
 
 bool IsFullKeyboardAccessEnabled() {
diff --git a/ui/color/color_id.h b/ui/color/color_id.h
index 524f145..cabd236e 100644
--- a/ui/color/color_id.h
+++ b/ui/color/color_id.h
@@ -241,10 +241,12 @@
   E_CPONLY(kColorProgressBar) \
   E_CPONLY(kColorProgressBarPaused) \
   E_CPONLY(kColorReadAnythingBackground) \
+  E_CPONLY(kColorReadAnythingBackgroundBlue) \
   E_CPONLY(kColorReadAnythingBackgroundDark) \
   E_CPONLY(kColorReadAnythingBackgroundLight) \
   E_CPONLY(kColorReadAnythingBackgroundYellow) \
   E_CPONLY(kColorReadAnythingForeground) \
+  E_CPONLY(kColorReadAnythingForegroundBlue) \
   E_CPONLY(kColorReadAnythingForegroundDark) \
   E_CPONLY(kColorReadAnythingForegroundLight) \
   E_CPONLY(kColorReadAnythingForegroundYellow) \
diff --git a/ui/color/ui_color_mixer.cc b/ui/color/ui_color_mixer.cc
index c2bf7af..80394f2 100644
--- a/ui/color/ui_color_mixer.cc
+++ b/ui/color/ui_color_mixer.cc
@@ -157,12 +157,14 @@
   mixer[kColorReadAnythingBackground] = {
       dark_mode ? kColorReadAnythingBackgroundDark
                 : kColorReadAnythingBackgroundLight};
+  mixer[kColorReadAnythingBackgroundBlue] = {gfx::kGoogleBlue200};
   mixer[kColorReadAnythingBackgroundDark] = {gfx::kGoogleGrey900};
   mixer[kColorReadAnythingBackgroundLight] = {gfx::kGoogleGrey050};
   mixer[kColorReadAnythingBackgroundYellow] = {gfx::kGoogleYellow200};
   mixer[kColorReadAnythingForeground] = {
       dark_mode ? kColorReadAnythingForegroundDark
                 : kColorReadAnythingForegroundLight};
+  mixer[kColorReadAnythingForegroundBlue] = {gfx::kGoogleGrey900};
   mixer[kColorReadAnythingForegroundDark] = {gfx::kGoogleGrey200};
   mixer[kColorReadAnythingForegroundLight] = {gfx::kGoogleGrey800};
   mixer[kColorReadAnythingForegroundYellow] = {gfx::kGoogleGrey800};
diff --git a/ui/file_manager/BUILD.gn b/ui/file_manager/BUILD.gn
index 298661f..7750c6e 100644
--- a/ui/file_manager/BUILD.gn
+++ b/ui/file_manager/BUILD.gn
@@ -239,6 +239,14 @@
   outputs = [ "$preprocess_folder/file_manager/externs/{{source_file_part}}" ]
 }
 
+copy("for_image_loader") {
+  sources = [
+    "file_manager/externs/ts/state.js",
+    "file_manager/foreground/js/metadata/metadata_item.js",
+  ]
+  outputs = [ "$target_gen_dir/{{source_target_relative}}" ]
+}
+
 js_library("js_from_ts") {
   sources = []
   foreach(_t, ts_files) {
@@ -276,7 +284,10 @@
       "file_manager/foreground/js/metadata_dispatcher.rollup.js",
       "file_manager/foreground/js/shared.rollup.js",
 
+      # For Image Loader unittests:
       "file_manager/common/js/file_types_data.js",
+      "file_manager/externs/ts/state.js",
+      "file_manager/foreground/js/metadata/metadata_item.js",
     ]
 
     resource_path_rewrites += [
@@ -286,6 +297,7 @@
     ]
 
     deps += [
+      ":for_image_loader",
       "//ui/file_manager/file_manager/foreground/elements:elements",
       "//ui/file_manager/file_manager/foreground/js:build",
       "//ui/file_manager/file_manager/foreground/js:build_worker",
diff --git a/ui/file_manager/file_manager/BUILD.gn b/ui/file_manager/file_manager/BUILD.gn
index fe2699c8..c746dd3 100644
--- a/ui/file_manager/file_manager/BUILD.gn
+++ b/ui/file_manager/file_manager/BUILD.gn
@@ -26,7 +26,7 @@
     "common/js/files_app_state.js",
     "common/js/icon_util.js",
     "common/js/mock_chrome.js",
-    "common/js/storage_adapter.js",
+    "common/js/storage.js",
     "common/js/test_error_reporting.js",
     "common/js/volume_manager_types.js",
     "common/js/url_constants.js",
diff --git a/ui/file_manager/file_manager/common/js/BUILD.gn b/ui/file_manager/file_manager/common/js/BUILD.gn
index 8e0e12c..eaea000 100644
--- a/ui/file_manager/file_manager/common/js/BUILD.gn
+++ b/ui/file_manager/file_manager/common/js/BUILD.gn
@@ -40,7 +40,7 @@
     ":notifications_browser_proxy",
     ":progress_center_common",
     ":recent_date_bucket",
-    ":storage_adapter",
+    ":storage",
     ":ui",
     ":url_constants",
     ":util",
@@ -69,7 +69,7 @@
     ":notifications_browser_proxy",
     ":progress_center_common",
     ":recent_date_bucket",
-    ":storage_adapter",
+    ":storage",
     ":ui",
     ":url_constants",
     ":util",
@@ -110,7 +110,7 @@
 
 js_library("app_util") {
   deps = [
-    ":storage_adapter",
+    ":storage",
     "//ui/file_manager/file_manager/externs:file_manager_private",
     "//ui/file_manager/file_manager/externs:volume_manager",
   ]
@@ -183,6 +183,7 @@
     ":files_app_entry_types",
     "//ui/file_manager/file_manager/common/js:volume_manager_types",
     "//ui/file_manager/file_manager/externs:files_app_entry_interfaces",
+    "//ui/file_manager/file_manager/externs/ts:state",
     "//ui/webui/resources/js:assert",
   ]
 }
@@ -283,12 +284,12 @@
   ]
 }
 
-js_library("storage_adapter") {
+js_library("storage") {
 }
 
-js_unittest("storage_adapter_unittest") {
+js_unittest("storage_unittest") {
   deps = [
-    ":storage_adapter",
+    ":storage",
     "//chrome/test/data/webui/chromeos:chai_assert",
   ]
 }
@@ -359,7 +360,7 @@
     ":filtered_volume_manager_unittest",
     ":lru_cache_unittest",
     ":recent_date_bucket_unittest",
-    ":storage_adapter_unittest",
+    ":storage_unittest",
     ":util_unittest",
     ":volume_manager_types_unittest",
   ]
diff --git a/ui/file_manager/file_manager/common/js/app_util.js b/ui/file_manager/file_manager/common/js/app_util.js
index 9cf3545..d0abbce1 100644
--- a/ui/file_manager/file_manager/common/js/app_util.js
+++ b/ui/file_manager/file_manager/common/js/app_util.js
@@ -4,7 +4,7 @@
 
 import {VolumeManager} from '../../externs/volume_manager.js';
 
-import {storage} from './storage_adapter.js';
+import {storage} from './storage.js';
 
 const appUtil = {};
 
diff --git a/ui/file_manager/file_manager/common/js/file_type.js b/ui/file_manager/file_manager/common/js/file_type.js
index 2eefcd1..df0628a 100644
--- a/ui/file_manager/file_manager/common/js/file_type.js
+++ b/ui/file_manager/file_manager/common/js/file_type.js
@@ -5,6 +5,7 @@
 import {assert} from 'chrome://resources/js/assert.js';
 
 import {FilesAppEntry} from '../../externs/files_app_entry_interfaces.js';
+import {FileData} from '../../externs/ts/state.js';
 
 import {EXTENSION_TO_TYPE, FileExtensionType, MIME_TO_TYPE} from './file_types_data.js';
 import {VolumeEntry} from './files_app_entry_types.js';
@@ -231,7 +232,7 @@
 };
 
 /**
- * @param {Entry|VolumeEntry} entry Reference to the file.
+ * @param {Entry|VolumeEntry|FileData} entry Reference to the file.
  * @param {string=} opt_mimeType Optional mime type for the file.
  * @param {VolumeManagerCommon.RootType=} opt_rootType The root type of the
  *     entry.
@@ -240,10 +241,16 @@
  */
 FileType.getIcon = (entry, opt_mimeType, opt_rootType) => {
   let icon;
+  // Handles the FileData and FilesAppEntry types.
+  if (entry && entry.iconName) {
+    return entry.iconName;
+  }
+  // Handles other types of entries.
   if (entry) {
+    entry = /** @type {!Entry|!VolumeEntry} */ (entry);
     const fileType = FileType.getType(entry, opt_mimeType);
     const overridenIcon = FileType.getIconOverrides(entry, opt_rootType);
-    icon = entry.iconName || overridenIcon || fileType.icon || fileType.type;
+    icon = overridenIcon || fileType.icon || fileType.type;
   }
   return icon || 'unknown';
 };
diff --git a/ui/file_manager/file_manager/common/js/storage_adapter.js b/ui/file_manager/file_manager/common/js/storage.js
similarity index 100%
rename from ui/file_manager/file_manager/common/js/storage_adapter.js
rename to ui/file_manager/file_manager/common/js/storage.js
diff --git a/ui/file_manager/file_manager/common/js/storage_adapter_unittest.js b/ui/file_manager/file_manager/common/js/storage_unittest.js
similarity index 97%
rename from ui/file_manager/file_manager/common/js/storage_adapter_unittest.js
rename to ui/file_manager/file_manager/common/js/storage_unittest.js
index 6eae21a..064ce6dd 100644
--- a/ui/file_manager/file_manager/common/js/storage_adapter_unittest.js
+++ b/ui/file_manager/file_manager/common/js/storage_unittest.js
@@ -4,7 +4,7 @@
 
 import {assertDeepEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
 
-import {storage} from './storage_adapter.js';
+import {storage} from './storage.js';
 import {waitUntil} from './test_error_reporting.js';
 
 /**
diff --git a/ui/file_manager/file_manager/containers/nudge_container.ts b/ui/file_manager/file_manager/containers/nudge_container.ts
index 7efa6f68..1999673 100644
--- a/ui/file_manager/file_manager/containers/nudge_container.ts
+++ b/ui/file_manager/file_manager/containers/nudge_container.ts
@@ -4,7 +4,7 @@
 
 import '../widgets/xf_nudge.js';
 
-import {storage} from '../common/js/storage_adapter.js';
+import {storage} from '../common/js/storage.js';
 import {str} from '../common/js/util.js';
 import {NudgeDirection, XfNudge} from '../widgets/xf_nudge.js';
 
diff --git a/ui/file_manager/file_manager/definitions/file_manager.d.ts b/ui/file_manager/file_manager/definitions/file_manager.d.ts
index 4d845ee..1c88d6e 100644
--- a/ui/file_manager/file_manager/definitions/file_manager.d.ts
+++ b/ui/file_manager/file_manager/definitions/file_manager.d.ts
@@ -13,6 +13,10 @@
 interface FileManager {
   volumeManager: VolumeManager;
   metadataModel: MetadataModel;
+  crostini: Crostini;
+  selectionHandler: FileSelectionHandler;
+  taskController: TaskController;
+  dialogType: DialogType;
 }
 
 /**
diff --git a/ui/file_manager/file_manager/externs/ts/BUILD.gn b/ui/file_manager/file_manager/externs/ts/BUILD.gn
index 00dd920..1edf3e5 100644
--- a/ui/file_manager/file_manager/externs/ts/BUILD.gn
+++ b/ui/file_manager/file_manager/externs/ts/BUILD.gn
@@ -5,7 +5,10 @@
 import("//third_party/closure_compiler/compile_js.gni")
 
 js_library("state") {
-  deps = [ "..:files_app_entry_interfaces" ]
+  deps = [
+    "..:files_app_entry_interfaces",
+    "//ui/file_manager/file_manager/foreground/js/metadata:metadata_item",
+  ]
 }
 
 js_library("store") {
diff --git a/ui/file_manager/file_manager/externs/ts/state.js b/ui/file_manager/file_manager/externs/ts/state.js
index dfcc1c2..d8515bd 100644
--- a/ui/file_manager/file_manager/externs/ts/state.js
+++ b/ui/file_manager/file_manager/externs/ts/state.js
@@ -34,6 +34,7 @@
  * The data for each individual file/entry.
  * @typedef {{
  *   entry: (Entry|FilesAppEntry),
+ *   iconName: (string|undefined),
  *   label: string,
  *   volumeType: (VolumeManagerCommon.VolumeType|null),
  *   metadata: !MetadataItem,
@@ -131,14 +132,16 @@
  * NOTE: This is slightly different from the FileTask from the
  * FileManagerPrivate API. Here the task is enhanced to deal with different
  * displaying icons and labels.
+ * TODO(lucmult): Change isDefault and isGenericFileHandler to boolean when
+ * non-Store version doesn't have to be supported anymore.
  *
  * @typedef {{
  *   descriptor: !FileTaskDescriptor,
  *   title: string,
  *   iconUrl: (string|undefined),
  *   iconType: string,
- *   isDefault: boolean,
- *   isGeneric: boolean,
+ *   isDefault: (boolean|undefined),
+ *   isGenericFileHandler: (boolean|undefined),
  * }}
  */
 export let FileTask;
@@ -153,9 +156,10 @@
  *
  * @typedef {{
  *   tasks: !Array<!FileTask>,
- *   defaultHandlerPolicy:
+ *   policyDefaultHandlerStatus:
  *      (chrome.fileManagerPrivate.PolicyDefaultHandlerStatus|undefined),
- *   status: !PropStatus, keys: !Array<!FileKey>,
+ *   defaultTask: (FileTask|undefined),
+ *   status: !PropStatus,
  * }}
  */
 export let FileTasks;
diff --git a/ui/file_manager/file_manager/foreground/js/BUILD.gn b/ui/file_manager/file_manager/foreground/js/BUILD.gn
index f485127..061d6cc3 100644
--- a/ui/file_manager/file_manager/foreground/js/BUILD.gn
+++ b/ui/file_manager/file_manager/foreground/js/BUILD.gn
@@ -210,7 +210,7 @@
     "//ui/file_manager/file_manager/common/js:api",
     "//ui/file_manager/file_manager/common/js:async_util",
     "//ui/file_manager/file_manager/common/js:dialog_type",
-    "//ui/file_manager/file_manager/common/js:storage_adapter",
+    "//ui/file_manager/file_manager/common/js:storage",
     "//ui/file_manager/file_manager/common/js:volume_manager_types",
     "//ui/file_manager/file_manager/externs:banner",
     "//ui/file_manager/file_manager/externs:files_app_entry_interfaces",
@@ -229,7 +229,7 @@
     "//ui/file_manager/file_manager/background/js:mock_volume_manager",
     "//ui/file_manager/file_manager/common/js:dialog_type",
     "//ui/file_manager/file_manager/common/js:mock_chrome",
-    "//ui/file_manager/file_manager/common/js:storage_adapter",
+    "//ui/file_manager/file_manager/common/js:storage",
     "//ui/file_manager/file_manager/common/js:test_error_reporting",
     "//ui/file_manager/file_manager/common/js:volume_manager_types",
     "//ui/file_manager/file_manager/externs:banner",
@@ -623,7 +623,7 @@
     "//ui/file_manager/file_manager/common/js:filtered_volume_manager",
     "//ui/file_manager/file_manager/common/js:metrics",
     "//ui/file_manager/file_manager/common/js:progress_center_common",
-    "//ui/file_manager/file_manager/common/js:storage_adapter",
+    "//ui/file_manager/file_manager/common/js:storage",
     "//ui/file_manager/file_manager/common/js:util",
     "//ui/file_manager/file_manager/common/js:volume_manager_types",
     "//ui/file_manager/file_manager/externs:command_handler_deps",
diff --git a/ui/file_manager/file_manager/foreground/js/app_state_controller.js b/ui/file_manager/file_manager/foreground/js/app_state_controller.js
index 7f2fb57..a7afa77c 100644
--- a/ui/file_manager/file_manager/foreground/js/app_state_controller.js
+++ b/ui/file_manager/file_manager/foreground/js/app_state_controller.js
@@ -6,7 +6,7 @@
 
 import {appUtil} from '../../common/js/app_util.js';
 import {DialogType} from '../../common/js/dialog_type.js';
-import {storage} from '../../common/js/storage_adapter.js';
+import {storage} from '../../common/js/storage.js';
 import {util} from '../../common/js/util.js';
 
 import {DirectoryModel} from './directory_model.js';
diff --git a/ui/file_manager/file_manager/foreground/js/banner_controller.js b/ui/file_manager/file_manager/foreground/js/banner_controller.js
index 51487ec8..63a7230 100644
--- a/ui/file_manager/file_manager/foreground/js/banner_controller.js
+++ b/ui/file_manager/file_manager/foreground/js/banner_controller.js
@@ -7,7 +7,7 @@
 import {getDriveQuotaMetadata, getSizeStats} from '../../common/js/api.js';
 import {RateLimiter} from '../../common/js/async_util.js';
 import {DialogType} from '../../common/js/dialog_type.js';
-import {storage} from '../../common/js/storage_adapter.js';
+import {storage} from '../../common/js/storage.js';
 import {util} from '../../common/js/util.js';
 import {VolumeManagerCommon} from '../../common/js/volume_manager_types.js';
 import {Crostini} from '../../externs/background/crostini.js';
diff --git a/ui/file_manager/file_manager/foreground/js/banner_controller_unittest.js b/ui/file_manager/file_manager/foreground/js/banner_controller_unittest.js
index 5992775..8bd22b7 100644
--- a/ui/file_manager/file_manager/foreground/js/banner_controller_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/banner_controller_unittest.js
@@ -6,7 +6,7 @@
 
 import {DialogType} from '../../common/js/dialog_type.js';
 import {installMockChrome, MockChromeFileManagerPrivateDirectoryChanged, MockChromeStorageAPI} from '../../common/js/mock_chrome.js';
-import {storage} from '../../common/js/storage_adapter.js';
+import {storage} from '../../common/js/storage.js';
 import {waitUntil} from '../../common/js/test_error_reporting.js';
 import {VolumeManagerCommon} from '../../common/js/volume_manager_types.js';
 import {Crostini} from '../../externs/background/crostini.js';
diff --git a/ui/file_manager/file_manager/foreground/js/file_tasks.ts b/ui/file_manager/file_manager/foreground/js/file_tasks.ts
index 0bc470b..064aac0 100644
--- a/ui/file_manager/file_manager/foreground/js/file_tasks.ts
+++ b/ui/file_manager/file_manager/foreground/js/file_tasks.ts
@@ -19,6 +19,7 @@
 import {VolumeManagerCommon} from '../../common/js/volume_manager_types.js';
 import {Crostini} from '../../externs/background/crostini.js';
 import {ProgressCenter} from '../../externs/background/progress_center.js';
+import {FileData} from '../../externs/ts/state.js';
 import {VolumeInfo} from '../../externs/volume_info.js';
 import {VolumeManager} from '../../externs/volume_manager.js';
 import {FilesPasswordDialog} from '../elements/files_password_dialog.js';
@@ -107,10 +108,12 @@
               task.descriptor, INSTALL_LINUX_PACKAGE_TASK_DESCRIPTOR));
     }
 
-    resultingTasks.tasks =
-        FileTasks.annotateTasks_(resultingTasks.tasks, entries);
+    const tasks = annotateTasks(resultingTasks.tasks, entries);
+    resultingTasks.tasks = tasks;
 
-    const defaultTask = FileTasks.getDefaultTask(resultingTasks, taskHistory);
+    const defaultTask = getDefaultTask(
+        tasks, resultingTasks.policyDefaultHandlerStatus, taskHistory);
+
 
     return new FileTasks(
         volumeManager, metadataModel, directoryModel, ui,
@@ -126,9 +129,9 @@
     return this.defaultTask_;
   }
 
-  /** Gets task items.  */
-  getTaskItems(): chrome.fileManagerPrivate.FileTask[] {
-    return this.resultingTasks_.tasks;
+  getAnnotatedTasks(): AnnotatedTask[] {
+    // resultingTasks_.tasks is annotated at create().
+    return this.resultingTasks_.tasks as AnnotatedTask[];
   }
 
   /** Gets the policy default handler status.  */
@@ -298,87 +301,6 @@
   }
 
   /**
-   * Annotates tasks returned from the API.
-   * @param tasks Input tasks from the API.
-   * @param entries List of entries for the tasks.
-   * @private
-   */
-  private static annotateTasks_(
-      tasks: chrome.fileManagerPrivate.FileTask[],
-      entries: Entry[]): chrome.fileManagerPrivate.FileTask[] {
-    const result = [];
-    for (const task of (tasks as AnnotatedTask[])) {
-      const {appId, taskType, actionId} = task.descriptor;
-      const parsedActionId = parseActionId(actionId);
-
-      // Skip internal Files app's handlers.
-      if (isFilesAppId(appId) &&
-          (parsedActionId === 'select' || parsedActionId === 'open')) {
-        continue;
-      }
-
-      // Tweak images, titles of internal tasks.
-      if (isFilesAppId(appId) && (taskType === 'app' || taskType === 'web')) {
-        if (parsedActionId === 'mount-archive') {
-          task.iconType = 'archive';
-          task.title = str('MOUNT_ARCHIVE');
-        } else if (parsedActionId === 'open-hosted-generic') {
-          if (entries.length > 1) {
-            task.iconType = 'generic';
-          } else {  // Use specific icon.
-            task.iconType = FileType.getIcon(entries[0]!);
-          }
-          task.title = str('TASK_OPEN');
-        } else if (parsedActionId === 'open-hosted-gdoc') {
-          task.iconType = 'gdoc';
-          task.title = str('TASK_OPEN_GDOC');
-        } else if (parsedActionId === 'open-hosted-gsheet') {
-          task.iconType = 'gsheet';
-          task.title = str('TASK_OPEN_GSHEET');
-        } else if (parsedActionId === 'open-hosted-gslides') {
-          task.iconType = 'gslides';
-          task.title = str('TASK_OPEN_GSLIDES');
-        } else if (parsedActionId === 'open-web-drive-office-word') {
-          task.iconType = 'gdoc';
-          task.title = str('TASK_OPEN_GDOC');
-        } else if (parsedActionId === 'open-web-drive-office-excel') {
-          task.iconType = 'gsheet';
-          task.title = str('TASK_OPEN_GSHEET');
-        } else if (parsedActionId === 'upload-office-to-drive') {
-          task.iconType = 'generic';
-          task.title = 'Upload to Drive';
-        } else if (parsedActionId === 'open-web-drive-office-powerpoint') {
-          task.iconType = 'gslides';
-          task.title = str('TASK_OPEN_GSLIDES');
-        } else if (parsedActionId === 'open-in-office') {
-          task.iconUrl =
-              toFilesAppURL('foreground/images/files/ui/ms365.svg').toString();
-          task.title = str('TASK_OPEN_MICROSOFT_365');
-        } else if (parsedActionId === 'install-linux-package') {
-          task.iconType = 'crostini';
-          task.title = str('TASK_INSTALL_LINUX_PACKAGE');
-        } else if (parsedActionId === 'import-crostini-image') {
-          task.iconType = 'tini';
-          task.title = str('TASK_IMPORT_CROSTINI_IMAGE');
-        } else if (parsedActionId === 'view-pdf') {
-          task.iconType = 'pdf';
-          task.title = str('TASK_VIEW');
-        } else if (parsedActionId === 'view-in-browser') {
-          task.iconType = 'generic';
-          task.title = str('TASK_VIEW');
-        }
-      }
-      if (!task.iconType && taskType === 'web-intent') {
-        task.iconType = 'generic';
-      }
-
-      result.push(task);
-    }
-
-    return result;
-  }
-
-  /**
    * Show dialog when user opens or drags a file with PluginVM and the file
    * is not in PvmSharedDir or shared with PluginVM. The dialog tells the
    * user to move or copy the file to PvmSharedDir and offers an action to do
@@ -832,12 +754,6 @@
     const tracker = this.directoryModel_.createDirectoryChangeTracker();
     tracker.start();
     try {
-      this.entries_.forEach(entry => entry.getMetadata(metadata => {
-        const extension = entry.name.split('.').pop()?.toLowerCase();
-        metrics.recordSmallCount(
-            `ArchiveSize.${extension}`,
-            Math.ceil(metadata.size / 104857600));  // Each unit = 100MiB
-      }));
       // TODO(mtomasz): Move conversion from entry to url to custom bindings.
       // crbug.com/345527.
       const urls = util.entriesToURLs(this.entries_);
@@ -881,57 +797,6 @@
         });
   }
 
-  /**
-   * Gets the default task from tasks. In case there is no such task (i.e. all
-   * tasks are generic file handlers), then return null.
-   *
-   * @param resultingTasks The list of tasks from where to choose the default
-   *     task.
-   * @return the default task, or null if no default task found.
-   */
-  static getDefaultTask(
-      resultingTasks: chrome.fileManagerPrivate.ResultingTasks,
-      taskHistory: TaskHistory): chrome.fileManagerPrivate.FileTask|null {
-    const {tasks, policyDefaultHandlerStatus} = resultingTasks;
-
-    // If policy assignment is incorrect, then no default should be set.
-    if (policyDefaultHandlerStatus &&
-        policyDefaultHandlerStatus ===
-            chrome.fileManagerPrivate.PolicyDefaultHandlerStatus
-                .INCORRECT_ASSIGNMENT) {
-      return null;
-    }
-
-    // 1. Default app set for MIME or file extension by user, or built-in app.
-    for (const task of tasks) {
-      if (task.isDefault) {
-        return task;
-      }
-    }
-
-    // If policy assignment is marked as correct, then by this moment we
-    // should've already found the default.
-    assert(
-        !(policyDefaultHandlerStatus &&
-          policyDefaultHandlerStatus ===
-              chrome.fileManagerPrivate.PolicyDefaultHandlerStatus
-                  .DEFAULT_HANDLER_ASSIGNED_BY_POLICY));
-
-    const nonGenericTasks = tasks.filter(t => !t.isGenericFileHandler);
-    if (nonGenericTasks.length === 0) {
-      return null;
-    }
-
-    // 2. Most recently executed or sole non-generic task.
-    const latest = nonGenericTasks[0]!;
-    if (nonGenericTasks.length == 1 ||
-        taskHistory.getLastExecutedTime(latest.descriptor)) {
-      return latest;
-    }
-
-    return null;
-  }
-
   private static async getPvmSharedDir_(volumeManager: VolumeManager):
       Promise<DirectoryEntry> {
     const volumeInfo = volumeManager.getCurrentProfileVolumeInfo(
@@ -945,7 +810,7 @@
 }
 
 /** The task descriptor of 'Install Linux package'. */
-const INSTALL_LINUX_PACKAGE_TASK_DESCRIPTOR = {
+export const INSTALL_LINUX_PACKAGE_TASK_DESCRIPTOR = {
   appId: LEGACY_FILES_EXTENSION_ID,
   taskType: 'app',
   actionId: 'install-linux-package',
@@ -1035,3 +900,133 @@
   return !!location &&
       location.rootType === VolumeManagerCommon.RootType.DOWNLOADS;
 }
+
+/**
+ * Annotates tasks returned from the API.
+ * @param tasks Input tasks from the API.
+ * @param entries List of entries for the tasks.
+ */
+export function annotateTasks(
+    tasks: chrome.fileManagerPrivate.FileTask[],
+    entries: Entry[]|FileData[]): AnnotatedTask[] {
+  const result: AnnotatedTask[] = [];
+  for (const task of tasks) {
+    const {appId, taskType, actionId} = task.descriptor;
+    const parsedActionId = parseActionId(actionId);
+
+    // Skip internal Files app's handlers.
+    if (isFilesAppId(appId) &&
+        (parsedActionId === 'select' || parsedActionId === 'open')) {
+      continue;
+    }
+
+    // Tweak images, titles of internal tasks.
+    const annotateTask: AnnotatedTask = {...task, iconType: ''};
+    if (isFilesAppId(appId) && (taskType === 'app' || taskType === 'web')) {
+      if (parsedActionId === 'mount-archive') {
+        annotateTask.iconType = 'archive';
+        annotateTask.title = str('MOUNT_ARCHIVE');
+      } else if (parsedActionId === 'open-hosted-generic') {
+        if (entries.length > 1) {
+          annotateTask.iconType = 'generic';
+        } else {  // Use specific icon.
+          annotateTask.iconType = FileType.getIcon(entries[0]!);
+        }
+        annotateTask.title = str('TASK_OPEN');
+      } else if (parsedActionId === 'open-hosted-gdoc') {
+        annotateTask.iconType = 'gdoc';
+        annotateTask.title = str('TASK_OPEN_GDOC');
+      } else if (parsedActionId === 'open-hosted-gsheet') {
+        annotateTask.iconType = 'gsheet';
+        annotateTask.title = str('TASK_OPEN_GSHEET');
+      } else if (parsedActionId === 'open-hosted-gslides') {
+        annotateTask.iconType = 'gslides';
+        annotateTask.title = str('TASK_OPEN_GSLIDES');
+      } else if (parsedActionId === 'open-web-drive-office-word') {
+        annotateTask.iconType = 'gdoc';
+        annotateTask.title = str('TASK_OPEN_GDOC');
+      } else if (parsedActionId === 'open-web-drive-office-excel') {
+        annotateTask.iconType = 'gsheet';
+        annotateTask.title = str('TASK_OPEN_GSHEET');
+      } else if (parsedActionId === 'upload-office-to-drive') {
+        annotateTask.iconType = 'generic';
+        annotateTask.title = 'Upload to Drive';
+      } else if (parsedActionId === 'open-web-drive-office-powerpoint') {
+        annotateTask.iconType = 'gslides';
+        annotateTask.title = str('TASK_OPEN_GSLIDES');
+      } else if (parsedActionId === 'open-in-office') {
+        annotateTask.iconUrl =
+            toFilesAppURL('foreground/images/files/ui/ms365.svg').toString();
+        annotateTask.title = str('TASK_OPEN_MICROSOFT_365');
+      } else if (parsedActionId === 'install-linux-package') {
+        annotateTask.iconType = 'crostini';
+        annotateTask.title = str('TASK_INSTALL_LINUX_PACKAGE');
+      } else if (parsedActionId === 'import-crostini-image') {
+        annotateTask.iconType = 'tini';
+        annotateTask.title = str('TASK_IMPORT_CROSTINI_IMAGE');
+      } else if (parsedActionId === 'view-pdf') {
+        annotateTask.iconType = 'pdf';
+        annotateTask.title = str('TASK_VIEW');
+      } else if (parsedActionId === 'view-in-browser') {
+        annotateTask.iconType = 'generic';
+        annotateTask.title = str('TASK_VIEW');
+      }
+    }
+    if (!annotateTask.iconType && taskType === 'web-intent') {
+      annotateTask.iconType = 'generic';
+    }
+
+    result.push(annotateTask);
+  }
+
+  return result;
+}
+
+/**
+ * Gets the default task from tasks. In case there is no such task (i.e. all
+ * tasks are generic file handlers), then return null.
+ */
+export function getDefaultTask(
+    tasks: AnnotatedTask[],
+    policyDefaultHandlerStatus:
+        chrome.fileManagerPrivate.PolicyDefaultHandlerStatus|undefined,
+    taskHistory: TaskHistory): AnnotatedTask|null {
+  const INCORRECT_ASSIGNMENT =
+      chrome.fileManagerPrivate.PolicyDefaultHandlerStatus.INCORRECT_ASSIGNMENT;
+  const DEFAULT_HANDLER_ASSIGNED_BY_POLICY =
+      chrome.fileManagerPrivate.PolicyDefaultHandlerStatus
+          .DEFAULT_HANDLER_ASSIGNED_BY_POLICY;
+
+  // If policy assignment is incorrect, then no default should be set.
+  if (policyDefaultHandlerStatus &&
+      policyDefaultHandlerStatus === INCORRECT_ASSIGNMENT) {
+    return null;
+  }
+
+  // 1. Default app set for MIME or file extension by user, or built-in app.
+  for (const task of tasks) {
+    if (task.isDefault) {
+      return task;
+    }
+  }
+
+  // If policy assignment is marked as correct, then by this moment we
+  // should've already found the default.
+  console.assert(
+      !(policyDefaultHandlerStatus &&
+        policyDefaultHandlerStatus === DEFAULT_HANDLER_ASSIGNED_BY_POLICY));
+
+  const nonGenericTasks = tasks.filter(t => !t.isGenericFileHandler);
+  if (nonGenericTasks.length === 0) {
+    return null;
+  }
+
+  // 2. Most recently executed or sole non-generic task.
+  const latest = nonGenericTasks[0]!;
+  if (nonGenericTasks.length == 1 ||
+      taskHistory.getLastExecutedTime(latest.descriptor)) {
+    return latest;
+  }
+
+  return null;
+}
diff --git a/ui/file_manager/file_manager/foreground/js/holding_space_util.js b/ui/file_manager/file_manager/foreground/js/holding_space_util.js
index 70183778..8eaa63d 100644
--- a/ui/file_manager/file_manager/foreground/js/holding_space_util.js
+++ b/ui/file_manager/file_manager/foreground/js/holding_space_util.js
@@ -7,7 +7,7 @@
  */
 
 import {metrics} from '../../common/js/metrics.js';
-import {storage} from '../../common/js/storage_adapter.js';
+import {storage} from '../../common/js/storage.js';
 import {VolumeManagerCommon} from '../../common/js/volume_manager_types.js';
 
 export class HoldingSpaceUtil {
diff --git a/ui/file_manager/file_manager/foreground/js/quick_view_controller.js b/ui/file_manager/file_manager/foreground/js/quick_view_controller.js
index d11ce07..187f0b4 100644
--- a/ui/file_manager/file_manager/foreground/js/quick_view_controller.js
+++ b/ui/file_manager/file_manager/foreground/js/quick_view_controller.js
@@ -487,7 +487,7 @@
    * @private
    */
   async onMetadataLoaded_(entry, items, fileTasks, canDelete) {
-    const tasks = fileTasks.getTaskItems();
+    const tasks = fileTasks.getAnnotatedTasks();
 
     const params =
         await this.getQuickViewParameters_(entry, items, tasks, canDelete);
diff --git a/ui/file_manager/file_manager/foreground/js/task_controller.ts b/ui/file_manager/file_manager/foreground/js/task_controller.ts
index 30f0e3b..34e8633 100644
--- a/ui/file_manager/file_manager/foreground/js/task_controller.ts
+++ b/ui/file_manager/file_manager/foreground/js/task_controller.ts
@@ -22,7 +22,7 @@
 
 import {DirectoryModel} from './directory_model.js';
 import {FileSelection, FileSelectionHandler} from './file_selection.js';
-import {AnnotatedTask, FileTasks, TaskPickerType} from './file_tasks.js';
+import {AnnotatedTask, FileTasks, getDefaultTask, TaskPickerType} from './file_tasks.js';
 import {FileTransferController} from './file_transfer_controller.js';
 import {MetadataModel} from './metadata/metadata_model.js';
 import {MetadataUpdateController} from './metadata_update_controller.js';
@@ -201,7 +201,7 @@
    */
   private updateTasksDropdown_(fileTasks: FileTasks) {
     const combobutton = this.ui_.taskMenuButton;
-    const tasks = fileTasks.getTaskItems();
+    const tasks = fileTasks.getAnnotatedTasks();
 
     combobutton.hidden =
         tasks.length == 0 || fileTasks.entries.some(e => e.isDirectory);
@@ -268,7 +268,7 @@
    * @return Created array can be used to feed combobox, menus and so on.
    */
   createItems(fileTasks: FileTasks): DropdownItem[] {
-    const tasks = fileTasks.getTaskItems();
+    const tasks = fileTasks.getAnnotatedTasks();
     const items = [];
 
     // Create items.
@@ -364,13 +364,11 @@
       // Compare entries while ignoring changes inside directories.
       if (!util.isSameEntries(this.lastSelectedEntries_, selection.entries)) {
         // Update the context menu if selection changed.
-        this.updateContextMenuTaskItems_(
-            {tasks: [], policyDefaultHandlerStatus: undefined});
+        this.updateContextMenuTaskItems_([]);
       }
     } else {
       // Update context menu.
-      this.updateContextMenuTaskItems_(
-          {tasks: [], policyDefaultHandlerStatus: undefined});
+      this.updateContextMenuTaskItems_([]);
     }
     this.lastSelectedEntries_ = selection.entries;
   }
@@ -410,10 +408,9 @@
       const tasks = await this.getFileTasks();
       // Update the DOM.
       this.display_(tasks);
-      const openTaskItems = tasks.getTaskItems();
-      const policyDefaultHandlerStatus = tasks.getPolicyDefaultHandlerStatus();
+      const openTaskItems = tasks.getAnnotatedTasks();
       this.updateContextMenuTaskItems_(
-          {tasks: openTaskItems, policyDefaultHandlerStatus});
+          openTaskItems, tasks.getPolicyDefaultHandlerStatus());
       if (window.IN_TEST) {
         this.ui_.taskMenuButton.toggleAttribute('get-tasks-completed', true);
       }
@@ -479,9 +476,13 @@
    * @param openTasks List of OPEN tasks.
    */
   private updateContextMenuTaskItems_(
-      openTasks: chrome.fileManagerPrivate.ResultingTasks) {
-    const taskCount = openTasks.tasks.length;
-    const defaultTask = FileTasks.getDefaultTask(openTasks, this.taskHistory_);
+      tasks: AnnotatedTask[],
+      policyDefaultHandlerStatus?:
+          chrome.fileManagerPrivate.PolicyDefaultHandlerStatus) {
+    const taskCount = tasks.length;
+    const defaultTask =
+        getDefaultTask(tasks, policyDefaultHandlerStatus, this.taskHistory_);
+
     if (taskCount > 0) {
       if (defaultTask) {
         const menuItem = this.ui_.defaultTaskMenuItem;
@@ -506,8 +507,7 @@
           menuItem.setIconEndHidden(true);
         }
 
-        menuItem.toggleManagedIcon(
-            /*visible=*/ !!openTasks.policyDefaultHandlerStatus);
+        menuItem.toggleManagedIcon(/*visible=*/ !!policyDefaultHandlerStatus);
 
         menuItem.label = defaultTask.title;
         menuItem.descriptor = defaultTask.descriptor;
diff --git a/ui/file_manager/file_manager/foreground/js/task_history.js b/ui/file_manager/file_manager/foreground/js/task_history.js
index 08e6d7c..948f5ec 100644
--- a/ui/file_manager/file_manager/foreground/js/task_history.js
+++ b/ui/file_manager/file_manager/foreground/js/task_history.js
@@ -5,7 +5,7 @@
 import {dispatchSimpleEvent} from 'chrome://resources/ash/common/cr_deprecated.js';
 import {NativeEventTarget as EventTarget} from 'chrome://resources/ash/common/event_target.js';
 
-import {storage} from '../../common/js/storage_adapter.js';
+import {storage} from '../../common/js/storage.js';
 import {util} from '../../common/js/util.js';
 
 /**
diff --git a/ui/file_manager/file_manager/foreground/js/ui/dialogs.js b/ui/file_manager/file_manager/foreground/js/ui/dialogs.js
index 7a8638c..02f5f8e 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/dialogs.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/dialogs.js
@@ -112,12 +112,14 @@
     this.frame.appendChild(this.buttons);
 
     this.okButton = doc.createElement('button');
+    this.okButton.setAttribute('tabindex', 0);
     this.okButton.className = 'cr-dialog-ok';
     this.okButton.textContent = BaseDialog.OK_LABEL;
     this.okButton.addEventListener('click', this.onOkClick_.bind(this));
     this.buttons.appendChild(this.okButton);
 
     this.cancelButton = doc.createElement('button');
+    this.cancelButton.setAttribute('tabindex', 1);
     this.cancelButton.className = 'cr-dialog-cancel';
     this.cancelButton.textContent = BaseDialog.CANCEL_LABEL;
     this.cancelButton.addEventListener('click', this.onCancelClick_.bind(this));
diff --git a/ui/file_manager/file_manager/lib/actions_producer_unittest.ts b/ui/file_manager/file_manager/lib/actions_producer_unittest.ts
index ab2d4201..bddf91a7 100644
--- a/ui/file_manager/file_manager/lib/actions_producer_unittest.ts
+++ b/ui/file_manager/file_manager/lib/actions_producer_unittest.ts
@@ -1,11 +1,12 @@
 // 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 {assertEquals} from 'chrome://webui-test/chromeos/chai_assert.js';
+import {assertEquals, assertNotReached, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {waitUntil} from '../common/js/test_error_reporting.js';
 
-import {keepLatest} from './concurrency_models.js';
+import {ConcurrentActionInvalidatedError} from './actions_producer.js';
+import {keepLatest, keyedKeepFirst} from './concurrency_models.js';
 import {actionsProducerSuccess, TestAction} from './for_tests.js';
 
 /**
@@ -68,3 +69,62 @@
 
   done();
 }
+
+/**
+ * Tests the keyedKeepFirst() concurrency model. Checks that the first call
+ * with the same key, doesn't start a new AP, and calls with a new key cancels
+ * the previous APs and starts a new AP.
+ */
+export async function testKeyedKeepFirst(done: () => void) {
+  const action = keyedKeepFirst(actionsProducerSuccess, (payload: string) => {
+    return `key-${payload}`;
+  });
+
+  // `first` here is a generator,  an ActionsProducer, wrapped in the
+  // concurrency model `keyedKeepFirst`.
+  const first = action('file-key-1');
+
+  // Starts consuming the generated actions and can start another one in
+  // parallel.
+  const {value} = await first.next();
+  assertEquals(value!.type, 'step#0');
+  assertEquals(value!.payload, 'file-key-1');
+
+  // Make a second call with the same key, which finishes in the first iteration
+  // without generating any action.
+  const second = action('file-key-1');
+  const secondValue = await second.next();
+  assertEquals(secondValue!.value, undefined);
+  assertEquals(secondValue!.done, true);
+
+  // Start a new call with different key.
+  // Array to collect all the generated actions.
+  const results: TestAction[] = [];
+  const third = action('another-key-2');
+  const thirdValue = await third.next();
+  assertEquals(thirdValue!.value!.type, 'step#0');
+  assertEquals(thirdValue!.value!.payload, 'another-key-2');
+  results.push(thirdValue.value!);
+
+  // At this point `first` should be cancelled by the keyedKeepFirst().
+  // However, the exception only shows up in the next iteration of the AP.
+  try {
+    await first.next();
+    assertNotReached('`first` should have failed');
+  } catch (error) {
+    assertTrue(error instanceof ConcurrentActionInvalidatedError);
+    // Check that the generator is in `done=true` state.
+    const {value, done} = await first.next();
+    assertEquals(value, undefined);
+    assertEquals(done, true);
+  }
+
+  // Await for the third generator to be fully consumed.
+  await consumeGenerator(third, results);
+  // The third action generates 4 results: 1 at start, 2 from the args [2,
+  // 2] / and 1 for the final action.
+  await waitUntil(
+      () => results.filter(r => r.payload === 'another-key-2').length === 4);
+
+  done();
+}
diff --git a/ui/file_manager/file_manager/lib/concurrency_models.ts b/ui/file_manager/file_manager/lib/concurrency_models.ts
index 8705ff7..937dc126 100644
--- a/ui/file_manager/file_manager/lib/concurrency_models.ts
+++ b/ui/file_manager/file_manager/lib/concurrency_models.ts
@@ -46,3 +46,54 @@
   }
   return wrap;
 }
+
+/**
+ * While the key is the same it doesn't start a new Actions Producer (AP).
+ *
+ * If the key changes, then it cancels the previous one and starts a new one.
+ *
+ * If there is no other running AP, then it just starts a new one.
+ */
+export function keyedKeepFirst<T extends BaseAction, Args extends any[]>(
+    actionsProducer: ActionsProducer<T, Args>,
+    generateKey: (...args: Args) => string): ActionsProducer<T, Args> {
+  // Scope #1: Initial setup.
+  // Key for the current AP.
+  let inFlightKey: string|null = null;
+
+  async function* wrap(...args: Args): ActionsProducerGen<T> {
+    // Scope #2: Per-call to the ActionsProducer.
+    const key = generateKey(...args);
+    // One already exists, just leave that finish.
+    if (inFlightKey && inFlightKey === key) {
+      return;
+    }
+
+    // This will force the previously running AP to cancel when yielding.
+    inFlightKey = key;
+
+    const generator = actionsProducer(...args);
+    try {
+      for await (const producedAction of generator) {
+        // Scope #3: The generated action.
+        if (inFlightKey && inFlightKey !== key) {
+          const error = new ConcurrentActionInvalidatedError(
+              `ActionsProducer invalidated running key: ${key} current: ${
+                  inFlightKey}:`);
+          generator.throw(error);
+          throw error;
+        }
+        yield producedAction;
+      }
+    } catch (error) {
+      if (error instanceof ConcurrentActionInvalidatedError) {
+        // This error we don't want to clear the `inFlightKey`.
+        throw error;
+      }
+    }
+
+    // Clear the key if it wasn't invalidated.
+    inFlightKey = null;
+  }
+  return wrap;
+}
diff --git a/ui/file_manager/file_manager/state/README.md b/ui/file_manager/file_manager/state/README.md
index 38e82f13..7500633 100644
--- a/ui/file_manager/file_manager/state/README.md
+++ b/ui/file_manager/file_manager/state/README.md
@@ -428,7 +428,7 @@
 `./actions_producers/ui_settings.ts`.
 
 ```typescript
-import {storage} from '../../common/js/storage_adapter.js';
+import {storage} from '../../common/js/storage.js';
 import {ColumnName, PropStatus, SortOrder, ViewType} from '../../externs/ts/state.js';
 import {ActionsProducerGen} from '../../lib/actions_producer.js';
 import {keepLatest, serialize} from '../../lib/concurrency_models.js';
diff --git a/ui/file_manager/file_manager/state/reducers/all_entries.ts b/ui/file_manager/file_manager/state/reducers/all_entries.ts
index 19b4d034..8af8b87 100644
--- a/ui/file_manager/file_manager/state/reducers/all_entries.ts
+++ b/ui/file_manager/file_manager/state/reducers/all_entries.ts
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {FileType} from '../../common/js/file_type.js';
 import {util} from '../../common/js/util.js';
 import {VolumeManagerCommon} from '../../common/js/volume_manager_types.js';
 import {FilesAppEntry} from '../../externs/files_app_entry_interfaces.js';
@@ -87,6 +88,8 @@
   allEntries[key] = {
     ...entryData,
     entry,
+    iconName:
+        FileType.getIcon(entry as Entry, undefined, locationInfo?.rootType),
     type: getEntryType(entry),
     isDirectory: entry.isDirectory,
     label,
diff --git a/ui/file_manager/file_manager/state/reducers/all_entries_unittest.ts b/ui/file_manager/file_manager/state/reducers/all_entries_unittest.ts
index 917a54d..e4a42b49 100644
--- a/ui/file_manager/file_manager/state/reducers/all_entries_unittest.ts
+++ b/ui/file_manager/file_manager/state/reducers/all_entries_unittest.ts
@@ -5,13 +5,17 @@
 import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chromeos/chai_assert.js';
 
 import {MockVolumeManager} from '../../background/js/mock_volume_manager.js';
+import {DialogType} from '../../common/js/dialog_type.js';
 import {FakeEntryImpl, VolumeEntry} from '../../common/js/files_app_entry_types.js';
 import {MockFileSystem} from '../../common/js/mock_entry.js';
 import {waitUntil} from '../../common/js/test_error_reporting.js';
 import {VolumeManagerCommon} from '../../common/js/volume_manager_types.js';
+import {Crostini} from '../../externs/background/crostini.js';
 import {EntryType, FileData} from '../../externs/ts/state.js';
+import {FileSelectionHandler} from '../../foreground/js/file_selection.js';
 import {MetadataModel} from '../../foreground/js/metadata/metadata_model.js';
 import {MockMetadataModel} from '../../foreground/js/metadata/mock_metadata.js';
+import {TaskController} from '../../foreground/js/task_controller.js';
 import {ActionType} from '../actions.js';
 import {ClearStaleCachedEntriesAction} from '../actions/all_entries.js';
 import {cd, changeSelection} from '../for_tests.js';
@@ -30,6 +34,10 @@
   window.fileManager = {
     volumeManager: volumeManager,
     metadataModel: new MockMetadataModel({}) as unknown as MetadataModel,
+    crostini: {} as unknown as Crostini,
+    selectionHandler: {} as unknown as FileSelectionHandler,
+    taskController: {} as unknown as TaskController,
+    dialogType: DialogType.FULL_PAGE,
   };
 
   store.init(getEmptyState());
diff --git a/ui/file_manager/file_manager/state/reducers/current_directory.ts b/ui/file_manager/file_manager/state/reducers/current_directory.ts
index b748417..940bc88 100644
--- a/ui/file_manager/file_manager/state/reducers/current_directory.ts
+++ b/ui/file_manager/file_manager/state/reducers/current_directory.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 {CurrentDirectory, PropStatus, Selection, State} from '../../externs/ts/state.js';
+import {CurrentDirectory, FileKey, PropStatus, Selection, State} from '../../externs/ts/state.js';
 import {PathComponent} from '../../foreground/js/path_component.js';
 import {ChangeDirectoryAction, ChangeSelectionAction} from '../actions/current_directory.js';
 
@@ -31,9 +31,9 @@
       offlineCachedCount: undefined,
       fileTasks: {
         tasks: [],
-        defaultHandlerPolicy: undefined,
+        policyDefaultHandlerStatus: undefined,
+        defaultTask: undefined,
         status: PropStatus.SUCCESS,
-        keys: [],
       },
     };
   }
@@ -77,15 +77,9 @@
   };
 }
 
-/**
- * Updates the `currentDirectory.selection` state.
- */
-export function updateSelection(
-    currentState: State, action: ChangeSelectionAction): State {
-  // TODO: When we have all the keys from current directory, we should validate
-  // that selectedKeys belongs to current directory.
-  const selection: Selection = {
-    keys: action.payload.selectedKeys,
+function getEmptySelection(keys: FileKey[] = []): Selection {
+  return {
+    keys,
     dirCount: 0,
     fileCount: 0,
     // hostedCount might be updated to undefined in the for loop below.
@@ -94,11 +88,21 @@
     offlineCachedCount: 0,
     fileTasks: {
       tasks: [],
-      defaultHandlerPolicy: undefined,
+      defaultTask: undefined,
+      policyDefaultHandlerStatus: undefined,
       status: PropStatus.STARTED,
-      keys: action.payload.selectedKeys,
     },
   };
+}
+
+/**
+ * Updates the `currentDirectory.selection` state.
+ */
+export function updateSelection(
+    currentState: State, action: ChangeSelectionAction): State {
+  // TODO: When we have all the keys from current directory, we should validate
+  // that selectedKeys belongs to current directory.
+  const selection = getEmptySelection(action.payload.selectedKeys);
 
   for (const key of action.payload.selectedKeys) {
     const fileData = currentState.allEntries[key];
diff --git a/ui/file_manager/file_manager/state/reducers/current_directory_unittest.ts b/ui/file_manager/file_manager/state/reducers/current_directory_unittest.ts
index 8a0790a..dda6830 100644
--- a/ui/file_manager/file_manager/state/reducers/current_directory_unittest.ts
+++ b/ui/file_manager/file_manager/state/reducers/current_directory_unittest.ts
@@ -5,11 +5,15 @@
 import {assertTrue} from 'chrome://webui-test/chai_assert.js';
 
 import {MockVolumeManager} from '../../background/js/mock_volume_manager.js';
+import {DialogType} from '../../common/js/dialog_type.js';
 import {MockFileSystem} from '../../common/js/mock_entry.js';
 import {VolumeManagerCommon} from '../../common/js/volume_manager_types.js';
+import {Crostini} from '../../externs/background/crostini.js';
 import {CurrentDirectory, PropStatus} from '../../externs/ts/state.js';
+import {FileSelectionHandler} from '../../foreground/js/file_selection.js';
 import {MetadataModel} from '../../foreground/js/metadata/metadata_model.js';
 import {MockMetadataModel} from '../../foreground/js/metadata/mock_metadata.js';
+import {TaskController} from '../../foreground/js/task_controller.js';
 import {changeDirectory, updateSelection} from '../actions/current_directory.js';
 import {assertStateEquals} from '../for_tests.js';
 import {getEmptyState, getStore, Store} from '../store.js';
@@ -22,6 +26,10 @@
   window.fileManager = {
     volumeManager: volumeManager,
     metadataModel: new MockMetadataModel({}) as unknown as MetadataModel,
+    crostini: {} as unknown as Crostini,
+    selectionHandler: {} as unknown as FileSelectionHandler,
+    taskController: {} as unknown as TaskController,
+    dialogType: DialogType.FULL_PAGE,
   };
 
   fileSystem = volumeManager.getCurrentProfileVolumeInfo(
@@ -72,10 +80,10 @@
       hostedCount: undefined,
       offlineCachedCount: undefined,
       fileTasks: {
-        defaultHandlerPolicy: undefined,
+        policyDefaultHandlerStatus: undefined,
+        defaultTask: undefined,
         tasks: [],
         status: PropStatus.SUCCESS,
-        keys: [],
       },
     },
   };
@@ -118,10 +126,10 @@
       hostedCount: undefined,
       offlineCachedCount: undefined,
       fileTasks: {
-        defaultHandlerPolicy: undefined,
+        policyDefaultHandlerStatus: undefined,
+        defaultTask: undefined,
         tasks: [],
         status: PropStatus.SUCCESS,
-        keys: [],
       },
     },
   };
@@ -153,10 +161,10 @@
       hostedCount: undefined,
       offlineCachedCount: undefined,
       fileTasks: {
-        defaultHandlerPolicy: undefined,
+        policyDefaultHandlerStatus: undefined,
+        defaultTask: undefined,
         tasks: [],
         status: PropStatus.STARTED,
-        keys: [subDir.toURL()],
       },
     },
   };
@@ -167,7 +175,6 @@
   want.selection.keys = [file.toURL()];
   want.selection.dirCount = 0;
   want.selection.fileCount = 1;
-  want.selection.fileTasks.keys = [file.toURL()];
   assertStateEquals(want, store.getState().currentDirectory);
 
   // Append to the selection.
@@ -175,6 +182,5 @@
   want.selection.keys = [file.toURL(), subDir.toURL()];
   want.selection.dirCount = 1;
   want.selection.fileCount = 1;
-  want.selection.fileTasks.keys = [file.toURL(), subDir.toURL()];
   assertStateEquals(want, store.getState().currentDirectory);
 }
diff --git a/ui/file_manager/file_names.gni b/ui/file_manager/file_names.gni
index 38ffd53..861574d 100644
--- a/ui/file_manager/file_names.gni
+++ b/ui/file_manager/file_names.gni
@@ -62,7 +62,7 @@
   "file_manager/common/js/notifications_browser_proxy.js",
   "file_manager/common/js/progress_center_common.js",
   "file_manager/common/js/recent_date_bucket.js",
-  "file_manager/common/js/storage_adapter.js",
+  "file_manager/common/js/storage.js",
   "file_manager/common/js/test_error_reporting.js",
   "file_manager/common/js/ui.js",
   "file_manager/common/js/unittest_util.js",
@@ -413,7 +413,7 @@
   "file_manager/common/js/lru_cache_unittest.js",
   "file_manager/common/js/files_app_entry_types_unittest.js",
   "file_manager/common/js/recent_date_bucket_unittest.js",
-  "file_manager/common/js/storage_adapter_unittest.js",
+  "file_manager/common/js/storage_unittest.js",
   "file_manager/common/js/volume_manager_types_unittest.js",
 
   # Background:
diff --git a/ui/gfx/linux/gbm_wrapper.cc b/ui/gfx/linux/gbm_wrapper.cc
index 089d4668..973a93ac 100644
--- a/ui/gfx/linux/gbm_wrapper.cc
+++ b/ui/gfx/linux/gbm_wrapper.cc
@@ -127,7 +127,7 @@
 
   ~Buffer() override {
     DCHECK(!mmap_data_);
-    gbm_bo_destroy(bo_);
+    gbm_bo_destroy(bo_.ExtractAsDangling());
   }
 
   uint32_t GetFormat() const override { return format_; }
@@ -219,7 +219,7 @@
     buffer->mmap_data_ = nullptr;
   }
 
-  const raw_ptr<gbm_bo, DanglingUntriaged> bo_;
+  raw_ptr<gbm_bo> bo_;
   void* mmap_data_ = nullptr;
 
   const uint32_t format_;
diff --git a/ui/gl/dc_layer_tree.cc b/ui/gl/dc_layer_tree.cc
index e030153..eaf93f8 100644
--- a/ui/gl/dc_layer_tree.cc
+++ b/ui/gl/dc_layer_tree.cc
@@ -298,11 +298,13 @@
                "num_pending_overlays", pending_overlays_.size());
   DCHECK(!needs_rebuild_visual_tree_ || ink_renderer_->HasBeenInitialized());
 
-  if (root_surface->swap_chain() != root_swap_chain_ ||
-      root_surface->dcomp_surface() != root_dcomp_surface_) {
-    root_swap_chain_ = root_surface->swap_chain();
-    root_dcomp_surface_ = root_surface->dcomp_surface();
-    needs_rebuild_visual_tree_ = true;
+  if (root_surface) {
+    if (root_surface->swap_chain() != root_swap_chain_ ||
+        root_surface->dcomp_surface() != root_dcomp_surface_) {
+      root_swap_chain_ = root_surface->swap_chain();
+      root_dcomp_surface_ = root_surface->dcomp_surface();
+      needs_rebuild_visual_tree_ = true;
+    }
   }
 
   std::vector<std::unique_ptr<ui::DCRendererLayerParams>> overlays;
@@ -316,14 +318,18 @@
     needs_rebuild_visual_tree_ = true;
   }
 
-  // Add a placeholder overlay for the root surface, at a z-order of 0.
-  auto root_params = std::make_unique<ui::DCRendererLayerParams>();
-  root_params->z_order = 0;
-  root_params->dcomp_visual_content =
-      root_swap_chain_ ? static_cast<IUnknown*>(root_swap_chain_.Get())
-                       : static_cast<IUnknown*>(root_dcomp_surface_.Get());
-  root_params->dcomp_surface_serial = root_surface->dcomp_surface_serial();
-  overlays.emplace_back(std::move(root_params));
+  // DCompSurfaceless also uses DCLayerTree and lets its caller schedule an
+  // overlay for the root surface, instead of owning its own.
+  if (root_surface) {
+    // Add a placeholder overlay for the root surface, at a z-order of 0.
+    auto root_params = std::make_unique<ui::DCRendererLayerParams>();
+    root_params->z_order = 0;
+    root_params->dcomp_visual_content =
+        root_swap_chain_ ? static_cast<IUnknown*>(root_swap_chain_.Get())
+                         : static_cast<IUnknown*>(root_dcomp_surface_.Get());
+    root_params->dcomp_surface_serial = root_surface->dcomp_surface_serial();
+    overlays.emplace_back(std::move(root_params));
+  }
 
   // Sort layers by z-order.
   std::sort(overlays.begin(), overlays.end(),
diff --git a/ui/gl/dcomp_presenter.cc b/ui/gl/dcomp_presenter.cc
index 01171fc..0c28a331 100644
--- a/ui/gl/dcomp_presenter.cc
+++ b/ui/gl/dcomp_presenter.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 The Chromium Authors
+// 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.
 
@@ -18,6 +18,7 @@
 #include "ui/gl/direct_composition_child_surface_win.h"
 #include "ui/gl/direct_composition_support.h"
 #include "ui/gl/gl_angle_util_win.h"
+#include "ui/gl/gl_surface_egl.h"
 #include "ui/gl/vsync_thread_win.h"
 
 namespace gl {
@@ -40,19 +41,17 @@
 DCompPresenter::PendingFrame& DCompPresenter::PendingFrame::operator=(
     PendingFrame&& other) = default;
 
-DCompPresenter::DCompPresenter(GLDisplayEGL* display,
-                               HWND parent_window,
-                               VSyncCallback vsync_callback,
-                               const Settings& settings)
-    : GLSurfaceEGL(display),
+DCompPresenter::DCompPresenter(
+    GLDisplayEGL* display,
+    HWND parent_window,
+    VSyncCallback vsync_callback,
+    const DirectCompositionSurfaceWin::Settings& settings)
+    : SurfacelessEGL(display, gfx::Size(1, 1)),
       child_window_(parent_window),
       vsync_callback_(std::move(vsync_callback)),
       vsync_thread_(VSyncThreadWin::GetInstance()),
       task_runner_(base::SingleThreadTaskRunner::GetCurrentDefault()),
       max_pending_frames_(settings.max_pending_frames),
-      root_surface_(new DirectCompositionChildSurfaceWin(
-          display,
-          settings.use_angle_texture_offset)),
       layer_tree_(std::make_unique<DCLayerTree>(
           settings.disable_nv12_dynamic_textures,
           settings.disable_vp_scaling,
@@ -78,9 +77,6 @@
   if (!layer_tree_->Initialize(window_))
     return false;
 
-  if (!root_surface_->Initialize(GLSurfaceFormat()))
-    return false;
-
   return true;
 }
 
@@ -92,7 +88,6 @@
   if (vsync_thread_started_)
     vsync_thread_->RemoveObserver(this);
 
-  root_surface_->Destroy();
   // Freeing DComp resources such as visuals and surfaces causes the
   // device to become 'dirty'. We must commit the changes to the device
   // in order for the objects to actually be destroyed.
@@ -104,45 +99,37 @@
     dcomp_device->Commit();
 }
 
-gfx::Size DCompPresenter::GetSize() {
-  return root_surface_->GetSize();
-}
-
 bool DCompPresenter::IsOffscreen() {
   return false;
 }
 
-void* DCompPresenter::GetHandle() {
-  return root_surface_->GetHandle();
-}
-
 bool DCompPresenter::Resize(const gfx::Size& size,
                             float scale_factor,
                             const gfx::ColorSpace& color_space,
                             bool has_alpha) {
+  if (!SurfacelessEGL::Resize(size, scale_factor, color_space, has_alpha)) {
+    return false;
+  }
+
   // Force a resize and redraw (but not a move, activate, etc.).
   if (!SetWindowPos(window_, nullptr, 0, 0, size.width(), size.height(),
                     SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOCOPYBITS |
                         SWP_NOOWNERZORDER | SWP_NOZORDER)) {
     return false;
   }
-  return root_surface_->Resize(size, scale_factor, color_space, has_alpha);
+  return true;
 }
 
 gfx::SwapResult DCompPresenter::SwapBuffers(PresentationCallback callback,
                                             FrameData data) {
   TRACE_EVENT0("gpu", "DCompPresenter::SwapBuffers");
 
-  gfx::Rect swap_rect;
-  bool success = root_surface_->EndDraw(&swap_rect);
-  // Do not create query for empty damage so that 3D engine is not used when
-  // only presenting video in overlay. Callback will be dequeued on next vsync.
+  // Callback will be dequeued on next vsync.
   EnqueuePendingFrame(std::move(callback),
-                      /*create_query=*/!swap_rect.IsEmpty());
-  if (!success)
-    return gfx::SwapResult::SWAP_FAILED;
+                      /*create_query=*/create_query_this_frame_);
+  create_query_this_frame_ = false;
 
-  if (!layer_tree_->CommitAndClearPendingOverlays(root_surface_.get()))
+  if (!layer_tree_->CommitAndClearPendingOverlays(nullptr))
     return gfx::SwapResult::SWAP_FAILED;
 
   return gfx::SwapResult::SWAP_ACK;
@@ -163,10 +150,6 @@
   return vsync_thread_->vsync_provider();
 }
 
-void DCompPresenter::SetVSyncEnabled(bool enabled) {
-  root_surface_->SetVSyncEnabled(enabled);
-}
-
 void DCompPresenter::OnVSync(base::TimeTicks vsync_time,
                              base::TimeDelta interval) {
   // Main thread will run vsync callback in low latency presentation mode.
@@ -195,10 +178,6 @@
   layer_tree_->SetFrameRate(frame_rate);
 }
 
-bool DCompPresenter::SetEnableDCLayers(bool enable) {
-  return root_surface_->SetEnableDCLayers(enable);
-}
-
 gfx::SurfaceOrigin DCompPresenter::GetOrigin() const {
   return gfx::SurfaceOrigin::kTopLeft;
 }
@@ -207,10 +186,6 @@
   return true;
 }
 
-bool DCompPresenter::OnMakeCurrent(GLContext* context) {
-  return root_surface_->OnMakeCurrent(context);
-}
-
 bool DCompPresenter::SupportsDCLayers() const {
   return true;
 }
@@ -222,11 +197,10 @@
 }
 
 bool DCompPresenter::SetDrawRectangle(const gfx::Rect& rect) {
-  return root_surface_->SetDrawRectangle(rect);
-}
-
-gfx::Vector2d DCompPresenter::GetDrawOffset() const {
-  return root_surface_->GetDrawOffset();
+  // Do not create query for empty damage so that 3D engine is not used when
+  // only presenting video in overlay.
+  create_query_this_frame_ = !rect.IsEmpty();
+  return true;
 }
 
 bool DCompPresenter::SupportsGpuVSync() const {
@@ -259,22 +233,12 @@
 
 scoped_refptr<base::TaskRunner>
 DCompPresenter::GetWindowTaskRunnerForTesting() {
-  return child_window_.GetTaskRunnerForTesting();
+  return child_window_.GetTaskRunnerForTesting();  // IN-TEST
 }
 
 Microsoft::WRL::ComPtr<IDXGISwapChain1>
 DCompPresenter::GetLayerSwapChainForTesting(size_t index) const {
-  return layer_tree_->GetLayerSwapChainForTesting(index);
-}
-
-Microsoft::WRL::ComPtr<IDXGISwapChain1>
-DCompPresenter::GetBackbufferSwapChainForTesting() const {
-  return root_surface_->swap_chain();
-}
-
-scoped_refptr<DirectCompositionChildSurfaceWin>
-DCompPresenter::GetRootSurfaceForTesting() const {
-  return root_surface_;
+  return layer_tree_->GetLayerSwapChainForTesting(index);  // IN-TEST
 }
 
 void DCompPresenter::GetSwapChainVisualInfoForTesting(
diff --git a/ui/gl/dcomp_presenter.h b/ui/gl/dcomp_presenter.h
index d8ac81a..2f22c308 100644
--- a/ui/gl/dcomp_presenter.h
+++ b/ui/gl/dcomp_presenter.h
@@ -1,13 +1,13 @@
-// Copyright 2017 The Chromium Authors
+// 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 UI_GL_DCOMP_PRESENTER_H_
 #define UI_GL_DCOMP_PRESENTER_H_
 
-#include <windows.h>
 #include <d3d11.h>
 #include <dcomp.h>
+#include <windows.h>
 #include <wrl/client.h>
 
 #include "base/containers/circular_deque.h"
@@ -18,6 +18,7 @@
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "ui/gfx/geometry/transform.h"
 #include "ui/gl/child_window_win.h"
+#include "ui/gl/direct_composition_surface_win.h"
 #include "ui/gl/gl_export.h"
 #include "ui/gl/gl_surface_egl.h"
 #include "ui/gl/vsync_observer.h"
@@ -36,27 +37,19 @@
 namespace gl {
 class VSyncThreadWin;
 class DCLayerTree;
-class DirectCompositionChildSurfaceWin;
 
-class GL_EXPORT DCompPresenter : public GLSurfaceEGL, public VSyncObserver {
+// This class owns the DComp layer tree and its presentation. It does not own
+// the root surface.
+class GL_EXPORT DCompPresenter : public SurfacelessEGL, public VSyncObserver {
  public:
   using VSyncCallback =
       base::RepeatingCallback<void(base::TimeTicks, base::TimeDelta)>;
   using OverlayHDRInfoUpdateCallback = base::RepeatingClosure;
 
-  struct Settings {
-    bool disable_nv12_dynamic_textures = false;
-    bool disable_vp_scaling = false;
-    bool disable_vp_super_resolution = false;
-    size_t max_pending_frames = 2;
-    bool use_angle_texture_offset = false;
-    bool no_downscaled_overlay_promotion = false;
-  };
-
   DCompPresenter(GLDisplayEGL* display,
                  HWND parent_window,
                  VSyncCallback vsync_callback,
-                 const DCompPresenter::Settings& settings);
+                 const DirectCompositionSurfaceWin::Settings& settings);
 
   DCompPresenter(const DCompPresenter&) = delete;
   DCompPresenter& operator=(const DCompPresenter&) = delete;
@@ -64,9 +57,7 @@
   // GLSurfaceEGL implementation.
   bool Initialize(GLSurfaceFormat format) override;
   void Destroy() override;
-  gfx::Size GetSize() override;
   bool IsOffscreen() override;
-  void* GetHandle() override;
   bool Resize(const gfx::Size& size,
               float scale_factor,
               const gfx::ColorSpace& color_space,
@@ -80,15 +71,11 @@
                                 PresentationCallback callback,
                                 FrameData data) override;
   gfx::VSyncProvider* GetVSyncProvider() override;
-  void SetVSyncEnabled(bool enabled) override;
-  bool SetEnableDCLayers(bool enable) override;
   gfx::SurfaceOrigin GetOrigin() const override;
   bool SupportsPostSubBuffer() override;
-  bool OnMakeCurrent(GLContext* context) override;
   bool SupportsDCLayers() const override;
   bool SupportsProtectedVideo() const override;
   bool SetDrawRectangle(const gfx::Rect& rect) override;
-  gfx::Vector2d GetDrawOffset() const override;
   bool SupportsGpuVSync() const override;
   void SetGpuVSyncEnabled(bool enabled) override;
   // This schedules an overlay plane to be displayed on the next SwapBuffers
@@ -117,12 +104,6 @@
   Microsoft::WRL::ComPtr<IDXGISwapChain1> GetLayerSwapChainForTesting(
       size_t index) const;
 
-  Microsoft::WRL::ComPtr<IDXGISwapChain1> GetBackbufferSwapChainForTesting()
-      const;
-
-  scoped_refptr<DirectCompositionChildSurfaceWin> GetRootSurfaceForTesting()
-      const;
-
   void GetSwapChainVisualInfoForTesting(size_t index,
                                         gfx::Transform* transform,
                                         gfx::Point* offset,
@@ -179,9 +160,13 @@
   base::TimeTicks last_vsync_time_;
   base::TimeDelta last_vsync_interval_;
 
-  scoped_refptr<DirectCompositionChildSurfaceWin> root_surface_;
   std::unique_ptr<DCLayerTree> layer_tree_;
 
+  // Set in |SetDrawRectangle| and cleared in |SwapBuffers|. Used to determine
+  // if a D3D query should be created for this frame, due to a non-empty draw
+  // rectangle.
+  bool create_query_this_frame_ = false;
+
   base::WeakPtrFactory<DCompPresenter> weak_factory_{this};
 };
 
diff --git a/ui/gl/dcomp_presenter_unittest.cc b/ui/gl/dcomp_presenter_unittest.cc
index 54f3cdf..75d2c23 100644
--- a/ui/gl/dcomp_presenter_unittest.cc
+++ b/ui/gl/dcomp_presenter_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 The Chromium Authors
+// 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.
 
@@ -24,6 +24,7 @@
 #include "ui/gl/dc_renderer_layer_params.h"
 #include "ui/gl/direct_composition_child_surface_win.h"
 #include "ui/gl/direct_composition_support.h"
+#include "ui/gl/direct_composition_surface_win.h"
 #include "ui/gl/gl_angle_util_win.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_context.h"
@@ -157,8 +158,6 @@
     }
     surface_ = CreateDCompPresenter();
     context_ = CreateGLContext(surface_);
-    if (surface_)
-      surface_->SetEnableDCLayers(true);
     SetDirectCompositionScaledOverlaysSupportedForTesting(false);
     SetDirectCompositionOverlayFormatUsedForTesting(DXGI_FORMAT_NV12);
   }
@@ -171,7 +170,7 @@
   }
 
   scoped_refptr<DCompPresenter> CreateDCompPresenter() {
-    DCompPresenter::Settings settings;
+    DirectCompositionSurfaceWin::Settings settings;
     scoped_refptr<DCompPresenter> surface =
         base::MakeRefCounted<DCompPresenter>(
             gl::GLSurfaceEGL::GetGLDisplayEGL(), parent_window_,
@@ -203,132 +202,6 @@
   raw_ptr<GLDisplay> display_ = nullptr;
 };
 
-TEST_F(DCompPresenterTest, TestMakeCurrent) {
-  if (!surface_)
-    return;
-  EXPECT_TRUE(
-      surface_->Resize(gfx::Size(100, 100), 1.0, gfx::ColorSpace(), true));
-
-  // First SetDrawRectangle must be full size of surface.
-  EXPECT_FALSE(surface_->SetDrawRectangle(gfx::Rect(0, 0, 50, 50)));
-  EXPECT_TRUE(surface_->SetDrawRectangle(gfx::Rect(0, 0, 100, 100)));
-
-  // SetDrawRectangle can't be called again until swap.
-  EXPECT_FALSE(surface_->SetDrawRectangle(gfx::Rect(0, 0, 100, 100)));
-
-  EXPECT_EQ(gfx::SwapResult::SWAP_ACK,
-            surface_->SwapBuffers(base::DoNothing(), FrameData()));
-
-  EXPECT_TRUE(context_->IsCurrent(surface_.get()));
-
-  // SetDrawRectangle must be contained within surface.
-  EXPECT_FALSE(surface_->SetDrawRectangle(gfx::Rect(0, 0, 101, 101)));
-  EXPECT_TRUE(surface_->SetDrawRectangle(gfx::Rect(0, 0, 100, 100)));
-  EXPECT_TRUE(context_->IsCurrent(surface_.get()));
-
-  EXPECT_TRUE(
-      surface_->Resize(gfx::Size(50, 50), 1.0, gfx::ColorSpace(), true));
-  EXPECT_TRUE(context_->IsCurrent(surface_.get()));
-  EXPECT_TRUE(surface_->SetDrawRectangle(gfx::Rect(0, 0, 50, 50)));
-  EXPECT_TRUE(context_->IsCurrent(surface_.get()));
-
-  scoped_refptr<DCompPresenter> surface2 = CreateDCompPresenter();
-  scoped_refptr<GLContext> context2 = CreateGLContext(surface2.get());
-
-  surface2->SetEnableDCLayers(true);
-  EXPECT_TRUE(
-      surface2->Resize(gfx::Size(100, 100), 1.0, gfx::ColorSpace(), true));
-  // The previous IDCompositionSurface should be suspended when another
-  // surface is being drawn to.
-  EXPECT_TRUE(surface2->SetDrawRectangle(gfx::Rect(0, 0, 100, 100)));
-  EXPECT_TRUE(context2->IsCurrent(surface2.get()));
-
-  // It should be possible to switch back to the previous surface and
-  // unsuspend it.
-  EXPECT_TRUE(context_->MakeCurrent(surface_.get()));
-  context2 = nullptr;
-  DestroySurface(std::move(surface2));
-}
-
-// Tests that switching using EnableDCLayers works.
-TEST_F(DCompPresenterTest, DXGIDCLayerSwitch) {
-  if (!surface_)
-    return;
-  surface_->SetEnableDCLayers(false);
-  EXPECT_TRUE(
-      surface_->Resize(gfx::Size(100, 100), 1.0, gfx::ColorSpace(), true));
-  EXPECT_FALSE(surface_->GetBackbufferSwapChainForTesting());
-
-  // First SetDrawRectangle must be full size of surface for DXGI swapchain.
-  EXPECT_FALSE(surface_->SetDrawRectangle(gfx::Rect(0, 0, 50, 50)));
-  EXPECT_TRUE(surface_->SetDrawRectangle(gfx::Rect(0, 0, 100, 100)));
-  EXPECT_TRUE(surface_->GetBackbufferSwapChainForTesting());
-
-  // SetDrawRectangle and SetEnableDCLayers can't be called again until swap.
-  EXPECT_FALSE(surface_->SetDrawRectangle(gfx::Rect(0, 0, 100, 100)));
-
-  EXPECT_EQ(gfx::SwapResult::SWAP_ACK,
-            surface_->SwapBuffers(base::DoNothing(), FrameData()));
-  EXPECT_TRUE(context_->IsCurrent(surface_.get()));
-
-  surface_->SetEnableDCLayers(true);
-
-  // Surface switched to use IDCompositionSurface, so must draw to entire
-  // surface.
-  EXPECT_FALSE(surface_->SetDrawRectangle(gfx::Rect(0, 0, 50, 50)));
-  EXPECT_TRUE(surface_->SetDrawRectangle(gfx::Rect(0, 0, 100, 100)));
-  EXPECT_FALSE(surface_->GetBackbufferSwapChainForTesting());
-
-  EXPECT_EQ(gfx::SwapResult::SWAP_ACK,
-            surface_->SwapBuffers(base::DoNothing(), FrameData()));
-  EXPECT_TRUE(context_->IsCurrent(surface_.get()));
-
-  surface_->SetEnableDCLayers(false);
-
-  // Surface switched to use IDXGISwapChain, so must draw to entire surface.
-  EXPECT_FALSE(surface_->SetDrawRectangle(gfx::Rect(0, 0, 50, 50)));
-  EXPECT_TRUE(surface_->SetDrawRectangle(gfx::Rect(0, 0, 100, 100)));
-  EXPECT_TRUE(surface_->GetBackbufferSwapChainForTesting());
-
-  EXPECT_EQ(gfx::SwapResult::SWAP_ACK,
-            surface_->SwapBuffers(base::DoNothing(), FrameData()));
-  EXPECT_TRUE(context_->IsCurrent(surface_.get()));
-}
-
-// Ensure that the swapchain's alpha is correct.
-TEST_F(DCompPresenterTest, SwitchAlpha) {
-  if (!surface_)
-    return;
-  surface_->SetEnableDCLayers(false);
-  EXPECT_TRUE(
-      surface_->Resize(gfx::Size(100, 100), 1.0, gfx::ColorSpace(), true));
-  EXPECT_FALSE(surface_->GetBackbufferSwapChainForTesting());
-
-  EXPECT_TRUE(surface_->SetDrawRectangle(gfx::Rect(0, 0, 100, 100)));
-  Microsoft::WRL::ComPtr<IDXGISwapChain1> swap_chain =
-      surface_->GetBackbufferSwapChainForTesting();
-  ASSERT_TRUE(swap_chain);
-  DXGI_SWAP_CHAIN_DESC1 desc;
-  swap_chain->GetDesc1(&desc);
-  EXPECT_EQ(DXGI_ALPHA_MODE_PREMULTIPLIED, desc.AlphaMode);
-
-  // Resize to the same parameters should have no effect.
-  EXPECT_TRUE(
-      surface_->Resize(gfx::Size(100, 100), 1.0, gfx::ColorSpace(), true));
-  EXPECT_TRUE(surface_->GetBackbufferSwapChainForTesting());
-
-  EXPECT_TRUE(
-      surface_->Resize(gfx::Size(100, 100), 1.0, gfx::ColorSpace(), false));
-  EXPECT_FALSE(surface_->GetBackbufferSwapChainForTesting());
-
-  EXPECT_TRUE(surface_->SetDrawRectangle(gfx::Rect(0, 0, 100, 100)));
-
-  swap_chain = surface_->GetBackbufferSwapChainForTesting();
-  ASSERT_TRUE(swap_chain);
-  swap_chain->GetDesc1(&desc);
-  EXPECT_EQ(DXGI_ALPHA_MODE_IGNORE, desc.AlphaMode);
-}
-
 // Ensure that the GLImage isn't presented again unless it changes.
 TEST_F(DCompPresenterTest, NoPresentTwice) {
   if (!surface_)
@@ -625,8 +498,8 @@
     EXPECT_EQ(0u, hw_protected_flag);
   }
 
-  // TODO(magchen): Add a hardware protected video test when hardware procted
-  // video support is enabled by defaut in the Intel driver and Chrome
+  // TODO(magchen): Add a hardware protected video test when hardware protected
+  // video support is enabled by default in the Intel driver and Chrome
 }
 
 class DCompPresenterPixelTest : public DCompPresenterTest {
@@ -649,15 +522,57 @@
     DCompPresenterTest::TearDown();
   }
 
+  // DCompPresenter is surfaceless--it's root surface is achieved
+  // via an overlay the size of the window.
+  void InitializeRootAndScheduleRootSurface(const gfx::Size& window_size,
+                                            SkColor4f initial_color) {
+    Microsoft::WRL::ComPtr<IDCompositionDevice2> dcomp_device =
+        gl::GetDirectCompositionDevice();
+    Microsoft::WRL::ComPtr<IDCompositionSurface> root_surface;
+    ASSERT_HRESULT_SUCCEEDED(dcomp_device->CreateSurface(
+        window_size.width(), window_size.height(), DXGI_FORMAT_B8G8R8A8_UNORM,
+        DXGI_ALPHA_MODE_IGNORE, &root_surface));
+
+    // Clear the root surface to |initial_color|
+    Microsoft::WRL::ComPtr<ID3D11Texture2D> update_texture;
+    RECT rect = gfx::Rect(window_size).ToRECT();
+    POINT update_offset;
+    ASSERT_HRESULT_SUCCEEDED(root_surface->BeginDraw(
+        &rect, IID_PPV_ARGS(&update_texture), &update_offset));
+
+    Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device =
+        gl::QueryD3D11DeviceObjectFromANGLE();
+    Microsoft::WRL::ComPtr<ID3D11DeviceContext> immediate_context;
+    d3d11_device->GetImmediateContext(&immediate_context);
+    Microsoft::WRL::ComPtr<ID3D11RenderTargetView> rtv;
+    D3D11_RENDER_TARGET_VIEW_DESC desc;
+    desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
+    desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+    desc.Texture2D.MipSlice = 0;
+    ASSERT_HRESULT_SUCCEEDED(d3d11_device->CreateRenderTargetView(
+        update_texture.Get(), &desc, &rtv));
+    immediate_context->ClearRenderTargetView(rtv.Get(), initial_color.vec());
+
+    ASSERT_HRESULT_SUCCEEDED(root_surface->EndDraw());
+
+    // Schedule the root surface as a normal overlay
+    std::unique_ptr<ui::DCRendererLayerParams> params =
+        std::make_unique<ui::DCRendererLayerParams>();
+    params->z_order = 0;
+    params->quad_rect = gfx::Rect(window_size);
+    params->content_rect = params->quad_rect;
+    params->dcomp_visual_content = root_surface;
+    params->dcomp_surface_serial = 0;
+    EXPECT_TRUE(surface_->ScheduleDCLayer(std::move(params)));
+  }
+
   void InitializeForPixelTest(const gfx::Size& window_size,
                               const gfx::Size& texture_size,
                               const gfx::Rect& content_rect,
                               const gfx::Rect& quad_rect) {
     EXPECT_TRUE(surface_->Resize(window_size, 1.0, gfx::ColorSpace(), true));
-    EXPECT_TRUE(surface_->SetDrawRectangle(gfx::Rect(window_size)));
 
-    glClearColor(0.0, 0.0, 0.0, 1.0);
-    glClear(GL_COLOR_BUFFER_BIT);
+    InitializeRootAndScheduleRootSurface(window_size, SkColors::kBlack);
 
     Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device =
         QueryD3D11DeviceObjectFromANGLE();
@@ -691,47 +606,10 @@
     Sleep(1000);
   }
 
-  void PixelTestSwapChain(bool layers_enabled) {
-    if (!surface_)
-      return;
-    if (!layers_enabled)
-      surface_->SetEnableDCLayers(false);
-
-    gfx::Size window_size(100, 100);
-    EXPECT_TRUE(surface_->Resize(window_size, 1.0, gfx::ColorSpace(), true));
-    EXPECT_TRUE(surface_->SetDrawRectangle(gfx::Rect(window_size)));
-
-    glClearColor(1.0, 0.0, 0.0, 1.0);
-    glClear(GL_COLOR_BUFFER_BIT);
-
-    EXPECT_EQ(gfx::SwapResult::SWAP_ACK,
-              surface_->SwapBuffers(base::DoNothing(), FrameData()));
-
-    // Ensure DWM swap completed.
-    Sleep(1000);
-
-    SkColor expected_color = SK_ColorRED;
-    SkColor actual_color =
-        GLTestHelper::ReadBackWindowPixel(window_.hwnd(), gfx::Point(75, 75));
-    EXPECT_EQ(expected_color, actual_color)
-        << std::hex << "Expected " << expected_color << " Actual "
-        << actual_color;
-
-    EXPECT_TRUE(context_->IsCurrent(surface_.get()));
-  }
-
   TestPlatformDelegate platform_delegate_;
   ui::WinWindow window_;
 };
 
-TEST_F(DCompPresenterPixelTest, DCLayersEnabled) {
-  PixelTestSwapChain(true);
-}
-
-TEST_F(DCompPresenterPixelTest, DCLayersDisabled) {
-  PixelTestSwapChain(false);
-}
-
 bool AreColorsSimilar(int a, int b) {
   // The precise colors may differ depending on the video processor, so allow
   // a margin for error.
@@ -922,8 +800,7 @@
   EXPECT_TRUE(surface_->Resize(window_size, 1.0, gfx::ColorSpace(), true));
   EXPECT_TRUE(surface_->SetDrawRectangle(gfx::Rect(window_size)));
 
-  glClearColor(0.0, 0.0, 0.0, 1.0);
-  glClear(GL_COLOR_BUFFER_BIT);
+  InitializeRootAndScheduleRootSurface(window_size, SkColors::kBlack);
 
   Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device =
       QueryD3D11DeviceObjectFromANGLE();
@@ -1089,8 +966,7 @@
   EXPECT_TRUE(surface_->Resize(window_size, 1.0, gfx::ColorSpace(), true));
   EXPECT_TRUE(surface_->SetDrawRectangle(gfx::Rect(window_size)));
 
-  glClearColor(0.0, 0.0, 0.0, 1.0);
-  glClear(GL_COLOR_BUFFER_BIT);
+  InitializeRootAndScheduleRootSurface(window_size, SkColors::kBlack);
 
   Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device =
       QueryD3D11DeviceObjectFromANGLE();
@@ -1289,8 +1165,7 @@
   EXPECT_TRUE(surface_->Resize(window_size, 1.0, gfx::ColorSpace(), true));
   EXPECT_TRUE(surface_->SetDrawRectangle(gfx::Rect(window_size)));
 
-  glClearColor(0.0, 0.0, 0.0, 1.0);
-  glClear(GL_COLOR_BUFFER_BIT);
+  InitializeRootAndScheduleRootSurface(window_size, SkColors::kBlack);
 
   DXGI_PRESENT_PARAMETERS present_params = {};
   present_params.DirtyRectsCount = 0;
@@ -1393,145 +1268,63 @@
   }
 }
 
-// Offsets BeginDraw update rect so that the returned update offset is also
-// offset by at least the same amount from the original update rect.
-class DrawOffsetOverridingDCompositionSurface
-    : public Microsoft::WRL::RuntimeClass<
-          Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
-          IDCompositionSurface> {
+class DCompPresenterBufferCountTest : public DCompPresenterTest,
+                                      public testing::WithParamInterface<bool> {
  public:
-  DrawOffsetOverridingDCompositionSurface(
-      Microsoft::WRL::ComPtr<IDCompositionSurface> surface,
-      const gfx::Point& draw_offset)
-      : surface_(std::move(surface)), draw_offset_(draw_offset) {}
-
-  IFACEMETHODIMP BeginDraw(const RECT* updateRect,
-                           REFIID iid,
-                           void** updateObject,
-                           POINT* updateOffset) override {
-    RECT offsetRect = *updateRect;
-    offsetRect.left += draw_offset_.x();
-    offsetRect.right += draw_offset_.x();
-    offsetRect.top += draw_offset_.y();
-    offsetRect.bottom += draw_offset_.y();
-    return surface_->BeginDraw(&offsetRect, iid, updateObject, updateOffset);
+  static const char* GetParamName(
+      const testing::TestParamInfo<ParamType>& info) {
+    return info.param ? "DCompTripleBufferVideoSwapChain" : "default";
   }
 
-  IFACEMETHODIMP EndDraw() override { return surface_->EndDraw(); }
+ protected:
+  void SetUp() override {
+    if (GetParam()) {
+      enabled_features_.InitWithFeatures(
+          {features::kDCompTripleBufferVideoSwapChain}, {});
+    } else {
+      enabled_features_.InitWithFeatures(
+          {}, {features::kDCompTripleBufferVideoSwapChain});
+    }
 
-  IFACEMETHODIMP ResumeDraw() override { return surface_->ResumeDraw(); }
-
-  IFACEMETHODIMP SuspendDraw() override { return surface_->SuspendDraw(); }
-
-  IFACEMETHODIMP Scroll(const RECT* scrollRect,
-                        const RECT* clipRect,
-                        int offsetX,
-                        int offsetY) override {
-    return surface_->Scroll(scrollRect, clipRect, offsetX, offsetY);
+    DCompPresenterTest::SetUp();
   }
 
- private:
-  Microsoft::WRL::ComPtr<IDCompositionSurface> surface_;
-  const gfx::Point draw_offset_;
+  base::test::ScopedFeatureList enabled_features_;
 };
 
-TEST_F(DCompPresenterPixelTest, RootSurfaceDrawOffset) {
+TEST_P(DCompPresenterBufferCountTest, VideoSwapChainBufferCount) {
   if (!surface_)
     return;
 
+  SetDirectCompositionScaledOverlaysSupportedForTesting(true);
+
   constexpr gfx::Size window_size(100, 100);
   EXPECT_TRUE(surface_->Resize(window_size, 1.0, gfx::ColorSpace(), true));
   EXPECT_TRUE(surface_->SetDrawRectangle(gfx::Rect(window_size)));
 
-  glClearColor(0.0, 0.0, 1.0, 1.0);
-  glClear(GL_COLOR_BUFFER_BIT);
-
-  EXPECT_EQ(gfx::SwapResult::SWAP_ACK,
-            surface_->SwapBuffers(base::DoNothing(), FrameData()));
-
-  constexpr gfx::Point draw_offset(50, 50);
-  auto root_surface = surface_->GetRootSurfaceForTesting();
-  auto dcomp_surface =
-      Microsoft::WRL::Make<DrawOffsetOverridingDCompositionSurface>(
-          root_surface->dcomp_surface(), draw_offset);
-  root_surface->SetDCompSurfaceForTesting(std::move(dcomp_surface));
-
-  // Even though draw_rect is the first quadrant, the rendering will be limited
-  // to the third quadrant because the dcomp surface will return that offset.
-  constexpr gfx::Rect draw_rect(0, 0, 50, 50);
-  EXPECT_TRUE(surface_->SetDrawRectangle(draw_rect));
-
-  glClearColor(1.0, 0.0, 0.0, 1.0);
-  glClear(GL_COLOR_BUFFER_BIT);
-
-  EXPECT_EQ(gfx::SwapResult::SWAP_ACK,
-            surface_->SwapBuffers(base::DoNothing(), FrameData()));
-
-  Sleep(1000);
-
-  // Note: The colors read back are BGRA so the expected colors are inverted
-  // with respect to the clear color.
-  struct {
-    gfx::Point position;
-    SkColor expected_color;
-  } test_cases[] = {{gfx::Point(75, 75), SkColorSetRGB(255, 0, 0)},
-                    {gfx::Point(25, 25), SkColorSetRGB(0, 0, 255)}};
-
-  for (const auto& test_case : test_cases) {
-    SkColor actual_color =
-        GLTestHelper::ReadBackWindowPixel(window_.hwnd(), test_case.position);
-    EXPECT_TRUE(AreColorsSimilar(test_case.expected_color, actual_color))
-        << std::hex << "Expected " << test_case.expected_color << " Actual "
-        << actual_color;
-  }
-}
-
-void RunBufferCountTest(scoped_refptr<DCompPresenter> surface,
-                        UINT buffer_count,
-                        bool for_video) {
-  if (!surface)
-    return;
-
-  if (for_video) {
-    SetDirectCompositionScaledOverlaysSupportedForTesting(true);
-    EXPECT_TRUE(surface->SetEnableDCLayers(true));
-  } else {
-    EXPECT_TRUE(surface->SetEnableDCLayers(false));
-  }
-
-  constexpr gfx::Size window_size(100, 100);
-  EXPECT_TRUE(surface->Resize(window_size, 1.0, gfx::ColorSpace(), true));
-  EXPECT_TRUE(surface->SetDrawRectangle(gfx::Rect(window_size)));
-
-  glClearColor(0.0, 0.0, 0.0, 1.0);
-  glClear(GL_COLOR_BUFFER_BIT);
-
   constexpr gfx::Size texture_size(50, 50);
-  if (for_video) {
-    Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device =
-        QueryD3D11DeviceObjectFromANGLE();
-    ASSERT_TRUE(d3d11_device);
 
-    Microsoft::WRL::ComPtr<ID3D11Texture2D> texture =
-        CreateNV12Texture(d3d11_device, texture_size, /*shared=*/false);
-    // The format doesn't matter, since we aren't binding.
-    scoped_refptr<GLImageDXGI> image_dxgi(
-        new GLImageDXGI(texture_size, nullptr));
-    image_dxgi->SetTexture(texture, /*level=*/0);
+  Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device =
+      QueryD3D11DeviceObjectFromANGLE();
+  ASSERT_TRUE(d3d11_device);
 
-    std::unique_ptr<ui::DCRendererLayerParams> params =
-        std::make_unique<ui::DCRendererLayerParams>();
-    params->images[0] = image_dxgi;
-    params->content_rect = gfx::Rect(texture_size);
-    params->quad_rect = gfx::Rect(window_size);
-    EXPECT_TRUE(surface->ScheduleDCLayer(std::move(params)));
-  }
+  Microsoft::WRL::ComPtr<ID3D11Texture2D> texture =
+      CreateNV12Texture(d3d11_device, texture_size, /*shared=*/false);
+  // The format doesn't matter, since we aren't binding.
+  scoped_refptr<GLImageDXGI> image_dxgi(new GLImageDXGI(texture_size, nullptr));
+  image_dxgi->SetTexture(texture, /*level=*/0);
+
+  std::unique_ptr<ui::DCRendererLayerParams> params =
+      std::make_unique<ui::DCRendererLayerParams>();
+  params->images[0] = image_dxgi;
+  params->content_rect = gfx::Rect(texture_size);
+  params->quad_rect = gfx::Rect(window_size);
+  EXPECT_TRUE(surface_->ScheduleDCLayer(std::move(params)));
 
   EXPECT_EQ(gfx::SwapResult::SWAP_ACK,
-            surface->SwapBuffers(base::DoNothing(), FrameData()));
+            surface_->SwapBuffers(base::DoNothing(), FrameData()));
 
-  auto swap_chain = for_video ? surface->GetLayerSwapChainForTesting(0)
-                              : surface->GetBackbufferSwapChainForTesting();
+  auto swap_chain = surface_->GetLayerSwapChainForTesting(0);
   ASSERT_TRUE(swap_chain);
 
   DXGI_SWAP_CHAIN_DESC1 desc;
@@ -1539,41 +1332,17 @@
   // The expected size is window_size(100, 100).
   EXPECT_EQ(100u, desc.Width);
   EXPECT_EQ(100u, desc.Height);
-  EXPECT_EQ(buffer_count, desc.BufferCount);
-}
-
-TEST_F(DCompPresenterTest, RootSwapChainBufferCount) {
-  RunBufferCountTest(surface_, /*buffer_count=*/2u, /*for_video=*/false);
-}
-
-TEST_F(DCompPresenterTest, VideoSwapChainBufferCount) {
-  RunBufferCountTest(surface_, /*buffer_count=*/2u, /*for_video=*/true);
-}
-
-class DCompPresenterTripleBufferingTest : public DCompPresenterTest {
- public:
-  DCompPresenterTripleBufferingTest() = default;
-  ~DCompPresenterTripleBufferingTest() override = default;
-
- protected:
-  void SetUp() override {
-    feature_list_.InitWithFeatures({features::kDCompTripleBufferRootSwapChain,
-                                    features::kDCompTripleBufferVideoSwapChain},
-                                   {});
-    DCompPresenterTest::SetUp();
+  if (GetParam()) {
+    EXPECT_EQ(3u, desc.BufferCount);
+  } else {
+    EXPECT_EQ(2u, desc.BufferCount);
   }
-
- private:
-  base::test::ScopedFeatureList feature_list_;
-};
-
-TEST_F(DCompPresenterTripleBufferingTest, MainSwapChainBufferCount) {
-  RunBufferCountTest(surface_, /*buffer_count=*/3u, /*for_video=*/false);
 }
 
-TEST_F(DCompPresenterTripleBufferingTest, VideoSwapChainBufferCount) {
-  RunBufferCountTest(surface_, /*buffer_count=*/3u, /*for_video=*/true);
-}
+INSTANTIATE_TEST_SUITE_P(All,
+                         DCompPresenterBufferCountTest,
+                         testing::Bool(),
+                         &DCompPresenterBufferCountTest::GetParamName);
 
 }  // namespace
 }  // namespace gl
diff --git a/ui/gl/init/gl_factory_mac.cc b/ui/gl/init/gl_factory_mac.cc
index 82a64f8..30c0e68 100644
--- a/ui/gl/init/gl_factory_mac.cc
+++ b/ui/gl/init/gl_factory_mac.cc
@@ -5,6 +5,7 @@
 #include "ui/gl/init/gl_factory.h"
 
 #include "base/check_op.h"
+#include "base/mac/mac_util.h"
 #include "base/notreached.h"
 #include "base/trace_event/trace_event.h"
 #include "ui/gl/buildflags.h"
@@ -25,7 +26,16 @@
 
 std::vector<GLImplementationParts> GetAllowedGLImplementations() {
   std::vector<GLImplementationParts> impls;
-  impls.emplace_back(GLImplementationParts(kGLImplementationEGLANGLE));
+  impls.emplace_back(GLImplementationParts(gl::ANGLEImplementation::kDefault));
+  impls.emplace_back(GLImplementationParts(gl::ANGLEImplementation::kOpenGL));
+  impls.emplace_back(GLImplementationParts(gl::ANGLEImplementation::kMetal));
+  // crbug.com/1378476: LLVM 10 is used as the JIT compiler for SwiftShader,
+  // which doesn't properly support ARM. Disable Swiftshader on ARM CPUs until
+  // LLVM is upgraded.
+  if (base::mac::GetCPUType() != base::mac::CPUType::kArm) {
+    impls.emplace_back(
+        GLImplementationParts(gl::ANGLEImplementation::kSwiftShader));
+  }
   return impls;
 }
 
diff --git a/ui/ozone/platform/flatland/flatland_sysmem_buffer_collection.cc b/ui/ozone/platform/flatland/flatland_sysmem_buffer_collection.cc
index e483bdf..d709737 100644
--- a/ui/ozone/platform/flatland/flatland_sysmem_buffer_collection.cc
+++ b/ui/ozone/platform/flatland/flatland_sysmem_buffer_collection.cc
@@ -332,16 +332,17 @@
       buffers_info_.settings.buffer_settings.coherency_domain ==
       fuchsia::sysmem::CoherencyDomain::RAM;
 
+  // `handle.planes` need to be filled in only for mappable buffers.
+  if (!is_mappable())
+    return new FlatlandSysmemNativePixmap(this, std::move(handle), size);
+
   zx::vmo main_plane_vmo;
-  if (is_mappable()) {
-    DCHECK(buffers_info_.buffers[handle.buffer_index].vmo.is_valid());
-    zx_status_t status =
-        buffers_info_.buffers[handle.buffer_index].vmo.duplicate(
-            ZX_RIGHT_SAME_RIGHTS, &main_plane_vmo);
-    if (status != ZX_OK) {
-      ZX_DLOG(ERROR, status) << "zx_handle_duplicate";
-      return nullptr;
-    }
+  DCHECK(buffers_info_.buffers[handle.buffer_index].vmo.is_valid());
+  zx_status_t status = buffers_info_.buffers[handle.buffer_index].vmo.duplicate(
+      ZX_RIGHT_SAME_RIGHTS, &main_plane_vmo);
+  if (status != ZX_OK) {
+    ZX_DLOG(ERROR, status) << "zx_handle_duplicate";
+    return nullptr;
   }
 
   const fuchsia::sysmem::ImageFormatConstraints& format =
@@ -362,8 +363,17 @@
   if (format_ == gfx::BufferFormat::YUV_420_BIPLANAR) {
     size_t uv_plane_offset = plane_offset + plane_size;
     size_t uv_plane_size = plane_size / 2;
+
+    zx::vmo uv_plane_vmo;
+    status =
+        handle.planes[0].vmo.duplicate(ZX_RIGHT_SAME_RIGHTS, &uv_plane_vmo);
+    if (status != ZX_OK) {
+      ZX_DLOG(ERROR, status) << "zx_handle_duplicate";
+      return nullptr;
+    }
+
     handle.planes.emplace_back(stride, uv_plane_offset, uv_plane_size,
-                               zx::vmo());
+                               std::move(uv_plane_vmo));
     DCHECK_LE(uv_plane_offset + uv_plane_size, buffer_size_);
   }
 
diff --git a/ui/ozone/platform/scenic/sysmem_buffer_collection.cc b/ui/ozone/platform/scenic/sysmem_buffer_collection.cc
index 457b1e8..98c815d0 100644
--- a/ui/ozone/platform/scenic/sysmem_buffer_collection.cc
+++ b/ui/ozone/platform/scenic/sysmem_buffer_collection.cc
@@ -325,16 +325,17 @@
       buffers_info_.settings.buffer_settings.coherency_domain ==
       fuchsia::sysmem::CoherencyDomain::RAM;
 
+  // `handle.planes` need to be filled in only for mappable buffers.
+  if (!is_mappable())
+    return new SysmemNativePixmap(this, std::move(handle), size);
+
   zx::vmo main_plane_vmo;
-  if (is_mappable()) {
-    DCHECK(buffers_info_.buffers[handle.buffer_index].vmo.is_valid());
-    zx_status_t status =
-        buffers_info_.buffers[handle.buffer_index].vmo.duplicate(
-            ZX_RIGHT_SAME_RIGHTS, &main_plane_vmo);
-    if (status != ZX_OK) {
-      ZX_DLOG(ERROR, status) << "zx_handle_duplicate";
-      return nullptr;
-    }
+  DCHECK(buffers_info_.buffers[handle.buffer_index].vmo.is_valid());
+  zx_status_t status = buffers_info_.buffers[handle.buffer_index].vmo.duplicate(
+      ZX_RIGHT_SAME_RIGHTS, &main_plane_vmo);
+  if (status != ZX_OK) {
+    ZX_DLOG(ERROR, status) << "zx_handle_duplicate";
+    return nullptr;
   }
 
   const fuchsia::sysmem::ImageFormatConstraints& format =
@@ -355,8 +356,17 @@
   if (format_ == gfx::BufferFormat::YUV_420_BIPLANAR) {
     size_t uv_plane_offset = plane_offset + plane_size;
     size_t uv_plane_size = plane_size / 2;
+
+    zx::vmo uv_plane_vmo;
+    status =
+        handle.planes[0].vmo.duplicate(ZX_RIGHT_SAME_RIGHTS, &uv_plane_vmo);
+    if (status != ZX_OK) {
+      ZX_DLOG(ERROR, status) << "zx_handle_duplicate";
+      return nullptr;
+    }
+
     handle.planes.emplace_back(stride, uv_plane_offset, uv_plane_size,
-                               zx::vmo());
+                               std::move(uv_plane_vmo));
     DCHECK_LE(uv_plane_offset + uv_plane_size, buffer_size_);
   }
 
diff --git a/ui/ozone/platform/wayland/host/wayland_input_method_context.cc b/ui/ozone/platform/wayland/host/wayland_input_method_context.cc
index 9b0ae0f0..ae25d11 100644
--- a/ui/ozone/platform/wayland/host/wayland_input_method_context.cc
+++ b/ui/ozone/platform/wayland/host/wayland_input_method_context.cc
@@ -448,17 +448,40 @@
     return;
   }
 
-  if (index < 0 || static_cast<uint32_t>(index) > surrounding_text_.size()) {
+  // Adjust index and anchor to the position in `surrounding_text_`.
+  // `index` and `anchor` sent from Exo is for the surrounding text sent to Exo
+  // which could be trimmed when the actual surrounding text is longer than 4000
+  // bytes.
+  // Note that `index` and `anchor` is guaranteed to be under 4000 bytes,
+  // adjusted index and anchor below won't overflow.
+  size_t adjusted_index = index + surrounding_text_offset_;
+  size_t adjusted_anchor = anchor + surrounding_text_offset_;
+
+  if (adjusted_index > surrounding_text_.size()) {
     LOG(ERROR) << "Invalid index is specified.";
     return;
   }
-  if (anchor < 0 || static_cast<uint32_t>(anchor) > surrounding_text_.size()) {
+  if (adjusted_anchor > surrounding_text_.size()) {
     LOG(ERROR) << "Invalid anchor is specified.";
     return;
   }
 
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
-  if (selection_range_utf8_ == gfx::Range(index, anchor)) {
+  // Cursor position may be wrong on Lacros due to timing issue for some
+  // scenario when surrounding text is longer than wayland message size
+  // limitation (4000 bytes) such as:
+  // 1. Set surrounding text with 8000 bytes and send the selection adjusted to
+  // 4000 bytes (wayland message size maximum).
+  // 2. Exo requests to delete surrounding text sent from 1.
+  // 3. Before receiving OnDeleteSurrounding, move the selection to 4000 bytes
+  // (this implies that surrounding text sent to Exo is changed) on wayland and
+  // set surrounding text.
+  // In this case, Exo can only know the relative position to the offset trimmed
+  // on Wayland, so the position is mismatched to Wayland.
+  //
+  // This timing issue will be fixed by sending whole surrounding text instead
+  // of trimmed text.
+  if (selection_range_utf8_ == gfx::Range(adjusted_index, adjusted_anchor)) {
     pending_keep_selection_ = true;
   } else {
     NOTIMPLEMENTED_LOG_ONCE();
@@ -620,7 +643,8 @@
 
 void WaylandInputMethodContext::OnClearGrammarFragments(
     const gfx::Range& range) {
-  std::vector<size_t> offsets = {range.start(), range.end()};
+  std::vector<size_t> offsets = {range.start() + surrounding_text_offset_,
+                                 range.end() + surrounding_text_offset_};
   base::UTF8ToUTF16AndAdjustOffsets(surrounding_text_, &offsets);
   ime_delegate_->OnClearGrammarFragments(gfx::Range(
       static_cast<uint32_t>(offsets[0]), static_cast<uint32_t>(offsets[1])));
@@ -628,7 +652,9 @@
 
 void WaylandInputMethodContext::OnAddGrammarFragment(
     const GrammarFragment& fragment) {
-  std::vector<size_t> offsets = {fragment.range.start(), fragment.range.end()};
+  std::vector<size_t> offsets = {
+      fragment.range.start() + surrounding_text_offset_,
+      fragment.range.end() + surrounding_text_offset_};
   base::UTF8ToUTF16AndAdjustOffsets(surrounding_text_, &offsets);
   ime_delegate_->OnAddGrammarFragment(
       {GrammarFragment(gfx::Range(static_cast<uint32_t>(offsets[0]),
@@ -637,7 +663,9 @@
 }
 
 void WaylandInputMethodContext::OnSetAutocorrectRange(const gfx::Range& range) {
-  ime_delegate_->OnSetAutocorrectRange(range);
+  ime_delegate_->OnSetAutocorrectRange(
+      gfx::Range(range.start() + surrounding_text_offset_,
+                 range.end() + surrounding_text_offset_));
 }
 
 void WaylandInputMethodContext::OnSetVirtualKeyboardOccludedBounds(
diff --git a/ui/ozone/platform/wayland/host/wayland_input_method_context.h b/ui/ozone/platform/wayland/host/wayland_input_method_context.h
index b9636d7..81dcf4e 100644
--- a/ui/ozone/platform/wayland/host/wayland_input_method_context.h
+++ b/ui/ozone/platform/wayland/host/wayland_input_method_context.h
@@ -128,9 +128,13 @@
   CharacterComposer character_composer_;
 
   // Stores the parameters required for OnDeleteSurroundingText.
-  // The index moved by SetSurroundingText. This is byte-offset in UTF8 form.
+  // The index moved by SetSurroundingText due to the maximum length of wayland
+  // messages limitation. It is specified as 4000 bytes in the protocol spec of
+  // text-input-unstable-v3.
+  // This is byte-offset in UTF8 form.
   size_t surrounding_text_offset_ = 0;
-  // The string in SetSurroundingText.
+  // The string in SetSurroundingText. This is NOT trimmed by the wayland
+  // message size limitation.
   std::string surrounding_text_;
   // The selection range in UTF-8 offsets in the |surrounding_text_|.
   gfx::Range selection_range_utf8_ = gfx::Range::InvalidRange();
diff --git a/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc b/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc
index fd03c68..8932350 100644
--- a/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc
+++ b/ui/ozone/platform/wayland/host/wayland_input_method_context_unittest.cc
@@ -715,6 +715,42 @@
       input_method_context_delegate_->was_on_confirm_composition_text_called());
 }
 
+TEST_F(WaylandInputMethodContextTest,
+       MAYBE(OnConfirmCompositionTextForLongRange)) {
+  const std::u16string original_text(5000, u'あ');
+  constexpr gfx::Range original_range(4000, 4500);
+
+  // Text longer than 4000 bytes is trimmed to meet the limitation.
+  // Selection range is also adjusted by the trimmed text before sendin to Exo.
+  const std::string kExpectedSentText(
+      base::UTF16ToUTF8(std::u16string(1332, u'あ')));
+  constexpr gfx::Range kExpectedSentRange(1248, 2748);
+
+  // SetSurroundingText should be called in UTF-8.
+  PostToServerAndWait([kExpectedSentText, kExpectedSentRange](
+                          wl::TestWaylandServerThread* server) {
+    EXPECT_CALL(*server->text_input_manager_v1()->text_input(),
+                SetSurroundingText(kExpectedSentText, kExpectedSentRange));
+  });
+  input_method_context_->SetSurroundingText(original_text, original_range);
+  connection_->Flush();
+
+  PostToServerAndWait([kExpectedSentText, kExpectedSentRange](
+                          wl::TestWaylandServerThread* server) {
+    auto* text_input = server->text_input_manager_v1()->text_input();
+    Mock::VerifyAndClearExpectations(text_input);
+
+    zwp_text_input_v1_send_cursor_position(text_input->resource(),
+                                           kExpectedSentRange.start(),
+                                           kExpectedSentRange.end());
+    zwp_text_input_v1_send_commit_string(text_input->resource(), 0,
+                                         kExpectedSentText.c_str());
+  });
+
+  EXPECT_TRUE(
+      input_method_context_delegate_->was_on_confirm_composition_text_called());
+}
+
 TEST_F(WaylandInputMethodContextTest, OnSetPreeditRegion_Success) {
   constexpr char16_t text[] = u"abcあdef";
   const gfx::Range range(3, 4);  // あ is selected.
diff --git a/ui/ozone/platform/wayland/host/wayland_screen.cc b/ui/ozone/platform/wayland/host/wayland_screen.cc
index a5caae3..ab984d7 100644
--- a/ui/ozone/platform/wayland/host/wayland_screen.cc
+++ b/ui/ozone/platform/wayland/host/wayland_screen.cc
@@ -226,6 +226,10 @@
     color_spaces.SetOutputColorSpaceAndBufferFormat(
         gfx::ContentColorUsage::kWideColorGamut, false,
         gfx::ColorSpace::CreateDisplayP3D65(), image_format_no_alpha_.value());
+    // SRGB10Bit was designed to provide 5x relative brightness.
+    color_spaces.SetHDRMaxLuminanceRelative(5);
+    // sRGB is defined to have a luminance level of 80 nits.
+    color_spaces.SetSDRMaxLuminanceNits(80);
   }
 #endif
 
diff --git a/ui/touch_selection/BUILD.gn b/ui/touch_selection/BUILD.gn
index 97627d4..219b8ee 100644
--- a/ui/touch_selection/BUILD.gn
+++ b/ui/touch_selection/BUILD.gn
@@ -22,6 +22,8 @@
     "touch_selection_controller.cc",
     "touch_selection_controller.h",
     "touch_selection_draggable.h",
+    "touch_selection_magnifier_runner.cc",
+    "touch_selection_magnifier_runner.h",
     "touch_selection_menu_runner.cc",
     "touch_selection_menu_runner.h",
     "ui_touch_selection_export.h",
diff --git a/ui/touch_selection/touch_selection_magnifier_runner.cc b/ui/touch_selection/touch_selection_magnifier_runner.cc
new file mode 100644
index 0000000..91b6458b
--- /dev/null
+++ b/ui/touch_selection/touch_selection_magnifier_runner.cc
@@ -0,0 +1,31 @@
+// 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 "ui/touch_selection/touch_selection_magnifier_runner.h"
+
+#include "base/check_op.h"
+
+namespace ui {
+
+namespace {
+
+TouchSelectionMagnifierRunner* g_touch_selection_magnifier_runner = nullptr;
+
+}  // namespace
+
+TouchSelectionMagnifierRunner::~TouchSelectionMagnifierRunner() {
+  DCHECK_EQ(this, g_touch_selection_magnifier_runner);
+  g_touch_selection_magnifier_runner = nullptr;
+}
+
+TouchSelectionMagnifierRunner* TouchSelectionMagnifierRunner::GetInstance() {
+  return g_touch_selection_magnifier_runner;
+}
+
+TouchSelectionMagnifierRunner::TouchSelectionMagnifierRunner() {
+  DCHECK(!g_touch_selection_magnifier_runner);
+  g_touch_selection_magnifier_runner = this;
+}
+
+}  // namespace ui
diff --git a/ui/touch_selection/touch_selection_magnifier_runner.h b/ui/touch_selection/touch_selection_magnifier_runner.h
new file mode 100644
index 0000000..3ce88328
--- /dev/null
+++ b/ui/touch_selection/touch_selection_magnifier_runner.h
@@ -0,0 +1,50 @@
+// 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 UI_TOUCH_SELECTION_TOUCH_SELECTION_MAGNIFIER_RUNNER_H_
+#define UI_TOUCH_SELECTION_TOUCH_SELECTION_MAGNIFIER_RUNNER_H_
+
+#include "ui/touch_selection/ui_touch_selection_export.h"
+
+namespace aura {
+class Window;
+}  // namespace aura
+
+namespace gfx {
+class PointF;
+}  // namespace gfx
+
+namespace ui {
+
+// An interface for the singleton object responsible for running the touch
+// selection magnifier.
+class UI_TOUCH_SELECTION_EXPORT TouchSelectionMagnifierRunner {
+ public:
+  TouchSelectionMagnifierRunner(const TouchSelectionMagnifierRunner&) = delete;
+  TouchSelectionMagnifierRunner& operator=(
+      const TouchSelectionMagnifierRunner&) = delete;
+
+  virtual ~TouchSelectionMagnifierRunner();
+
+  static TouchSelectionMagnifierRunner* GetInstance();
+
+  // Creates and shows a magnifier, or updates the running magnifier's position
+  // if the runner is already showing a magnifier. `position` specifies
+  // coordinates in the context window.
+  virtual void ShowMagnifier(aura::Window* context,
+                             const gfx::PointF& position) = 0;
+
+  // Closes and stops showing the running magnifier.
+  virtual void CloseMagnifier() = 0;
+
+  // Returns true if the runner is currently showing a magnifier.
+  virtual bool IsRunning() const = 0;
+
+ protected:
+  TouchSelectionMagnifierRunner();
+};
+
+}  // namespace ui
+
+#endif  // UI_TOUCH_SELECTION_TOUCH_SELECTION_MAGNIFIER_RUNNER_H_
diff --git a/ui/views/cocoa/drag_drop_client_mac.mm b/ui/views/cocoa/drag_drop_client_mac.mm
index 34b0eb96..b4fc510 100644
--- a/ui/views/cocoa/drag_drop_client_mac.mm
+++ b/ui/views/cocoa/drag_drop_client_mac.mm
@@ -63,8 +63,21 @@
   NSImage* image = gfx::NSImageFromImageSkiaWithColorSpace(
       provider_mac.GetDragImage(), base::mac::GetSRGBColorSpace());
 
-  DCHECK(!NSEqualSizes([image size], NSZeroSize));
-  NSDraggingItem* drag_item = provider_mac.GetDraggingItem();
+  DCHECK(!NSEqualSizes(image.size, NSZeroSize));
+  NSArray<NSDraggingItem*>* drag_items = provider_mac.GetDraggingItems();
+  if (!drag_items) {
+    // The source of this data is ultimately the OS, and while this shouldn't be
+    // nil, it is documented as possibly being so if things are broken. If so,
+    // fail early rather than try to start a drag of a nil item list and making
+    // things worse.
+    return;
+  }
+
+  // At this point the mismatch between the Views drag API, which assumes a
+  // single drag item, and the macOS drag API, which allows for multiple items,
+  // is encountered. For now, set the dragging frame and image on the first
+  // item, and set nil images for the remaining items. In the future, when Views
+  // becomes more capable in the area of the clipboard, revisit this.
 
   // Create the frame to cause the mouse to be centered over the image, with the
   // image slightly above the mouse pointer for visibility.
@@ -72,9 +85,15 @@
       NSMakeRect(event.locationInWindow.x - image.size.width / 2,
                  event.locationInWindow.y - image.size.height / 4,
                  image.size.width, image.size.height);
-  [drag_item setDraggingFrame:dragging_frame contents:image];
+  for (NSUInteger i = 0; i < drag_items.count; ++i) {
+    if (i == 0) {
+      [drag_items[i] setDraggingFrame:dragging_frame contents:image];
+    } else {
+      [drag_items[i] setDraggingFrame:NSMakeRect(0, 0, 1, 1) contents:nil];
+    }
+  }
 
-  [bridge_->ns_view() beginDraggingSessionWithItems:@[ drag_item ]
+  [bridge_->ns_view() beginDraggingSessionWithItems:drag_items
                                               event:event
                                              source:bridge_->ns_view()];
 
diff --git a/ui/views/cocoa/native_widget_mac_ns_window_host.h b/ui/views/cocoa/native_widget_mac_ns_window_host.h
index 1c30148..f6d8e88 100644
--- a/ui/views/cocoa/native_widget_mac_ns_window_host.h
+++ b/ui/views/cocoa/native_widget_mac_ns_window_host.h
@@ -330,7 +330,6 @@
                                 bool full_keyboard_access_enabled) override;
   void OnWindowStateRestorationDataChanged(
       const std::vector<uint8_t>& data) override;
-  void OnWindowParentChanged(uint64_t new_parent_id) override;
   void DoDialogButtonAction(ui::DialogButton button) override;
   bool GetDialogButtonInfo(ui::DialogButton type,
                            bool* button_exists,
diff --git a/ui/views/cocoa/native_widget_mac_ns_window_host.mm b/ui/views/cocoa/native_widget_mac_ns_window_host.mm
index ac47886..020c952e 100644
--- a/ui/views/cocoa/native_widget_mac_ns_window_host.mm
+++ b/ui/views/cocoa/native_widget_mac_ns_window_host.mm
@@ -94,7 +94,6 @@
                                 bool full_keyboard_access_enabled) override {}
   void OnWindowStateRestorationDataChanged(
       const std::vector<uint8_t>& data) override {}
-  void OnWindowParentChanged(uint64_t new_parent_id) override {}
   void DoDialogButtonAction(ui::DialogButton button) override {}
   void OnFocusWindowToolbar() override {}
   void SetRemoteAccessibilityTokens(
@@ -657,7 +656,17 @@
 }
 
 gfx::Rect NativeWidgetMacNSWindowHost::GetContentBoundsInScreen() const {
-  return content_bounds_in_screen_;
+  NSView* contentView =
+      (NSView*)GetNativeWindowProperty(kImmersiveContentNSView);
+  if (!contentView)
+    return content_bounds_in_screen_;
+
+  // In immersive fullscreen, the content view is hosted in another NSWindow.
+  NSRect boundsInWindow = [contentView convertRect:contentView.bounds
+                                            toView:nil];
+  NSRect boundsInScreen =
+      [contentView.window convertRectToScreen:boundsInWindow];
+  return gfx::ScreenRectFromNSRect(boundsInScreen);
 }
 
 gfx::Rect NativeWidgetMacNSWindowHost::GetRestoredBounds() const {
@@ -1232,30 +1241,6 @@
   native_widget_mac_->GetWidget()->OnNativeWidgetWorkspaceChanged();
 }
 
-void NativeWidgetMacNSWindowHost::OnWindowParentChanged(
-    uint64_t new_parent_id) {
-  NativeWidgetMacNSWindowHost* new_parent = GetFromId(new_parent_id);
-
-  if (new_parent == parent_)
-    return;
-
-  if (parent_) {
-    auto found = base::ranges::find(parent_->children_, this);
-    CHECK(found != parent_->children_.end());
-    parent_->children_.erase(found);
-    parent_ = nullptr;
-  }
-
-  parent_ = new_parent;
-  if (parent_)
-    parent_->children_.push_back(this);
-
-  if (Widget* widget = native_widget_mac_->GetWidget()) {
-    widget->OnNativeWidgetParentChanged(
-        parent_ ? parent_->native_widget_mac()->GetNativeView() : nullptr);
-  }
-}
-
 void NativeWidgetMacNSWindowHost::DoDialogButtonAction(
     ui::DialogButton button) {
   views::DialogDelegate* dialog =
diff --git a/ui/views/controls/combobox/combobox.cc b/ui/views/controls/combobox/combobox.cc
index f0bf1b4..3836ea44 100644
--- a/ui/views/controls/combobox/combobox.cc
+++ b/ui/views/controls/combobox/combobox.cc
@@ -147,7 +147,7 @@
 
   if (features::IsChromeRefresh2023()) {
     // TODO(crbug.com/1392549): Replace placeholder color id.
-    SetBackgroundColorId(ui::kColorAlertHighSeverity);
+    SetBackgroundColorId(ui::kColorSubtleAccent);
   } else {
     SetBackgroundColorId(ui::kColorTextfieldBackground);
   }
@@ -342,7 +342,7 @@
 
   // If an arrow is being shown, add extra width to include that arrow.
   if (should_show_arrow_) {
-    width += kComboboxArrowContainerWidth;
+    width += GetComboboxArrowContainerWidthAndMargins();
   }
 
   const int height = LayoutProvider::GetControlHeightForFont(
@@ -595,7 +595,7 @@
   int text_width = gfx::GetStringWidth(text, font_list);
   int available_width = width() - x - insets.right();
   if (should_show_arrow_) {
-    available_width -= kComboboxArrowContainerWidth;
+    available_width -= GetComboboxArrowContainerWidthAndMargins();
   }
   text_width = std::min(text_width, available_width);
 
@@ -604,11 +604,20 @@
   canvas->DrawStringRect(text, font_list, text_color, text_bounds);
 
   // Draw the arrow.
+  // TODO(crbug.com/1392549): Replace placeholder spacing and color values for
+  // ChromeRefresh2023.
   if (should_show_arrow_) {
-    gfx::Rect arrow_bounds(width() - kComboboxArrowContainerWidth, 0,
-                           kComboboxArrowContainerWidth, height());
+    gfx::Rect arrow_bounds(width() - GetComboboxArrowContainerWidthAndMargins(),
+                           0, kComboboxArrowContainerWidth, height());
     arrow_bounds.ClampToCenteredSize(ComboboxArrowSize());
     AdjustBoundsForRTLUI(&arrow_bounds);
+
+    if (features::IsChromeRefresh2023()) {
+      PaintComboboxArrowBackground(
+          GetColorProvider()->GetColor(ui::kColorAlertHighSeverity), canvas,
+          gfx::PointF(width() - GetComboboxArrowContainerWidthAndMargins(),
+                      (height() - kComboboxArrowContainerWidth) / 2.0f));
+    }
     PaintComboboxArrow(text_color, arrow_bounds, canvas);
   }
 }
diff --git a/ui/views/controls/combobox/combobox_util.cc b/ui/views/controls/combobox/combobox_util.cc
index 73429f4..60b73be 100644
--- a/ui/views/controls/combobox/combobox_util.cc
+++ b/ui/views/controls/combobox/combobox_util.cc
@@ -6,8 +6,12 @@
 
 #include "cc/paint/paint_flags.h"
 #include "third_party/skia/include/core/SkColor.h"
+#include "ui/base/ui_base_features.h"
 #include "ui/gfx/canvas.h"
+#include "ui/gfx/geometry/point_f.h"
 #include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size_f.h"
+#include "ui/views/layout/layout_provider.h"
 
 namespace views {
 
@@ -15,6 +19,35 @@
 const int kComboboxArrowContainerWidth =
     ComboboxArrowSize().width() + kComboboxArrowPaddingWidth * 2;
 
+int GetComboboxArrowContainerWidthAndMargins() {
+  // Since the container will be visible, we need some extra margins for the
+  // ChromeRefresh case.
+  // TODO(crbug.com/1392549): Replace placeholder values and potentially combine
+  // use cases with INSETS_VECTOR_IMAGE_BUTTON.
+  gfx::Insets margins_chromerefresh2023 =
+      LayoutProvider::Get()->GetInsetsMetric(INSETS_VECTOR_IMAGE_BUTTON);
+  return features::IsChromeRefresh2023()
+             ? kComboboxArrowContainerWidth + margins_chromerefresh2023.left() +
+                   margins_chromerefresh2023.right()
+             : kComboboxArrowContainerWidth;
+}
+
+void PaintComboboxArrowBackground(SkColor color,
+                                  gfx::Canvas* canvas,
+                                  gfx::PointF origin) {
+  cc::PaintFlags flags;
+  gfx::RectF background_bounds(
+      origin,
+      gfx::SizeF(kComboboxArrowContainerWidth, kComboboxArrowContainerWidth));
+  flags.setColor(color);
+  // TODO(crbug.com/1392549): Replace placeholder value for corner radius.
+  int background_corner_radius_chromerefresh2023 =
+      views::LayoutProvider::Get()->GetCornerRadiusMetric(
+          views::Emphasis::kLow);
+  canvas->DrawRoundRect(background_bounds,
+                        background_corner_radius_chromerefresh2023, flags);
+}
+
 void PaintComboboxArrow(SkColor color,
                         const gfx::Rect& bounds,
                         gfx::Canvas* canvas) {
diff --git a/ui/views/controls/combobox/combobox_util.h b/ui/views/controls/combobox/combobox_util.h
index 93fdca60..2e45066 100644
--- a/ui/views/controls/combobox/combobox_util.h
+++ b/ui/views/controls/combobox/combobox_util.h
@@ -14,6 +14,7 @@
 namespace gfx {
 class Canvas;
 class Rect;
+class PointF;
 }  // namespace gfx
 
 namespace views {
@@ -25,11 +26,18 @@
 extern const int kComboboxArrowPaddingWidth;
 extern const int kComboboxArrowContainerWidth;
 
+int GetComboboxArrowContainerWidthAndMargins();
+
 // Paints the arrow for a combobox.
 void PaintComboboxArrow(SkColor color,
                         const gfx::Rect& bounds,
                         gfx::Canvas* canvas);
 
+// Draws a background around the combobox arrow.
+void PaintComboboxArrowBackground(SkColor color,
+                                  gfx::Canvas* canvas,
+                                  gfx::PointF origin);
+
 }  // namespace views
 
 #endif  // UI_VIEWS_CONTROLS_COMBOBOX_COMBOBOX_UTIL_H_
diff --git a/ui/views/controls/editable_combobox/editable_combobox.cc b/ui/views/controls/editable_combobox/editable_combobox.cc
index 0575abb6..a588a52 100644
--- a/ui/views/controls/editable_combobox/editable_combobox.cc
+++ b/ui/views/controls/editable_combobox/editable_combobox.cc
@@ -26,6 +26,7 @@
 #include "ui/base/models/combobox_model_observer.h"
 #include "ui/base/models/menu_model.h"
 #include "ui/base/models/menu_separator_types.h"
+#include "ui/base/ui_base_features.h"
 #include "ui/base/ui_base_types.h"
 #include "ui/events/event.h"
 #include "ui/events/types/event_type.h"
@@ -107,6 +108,12 @@
     canvas->ClipRect(GetContentsBounds());
     gfx::Rect arrow_bounds = GetLocalBounds();
     arrow_bounds.ClampToCenteredSize(ComboboxArrowSize());
+    if (features::IsChromeRefresh2023()) {
+      PaintComboboxArrowBackground(
+          GetColorProvider()->GetColor(ui::kColorAlertHighSeverity), canvas,
+          gfx::PointF(arrow_bounds.x() - kComboboxArrowPaddingWidth,
+                      (height() - kComboboxArrowContainerWidth) / 2.0f));
+    }
     // Make sure the arrow use the same color as the text in the combobox.
     PaintComboboxArrow(style::GetColor(*this, style::CONTEXT_TEXTFIELD,
                                        GetEnabled() ? style::STYLE_PRIMARY
@@ -422,8 +429,9 @@
 void EditableCombobox::Layout() {
   View::Layout();
   if (arrow_) {
-    gfx::Rect arrow_bounds(/*x=*/width() - kComboboxArrowContainerWidth,
-                           /*y=*/0, kComboboxArrowContainerWidth, height());
+    gfx::Rect arrow_bounds(
+        /*x=*/width() - GetComboboxArrowContainerWidthAndMargins(),
+        /*y=*/0, kComboboxArrowContainerWidth, height());
     arrow_->SetBoundsRect(arrow_bounds);
   }
 }
diff --git a/ui/views/corewm/tooltip_controller.cc b/ui/views/corewm/tooltip_controller.cc
index d9818a99..0b4d7f0 100644
--- a/ui/views/corewm/tooltip_controller.cc
+++ b/ui/views/corewm/tooltip_controller.cc
@@ -145,21 +145,6 @@
   state_manager_->RemoveObserver(observer);
 }
 
-void TooltipController::UpdateAndShow(aura::Window* window,
-                                      const std::u16string& text,
-                                      const gfx::Point& position,
-                                      const TooltipTrigger trigger,
-                                      const base::TimeDelta& show_delay,
-                                      const base::TimeDelta& hide_delay) {
-  // Use passed `show_delay` value regardless of `show_delay_enabled_` state.
-  state_manager_->Show(window, text, position, trigger, show_delay, hide_delay);
-}
-
-void TooltipController::HideAndReset() {
-  state_manager_->HideAndReset();
-  SetObservedWindow(nullptr);
-}
-
 int TooltipController::GetMaxWidth(const gfx::Point& location) const {
   return state_manager_->GetMaxWidth(location);
 }
@@ -367,6 +352,11 @@
 ////////////////////////////////////////////////////////////////////////////////
 // TooltipController private:
 
+void TooltipController::HideAndReset() {
+  state_manager_->HideAndReset();
+  SetObservedWindow(nullptr);
+}
+
 void TooltipController::UpdateIfRequired(TooltipTrigger trigger) {
   if (!tooltips_enabled_ || aura::Env::GetInstance()->IsMouseButtonDown() ||
       IsDragDropInProgress() ||
diff --git a/ui/views/corewm/tooltip_controller.h b/ui/views/corewm/tooltip_controller.h
index af5d307..82e523a 100644
--- a/ui/views/corewm/tooltip_controller.h
+++ b/ui/views/corewm/tooltip_controller.h
@@ -59,17 +59,6 @@
   void AddObserver(wm::TooltipObserver* observer);
   void RemoveObserver(wm::TooltipObserver* observer);
 
-  // Calls TooltipStateManager::Show with given params.
-  void UpdateAndShow(aura::Window* window,
-                     const std::u16string& text,
-                     const gfx::Point& position,
-                     const TooltipTrigger trigger,
-                     const base::TimeDelta& show_delay,
-                     const base::TimeDelta& hide_delay);
-
-  // Reset the window and calls `TooltipStateManager::HideAndReset`.
-  void HideAndReset();
-
   // Overridden from wm::TooltipClient.
   int GetMaxWidth(const gfx::Point& location) const override;
   void UpdateTooltip(aura::Window* target) override;
@@ -105,6 +94,9 @@
  private:
   friend class test::TooltipControllerTestHelper;
 
+  // Reset the window and calls `TooltipStateManager::HideAndReset`.
+  void HideAndReset();
+
   // Updates the tooltip if required (if there is any change in the tooltip
   // text, tooltip id or the aura::Window).
   void UpdateIfRequired(TooltipTrigger trigger);
diff --git a/ui/views/widget/native_widget_mac.mm b/ui/views/widget/native_widget_mac.mm
index f9d6283..009cf159 100644
--- a/ui/views/widget/native_widget_mac.mm
+++ b/ui/views/widget/native_widget_mac.mm
@@ -233,7 +233,15 @@
   // platform-specific corner cases.
   if (params.parent &&
       (!params.z_order || params.z_order == ui::ZOrderLevel::kNormal)) {
-    if (auto* parent_widget = Widget::GetWidgetForNativeView(params.parent)) {
+    // In immersive fullscreen, bubbles will be shown under the toolbar by
+    // default. Fix it by using a higher z-order level.
+    // TODO(mek): Figure out how to make this work with remote remote_cocoa
+    // windows.
+    if (remote_cocoa::IsNSToolbarFullScreenWindow(
+            params.parent.GetNativeNSView().window)) {
+      params.z_order = ui::ZOrderLevel::kFloatingWindow;
+    } else if (auto* parent_widget =
+                   Widget::GetWidgetForNativeView(params.parent)) {
       // If our parent is z-ordered above us, then float a bit higher.
       params.z_order =
           std::max(params.z_order.value_or(ui::ZOrderLevel::kNormal),
diff --git a/ui/webui/resources/cr_elements/cr_nav_menu_item_style.css b/ui/webui/resources/cr_elements/cr_nav_menu_item_style.css
index 7541b551..9fa8369 100644
--- a/ui/webui/resources/cr_elements/cr_nav_menu_item_style.css
+++ b/ui/webui/resources/cr_elements/cr_nav_menu_item_style.css
@@ -29,19 +29,13 @@
 }
 
 :host-context(cr-drawer) .cr-nav-menu-item {
-  border-end-end-radius: 0;
-  border-start-end-radius: 0;
-  font-size: inherit;
+  margin-inline-end: 8px;
 }
 
 .cr-nav-menu-item:hover {
   background: var(--google-grey-200);
 }
 
-:host-context(cr-drawer) .cr-nav-menu-item:hover {
-  background: transparent;
-}
-
 .cr-nav-menu-item[selected] {
   --iron-icon-fill-color: var(--google-blue-600);
   background: var(--google-blue-50);
@@ -64,15 +58,6 @@
     background: var(--google-blue-300);
     color: var(--google-grey-900);
   }
-
-  :host-context(cr-drawer) .cr-nav-menu-item[selected] {
-    --iron-icon-fill-color: var(--cr-link-color);
-    color: var(--cr-link-color);
-  }
-}
-
-:host-context(cr-drawer) .cr-nav-menu-item[selected] {
-  background: transparent;
 }
 
 .cr-nav-menu-item:focus {
@@ -93,7 +78,3 @@
   pointer-events: none;
   vertical-align: top;
 }
-
-:host-context(cr-drawer) .cr-nav-menu-item paper-ripple {
-  display: none;
-}
diff --git a/weblayer/app/content_main_delegate_impl.cc b/weblayer/app/content_main_delegate_impl.cc
index 7e4a98b..86094aa 100644
--- a/weblayer/app/content_main_delegate_impl.cc
+++ b/weblayer/app/content_main_delegate_impl.cc
@@ -198,7 +198,6 @@
     // TODO(crbug.com/1131016): Support Picture in Picture API on WebLayer.
     &media::kPictureInPictureAPI,
 
-    &::features::kDisableDeJelly,
     &::features::kDynamicColorGamut,
 #else
     // WebOTP is supported only on Android in WebLayer.